diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5a0d5e4 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b843786 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ + +# built stuff +*.pkg +*.bin +*.oelf +*.elf +*.self +*.suo +*.log +*.a +*.o +*.o.tmp + +.vs/ProjectSettings.json +.vs/slnx.sqlite +.vs/Store-GLES-iapps/v16/Browse.VC.db +.vs/Store-GLES-iapps/v16/Browse.VC.db-shm +.vs/Store-GLES-iapps/v16/Browse.VC.db-wal +.vs/Store-GLES-iapps/v16/Browse.VC.opendb + +# unwanted data +*.json +*.sqlite +*.ipch +*.db +*.db-wal +*.db-shm +*.opendb +App Media-Assets/rsa.pub +itemzflow/build_all_dev.sh +*.id0 +*.id1 +*.nam +*.id2 +*.til +external/libfuse.zip +itemzflow/source/test.c diff --git a/App-Media-Assets/Media/curl.prx b/App-Media-Assets/Media/curl.prx new file mode 100644 index 0000000..31b6bf6 Binary files /dev/null and b/App-Media-Assets/Media/curl.prx differ diff --git a/App-Media-Assets/Media/jb.prx b/App-Media-Assets/Media/jb.prx new file mode 100644 index 0000000..5a4d1fa Binary files /dev/null and b/App-Media-Assets/Media/jb.prx differ diff --git a/App-Media-Assets/Media/rsa.prx b/App-Media-Assets/Media/rsa.prx new file mode 100644 index 0000000..4162353 Binary files /dev/null and b/App-Media-Assets/Media/rsa.prx differ diff --git a/App-Media-Assets/Media/rsa.pub b/App-Media-Assets/Media/rsa.pub new file mode 100644 index 0000000..7f39394 --- /dev/null +++ b/App-Media-Assets/Media/rsa.pub @@ -0,0 +1,2 @@ +N = F1321AA3CC5CD71F82C1E551BEFC3D4F489C9A073AC8A8CECB616DB55406751D0717950F91DB91E1C45C1492F2F8DDC61FD357C68CB415866DB2F6CAC6EE7C1586AF4AD96C24FCBA13A51942017BD00611A48ABCE87920DD5344D81D0274FDA3BA1FFE1B760755C313FEB240081C74B9E821D50A9AFFE5ACA832CD619F4BE79292CB996D761104B77CB29FA771761B1914C41A57F5055095739D3395BB6CBA3FB0DAB78666868E4B02874FC6C9346A8DA45A36F1D2C39A93D596D6C598C986168D6226DE26309D73F8A1CC299A25BE865AC0E988F080192F8326FEA692A67FBC4C53C1EDB2DFDB550A90C23DA3638AB78C8F9AD0829704D7E61BD98A6F2C3BD9 +E = 010001 diff --git a/App-Media-Assets/assets/backgroundUnitOffline.png b/App-Media-Assets/assets/backgroundUnitOffline.png new file mode 100644 index 0000000..1c80aec Binary files /dev/null and b/App-Media-Assets/assets/backgroundUnitOffline.png differ diff --git a/App-Media-Assets/assets/buttons/btn_X.png b/App-Media-Assets/assets/buttons/btn_X.png new file mode 100644 index 0000000..672156b Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_X.png differ diff --git a/App-Media-Assets/assets/buttons/btn_down.png b/App-Media-Assets/assets/buttons/btn_down.png new file mode 100644 index 0000000..75c27bc Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_down.png differ diff --git a/App-Media-Assets/assets/buttons/btn_l1.png b/App-Media-Assets/assets/buttons/btn_l1.png new file mode 100644 index 0000000..ac4262e Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_l1.png differ diff --git a/App-Media-Assets/assets/buttons/btn_l2.png b/App-Media-Assets/assets/buttons/btn_l2.png new file mode 100644 index 0000000..b6b1eea Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_l2.png differ diff --git a/App-Media-Assets/assets/buttons/btn_left.png b/App-Media-Assets/assets/buttons/btn_left.png new file mode 100644 index 0000000..064d98b Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_left.png differ diff --git a/App-Media-Assets/assets/buttons/btn_o.png b/App-Media-Assets/assets/buttons/btn_o.png new file mode 100644 index 0000000..a80bbfc Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_o.png differ diff --git a/App-Media-Assets/assets/buttons/btn_options.png b/App-Media-Assets/assets/buttons/btn_options.png new file mode 100644 index 0000000..db0e7c0 Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_options.png differ diff --git a/App-Media-Assets/assets/buttons/btn_r1.png b/App-Media-Assets/assets/buttons/btn_r1.png new file mode 100644 index 0000000..8b5ca92 Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_r1.png differ diff --git a/App-Media-Assets/assets/buttons/btn_right.png b/App-Media-Assets/assets/buttons/btn_right.png new file mode 100644 index 0000000..c3fd4fe Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_right.png differ diff --git a/App-Media-Assets/assets/buttons/btn_sq.png b/App-Media-Assets/assets/buttons/btn_sq.png new file mode 100644 index 0000000..1f6957b Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_sq.png differ diff --git a/App-Media-Assets/assets/buttons/btn_tri.png b/App-Media-Assets/assets/buttons/btn_tri.png new file mode 100644 index 0000000..72aef21 Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_tri.png differ diff --git a/App-Media-Assets/assets/buttons/btn_up.png b/App-Media-Assets/assets/buttons/btn_up.png new file mode 100644 index 0000000..d0efd6d Binary files /dev/null and b/App-Media-Assets/assets/buttons/btn_up.png differ diff --git a/App-Media-Assets/assets/cover.png b/App-Media-Assets/assets/cover.png new file mode 100644 index 0000000..870b676 Binary files /dev/null and b/App-Media-Assets/assets/cover.png differ diff --git a/App-Media-Assets/assets/disc.png b/App-Media-Assets/assets/disc.png new file mode 100644 index 0000000..e72fc53 Binary files /dev/null and b/App-Media-Assets/assets/disc.png differ diff --git a/App-Media-Assets/assets/fonts/HelveticaWorld-Multi.ttf b/App-Media-Assets/assets/fonts/HelveticaWorld-Multi.ttf new file mode 100644 index 0000000..4b22a33 Binary files /dev/null and b/App-Media-Assets/assets/fonts/HelveticaWorld-Multi.ttf differ diff --git a/App-Media-Assets/assets/fonts/NotoSansJP-Regular.ttf b/App-Media-Assets/assets/fonts/NotoSansJP-Regular.ttf new file mode 100644 index 0000000..f948ae7 Binary files /dev/null and b/App-Media-Assets/assets/fonts/NotoSansJP-Regular.ttf differ diff --git a/App-Media-Assets/assets/fonts/NotoSansKR-Regular.ttf b/App-Media-Assets/assets/fonts/NotoSansKR-Regular.ttf new file mode 100644 index 0000000..46b8d98 Binary files /dev/null and b/App-Media-Assets/assets/fonts/NotoSansKR-Regular.ttf differ diff --git a/App-Media-Assets/assets/fonts/NotoSansSC-Regular.ttf b/App-Media-Assets/assets/fonts/NotoSansSC-Regular.ttf new file mode 100644 index 0000000..dd33fb7 Binary files /dev/null and b/App-Media-Assets/assets/fonts/NotoSansSC-Regular.ttf differ diff --git a/App-Media-Assets/assets/fonts/NotoSansTC-Regular.ttf b/App-Media-Assets/assets/fonts/NotoSansTC-Regular.ttf new file mode 100644 index 0000000..ea2de21 Binary files /dev/null and b/App-Media-Assets/assets/fonts/NotoSansTC-Regular.ttf differ diff --git a/App-Media-Assets/assets/fonts/NotoSansThai-Regular.ttf b/App-Media-Assets/assets/fonts/NotoSansThai-Regular.ttf new file mode 100644 index 0000000..44993f0 Binary files /dev/null and b/App-Media-Assets/assets/fonts/NotoSansThai-Regular.ttf differ diff --git a/App-Media-Assets/assets/no_save.png b/App-Media-Assets/assets/no_save.png new file mode 100644 index 0000000..13e3e73 Binary files /dev/null and b/App-Media-Assets/assets/no_save.png differ diff --git a/App-Media-Assets/assets/notis/error.png b/App-Media-Assets/assets/notis/error.png new file mode 100644 index 0000000..52ce7c0 Binary files /dev/null and b/App-Media-Assets/assets/notis/error.png differ diff --git a/App-Media-Assets/assets/notis/game.png b/App-Media-Assets/assets/notis/game.png new file mode 100644 index 0000000..628d731 Binary files /dev/null and b/App-Media-Assets/assets/notis/game.png differ diff --git a/App-Media-Assets/assets/notis/game_usb.png b/App-Media-Assets/assets/notis/game_usb.png new file mode 100644 index 0000000..88f390f Binary files /dev/null and b/App-Media-Assets/assets/notis/game_usb.png differ diff --git a/App-Media-Assets/assets/notis/info.png b/App-Media-Assets/assets/notis/info.png new file mode 100644 index 0000000..f962cc2 Binary files /dev/null and b/App-Media-Assets/assets/notis/info.png differ diff --git a/App-Media-Assets/assets/notis/kofi.png b/App-Media-Assets/assets/notis/kofi.png new file mode 100644 index 0000000..fdcb58c Binary files /dev/null and b/App-Media-Assets/assets/notis/kofi.png differ diff --git a/App-Media-Assets/assets/notis/profile.png b/App-Media-Assets/assets/notis/profile.png new file mode 100644 index 0000000..227badf Binary files /dev/null and b/App-Media-Assets/assets/notis/profile.png differ diff --git a/App-Media-Assets/assets/notis/success.png b/App-Media-Assets/assets/notis/success.png new file mode 100644 index 0000000..d41fae5 Binary files /dev/null and b/App-Media-Assets/assets/notis/success.png differ diff --git a/App-Media-Assets/assets/notis/warning.png b/App-Media-Assets/assets/notis/warning.png new file mode 100644 index 0000000..0e0aea2 Binary files /dev/null and b/App-Media-Assets/assets/notis/warning.png differ diff --git a/App-Media-Assets/itemzflow.gp4 b/App-Media-Assets/itemzflow.gp4 new file mode 100644 index 0000000..bfff242 --- /dev/null +++ b/App-Media-Assets/itemzflow.gp4 @@ -0,0 +1,98 @@ + + + + pkg_ps4_app + 2021-11-16 23:01:37 + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/App-Media-Assets/langs/0/lang.ini b/App-Media-Assets/langs/0/lang.ini new file mode 100644 index 0000000..dca2d8b --- /dev/null +++ b/App-Media-Assets/langs/0/lang.ini @@ -0,0 +1,483 @@ +[LOADER] +LOADER_FATAL=致命的! +FATAL_JB=FATAL ジェイルブレイクはコードで失敗しました +FATAL_REJAIL=FATAL rejail_multi がコードで失敗しました +SWU_ERROR=[SWU エラー] アップデートは取り消され、このアップデートを使用するとセキュア ブートがオフになります +RSA_LOAD=RSA署名をチェックしています... +RSA_FAILED=RSA チェックがエラー コードで失敗しました +SECURE_FAIL=セキュア ブートは有効になっていますが、CDN から Sig ファイルをダウンロードできませんでした +LOADER_ERROR=ItemzFlows ローダーでエラーが発生しました +MORE_INFO=詳細を確認するには: /mnt/usb0/itemzflow/loader.log アプリを閉じます +INI_FAIL=INI ファイルを作成できませんでした +STR_NOT_FOUND=文字列が見つかりません + +#strings IF +【ITEMZFLOW】 +RSA_LOAD=RSA署名をチェックしています... +RSA_FAILED=RSA チェックがエラー コードで失敗しました +OPT_UPDATE=アップデートが利用可能です。今すぐアップデートしますか? +SORT_OPTS=アプリの並べ替え +STR_NOT_FOUND=文字列が見つかりません +ITEMZ_SETTINGS=アイテムズフロー設定 +RESORT=リゾートゲーム・アプリ +MISSING_EBOOT=[内部] eboot.bin が /data/app/ または /hostapp/app/ にありません +MISSING_SFO=[内部] param.sfo が /data/app/sce_sys または /hostapp/app/sce_sys にありません +CORRUPT_SFO=param.sfo が壊れています +ON2=オン +OFF2=オフ +TRUE2=真 +FALSE2=偽 +STORAGE=ストレージ +ITEMZ_VER=Itemzflow バージョン +SYS_VER=システムバージョン +OTHER=その他 +INSTALLING=インストール中... +SETTINGS=設定 +ID2=ID +NAME2=名前 +DISC2=ディスク +INSTALL_FAILED=コードでインストールに失敗しました +INSTALL_OF=のインストール +COMPLETE=これで完了です! +FAILED_W_CODE=コードで失敗しました +FATAL_ERROR=致命的なエラー +PRESS_OK_CLOSE=OK を押した後、プログラムを閉じてください +WARNING2=警告 +FAILED_TTF=TTF からの読み込みに失敗しました +SWITCH_TO_EM=組み込みへの切り替え +INI_ERROR=INI ファイルが見つからない/開くことができませんでした +FAILED_DAEMON=IF デーモンが失敗しました +DAEMON_OFF=デーモンの自動起動がオフになっています +DAEMON_OFF2=これにより、いくつかのことが機能しなくなる可能性があります +DL_CACHE=Web サイトのファイルをダウンロードしてキャッシュしています... +PIG_FAIL=ピグレット (小売) の読み込みに失敗しました +NO_USB=USB が検出されませんでした。終了しています... +DUMP=[OK] を押すとゲームが起動します。数秒待ってからストアに戻ると、ゲームのダンプが開始されます。ダンプが完了するまで、ゲームを閉じたりストアしたりしないでください。 +UNINSTALL_UPDATE=ゲームのアップデートが正常にアンインストールされました +UNINSTAL_UPDATE_FAILED=ゲームアップデートのアンインストールに失敗しました +UNINSTALL_SUCCESS=ゲームが正常にアンインストールされました。インストールされたアプリのリストがリロードされます +UNINSTALL_FAILED=ゲームのアンインストールに失敗しました +COMING_SOON=近日公開予定 +RELOAD_IAPPS=インストール済みアプリのリストがリロードされます +APP_REQ=このゲーム ランチャーには最小要件があります。 4 アプリ それを使用するには、インストールする必要があります。 +MORE_APPS=その他のアプリ +DOWNLOADING_COVERS=サーバーからカバーをダウンロードしています +DL_FAILED_W=StatusCode でダウンロードに失敗しました: +STR_TOO_LONG=文字列が長すぎるか無効です有効なエントリを入力してください +INVAL_PATH=無効なパス! 有効なパスを入力してください +INVAL_TTF=INVALID .ttf パス ファイル拡張子が .ttf であることを確認してください +CACHE_CLEARED=キャッシュされたすべての画像が正常に削除/消去されました +CLEARING_CACHE=キャッシュされたコンテンツをクリアしています +CACHE_FAILED=キャッシュされたコンテンツのクリアに失敗しました +ITEMZ_FEATURE_DISABLED=この機能は無効です。理由: ItemzFlow デーモンが接続されていません +SAVE_ERROR=保存エラー +SAVE_SUCCESS=保存に成功しました +DL_FAILED2=コードでダウンロードに失敗しました +OBJ_EXPECTED=オブジェクトが必要です +CANT_OPEN=開くことができません +APP_DIED=アプリは終了コードで終了しました +PKG_TEAM=これが続く場合は、PKG-Zone チームに連絡してください +FATAL_DUMP_ERROR=ゲーム ダンプに失敗しました。アプリはリロードされます。[OK] を押して続行します。 +DUMP_OF=ダンプ +COMPLETE_WO_ERRORS=エラーなしで完了!: +DUMP_FAILED=すべてのファイルがダンプされたわけではありません! エクスプロイト ホストで MMAP パッチが有効になっていることを確認してください +EXCEED_LIMITS=ページ数がストアの制限を超えています! +DL_ERROR_PAGE=ページをダウンロードできませんでした: +ERROR_DL_ASSETS=アセットをダウンロードできませんでした: +APP_NOT_FOUND=アプリが見つかりません +APP_OPENED=アプリはすでに開かれています +APP_CLOSED=アプリを閉じました +APP_UNL=アプリは起動できません +ID_NOT_VAILD=TITLE_ID は無効です +LAUNCH_ERROR=アプリの起動がエラー コードで失敗しました +RELOAD_LIST=アプリリストをリロード中... +SEARCHING=検索中.... +WAITING_FOR_DAEMON=デーモンのウェルカム応答を待機中 (最大 1 分) +TRYING_TO_DL=カバーをダウンロードしようとしています +DL_COVERS=サーバーから表紙をダウンロード中 +STARTING_DUMPER=ダンパーを開始しています... +UU=アップデートのアンインストール +UG=ゲームのアンインストール +SETTINGS_1=ダンパー パス +SETTINGS_2=アップデートを確認 +SETTINGS_3=アプリの並べ替え +SETTINGS_4=デフォルトのダッシュボードとして設定 +SETTINGS_6=テーマインストーラー +SETTINGS_7=バックグラウンド MP3 パス +SETTINGS_8=ボタンコントロールを表示 +SETTINGS_9=PS4 メニューを開く +SETTINGS_10=PKGインストーラー +SETTINGS_11=コンソールの電源コントロール +SETTINGS_12=設定を保存 +NA_SORT1=ランダム +TID_ALPHA_SORT1=タイトル ID のアルファベット順 +TITLE_ALPHA_SORT1=アプリ名のアルファベット順 +UNINSTALL_GAME1=ゲーム/アプリのアンインストール +UNINSTALL_PATCH1=パッチのアンインストール +UNINSTALL_DLC1=DLC のアンインストール +UNINSTALL_NOTE=アンインストール オプションの選択を選択します +SEL_DUMP_ALL1=すべてダンプ +SEL_BASE_GAME1=基本ゲームのみをダンプ +SEL_GAME_PATCH1=パッチのみをダンプ +SEL_REMASTER1=リマスターのみをダンプ +SEL_DLC1=DLC のみをダンプ +LAUNCH_GAME=起動 +DUMP_1=ダンプ +TRAINERS=トレーナー +UNINSTALL=アンインストール +HIDE_APP=アプリを非表示 +CHANGE_ICON=アイコンの変更 (PNG) +CHANGE_APP_NAME=アプリ名の変更 ちゃん +タイトルIDの変更 +NAME_INFO=PS4s XMB (app.db) の PS4 アプリ名を変更します +IF_NOT_EFFECTED=注: Itemzflow には影響しません +TID_INFO=app.db のアプリ タイトル ID を変更します +ICON_INFO=選択したアプリの新しいカスタム Icon0 へのパスを入力してください +LAUNCH_INFO=選択したゲーム/アプリを起動します +TRAINER_INFO=選択したゲームのトレーナーを取得します +HIDE_INFO=PS4s app.db でゲーム/アプリを非表示にします +DUMP_OPT_INFO=選択してダンプ オプションを選択します +PLAYING_SINCE=以降のプレイ +PNG_NOTE=注意: 512x512 PNG のみ! +SUSPEND_IF=注: Itemzflow は中断されます +HIDE_OPT_INFO=注意: 設定メニューから Itemzflow から非表示にすることもできます +SEL_DUMP_ALL_INFO=ダンプ (すべて) ゲームと利用可能な DLC とパッチ +SEL_BASE_GAME_INFO=基本ゲームのみをダンプします +SEL_GAME_PATCH_INFO=ゲームパッチのみをダンプします +SEL_REMASTER_INFO=利用可能なリマスターのみをダンプ +SEL_DLC_INFO=利用可能なDLCのみをダンプ +SETTINGS=設定 +FTP_NOT_RUNNING=FTP が実行されていません (オフ) +FTP_RUNNING=FTP 実行中 (ON) +DUMPER_PATH_DESC=カスタム ダンプ パスを選択 +REBUILD_DB_OPTION_DESC=PS4s アプリ データベース (app.db) を再構築します。 +SORT_BY_OPTION_DESC=Itemzflow がアプリをソートする方法を選択します (IF を開くのが遅くなります) +HOME_MENU_OPTION_DESC=PS ホームボタンをこのアプリにリダイレクトします +FTP_SERVICE_OPTION_DESC=FTP を一時的にオンまたはオフにする +TTF_OPTION_DESC=カスタム TTF フォント パスを選択 +Background_MP3_OPTION_DESC=バックグラウンドで再生するカスタム 48Hz MP3 を選択します +SHOW_BUTTON_OPTION_DESC=ボタン コントロールの表示または非表示 +OPEN_DEBUG_MENU_DESC=PS4s デバッグまたは設定メニューを開きます +RDB=FPKG データベースの再構築 +RELOAD_APPS=アプリのリロード +#ボタン情報 +BUTTON_X_INFO=選択/確認 +BUTTON_O_INFO=戻る/キャンセル +BUTTON_LEFT_RIGHT_INFO=前へ/次へ +BUTTON_UP_DOWN_INFO=上/下 +BUTTON_TRIANGLE=アプリのリロード +BUTTON_CLOSE=アイテムズフローを終了 +BUTTON_CONFIRM_CLOSE=閉じることを確認 +CLOSE_GAME=開いているゲームを閉じる +FAILED_MENU_OPEN=メニューを開くことができませんでした +ERROR_CODE=エラーコード +SELECT_INTERACT=インタラクトするには X を押してください +GAME_SAVE_OPTS=ゲーム保存オプション +BACKUP_SAVE=すべての保存をバックアップ +IMPORT_SAVE=インポート保存 +SAVE_DELETE=すべての保存を削除 +SHOW_APP=非表示解除 +HIDE_APP_OPT=アプリの可視性 +PS4_REBOOT_REQ=変更には再起動が必要 +PLEASE_WAIT=お待ちください... +APPS_RELOADED=リロードされたアプリ +APPS_RELOADED_2=アプリ リストが更新されました +CON_DIS=コントローラーが切断されました +CON_DIS_2=コントローラーを再接続する +REALLY_HOT=PS4 めっちゃアツい! +REALLY_HOT_2=PS4 が 90C を超えています。新しいサーマル ペーストを検討してください +NO_SAVES=セーブ可能なゲームはありません +CANT_FIND_SAVE=保存が見つかりませんでした +SAVE_OPS_FAILED=保存操作に失敗しました +FAILED_INI_SD=セーブデータの初期化に失敗しました +FAILED_MOUNT_SD=保存のマウントに失敗しました +SD_SAVED=USB に保存されたゲームの保存 +SD_TRANSFER_FAIL=保存を転送できませんでした +SD_DELETED=削除されたゲームの保存 +CANT_DELETE_SD=削除できませんでした +DECRYPTED_SD=復号化された保存が見つかりません +NO_AVAIL_SAVE=利用できる保存はありません +SAVE_IMPORTED=ゲームセーブがインポートされました! +SAVE_IMPORT_2=タイトルを保存 +NO_USERID=ユーザー ID を取得できませんエラー +UNSUPPORTED_FS=サポートされていないファイルシステムが検出されました +RETAILO=小売 PS4 のみ +NO_GOLDHEN=GoldHEN または ps4debug がありません! +FAILED_SAVE_PATCHES=保存パッチの適用に失敗しました! +UNSUPPORTED_FW=サポートされていないFWバージョン +MP3_PLAYING=MP3再生中 +MP3_LOADED=MP3 ロード済み +FAILED_MP3=MP3 の読み込みに失敗しました +TRAINER_LOADED=トレーナーがロードされました +TRAINER_FAILED=トレーナーのロードに失敗しました +TRAINER_ESRCH=トレーナーが見つかりません +GAME_LAUCNHED=ゲームが起動されました +GAME_KILLED=ゲームが強制終了されました +GAME_RESUME=ゲームを再開 +PLUG_MNG=プラグインマネージャー +PLUG_LOADED=プラグインがロードされました +PLUG_FAILED=プラグインのロードに失敗しました +PLUG_ERROR=プラグイン エラー +LANG_NOT_SUPPORTED=ItemzFlowはあなたの言語ではありません +ENG_LOADED=代わりに英語がロードされました... +IF_UPDATE_SUCESS=Itemzflow が更新されました! +FAILED_ICON=アイコンの変更に失敗しました +DAEMON_FAILED_NOTIFY=ItemzDaemon の接続に失敗しました +DAEMON_FAILED_NOTIFY2=一部の機能が無効になります! +PWR_OFF_SYS=システムの電源を切る +RESTRT_SYS=システムの再起動 +SUSPEND_SYS=システムの一時停止 +NO_INTERNET=サーバーに接続できませんでした +BE_SURE_INTERNET=インターネットが有効になっていることを確認してください +SFO_OP_FAILED=SFO 操作が失敗しました! +ICON_OP_FAILED=アイコンの操作に失敗しました! +GAME_DUMP_FAILED=ゲームのダンプに失敗しました! +GAME_DUMP_FAILED2=ディスクに問題がないか確認してください +UNABLE_TO_TRANFER=転送に失敗しました! +FTP_START_NOTIFY=FTP プラグイン開始 +FTP_STOP_NOTIFY=FTP プラグインが停止しました +FTP_ERROR=FTP エラーが発生しました +REDIRECT_TURNED_ON=ホームメニューのリダイレクトが有効 +REDIRECT_TURNED_OFF=ホームメニューリダイレクト無効 +APP_DB_REBUILT=アプリ DB が修復されました +APP_DB_ERROR=アプリ DB の修復に失敗しました! +TTF_SUCCESS_NOTIFY=新しい TTF がロードされました +TTF_ERROR_NOTIFY=TTF フォントの読み込みに失敗しました +TTF_ERROR_NOTIFY2=デフォルト TTF をロードしました +SETTING_APPLIED=設定が適用されました +PKG_INST_FAILED=PKG のインストールに失敗しました! +PKG_INST_FAILED1=PKG を検証してください +PKG_INST_SUCCESS=PKG が正常にインストールされました +USB_NOTIFY=USB デバイスが挿入されました +USB_NOTIFY1=USB を使用する準備ができました +NOT_ENOUGH_FREE_SPACE=十分な空き容量がありません +UNHIDE_NOTIFY=可視性が変更されました +UNHIDE_SUCCESS_NOTIFY=アプリが表示されるようになりました +HIDE_SUCCESS_NOTIFY=アプリは Hideen になりました +UNHIDE_FAILED_NOTIFY=可視性の変更に失敗しました +FAILED_TO_CLOSE=アプリを閉じられませんでした +OPT_NOT_PERMITTED=ここではオプションを利用できません +TITLE_ID_NOT_RIGHT=タイトル ID が無効です +TILE_ID_CHANGED=タイトル ID が変更されました +TITLE_ID_FAILD=タイトル ID の変更に失敗しました! +PARAM_PATH_FAILED=SFO へのパッチ適用に失敗しました! +TITLE_CHANGED=アプリのタイトルが変更されました +FAILED_TITLE_CHANGE=ゲーム タイトルの変更に失敗しました +CONSIDER_SUPPORT=Ko-fi で私たちをサポートしてください! +DUMPER_PATH_NO_AVAIL=ダンパー パスが無効です! +FS_SEL_FAILED=ファイル セレクターを開けませんでした +FS_SEL_ERROR1=FS セレクターを開けません +FS_SEL_ERROR2=セレクターはすでに開始されています +ICON_CHANGED_SUCCESS=アイコンが変更されました! +ICON_CHANGE_FAILED=アイコンの変更に失敗しました +PNG_NOT_VAILD=PNG は有効ではありません! +FAILED_TO_COPY=コピーに失敗しました +FONT_CHANGED_SUCCESS=フォントが変更されました! +NEW_FONT_STRING=新しいフォント +DUMPER_PATH_UPDATED=ダンパー パスが更新されました! +NEW_PATH_STRING=新しいパス +PKG_IS_INSTALLING=PKG をインストールしています... +PKG_IS_INSTALLED=インストールが完了しました +VAR_IS_INSTALLED=現在インストールされています +FS_CONTROL_BUTTON_1=フォルダを入力してください +FS_CONTROL_BUTTON_2=前のフォルダ +FS_CONTROL_BUTTON_3=キャンセル/終了 +FS_CONTROL_BUTTON_4=ファイルを選択 +FS_CONTROL_BUTTON_4_1=フォルダを選択 +FS_CONTROL_BUTTON_5=ファイル パネルの切り替え +FS_CONTROL_BUTTON_6=新しいフォルダー +FS_CONTROL_BUTTON_7=コピー/貼り付け +FOLDER_MADE_SUCCESS=フォルダが作成されました! +FOLDER_MAKE_FAIL=フォルダの作成に失敗しました! +OP_CANNED=操作がキャンセルされました! +OP_CANNED_1=変更は適用されていません +MOVE_APP_OPT=USB に移動 +MOVE_APP_OPT_1=アプリ/ゲームの移動 +MOVE_APP_OPT_2=DLCの移動 +MOVE_APP_OPT_3=パッチを移動 +RESTORE_APP_OPT=USB から復元 +RESTORE_APP_OPT_1=アプリ/ゲームを復元 +RESTORE_APP_OPT_2=DLCを復元 +RESTORE_APP_OPT_3=パッチを復元 +RETAIL=小売 +RESTORE_SUCCESS=復元成功 +MOVE_SUCCESSFULLY=正常に移動しました +RESTORE_FAILED=復元に失敗しました +MOVE_FAILED=移動に失敗しました +APP_MOVE_NOTIFY=アプリを正常に移動しました +SELECT_A_FOLDER=続行するにはフォルダを選択してください +SELECT_A_FILE=続行するにはファイルを選択してください +APP_MOVING_MESSAGE=アプリの移動先 +APP_NOT_MOVED=復元するものがありません +BACKUP_FPKG=バックアップ FPKG +COPYING_FPKG=FPKG をコピーしています。お待ちください... +FPKG_COPY_SUCCESS=FPKG が正常にコピーされました +FPKG_COPY_FAILED=FPKG はコピーに失敗しました! +EXT_MOVE_NOT_SUPPORTED=外部アプリはサポートされていません! +PATCH_MOVE_NOTIFY=パッチが正常に移動されました +DLC_MOVE_NOTIFY=DLC は正常に移動されました +COPYING_FILE=ファイルをコピーしています。お待ちください... +RESTORE_INFO_TEXT=Itemzflow で移動したデジタル アプリを復元する +MOVE_INFO_TEXT=デジタルでダウンロードしたコンテンツを USB に移動 +OPTION_DOESNT_SUPPORT_DISC=このオプションはディスクをサポートしていません +BACKUP_FPKG_INFO=後で再インストールするためにゲーム FPKG をバックアップします (FPKG のみ) +GAME_CONTROL_INFO=ゲーム コントロール: アプリを再開または閉じる +CLOSE_OPEN_APP_INFO=現在開いているゲームまたはアプリを閉じる +GAME_CONTROLS=ゲーム コントロール +RESTORE_GAME_INFO=ストレージから復号化された保存 (フォルダ) をインポートして再署名する +BACKUP_GAME_INFO=このゲームのすべてのゲームセーブを復号化してバックアップ +DELETE_GAME_INFO=このゲームのセーブデータをすべて削除 +UNINSTALL_PATCH_INFO=このゲームにインストールされているすべてのパッチをアンインストールします +UNINSTALL_GAME_INFO=ゲーム/アプリとすべての添付ファイルをアンインストールします +SORT_RANDOM_INFO=アプリ/ゲームをランダムに並べ替える +SORT_ALPHA_NAME_INFO=アプリ/ゲームを名前のアルファベット順に並べ替えます +SORT_ALPHA_TID_INFO=アプリ/ゲームをタイトル ID のアルファベット順に並べ替える +THE_ITEM_IS_ALREADY_BP=選択したアイテムはすでにバックアップされています +IF_PKG_INSTALLER=IF パッケージ インストーラー +IF_PKG_INSTALLER_INFO=USB ドライブから PKG をインストールします +THEME_INSTALLER=IFテーマインストーラー +THEME_NOT_VAILD=テーマが無効です! +THEME_INSTALLER_INFO=USB ドライブから IF テーマをインストール +THEME_INSTALL_SUCCESS=テーマがインストールされ、適用されました! +THEME_FAILED_TO_APPLY=テーマの適用に失敗しました +FOUND_SAVE_MESSAGE=ゲームセーブが見つかりました +FOUND_SAVE_MESSAGE_OVER_1=ゲームの保存が見つかりました。1 件を表示しています... +USER_LANG=ユーザー +NO_SAVES_LANG=保存なし +DOWNLOAD_COVERS=カバーを今すぐチェックおよび/またはダウンロードしますか? +LOADING_GAME_LIST=ゲームリストを読み込んでいます... +RESTORE_NOTICE=復元すると、このゲームのすべての DLC とセーブデータが削除されます +INSTALLING_THEME=テーマのインストールと検証中... +RESTART_STR=再起動 +SHUTDOWN_STR=シャットダウン +SUSPEND_STR=サスペンド +ERROR_POWER_CONTROL=電力レベルの設定エラー +POWER_CONTROL_INFO=コンソールの電源オプション +USB_DISCONNECTED=USB が切断されました! +USB_DISCONNECTED1=USB デバイスが取り外されました +REINSTALL_APP_CONFIRMATION=このアプリは既にインストールされています。再インストールしますか? (すべてのゲームデータが削除されます!) +THEME_RESET=デフォルトのテーマが設定されました +NO_DLC_AVAIL=利用可能なDLCはありません +NO_PATCH_AVAIL=利用可能なパッチがありません +RELAUCHING_IN_5=IF を 5 秒後にリロードしています... +CREATE_CUSTOM_DIR=新しいフォルダ名を入力してください +FETCH_STATS=アプリの統計を取得しています... +STATS_MINS=プレイ時間 +STATS_HOURS=時間 +STATS_DAYS=日 +NO_STATS_AVAIL=利用可能なアプリ統計がありません +SAVE_OP_ON_GOING=保存操作が進行中です。お待ちください... +NO_UPDATE_FOUND=ItemzFlow の更新が見つかりません! +IF_UPDATE_FAILD=ItemzFlow アップデートのインストールに失敗しました! +NO_UPDATE_FOUND_INFO=インターネットは有効になっていますか? +CHECH_UPDATE_IN_PROGRESS=更新を確認しています... +CHECK_UPDATE_INFO=Itemzflow アップデート (OTA アップデート) をチェック +PSV_MENU=パワーセーブ設定 +EJECT_DISK=ディスクの取り出し +EJECT_DISK_ERROR=ディスク取り出しエラー +EJECT_DISK_SUCCESS=ディスクが正常に取り出されました +NO_DISC_INSERTED=ディスクが挿入されていません +OVERWRITE_SAVE=現在の保存を上書きしますか? +DUMPER_CANCELLED=ダンプ操作がキャンセルされました +REBUILDING_FOR_FPKG=データベースの再構築 +CURRENT_APP=Current App +TOTAL_NUM_OF_APPS=現在のアプリ +TOTAL_NUM_OF_APPS=アプリの総数 +NUMB_OF_FIXED_APPS=修正されたアプリの数 +NOT_FIXED=未修正 +LAUNCH_FAILED_BC_NOT_FOUND=PS4s アプリ データベースでアプリが見つからなかったため、起動に失敗しました +CONFIRMATION_2=このアプリを PS4s データベースに追加しますか? +IF_LAUNCH_TROUBLESHOOTER=IF トラブルシューターの起動 +GAME_INSERT_SUCCESSFUL=データベースに追加されました +GAME_INSERT_FAILED=アプリを PS4s データベースに追加できませんでした! +FIX_BROKEN_SFO_DB=PS4s データベースのアプリ情報が破損しているため、起動に失敗しました +CONFIRMATION_3=修復を試みますか? +REPAIR_ATTEMPTED=修復を試みました! +REPAIR_ATTEMPTED1=再起動を試みる +PLACEHOLDER=プレースホルダ +PLACEHOLDER_NOT_ENTER=プレースホルダーは操作できません +NO_PATCHES=パッチが見つかりません。 +PATCH0_APPLIED=パッチ適用済み: +PATCH1_APPLIED=適用されたパッチ: +SUSPEND_FAILED=重大なサスペンドに失敗しました +DAEMON_SUSPEND_FAILED=デーモンがクリティカル サスペンドのアクティブ化に失敗しました +NO_PATCH_SELECTED=パッチが選択されていません +NO_APP_OPENED_STR=アプリが開かれていません +PATCH_NUM=パッチ +PATCH_GAME_TITLE=パッチゲームのタイトル: +PATCH_NAME=パッチ名: +PATCH_APP_VER=パッチアプリのバージョン: +PATCH_AUTHOR=パッチ作成者: +PATCH_NOTE=パッチノート: +PATCH_VER=パッチ バージョン: +PATCH_ENABLED=パッチ有効: +PATCH_SET0=パッチ無効: +PATCH_SET1=パッチ有効: +PATCH_DL_QUESTION=パッチ データベースをダウンロード/更新しますか? +PATCH_DL_QUESTION_NO=パッチはダウンロードされません。 +PATCH_DL_QUESTION_YES=パッチ データベースをダウンロードしています... +PATCH_DL_COMPLETE=パッチ データベースのダウンロードに成功しました。 +BUTTON_PATCH_TRI_INFO=パッチ データベースのダウンロード/更新 +BUTTON_PATCH_SQUARE_INFO=パッチの詳細を表示 +CHANGE_CATEGORY=カテゴリーの変更 +SHOWING_CATEGORY=表示カテゴリ +RETAIL_GAMES=小売ゲーム +GAMES=ゲーム +HOMEBREW=自作 +FPKG_STR=FPKG +NONE=なし +NO_TRAINERS=トレーナーが見つかりません +UPDATED_CATEGORY=カテゴリーが更新されました! +INC_CAT=カテゴリに含める +CAT_REBUILD_WARNING=カテゴリを選択して再構築すると、そのカテゴリのゲームのみが再構築されます。 続けたいですか? +RESET_CAT=カテゴリをクリア +NO_APPS_FOUND=アプリが見つかりません! +NON_EBOOT_NOT_SUPPORTED1=非起動 eboot パッチが見つかりました +NON_EBOOT_NOT_SUPPORTED2=まだサポートされていません! +SKIPPING_MSG=スキップしています... +#NEW STRINGS +EXTRA_SETTING_1=カバーをダウンロード +EXTRA_SETTING_2=カスタマイズをリセット +EXTRA_SETTING_3=反射 +EXTRA_SETTING_4=背景画像を変更 +EXTRA_SETTING_5=スタートアップ カバー メッセージ +EXTRA_SETTING_6=フォントの変更 +ADVANCED_SETTINGS=高度な設定 +SETTINGS_5=FPKG データベースの再構築 +HIDE_ADVANCED_SETTINGS=詳細設定を非表示 +X_DL_COVER=カバーをダウンロードするには X を押してください +FAILED_TO_DOWNLOAD_COVER=カバーのダウンロードに失敗しました +COVERS_UP_TO_DATE=カバーは最新です! +IMAGE_APPLIED=画像が適用されました! +#新しい弦 +DISABLE_MUSIC=音楽を無効にする +REBUILD_DB_OPT_1=内部データベースの再構築 +REBUILD_DB_OPT_2=DLC のみを再構築 (拡張 HDD を含む) +REBUILD_DB_OPT_3=拡張機能を再度有効にします。 コンテンツ +REBUILD_DB_DESC_1=不足している XMB ゲーム/アプリ/DLC を内部ストレージ (Inc. App2usb) から復元します +REBUILD_DB_DESC_2=不足している XMB の内部および拡張ストレージ DLC を復元します +REBUILD_DB_DESC_3=無効になった拡張ストレージ ゲーム/アプリ/DLC を再度有効にする +REBUILDING_ADDCONT=DLC の再構築 +ADDCONT_REBUILT= DLC が正常に再構築されました! +ADDCONT_REACTED=外部コンテンツが正常に再アクティブ化されました! +ADDCONT_REACT_FAILED=失敗、外部コンテンツは再アクティブ化されていません! +ADDCONT_FAILED=失敗、一部の DLC が追加されていません! +SHUTDOWN_DAEMON=停止してデーモンを終了 +DB_MOD_WARNING=これにより、PS4s データベースが変更されます。 これによって引き起こされる不安定性や問題は、ユーザーの裁量に委ねられています。 +SIGN_IN_USER_NOTIF=サインインしたプロフィール +MUSIC_Q=キューに入れられた音楽 +PLAYING_NEXT=次の再生 +DELETING_GAME_FOLDER=ダンプは既に存在します。ゲーム フォルダを削除しています + +[DUMPER] +DUMP_INFO=ダンプ情報 +APP_NAME=アプリ名: +TITLE_ID=タイトル_ID: +DUMPER_SC0=sc0(sce_sys) コンテンツをダンプしています... +DUMPING_TROPHIES=トロフィーを捨てています... +CREATING_GP4=GP4 を作成中 ... +DEC_BIN=復号化ビン +DEL_SEM=セマフォを削除しています... +EXT_PATCH=ゲーム パッチ ファイルの抽出 +EXT_GAME_FILES=ベース ゲーム ファイルの抽出 +PROCESSING=処理中 \ No newline at end of file diff --git a/App-Media-Assets/langs/1/lang.ini b/App-Media-Assets/langs/1/lang.ini new file mode 100644 index 0000000..e56b3a7 --- /dev/null +++ b/App-Media-Assets/langs/1/lang.ini @@ -0,0 +1,483 @@ +#strings for loader +[LOADER] +LOADER_FATAL=FATAL! +FATAL_JB=FATAL Jailbreak failed with code +FATAL_REJAIL=FATAL rejail_multi failed with code +SWU_ERROR=[SWU Error] Update IS Revoked to use this Update turn off Secure Boot +RSA_LOAD=Checking RSA Sig... +RSA_FAILED=RSA Check has failed with Error Code +SECURE_FAIL=Secure Boot is enabled but we couldnt Download the Sig file from the CDN +LOADER_ERROR=ItemzFlows Loader has encountered an error +MORE_INFO=For more info check: /mnt/usb0/itemzflow/loader.log The App will now Close +INI_FAIL=Could not make create INI File +STR_NOT_FOUND=String not Found + +#strings IF +[ITEMZFLOW] +RSA_LOAD=Checking RSA Sig... +RSA_FAILED=RSA Check has failed with Error Code +OPT_UPDATE=An Update is available, Do you want to update now? +SORT_OPTS=Sort Apps +STR_NOT_FOUND=String not Found +ITEMZ_SETTINGS=Itemzflow Settings +RESORT=Resort Games/Apps +MISSING_EBOOT=[Internal] eboot.bin is missing from /data/app/ or /hostapp/app/ +MISSING_SFO=[Internal] param.sfo is missing from /data/app/sce_sys or /hostapp/app/sce_sys +CORRUPT_SFO=the param.sfo is corrupted +ON2=ON +OFF2=OFF +TRUE2=True +FALSE2=False +STORAGE=Storage +ITEMZ_VER=Itemzflow Version +SYS_VER=System Version +OTHER=Other +INSTALLING=Installing... +SETTINGS=Settings +ID2=Id +NAME2=Name +DISC2=Disc +INSTALL_FAILED=Install Failed with code +INSTALL_OF=Installation of +COMPLETE=is now Complete! +FAILED_W_CODE=has failed with code +FATAL_ERROR=Fatal Error +PRESS_OK_CLOSE=Please Close the Program after Pressing OK +WARNING2=Warning +FAILED_TTF=TTF Failed Loading from +SWITCH_TO_EM=Switching to Embedded +INI_ERROR=Could NOT find/open the INI File +FAILED_DAEMON=The IF Daemon has Failed +DAEMON_OFF=Daemon Auto start is turned off +DAEMON_OFF2=This may cause some things not work +DL_CACHE=Downloading and Caching Website files... +PIG_FAIL=Piglet (retail) failed to load with +NO_USB=No USB Detected, Exiting... +DUMP=AFTER the Game launches when you press OK wait few seconds then go back to the Store and the game will be begin dumping DO NOT CLOSE THE GAME OR STORE UNTIL THE DUMP IS COMPLETE +UNINSTALL_UPDATE=Game Update Uninstalled successfully +UNINSTAL_UPDATE_FAILED=Game Update Uninstall failed +UNINSTALL_SUCCESS=Game Uninstalled successfully, the installed App list will now reload +UNINSTALL_FAILED=Game Uninstall failed +COMING_SOON=Coming soon +RELOAD_IAPPS=The Installed Apps list will now Reload +APP_REQ=This Game Launcher has a Requirement of min. 4 Apps To use it you need to install: +MORE_APPS=More apps +DOWNLOADING_COVERS=Downloading Covers from the server +DL_FAILED_W=Download Failed with StatusCode: +STR_TOO_LONG=String is either too long or INVALID Please enter a vaild entry +INVAL_PATH=INVALID Path! enter a vaild path +INVAL_TTF=INVALID .ttf path Please ensure the file ext is .ttf +CACHE_CLEARED=Successfully Deleted/Cleared all Cached Images +CLEARING_CACHE=Clearing Cached contents +CACHE_FAILED=Clearing Cached content failed +ITEMZ_FEATURE_DISABLED=this feature is disabled, Reason: The ItemzFlow Daemon is NOT connected +SAVE_ERROR=Save Error +SAVE_SUCCESS=Saved successfully +DL_FAILED2=Download Failed with code +OBJ_EXPECTED=Object expected +CANT_OPEN=Unable to Open +APP_DIED=App has Died with exit code +PKG_TEAM=If this continues Contact the PKG-Zone team +FATAL_DUMP_ERROR=The Game Dump has failed to the app will now reload Press OK to continue +DUMP_OF=Dump of +COMPLETE_WO_ERRORS=is Complete without Errors!: +DUMP_FAILED=Has Completed with Issues NOT all files were dumped! Make sure your exploit hoster has MMAP patches enabled +EXCEED_LIMITS=Number of pages Exceeds the Stores Limits! +DL_ERROR_PAGE=Could not Download Page: +ERROR_DL_ASSETS=Could NOT Download Asset: +APP_NOT_FOUND=App is NOT Found +APP_OPENED=App is already opened +APP_CLOSED=App Closed +APP_UNL=App is NOT Launchable +ID_NOT_VAILD=TITLE_ID IS NOT VAILED +LAUNCH_ERROR=App Launch has failed with error code +RELOAD_LIST=Reloading App List ... +SEARCHING=Searching.... +WAITING_FOR_DAEMON=Waiting for Daemons Welcome Response (max 1 min) +TRYING_TO_DL=Trying to Download cover for +DL_COVERS=Downloading Covers from the server +STARTING_DUMPER=Starting the Dumper... +UU=Uninstall update +UG=Uninstall game +SETTINGS_1=Dumper Path +SETTINGS_2=Check for Updates +SETTINGS_3=Sort Apps by +SETTINGS_4=Set as default Dashboard +SETTINGS_6=Theme Installer +SETTINGS_7=Background MP3 Path +SETTINGS_8=Show Button Controls +SETTINGS_9=Open PS4 Menu +SETTINGS_10=PKG Installer +SETTINGS_11=Console Power Controls +SETTINGS_12=Save Settings +NA_SORT1=Random +TID_ALPHA_SORT1=Alphabetical by Title ID +TITLE_ALPHA_SORT1=Alphabetical by App Name +UNINSTALL_GAME1=Uninstall Game/App +UNINSTALL_PATCH1=Uninstall Patch +UNINSTALL_DLC1=Uninstall DLC +UNINSTALL_NOTE=Select to Choose a Uninstall Option +SEL_DUMP_ALL1=Dump All +SEL_BASE_GAME1=Dump Base Game Only +SEL_GAME_PATCH1=Dump Patch Only +SEL_REMASTER1=Dump Remaster Only +SEL_DLC1=Dump DLC Only +LAUNCH_GAME=Launch +DUMP_1=Dump +TRAINERS=Trainers +UNINSTALL=Uninstall +HIDE_APP=Hide App +CHANGE_ICON=Change Icon (PNG) +CHANGE_APP_NAME=Change App Name +CHANGE_TID=Change Title ID +NAME_INFO=Changes the PS4 App name in the PS4s XMB (app.db) +IF_NOT_EFFECTED=Note: Doesnt effect Itemzflow +TID_INFO=Changes the Apps Title ID in app.db +ICON_INFO=Type in a Path to a New Custom Icon0 for the Selected App +LAUNCH_INFO=Launches the Selected Game/App +TRAINER_INFO=Fetches Trainer(s) for the Selected Game +HIDE_INFO=Hides the Game/App in the PS4s app.db +DUMP_OPT_INFO=Select to Choose a Dumping Option +PLAYING_SINCE=Playing Since +PNG_NOTE=Note: 512x512 PNGs ONLY! +SUSPEND_IF=Note: Itemzflow will be Suspended +HIDE_OPT_INFO=Note: You can also hide it from Itemzflow via Settings Menu +SEL_DUMP_ALL_INFO=Dumps (All) The Game and Any Available DLC and Patch +SEL_BASE_GAME_INFO=Dumps Only The Base Game +SEL_GAME_PATCH_INFO=Dumps Only The Game Patch +SEL_REMASTER_INFO=Dumps Only Available Remaster(s) +SEL_DLC_INFO=Dumps Only Available DLC(s) +SETTINGS=Settings +FTP_NOT_RUNNING=FTP Not Running (OFF) +FTP_RUNNING=FTP Is Running (ON) +DUMPER_PATH_DESC=Select a Custom Dump Path +REBUILD_DB_OPTION_DESC=Rebuild the PS4s App Database (app.db) +SORT_BY_OPTION_DESC=Select How Itemzflow Sorts Apps (slows down opening IF) +HOME_MENU_OPTION_DESC=Redirects the PS Home Button to this App +FTP_SERVICE_OPTION_DESC=Turn ON or OFF FTP Temporarily +TTF_OPTION_DESC=Select a Custom TTF Font Path +BACKGROUND_MP3_OPTION_DESC=Select a Custom 48Hz MP3 to play in the Background +SHOW_BUTTON_OPTION_DESC=Show or Hide Button Controls +OPEN_DEBUG_MENU_DESC=Opens the PS4s Debug Or Settings Menu +RDB=Rebuild FPKG Database +RELOAD_APPS=Reload Apps +#BUTTON INFO +BUTTON_X_INFO=Select/Confirm +BUTTON_O_INFO=Back/Cancel +BUTTON_LEFT_RIGHT_INFO=Prev/Next +BUTTON_UP_DOWN_INFO=Up/Down +BUTTON_TRIANGLE=Reload Apps +BUTTON_CLOSE=Exit ItemzFlow +BUTTON_CONFIRM_CLOSE=Confirm Close +CLOSE_GAME=Close Open Game +FAILED_MENU_OPEN=Failed to Open Menu +ERROR_CODE=Error code +SELECT_INTERACT=Press X to Interact +GAME_SAVE_OPTS=Game Save Options +BACKUP_SAVE=Backup All Saves +IMPORT_SAVE=Import Save +SAVE_DELETE=Delete All Saves +SHOW_APP=UnHide +HIDE_APP_OPT=App Visibility +PS4_REBOOT_REQ=Reboot Required for Changes +PLEASE_WAIT=Please Wait... +APPS_RELOADED=Apps Reloaded +APPS_RELOADED_2=Apps list refreshed +CON_DIS=Controller Disconnected +CON_DIS_2=Reconnect The Controller +REALLY_HOT=PS4 Is really Hot! +REALLY_HOT_2=PS4 is Above 90C, Consider New Thermal Paste +NO_SAVES=No Game Saves Available +CANT_FIND_SAVE=Failed to find a Save +SAVE_OPS_FAILED=Save Operation failed +FAILED_INI_SD=Failed to initialize save data +FAILED_MOUNT_SD=Failed to mount Save +SD_SAVED=Game Save Saved to USB +SD_TRANSFER_FAIL=Could not Transfer save +SD_DELETED=Deleted Game Save +CANT_DELETE_SD=Could not Delete +DECRYPTED_SD=Cant find Decrypted Save +NO_AVAIL_SAVE=No Saves Available +SAVE_IMPORTED=Game Save Imported! +SAVE_IMPORT_2=Save Title +NO_USERID=Cannot get UserId Error +UNSUPPORTED_FS=Unsupported Filesystem Detected +RETAILO=Retail PS4s only +NO_GOLDHEN=Missing GoldHEN or ps4debug! +FAILED_SAVE_PATCHES=Failed to Apply Save Patches! +UNSUPPORTED_FW=Unsupported FW Version +MP3_PLAYING=MP3 Now Playing +MP3_LOADED=MP3 Loaded +FAILED_MP3=MP3 Failed to Load +TRAINER_LOADED=Trainer Loaded +TRAINER_FAILED=Trainer Failed to Loaded +TRAINER_ESRCH=No Trainers Found +GAME_LAUCNHED=Game Has been Launched +GAME_KILLED=Game Has been Killed +GAME_RESUME=Resume Game +PLUG_MNG=Plugin Manager +PLUG_LOADED=Plugin Loaded +PLUG_FAILED=Plugin Failed to Load +PLUG_ERROR=Plugin Error +LANG_NOT_SUPPORTED=ItemzFlow Doesnt your language +ENG_LOADED=English Loaded Instead ... +IF_UPDATE_SUCESS=Itemzflow Has Been Updated! +FAILED_ICON=Failed to Change Icon +DAEMON_FAILED_NOTIFY=ItemzDaemon Failed to connect +DAEMON_FAILED_NOTIFY2=Some Features will be Disabled! +PWR_OFF_SYS=Power off System +RESTRT_SYS=Restart System +SUSPEND_SYS=Suspend System +NO_INTERNET=Couldnt Contact The Server +BE_SURE_INTERNET=Be Sure Internet is Enabled +SFO_OP_FAILED=SFO Operation Failed! +ICON_OP_FAILED=Icon Operation Failed! +GAME_DUMP_FAILED=Game Dump has Failed! +GAME_DUMP_FAILED2=Check the Disc for Issues +UNABLE_TO_TRANFER=Transfer has Failed! +FTP_START_NOTIFY=FTP Plugin Started +FTP_STOP_NOTIFY=FTP Plugin Stopped +FTP_ERROR=an FTP error has Occurred +REDIRECT_TURNED_ON=Home Menu Redirect Enabled +REDIRECT_TURNED_OFF=Home Menu Redirect Disabled +APP_DB_REBUILT=App DB Has been Repaired +APP_DB_ERROR=App DB Repair has Failed! +TTF_SUCCESS_NOTIFY=New TTF Has been Loaded +TTF_ERROR_NOTIFY=Failed to Load TTF Font +TTF_ERROR_NOTIFY2=Loaded Default TTF +SETTING_APPLIED=Setting has been Applied +PKG_INST_FAILED=PKG Install failed! +PKG_INST_FAILED1=Please vaildate the PKG +PKG_INST_SUCCESS=PKG Installed Sucessfully +USB_NOTIFY=USB Device Inserted +USB_NOTIFY1=USB is Ready to use +NOT_ENOUGH_FREE_SPACE=Not Enough Free Space +UNHIDE_NOTIFY=Visibility Changed +UNHIDE_SUCCESS_NOTIFY=App is now Visible +HIDE_SUCCESS_NOTIFY=App is now Hideen +UNHIDE_FAILED_NOTIFY=Failed to Change Visibility +FAILED_TO_CLOSE=Failed to Close App +OPT_NOT_PERMITTED=Option not available here +TITLE_ID_NOT_RIGHT=Title ID NOT Vaild +TILE_ID_CHANGED=Tiltle ID Changed +TITLE_ID_FAILD=Title ID Failed to Change! +PARAM_PATH_FAILED=Patching SFO has failed! +TITLE_CHANGED=App Title Changed +FAILED_TITLE_CHANGE=Failed to Change Game Title +CONSIDER_SUPPORT=Support Us on Ko-fi! +DUMPER_PATH_NO_AVAIL=Dumper Path is invalid! +FS_SEL_FAILED=File Selector failed to Open +FS_SEL_ERROR1=Unable to open FS Selector +FS_SEL_ERROR2=Selector already started +ICON_CHANGED_SUCCESS=Icon Changed! +ICON_CHANGE_FAILED=Changing Icon failed +PNG_NOT_VAILD=PNG is not vaild! +FAILED_TO_COPY=Failed to Copy +FONT_CHANGED_SUCCESS=Font Changed! +NEW_FONT_STRING=New Font +DUMPER_PATH_UPDATED=Dumper Path Updated! +NEW_PATH_STRING=New Path +PKG_IS_INSTALLING=PKG is installing... +PKG_IS_INSTALLED=Installation is Complete +VAR_IS_INSTALLED=is Now installed +FS_CONTROL_BUTTON_1=Enter Folder +FS_CONTROL_BUTTON_2=Previous Folder +FS_CONTROL_BUTTON_3=Cancel/Exit +FS_CONTROL_BUTTON_4=Select File +FS_CONTROL_BUTTON_4_1=Select Folder +FS_CONTROL_BUTTON_5=Switch File Panels +FS_CONTROL_BUTTON_6=New Folder +FS_CONTROL_BUTTON_7=Copy/Paste +FOLDER_MADE_SUCCESS=Folder Created! +FOLDER_MAKE_FAIL=Failed Folder creation! +OP_CANNED=Operation Cancelled! +OP_CANNED_1=No Changes Applied +MOVE_APP_OPT=Move to USB +MOVE_APP_OPT_1=Move App/Game +MOVE_APP_OPT_2=Move DLC +MOVE_APP_OPT_3=Move Patch +RESTORE_APP_OPT=Restore from USB +RESTORE_APP_OPT_1=Restore App/Game +RESTORE_APP_OPT_2=Restore DLC +RESTORE_APP_OPT_3=Restore Patch +RETAIL=Retail +RESTORE_SUCCESS=Restore Successful +MOVE_SUCCESSFULLY=Moved Successfully +RESTORE_FAILED=Restore Failed +MOVE_FAILED=Failed to Move +APP_MOVE_NOTIFY=Moved App Successfully +SELECT_A_FOLDER=Select a Folder to continue +SELECT_A_FILE=Select a File to continue +APP_MOVING_MESSAGE=App is moving to +APP_NOT_MOVED=Nothing to Restore +BACKUP_FPKG=Backup FPKG +COPYING_FPKG=Copying FPKG, Please wait... +FPKG_COPY_SUCCESS=FPKG Copied Successfully +FPKG_COPY_FAILED=FPKG has failed to Copy! +EXT_MOVE_NOT_SUPPORTED=External Apps not Supported! +PATCH_MOVE_NOTIFY=Patch Moved Successfully +DLC_MOVE_NOTIFY=DLC Moved Successfully +COPYING_FILE=Copying File, Please wait... +RESTORE_INFO_TEXT=Restore Digital Apps Moved with Itemzflow +MOVE_INFO_TEXT=Move Digitally Downloaded Content to a USB +OPTION_DOESNT_SUPPORT_DISC=This Option does not support Discs +BACKUP_FPKG_INFO=Backs up the Games FPKG to reinstall later (FPKGs Only) +GAME_CONTROL_INFO=Game Controls: Resume or Close The App +CLOSE_OPEN_APP_INFO=Close the current open game or app +GAME_CONTROLS=Game Controls +RESTORE_GAME_INFO=Import & Resign A Decrypted Save (Folder) From Storage +BACKUP_GAME_INFO=Decrypt & Backup ALL Game Saves for this Game +DELETE_GAME_INFO=Delete ALL Game Saves for this Game +UNINSTALL_PATCH_INFO=Uninstall any Patches installed for this Game +UNINSTALL_GAME_INFO=Uninstall The Game/App & Everything Attached +SORT_RANDOM_INFO=Sort Apps/Games Randomly +SORT_ALPHA_NAME_INFO=Sort Apps/Games by Name Alphabetically +SORT_ALPHA_TID_INFO=Sort Apps/Games by Title ID Alphabetically +THE_ITEM_IS_ALREADY_BP=Selected Item is already Backed up +IF_PKG_INSTALLER=IF Package Installer +IF_PKG_INSTALLER_INFO=Install PKGs from a USB Drive +THEME_INSTALLER=IF Theme Installer +THEME_NOT_VAILD=Theme is not vaild! +THEME_INSTALLER_INFO=Install IF Themes from a USB Drive +THEME_INSTALL_SUCCESS=Theme Installed and Applied! +THEME_FAILED_TO_APPLY=Theme Failed to Apply +FOUND_SAVE_MESSAGE=Game Save(s) found +FOUND_SAVE_MESSAGE_OVER_1=Game Save(s) found, Showing 1... +USER_LANG=User +NO_SAVES_LANG=No Saves +DOWNLOAD_COVERS=do you want to check for and/or Download covers now? +LOADING_GAME_LIST=Loading for Games list ... +RESTORE_NOTICE=Restoring will delete all DLCs and Save Data for this game +INSTALLING_THEME=Installing and vaildating Theme... +RESTART_STR=Restart +SHUTDOWN_STR=Shutdown +SUSPEND_STR=Suspend +ERROR_POWER_CONTROL=Error Setting Power Level +POWER_CONTROL_INFO=Console Power Options +USB_DISCONNECTED=USB Disconnected! +USB_DISCONNECTED1=USB Device Unplugged +REINSTALL_APP_CONFIRMATION=This App is already installed do you want to reinstall it? (All Game data will be deleted!) +THEME_RESET=Default Theme has been set +NO_DLC_AVAIL=No DLC Available +NO_PATCH_AVAIL=No Patches Available +RELAUCHING_IN_5=Reloading IF in 5 seconds... +CREATE_CUSTOM_DIR=Type in a New Folder Name +FETCH_STATS=Fetching App Stats... +STATS_MINS=Minutes Played +STATS_HOURS=Hour(s) +STATS_DAYS=Day(s) +NO_STATS_AVAIL=No App Stats Available +SAVE_OP_ON_GOING=Save Operation is in progress, please wait... +NO_UPDATE_FOUND=No ItemzFlow Updates Found! +IF_UPDATE_FAILD=ItemzFlow Update Failed to Install! +NO_UPDATE_FOUND_INFO=Is Internet Enabled? +CHECH_UPDATE_IN_PROGRESS=Checking for Updates... +CHECK_UPDATE_INFO=Check for Itemzflow Updates (OTA Update) +PSV_MENU=Power Save Settings +EJECT_DISK=Eject Disc +EJECT_DISK_ERROR=Error Ejecting Disc +EJECT_DISK_SUCCESS=Disc Ejected Successfully +NO_DISC_INSERTED=No Disc Inserted +OVERWRITE_SAVE=Do you want to overwrite the current save? +DUMPER_CANCELLED=Dumping Operation was Cancelled +REBUILDING_FOR_FPKG=Rebuilding Database for FPKGs +CURRENT_APP=Current App +TOTAL_NUM_OF_APPS=Total Number Of Apps +NUMB_OF_FIXED_APPS=Number of Apps Fixed +NOT_FIXED=Not fixed +LAUNCH_FAILED_BC_NOT_FOUND=Launch has Failed because the App was not found in the PS4s App Database +CONFIRMATION_2=Do you want to add this App to the PS4s Database? +IF_LAUNCH_TROUBLESHOOTER=IF Launch Troubleshooter +GAME_INSERT_SUCCESSFUL=Added to the Database +GAME_INSERT_FAILED=App Failed to be Added to the PS4s Database! +FIX_BROKEN_SFO_DB=Launch has Failed because the App Info in the PS4s Database is corrupted +CONFIRMATION_3=Do you want to Attempt to Repair it? +REPAIR_ATTEMPTED=Repair Attempted! +REPAIR_ATTEMPTED1=Try to Launch again +PLACEHOLDER=Placeholder +PLACEHOLDER_NOT_ENTER=Placeholders are NOT interactable +NO_PATCHES=No Patches Found. +PATCH0_APPLIED=Patch Applied: +PATCH1_APPLIED=Patches Applied: +SUSPEND_FAILED=Critical Suspend Failed +DAEMON_SUSPEND_FAILED=Daemon Failed to Activate Critical Suspend +NO_PATCH_SELECTED=No Patch Selected +NO_APP_OPENED_STR=App is not Opened +PATCH_NUM=Patch +PATCH_GAME_TITLE=Patch Game Title: +PATCH_NAME=Patch Name: +PATCH_APP_VER=Patch App Version: +PATCH_AUTHOR=Patch Author: +PATCH_NOTE=Patch Note: +PATCH_VER=Patch Version: +PATCH_ENABLED=Patch Enabled: +PATCH_SET0=Patch Disabled: +PATCH_SET1=Patch Enabled: +PATCH_DL_QUESTION=Would you like to download/update the Patch Database? +PATCH_DL_QUESTION_NO=No Patches will be downloaded. +PATCH_DL_QUESTION_YES=Downloading Patch Database... +PATCH_DL_COMPLETE=Downloaded Patch Database successfully. +BUTTON_PATCH_TRI_INFO=Download/Update Patch Database +BUTTON_PATCH_SQUARE_INFO=View Patch Details +CHANGE_CATEGORY=Change Category +SHOWING_CATEGORY=Showing Category +RETAIL_GAMES=Retail Games +GAMES=Games +HOMEBREW=Homebrew +FPKG_STR=FPKGs +NONE=None +NO_TRAINERS=No Trainers Found +UPDATED_CATEGORY=Category Updated! +INC_CAT=Including with Category +CAT_REBUILD_WARNING=Rebuilding with a Category Selected will only Rebuild Games in that Category. Do you want to continue? +RESET_CAT=Clear Category +NO_APPS_FOUND=No Apps Found! +NON_EBOOT_NOT_SUPPORTED1=Found non startup eboot patch for +NON_EBOOT_NOT_SUPPORTED2=is not yet supported! +SKIPPING_MSG=Skipping... +#NEW STRINGS +EXTRA_SETTING_1=Download Covers +EXTRA_SETTING_2=Reset Customizations +EXTRA_SETTING_3=Reflections +EXTRA_SETTING_4=Change Background Image +EXTRA_SETTING_5=Startup Cover Message +EXTRA_SETTING_6=Change Font +ADVANCED_SETTINGS=Advanced Settings +SETTINGS_5=Rebuild FPKG Database +HIDE_ADVANCED_SETTINGS=Hide Advanced Settings +X_DL_COVER=Press X to download covers +FAILED_TO_DOWNLOAD_COVER=Failed to download covers +COVERS_UP_TO_DATE=Covers are now up to date! +IMAGE_APPLIED=Image Applied! +#new strings +DISABLE_MUSIC=Disable Music +REBUILD_DB_OPT_1=Rebuild Internal Database +REBUILD_DB_OPT_2=Rebuild only DLCs (Inc. ext hdd) +REBUILD_DB_OPT_3=Re-activate ext. Content +REBUILD_DB_DESC_1=Restore missing XMB games/apps/DLCs from internal storage (Inc. App2usb) +REBUILD_DB_DESC_2=Restore missing XMB internal and extended storage DLCs +REBUILD_DB_DESC_3=Reactivate extended storage games/apps/DLCs that got disabled +REBUILDING_ADDCONT=Rebuilding DLC +ADDCONT_REBUILT= DLC(s) have been rebuilt successfully! +ADDCONT_REACTED=External Content has been re-activated successfully! +ADDCONT_REACT_FAILED=Failure, External Content has not been re-activated! +ADDCONT_FAILED=Failure, Some DLC(s) have not been added! +SHUTDOWN_DAEMON=Stop & Exit Daemon +DB_MOD_WARNING=This will modify the PS4s Database. ANY instability or issues caused by this are at the users discretion. +SIGN_IN_USER_NOTIF=Profile Signed in +MUSIC_Q=Music Queued +PLAYING_NEXT=Playing Next +DELETING_GAME_FOLDER=Dump already Exists, Deleting Game Folder + +[DUMPER] +DUMP_INFO=Dump info +APP_NAME=App name: +TITLE_ID=TITLE_ID: +DUMPER_SC0=Dumping sc0(sce_sys) content ... +DUMPING_TROPHIES=Dumping Trophies ... +CREATING_GP4=Creating GP4 ... +DEC_BIN=Decrypting Bin +DEL_SEM=Deleting Semaphore ... +EXT_PATCH=Extracting Game Patch Files +EXT_GAME_FILES=Extracting Base Game Files +PROCESSING=Processing diff --git a/App-Media-Assets/langs/25/lang.ini b/App-Media-Assets/langs/25/lang.ini new file mode 100644 index 0000000..87cc31a --- /dev/null +++ b/App-Media-Assets/langs/25/lang.ini @@ -0,0 +1,483 @@ +#strings for loader +[LOADER] +LOADER_FATAL=ΣΦΑΛΜΑ! +FATAL_JB=Το Jailbreak απέτυχε με κωδικό +FATAL_REJAIL=Το rejail_multi απέτυχε με κωδικό +SWU_ERROR=[Σφάλμα SWU] Η ενημέρωση έχει ανακληθεί, για να χρησιμοποιήσετε αυτή την ενημέρωση απενεργοποιήστε την ασφαλή εκκίνηση +RSA_LOAD=Έλεγχος υπογραφής RSA... +RSA_FAILED=Ο έλεγχος RSA απέτυχε με κωδικό σφάλματος +SECURE_FAIL=Η ασφαλής εκκίνηση είναι ενεργοποιημένη, αλλά δεν μπορέσαμε να κατεβάσουμε το αρχείο υπογραφής από το CDN +LOADER_ERROR=Ο φορτωτής του ItemzFlow αντιμετώπισε σφάλμα +MORE_INFO=Για περισσότερες πληροφορίες δείτε:/mnt/usb0/itemzflow/loader.log Η εφαρμογή θα κλείσει τώρα +INI_FAIL=Δεν ήταν δυνατή η δημιουργία αρχείου INI +STR_NOT_FOUND=Συμβολοσειρά δεν βρέθηκε + +DISABLE_MUSIC=Απενεργοποίηση μουσικής +REBUILD_DB_OPT_1=Ανακατασκευή εσωτερικής βάσης δεδομένων +REBUILD_DB_OPT_2=Ανακατασκευή μόνο DLC (Inc. ext hdd) +REBUILD_DB_OPT_3=Επανενεργοποίηση εσωτ. Περιεχόμενο +REBUILD_DB_DESC_1=Επαναφορά παιχνιδιών/εφαρμογών/DLC XMB που λείπουν από τον εσωτερικό χώρο αποθήκευσης (Inc. App2usb) +REBUILD_DB_DESC_2=Επαναφορά εσωτερικών και εκτεταμένων DLC αποθήκευσης XMB που λείπουν +REBUILD_DB_DESC_3=Επανενεργοποίηση παιχνιδιών/εφαρμογών/DLC εκτεταμένης αποθήκευσης που απενεργοποιήθηκαν +REBUILDING_ADDCONT=Ανακατασκευή DLC +ADDCONT_REBUILT= Τα DLC αναδημιουργήθηκαν με επιτυχία! +ADDCONT_REACTED=Το εξωτερικό περιεχόμενο ενεργοποιήθηκε ξανά με επιτυχία! +ADDCONT_REACT_FAILED=Αποτυχία, το εξωτερικό περιεχόμενο δεν έχει ενεργοποιηθεί ξανά! +ADDCONT_FAILED=Αποτυχία, ορισμένα DLC δεν έχουν προστεθεί! +SHUTDOWN_DAEMON=Διακοπή και έξοδος από τον Daemon +DB_MOD_WARNING=Αυτό θα τροποποιήσει τη βάση δεδομένων του PS4. ΟΠΟΙΑΔΗΠΟΤΕ αστάθεια ή ζητήματα που προκαλούνται από αυτό είναι στη διακριτική ευχέρεια των χρηστών. +SIGN_IN_USER_NOTIF=Σύνδεση στο προφίλ +MUSIC_Q=Μουσική σε ουρά +PLAYING_NEXT=Αναπαραγωγή Επόμενο +DELETING_GAME_FOLDER=Το Dump υπάρχει ήδη, Διαγράφεται ο φάκελος του παιχνιδιού + +#strings IF +[ITEMZFLOW] +RSA_LOAD=Έλεγχος υπογραφής RSA... +RSA_FAILED=Ο έλεγχος RSA απέτυχε με κωδικό σφάλματος +OPT_UPDATE=Μια ενημέρωση είναι διαθέσιμη, Θέλετε να ενημερώσετε τώρα; +SORT_OPTS=Ταξινόμηση εφαρμογών +STR_NOT_FOUND=Συμβολοσειρά δεν βρέθηκε +ITEMZ_SETTINGS=Ρυθμίσεις Itemzflow +RESORT=Παιχνίδια/εφαρμογές θερέτρου +MISSING_EBOOT=[Internal] Το αρχείο eboot.bin λείπει από το /data/app/ ή /hostapp/app/ +MISSING_SFO=[Internal] Το αρχείο param.sfo λείπει από το αρχείο /data/app/sce_sys ή /hostapp/app/sce_sys +CORRUPT_SFO=Το param.sfo είναι κατεστραμμένο +ON2=Ενεργό +OFF2=Απενεργό +TRUE2=Σωστό +FALSE2=Λάθος +STORAGE=Χώρος αποθήκευσης +ITEMZ_VER=Έκδοση Itemzflow +SYS_VER=Έκδοση συστήματος +OTHER=Άλλα +INSTALLING=Εγκατάσταση... +SETTINGS=Ρυθμίσεις +ID2=Id +NAME2=Όνομα +DISC2=Δίσκος +INSTALL_FAILED=Εγκατάσταση Απέτυχε με κωδικό +INSTALL_OF=Εγκατάσταση του +COMPLETE=έχει ολοκληρωθεί! +FAILED_W_CODE=απέτυχε με κωδικό +FATAL_ERROR=Μοιραίο σφάλμα +PRESS_OK_CLOSE=Κλείστε το πρόγραμμα μετά το πάτημα του OK +WARNING2=Προειδοποίηση +FAILED_TTF=TTF απέτυχε φόρτωση από +SWITCH_TO_EM=Αλλαγή σε Ενσωματωμένο +INI_ERROR=ΔΕΝ μπόρεσε να βρεθεί/να ανοίξει το αρχείο INI +FAILED_DAEMON=Daemon IF έχει αποτύχει +DAEMON_OFF=Η αυτόματη εκκίνηση του daemon είναι απενεργοποιημένη +DAEMON_OFF2=Αυτό μπορεί να προκαλέσει κάποια πράγματα να μην λειτουργούν +DL_CACHE=Λήψη και προσωρινή αποθήκευση αρχείων ιστότοπου... +PIG_FAIL=Piglet (retail) απέτυχε να φορτώσει με +NO_USB=Δεν εντοπίστηκε USB, έξοδος... +DUMP=ΜΕΤΑ την εκκίνηση του παιχνιδιού, όταν πατήσετε OK, περιμένετε λίγα δευτερόλεπτα και μετά επιστρέψτε στο Store και το παιχνίδι θα αρχίσει να κάνει dump. ΜΗΝ ΚΛΕΙΣΕΤΕ ΤΟ ΠΑΙΧΝΙΔΙ Ή ΤΟ STORE ΜΕΧΡΙ ΝΑ ΟΛΟΚΛΗΡΩΘΕΙ ΤΟ DUMP. +UNINSTALL_UPDATE=Ενημέρωση παιχνιδιού απεγκαταστάθηκε με επιτυχία +UNINSTAL_UPDATE_FAILED=Αποτυχία απεγκατάστασης ενημέρωσης παιχνιδιού +UNINSTALL_SUCCESS=Το παιχνίδι απεγκαταστάθηκε με επιτυχία, η λίστα των εγκατεστημένων εφαρμογών θα επαναφορτωθεί τώρα. +UNINSTALL_FAILED=Αποτυχία απεγκατάστασης παιχνιδιού +COMING_SOON=Έρχεται Σύντομα +RELOAD_IAPPS=Η λίστα με τις εγκατεστημένες εφαρμογές θα ξαναφορτωθεί +APP_REQ=Αυτός ο εκκινητής παιχνιδιών έχει απαίτηση τουλάχιστον 4 Εφαρμογές Για να τον χρησιμοποιήσετε πρέπει να εγκαταστήσετε: +MORE_APPS=Περισσότερες εφαρμογές +DOWNLOADING_COVERS=Λήψη εξωφύλλων από τον διακομιστή +DL_FAILED_W=Η λήψη απέτυχε με Κωδικό Κατάστασης: +STR_TOO_LONG=Η συμβολοσειρά είναι είτε πολύ μεγάλη είτε ΛΑΘΟΣ Παρακαλώ εισάγετε μια έγκυρη καταχώρηση +INVAL_PATH=ΛΑΘΟΣ Μονοπάτι! εισαγάγετε ένα έγκυρο μονοπάτι +INVAL_TTF=ΛΑΘΟΣ .ttf μονοπάτι Παρακαλούμε βεβαιωθείτε ότι η επέκταση του αρχείου είναι .ttf +CACHE_CLEARED=Επιτυχής διαγραφή/εκκαθάριση όλων των προσωρινά αποθηκευμένων εικόνων +CLEARING_CACHE=Εκκαθάριση προσωρινών περιεχομένων +CACHE_FAILED=Αποτυχία εκκαθάρισης αποθηκευμένου περιεχομένου +ITEMZ_FEATURE_DISABLED=αυτή η λειτουργία είναι απενεργοποιημένη, Λόγος: Το Daemon ItemzFlow ΔΕΝ είναι συνδεδεμένο +SAVE_ERROR=Σφάλμα aποθήκευσης +SAVE_SUCCESS=Αποθηκεύτηκε με επιτυχία +DL_FAILED2=Λήψη Απέτυχε με κωδικό +OBJ_EXPECTED=Αναμενόμενο αντικείμενο +CANT_OPEN=Αδυναμία ανοίγματος +APP_DIED=Η εφαρμογή απεβίωσε με κωδικό εξόδου +PKG_TEAM=Εάν αυτό συνεχίζεται επικοινωνήστε με την ομάδα PKG-Zone +FATAL_DUMP_ERROR=Το Dump του παιχνιδιού απέτυχε και η εφαρμογή θα επαναφορτωθεί τώρα. Πιέστε OK για να συνεχίσετε. +DUMP_OF=Dump του +COMPLETE_WO_ERRORS=έχει ολοκληρωθεί χωρίς σφάλματα!: +DUMP_FAILED=Ολοκληρώθηκε με προβλήματα ΔΕΝ απορρίφθηκαν όλα τα αρχεία! Βεβαιωθείτε ότι το exploit host σας έχει ενεργοποιήσει τις επιδιορθώσεις MMAP +EXCEED_LIMITS=Ο αριθμός των σελίδων υπερβαίνει τα όρια του Store! +DL_ERROR_PAGE=Δεν ήταν δυνατή η λήψη της σελίδας: +ERROR_DL_ASSETS=Δεν μπόρεσε να κατεβάσει το Asset: +APP_NOT_FOUND=Η εφαρμογή ΔΕΝ βρέθηκε +APP_OPENED=Η εφαρμογή είναι ήδη ανοιχτή +APP_CLOSED=Εφαρμογή κλειστή +APP_UNL=Η εφαρμογή ΔΕΝ μπορεί να εκκινηθεί +ID_NOT_VAILD=TITLE_ID ΔΕΝ ΕΙΝΑΙ VAILED +LAUNCH_ERROR=Η εκκίνηση της εφαρμογής απέτυχε με κωδικό σφάλματος +RELOAD_LIST=Λίστα εφαρμογών επαναγέμισης ... +SEARCHING=Αναζήτηση.... +WAITING_FOR_DAEMON=Αναμονή για την απάντηση καλωσορίσματος του daemon (μέγιστο 1 λεπτό) +TRYING_TO_DL=Γινεται προσπάθεια να κατεβεί εξώφυλλο για +DL_COVERS=Λήψη εξωφύλλων από τον διακομιστή +STARTING_DUMPER=Εκκίνηση του Dumper... +UU=Απεγκατάσταση ενημέρωσης +UG=Απεγκατάσταση παιχνιδιού +SETTINGS_1=Μονοπάτι Dumper +SETTINGS_2=Έλεγχος για ενημερώσεις +SETTINGS_3=Ταξινόμηση εφαρμογών κατά +SETTINGS_4=Ορισμός ως προεπιλεγμένο Dashboard +SETTINGS_6=Εγκαταστάτης θέματος +SETTINGS_7=Μονοπάτι Background MP3 +SETTINGS_8=Εμφάνιση κουμπιών ελέγχου +SETTINGS_9=Άνοιγμα μενού PS4 +SETTINGS_10=Εγκαταστάτης PKG +SETTINGS_11=Κουμπιά Ελέγχου τροφοδοσίας της κονσόλας +SETTINGS_12=Αποθήκευση ρυθμίσεων +NA_SORT1=Τυχαία +TID_ALPHA_SORT1=Αλφαβητική σειρά κατά τίτλο ID +TITLE_ALPHA_SORT1=Αλφαβητική σειρά με βάση το όνομα της εφαρμογής +UNINSTALL_GAME1=Απεγκατάσταση παιχνιδιού/εφαρμογής +UNINSTALL_PATCH1=Απεγκατάσταση Patch +UNINSTALL_DLC1=Απεγκατάσταση DLC +UNINSTALL_NOTE=Διαλέξτε μια επιλογή απεγκατάστασης +SEL_DUMP_ALL1=Dump Όλα +SEL_BASE_GAME1=Dump μόνο το base παιχνίδι +SEL_GAME_PATCH1=Dump μόνο το Patch +SEL_REMASTER1=Dump μόνο το Remaster +SEL_DLC1=Dump μόνο DLC +LAUNCH_GAME=Έναρξη +DUMP_1=Dump +TRAINERS=Trainers +UNINSTALL=Απεγκατάσταση +HIDE_APP=Απόκρυψη εφαρμογής +CHANGE_ICON=Αλλαγή εικονιδίου (PNG) +CHANGE_APP_NAME=Αλλαγή ονόματος εφαρμογής +CHANGE_TID=Αλλαγή ID τίτλου +NAME_INFO=Αλλάζει το όνομα της εφαρμογής PS4 στο XMB του PS4 (app.db) +IF_NOT_EFFECTED=Σημείωση: Δεν επηρεάζει το Itemzflow +TID_INFO=Αλλάζει το ID τίτλου εφαρμογών στο app.db +ICON_INFO=Πληκτρολογήστε ένα μονοπάτι σε ένα νέο προσαρμοσμένο Icon0 για την επιλεγμένη εφαρμογή +LAUNCH_INFO=Εκκινεί το επιλεγμένο παιχνίδι/εφαρμογή +TRAINER_INFO=Βρίσκει Trainer(s) για το επιλεγμένο παιχνίδι +HIDE_INFO=Κρύβει το παιχνίδι/την εφαρμογή στο app.db του PS4 +DUMP_OPT_INFO=Επιλέξτε μια επιλογή Dumping +PLAYING_SINCE=Παίζοντας από +PNG_NOTE=Σημείωση: ΜΟΝΟ PNG 512x512! +SUSPEND_IF=Σημείωση: Το Itemzflow θα ανασταλεί +HIDE_OPT_INFO=Σημείωση: Μπορείτε επίσης να το αποκρύψετε από το Itemzflow μέσω του μενού Ρυθμίσεις +SEL_DUMP_ALL_INFO=Κάνει Dump (όλα) το παιχνίδι και όλα τα διαθέσιμα DLC και Patch +SEL_BASE_GAME_INFO=Κάνει Dump Μόνο το βασικό παιχνίδι +SEL_GAME_PATCH_INFO=Κάνει Dump Μόνο το Patch του παιχνιδιού +SEL_REMASTER_INFO=Κάνει Dump Μόνο τα διαθέσιμα Remaster(s) +SEL_DLC_INFO=Κάνει Dump Μόνο τα διαθέσιμα DLC(s) +SETTINGS=Ρυθμίσεις +FTP_NOT_RUNNING=Το FTP δεν είναι ενεργό (OFF) +FTP_RUNNING=Το FTP είναι ενεργό (ON) +DUMPER_PATH_DESC=Επιλέξτε μια προσαρμοσμένη διαδρομή Dump +REBUILD_DB_OPTION_DESC=Επαναδημιουργήστε τη βάση δεδομένων εφαρμογών του PS4 (app.db) +SORT_BY_OPTION_DESC=Επιλέξτε πώς το Itemzflow ταξινομεί τις εφαρμογές (επιβραδύνει το άνοιγμα IF) +HOME_MENU_OPTION_DESC=Επανακατευθύνει το κουμπί PS Home σε αυτήν την εφαρμογή +FTP_SERVICE_OPTION_DESC=Ενεργοποίηση ή απενεργοποίηση του FTP προσωρινά +TTF_OPTION_DESC=Επιλέξτε μια προσαρμοσμένη διαδρομή γραμματοσειράς TTF +BACKGROUND_MP3_OPTION_DESC=Επιλέξτε ένα προσαρμοσμένο MP3 48Hz για αναπαραγωγή στο παρασκήνιο +SHOW_BUTTON_OPTION_DESC=Εμφάνιση ή απόκρυψη κουμπιών ελέγχου +OPEN_DEBUG_MENU_DESC=Ανοίγει το μενού Debug ή Ρυθμίσεις του PS4 +RDB=Επαναδημιουργία βάσης δεδομένων FPKG +RELOAD_APPS=Επαναφόρτωση εφαρμογών +#BUTTON INFO +BUTTON_X_INFO=Επιλογή/Επιβεβαίωση +BUTTON_O_INFO=Πίσω/Ακύρωση +BUTTON_LEFT_RIGHT_INFO=Προηγούμενο/Επόμενο +BUTTON_UP_DOWN_INFO=Πάνω/Κάτω +BUTTON_TRIANGLE=Επαναφόρτωση εφαρμογών +BUTTON_CLOSE=Έξοδος ItemzFlow +BUTTON_CONFIRM_CLOSE=Επιβεβαίωση κλεισίματος +CLOSE_GAME=Κλείσιμο ανοικτού παιχνιδιού +FAILED_MENU_OPEN=Απέτυχε να ανοίξει το μενού +ERROR_CODE=Κωδικός σφάλματος +SELECT_INTERACT=Πατήστε το X για να αλληλεπιδράσετε +GAME_SAVE_OPTS=Επιλογές Game Save +BACKUP_SAVE=Δημιουργία αντιγράφων ασφαλείας όλων των Saves +IMPORT_SAVE=Εισαγωγή Save +SAVE_DELETE=Διαγραφή όλων των Save +SHOW_APP=Εμφάνιση +HIDE_APP_OPT=Ορατότητα εφαρμογών +PS4_REBOOT_REQ=Απαιτείται επανεκκίνηση για τις αλλαγές +PLEASE_WAIT=Παρακαλώ περιμένετε... +APPS_RELOADED=Οι εφαρμογές επαναφορτώθηκαν +APPS_RELOADED_2=Η λίστα εφαρμογών ανανεώθηκε +CON_DIS=Το χειριστήριο αποσυνδέθηκε +CON_DIS_2=Επανασυνδέστε το χειριστήριο +REALLY_HOT=Το PS4 είναι πολύ ζεστό! +REALLY_HOT_2=Το PS4 είναι πάνω από 90C, σκεφτείτε νέα θερμική πάστα +NO_SAVES=Δεν υπάρχουν διαθέσιμα Save παιχνιδιού +CANT_FIND_SAVE=Απέτυχε να βρεθεί Save +SAVE_OPS_FAILED=Η ενέργεια αποθήκευσης απέτυχε +FAILED_INI_SD=Απέτυχε η αρχικοποίηση των δεδομένων αποθήκευσης +FAILED_MOUNT_SD=Απέτυχε η τοποθέτηση Save +SD_SAVED=Αποθηκεύτηκε Save του παιχνιδιού στο USB +SD_TRANSFER_FAIL=Δεν είναι δυνατή η μεταφορά του save +SD_DELETED=Διαγράφηκε το Save του παιχνιδιού +CANT_DELETE_SD=Δεν μπόρεσε να διαγράψει +DECRYPTED_SD=Δεν βρέθηκε το αποκρυπτογραφημένο Save +NO_AVAIL_SAVE=Δεν υπάρχουν διαθέσιμα Saves +SAVE_IMPORTED=δεδομένα παιχνιδιού έχουν εισαχθεί! +SAVE_IMPORT_2=Τίτλος Save +NO_USERID=Δεν είναι δυνατή η λήψη του UserId Σφάλμα +UNSUPPORTED_FS=Ανιχνεύθηκε μη υποστηριζόμενο σύστημα αρχείων +RETAILO=Μόνο Retail PS4 +NO_GOLDHEN=Λείπει το GoldHEN ή το ps4debug! +FAILED_SAVE_PATCHES=Απέτυχαν να εφαρμοστούν τα Save Patches! +UNSUPPORTED_FW=Μη υποστηριζόμενη έκδοση FW +MP3_PLAYING=MP3 που παίζει τώρα +MP3_LOADED=MP3 φορτώθηκε +FAILED_MP3=MP3 Failed to Load +TRAINER_LOADED=Αποτυχία φόρτωσης MP3 +TRAINER_FAILED=Trainer απέτυχε να φορτωθεί +TRAINER_ESRCH=Δεν βρέθηκαν Trainers +GAME_LAUCNHED=Το παιχνίδι έχει εκκινηθεί +GAME_KILLED=Το παιχνίδι έχει τερματιστεί +GAME_RESUME=Συνεχίστε το παιχνίδι +PLUG_MNG=Διαχειριστής Plugin +PLUG_LOADED=Plugin φορτώθηκε +PLUG_FAILED=Το plugin απέτυχε να φορτώσει +PLUG_ERROR=Σφάλμα Plugin +LANG_NOT_SUPPORTED=Το ItemzFlow Δεν έχει τη γλώσσα σας +ENG_LOADED=Έχουν φορτωθεί τα Αγγλικά ... +IF_UPDATE_SUCESS=Το Itemzflow έχει ενημερωθεί! +FAILED_ICON=Απέτυχε να αλλάξει το εικονίδιο +DAEMON_FAILED_NOTIFY=ItemzDaemon Απέτυχε να συνδεθεί +DAEMON_FAILED_NOTIFY2=Ορισμένες λειτουργίες θα είναι απενεργοποιημένες! +PWR_OFF_SYS=Απενεργοποίηση συστήματος +RESTRT_SYS=Επανεκκίνηση συστήματος +SUSPEND_SYS=Αναστολή συστήματος +NO_INTERNET=Δεν μπορούσε να επικοινωνήσει με τον διακομιστή +BE_SURE_INTERNET=Βεβαιωθείτε ότι το Internet είναι ενεργοποιημένο +SFO_OP_FAILED=Η επιχείρηση SFO απέτυχε! +ICON_OP_FAILED=Η λειτουργία εικονιδίου απέτυχε! +GAME_DUMP_FAILED=Το Game Dump απέτυχε! +GAME_DUMP_FAILED2=Ελέγξτε το δίσκο για προβλήματα +UNABLE_TO_TRANFER=Η μεταφορά απέτυχε! +FTP_START_NOTIFY=Ξεκίνησε το FTP Plugin +FTP_STOP_NOTIFY=Το FTP Plugin σταμάτησε +FTP_ERROR=προέκυψε σφάλμα FTP +REDIRECT_TURNED_ON=Ενεργοποιημένη ανακατεύθυνση αρχικού μενού +REDIRECT_TURNED_OFF=Η ανακατεύθυνση του αρχικού μενού είναι απενεργοποιημένη +APP_DB_REBUILT=AppDB έχει επιδιορθωθεί +APP_DB_ERROR=Η επισκευή AppDB απέτυχε! +TTF_SUCCESS_NOTIFY=Το νέο TTF έχει φορτωθεί +TTF_ERROR_NOTIFY=Απέτυχε να φορτώσει γραμματοσειρά TTF +TTF_ERROR_NOTIFY2=Φορτωμένο προεπιλεγμένο TTF +SETTING_APPLIED=Η ρύθμιση έχει εφαρμοστεί +PKG_INST_FAILED=Η εγκατάσταση PKG απέτυχε! +PKG_INST_FAILED1=Παρακαλείστε να επικυρώσετε το PKG +PKG_INST_SUCCESS=Το PKG εγκαταστάθηκε επιτυχώς +USB_NOTIFY=Έχει τοποθετηθεί συσκευή USB +USB_NOTIFY1=Το USB είναι έτοιμο για χρήση +NOT_ENOUGH_FREE_SPACE=Δεν υπάρχει αρκετός ελεύθερος χώρος +UNHIDE_NOTIFY=Η ορατότητα άλλαξε +UNHIDE_SUCCESS_NOTIFY=Η εφαρμογή είναι τώρα ορατή +HIDE_SUCCESS_NOTIFY=Η εφαρμογή είναι τώρα κρυμμένη +UNHIDE_FAILED_NOTIFY=Απέτυχε να αλλάξει ορατότητα +FAILED_TO_CLOSE=Απέτυχε να κλείσει η εφαρμογή +OPT_NOT_PERMITTED=Η επιλογή δεν είναι διαθέσιμη εδώ +TITLE_ID_NOT_RIGHT=ID τίτλου ΔΕΝ ισχύει +TILE_ID_CHANGED=Το TiltleID έχει αλλάξει +TITLE_ID_FAILD=Το TitleID απέτυχε να αλλάξει! +PARAM_PATH_FAILED=Η επιδιόρθωση του SFO απέτυχε! +TITLE_CHANGED=Ο τίτλος της εφαρμογής άλλαξε +FAILED_TITLE_CHANGE=Απέτυχε να αλλάξει τίτλο παιχνιδιού +CONSIDER_SUPPORT=Υποστηρίξτε μας στο Ko-fi! +DUMPER_PATH_NO_AVAIL=Το μονοπάτι Dumper είναι άκυρο! +FS_SEL_FAILED=Ο επιλογέας αρχείων απέτυχε να ανοίξει +FS_SEL_ERROR1=Αδυναμία ανοίγματος του Επιλογέα FS +FS_SEL_ERROR2=Ο επιλογέας έχει ήδη ξεκινήσει +ICON_CHANGED_SUCCESS=Το εικονίδιο άλλαξε! +ICON_CHANGE_FAILED=Αλλαγή εικονιδίου απέτυχε +PNG_NOT_VAILD=Το PNG δεν είναι έγκυρο! +FAILED_TO_COPY=Απέτυχε η αντιγραφή +FONT_CHANGED_SUCCESS=Η γραμματοσειρά άλλαξε! +NEW_FONT_STRING=Νέα γραμματοσειρά +DUMPER_PATH_UPDATED=Το μονοπάτι Dumper έχει ενημερωθεί! +NEW_PATH_STRING=Νέο μονοπάτι +PKG_IS_INSTALLING=Το PKG είναι υπό εγκατάσταση... +PKG_IS_INSTALLED=Η εγκατάσταση ολοκληρώθηκε +VAR_IS_INSTALLED=είναι τώρα εγκατεστημένο +FS_CONTROL_BUTTON_1=Εισαγωγή φακέλου +FS_CONTROL_BUTTON_2=Προηγούμενος φάκελος +FS_CONTROL_BUTTON_3=Ακύρωση/Εξοδος +FS_CONTROL_BUTTON_4=Επιλέξτε Αρχείο +FS_CONTROL_BUTTON_4_1=Επιλέξτε Φάκελο +FS_CONTROL_BUTTON_5=Εναλλαγή των πάνελ αρχείων +FS_CONTROL_BUTTON_6=Νέος φάκελος +FS_CONTROL_BUTTON_7=Αντιγραφή/Επικόλληση +FOLDER_MADE_SUCCESS=Δημιουργήθηκε φάκελος! +FOLDER_MAKE_FAIL=Αποτυχημένη δημιουργία φακέλου! +OP_CANNED=Η επιχείρηση ακυρώθηκε! +OP_CANNED_1=Δεν έχουν εφαρμοστεί αλλαγές +MOVE_APP_OPT=Μετακίνηση στο USB +MOVE_APP_OPT_1=Μετακίνηση εφαρμογής/παιχνιδιού +MOVE_APP_OPT_2=Μετακίνηση DLC +MOVE_APP_OPT_3=Μετακίνηση Patch +RESTORE_APP_OPT=Επαναφορά από USB +RESTORE_APP_OPT_1=Επαναφορά εφαρμογής/παιχνιδιού +RESTORE_APP_OPT_2=Επαναφορά DLC +RESTORE_APP_OPT_3=Επαναφορά Patch +RETAIL=Retail +RESTORE_SUCCESS=Επαναφορά Επιτυχής +MOVE_SUCCESSFULLY=Μετακινήθηκε επιτυχώς +RESTORE_FAILED=Αποτυχία επαναφοράς +MOVE_FAILED=Απέτυχε να μετακινηθεί +APP_MOVE_NOTIFY=Μετακινήθηκε η εφαρμογή με επιτυχία +SELECT_A_FOLDER=Επιλέξτε έναν φάκελο για να συνεχίσετε +SELECT_A_FILE=Επιλέξτε ένα αρχείο για να συνεχίσετε +APP_MOVING_MESSAGE=Η εφαρμογή μετακινείται στο +APP_NOT_MOVED=Τίποτα προς επαναφορά +BACKUP_FPKG=Backup FPKG +COPYING_FPKG=Αντιγραφή FPKG, Παρακαλώ περιμένετε... +FPKG_COPY_SUCCESS=FPKG Αντιγράφηκε επιτυχώς +FPKG_COPY_FAILED=FPKG απέτυχε να αντιγράψει! +EXT_MOVE_NOT_SUPPORTED=Δεν υποστηρίζονται εξωτερικές εφαρμογές! +PATCH_MOVE_NOTIFY=Patch μεταφέρθηκε επιτυχώς +DLC_MOVE_NOTIFY=Το DLC μεταφέρθηκε επιτυχώς +COPYING_FILE=Αντιγραφή αρχείου, παρακαλώ περιμένετε... +RESTORE_INFO_TEXT=Επαναφορά ψηφιακών εφαρμογών που μετακινήθηκαν με το Itemzflow +MOVE_INFO_TEXT=Μετακίνηση ψηφιακά κατεβασμένου περιεχομένου σε USB +OPTION_DOESNT_SUPPORT_DISC=Αυτή η επιλογή δεν υποστηρίζει δίσκους +BACKUP_FPKG_INFO=Δημιουργεί αντίγραφα ασφαλείας των παιχνιδιών FPKG για επανεγκατάσταση αργότερα (Μόνο FPKGs) +GAME_CONTROL_INFO=Έλεγχοι παιχνιδιού: Συνέχιση ή κλείσιμο της εφαρμογής +CLOSE_OPEN_APP_INFO=Κλείστε το τρέχον ανοιχτό παιχνίδι ή εφαρμογή +GAME_CONTROLS=Έλεγχοι παιχνιδιού +RESTORE_GAME_INFO=Εισαγωγή και παραίτηση από αποκρυπτογραφημένο Save (φάκελο) από τον αποθηκευτικό χώρο +BACKUP_GAME_INFO=Αποκρυπτογράφηση & Δημιουργία αντιγράφων ασφαλείας ΟΛΩΝ των Save παιχνιδιών για αυτό το παιχνίδι +DELETE_GAME_INFO=Διαγραφή ΟΛΩΝ των Save παιχνιδιού για αυτό το παιχνίδι +UNINSTALL_PATCH_INFO=Απεγκαταστήστε όλα τα Patches που είναι εγκατεστημένα για αυτό το παιχνίδι +UNINSTALL_GAME_INFO=Απεγκαταστήστε το παιχνίδι/την εφαρμογή και όλα τα συνημμένα +SORT_RANDOM_INFO=Ταξινόμηση εφαρμογών/παιχνιδιών τυχαία +SORT_ALPHA_NAME_INFO=Ταξινόμηση εφαρμογών/παιχνιδιών με βάση το όνομα αλφαβητικά +SORT_ALPHA_TID_INFO=Ταξινόμηση εφαρμογών/παιχνιδιών με βάση το TitleID Αλφαβητικά +THE_ITEM_IS_ALREADY_BP=Για το επιλεγμένο στοιχείο έχει ήδη δημιουργηθεί αντίγραφο ασφαλείας +IF_PKG_INSTALLER=Εγκαθιστής πακέτων IF +IF_PKG_INSTALLER_INFO=Εγκατάσταση PKGs από μονάδα USB +THEME_INSTALLER=Εγκαταστάτης θέματος IF +THEME_NOT_VAILD=Το θέμα δεν είναι έγκυρο! +THEME_INSTALLER_INFO=Εγκατάσταση θεμάτων IF από μονάδα USB +THEME_INSTALL_SUCCESS=Θέμα Εγκατεστημένο και Εφαρμοσμένο! +THEME_FAILED_TO_APPLY=Το θέμα απέτυχε να εφαρμοστεί +FOUND_SAVE_MESSAGE=Βρέθηκαν Save(s) παιχνιδιού +FOUND_SAVE_MESSAGE_OVER_1=Game Save(s) found, Εμφάνιση 1... +USER_LANG=Χρήστης +NO_SAVES_LANG=Δεν υπάρχουν Save +DOWNLOAD_COVERS=θέλετε να ελέγξετε για ή/και να κατεβάσετε εξώφυλλα τώρα; +LOADING_GAME_LIST=Φόρτωση για τη λίστα παιχνιδιών ... +RESTORE_NOTICE=Η επαναφορά θα διαγράψει όλα τα DLC και τα Save για αυτό το παιχνίδι +INSTALLING_THEME=Εγκατάσταση και διαμόρφωση του θέματος... +RESTART_STR=Επανεκκίνηση +SHUTDOWN_STR=Τερματισμός λειτουργίας +SUSPEND_STR=Αναστολή λειτουργίας +ERROR_POWER_CONTROL=Σφάλμα ρύθμισης επιπέδου τροφοδοσίας +POWER_CONTROL_INFO=Επιλογές τροφοδοσίας κονσόλας +USB_DISCONNECTED=Το USB αποσυνδέθηκε! +USB_DISCONNECTED1=Η συσκευή USB είναι αποσυνδεδεμένη +REINSTALL_APP_CONFIRMATION=Αυτή η εφαρμογή είναι ήδη εγκατεστημένη και θέλετε να την επανεγκαταστήσετε; (Όλα τα δεδομένα του παιχνιδιού θα διαγραφούν!) +THEME_RESET=Έχει οριστεί το προεπιλεγμένο θέμα +NO_DLC_AVAIL=Δεν υπάρχει διαθέσιμο DLC +NO_PATCH_AVAIL=Δεν υπάρχουν διαθέσιμα patches +RELAUCHING_IN_5=Επαναφόρτωση IF σε 5 δευτερόλεπτα... +CREATE_CUSTOM_DIR=Πληκτρολογήστε ένα νέο όνομα φακέλου +FETCH_STATS=Ανάκτηση στατιστικών στοιχείων εφαρμογής... +STATS_MINS=Λεπτά που παίχτηκαν +STATS_HOURS=Ώρα(ες) +STATS_DAYS=Μέρα(ες) +NO_STATS_AVAIL=Δεν υπάρχουν διαθέσιμα στατιστικά στοιχεία εφαρμογής +SAVE_OP_ON_GOING=Η λειτουργία αποθήκευσης βρίσκεται σε εξέλιξη, παρακαλώ περιμένετε... +NO_UPDATE_FOUND=Δεν βρέθηκαν ενημερώσεις του ItemzFlow! +IF_UPDATE_FAILD=Η ενημέρωση ItemzFlow απέτυχε να εγκατασταθεί! +NO_UPDATE_FOUND_INFO=Είναι ενεργοποιημένο το Internet; +CHECH_UPDATE_IN_PROGRESS=Έλεγχος για ενημερώσεις... +CHECK_UPDATE_INFO=Έλεγχος για ενημερώσεις Itemzflow (Ενημέρωση OTA) +PSV_MENU=Ρυθμίσεις εξοικονόμησης ενέργειας +EJECT_DISK=Εκτίναξη δίσκου +EJECT_DISK_ERROR=Σφάλμα εκτίναξης δίσκου με επιτυχία +EJECT_DISK_SUCCESS=Ο δίσκος εκτινάχθηκε επιτυχώς +NO_DISC_INSERTED=Δεν έχει τοποθετηθεί δίσκος +OVERWRITE_SAVE=Θέλετε να αντικαταστήσετε το τρέχον Save; +DUMPER_CANCELLED=Η επιχείρηση Dumping ακυρώθηκε +REBUILDING_FOR_FPKG=Επαναδημιουργία βάσης δεδομένων για FPKGs +CURRENT_APP=Τρέχουσα εφαρμογή +TOTAL_NUM_OF_APPS=Συνολικός αριθμός εφαρμογών +NUMB_OF_FIXED_APPS=Αριθμός σταθερών εφαρμογών +NOT_FIXED=Οχι σταθερών +LAUNCH_FAILED_BC_NOT_FOUND=Η εκκίνηση απέτυχε επειδή η εφαρμογή δεν βρέθηκε στη βάση δεδομένων εφαρμογών του PS4 +CONFIRMATION_2=Θέλετε να προσθέσετε αυτή την εφαρμογή στη βάση δεδομένων PS4s; +IF_LAUNCH_TROUBLESHOOTER=Αντιμετώπιση προβλημάτων εκκίνησης IF +GAME_INSERT_SUCCESSFUL=Προστέθηκε στη Βάση Δεδομένων +GAME_INSERT_FAILED=Η εφαρμογή απέτυχε να προστεθεί στη βάση δεδομένων του PS4! +FIX_BROKEN_SFO_DB=Η εκκίνηση απέτυχε επειδή οι πληροφορίες εφαρμογής στη βάση δεδομένων του PS4 είναι κατεστραμμένες +CONFIRMATION_3=Θέλετε να προσπαθήσετε να το επισκευάσετε; +REPAIR_ATTEMPTED=Προσπάθεια επισκευής! +REPAIR_ATTEMPTED1=Προσπαθήστε να εκκινήσετε ξανά +PLACEHOLDER=Placeholder +PLACEHOLDER_NOT_ENTER=Τα placeholders ΔΕΝ είναι αλληλεπιδραστικά +NO_PATCHES=Δεν βρέθηκαν patches. +PATCH0_APPLIED=Εφαρμοσμένο patch: +PATCH1_APPLIED=Εφαρμοσμένα patches: +SUSPEND_FAILED=Αποτυχία κρίσιμης αναστολής +DAEMON_SUSPEND_FAILED=Το Daemon δεν κατάφερε να ενεργοποιήσει την κρίσιμη αναστολή +NO_PATCH_SELECTED=Δεν έχει επιλεχθεί Patch +NO_APP_OPENED_STR=Η εφαρμογή δεν είναι ανοιχτή +PATCH_NUM=Patch +PATCH_GAME_TITLE=Patch Τίτλος παιχνιδιού: +PATCH_NAME=Όνομα Patch: +PATCH_APP_VER=Έκδοση εφαρμογής Patch: +PATCH_AUTHOR=Συγγραφέας του Patch: +PATCH_NOTE=Σημειώσεις για το patch: +PATCH_VER=Έκδοση Patch: +PATCH_ENABLED=Patch Ενεργοποιημένο/α: +PATCH_SET0=Patch Απενεργοποιημένο/α: +PATCH_SET1=Patch Ενεργοποιημένο/α: +PATCH_DL_QUESTION=Θα θέλατε να κατεβάσετε/ενημερώσετε τη βάση δεδομένων Patch; +PATCH_DL_QUESTION_NO=Δεν θα μεταφορτωθούν patches. +PATCH_DL_QUESTION_YES=Λήψη της βάσης δεδομένων Patch... +PATCH_DL_COMPLETE=Λήψη της βάσης δεδομένων Patch με επιτυχία. +BUTTON_PATCH_TRI_INFO=Λήψη/ενημέρωση βάσης δεδομένων Patch +BUTTON_PATCH_SQUARE_INFO=Προβολή λεπτομερειών Patch +CHANGE_CATEGORY=Αλλαγή κατηγορίας +SHOWING_CATEGORY=Εμφάνιση κατηγορίας +RETAIL_GAMES=Παιχνίδια Retail +GAMES=Παιχνίδια +HOMEBREW=Homebrew +FPKG_STR=FPKGs +NONE=Κανένα +NO_TRAINERS=Δεν βρέθηκαν Trainers +UPDATED_CATEGORY=Η κατηγορία ενημερώθηκε! +INC_CAT=Συμπεριλαμβανομένης της κατηγορίας +CAT_REBUILD_WARNING=Η αναδημιουργία με επιλεγμένη μια κατηγορία θα αναδημιουργήσει μόνο παιχνίδια σε αυτή την κατηγορία. Θέλετε να συνεχίσετε; +RESET_CAT=Εκκαθάριση κατηγορίας +NO_APPS_FOUND=Δεν βρέθηκαν εφαρμογές! +NON_EBOOT_NOT_SUPPORTED1=Βρέθηκε patch μη εκκίνησης eboot για +NON_EBOOT_NOT_SUPPORTED2=δεν υποστηρίζεται ακόμα! +SKIPPING_MSG=Παραλείποντας... +#NEW STRINGS +EXTRA_SETTING_1=Λήψη εξωφύλλων +EXTRA_SETTING_2=Επαναφορά προσαρμογών +EXTRA_SETTING_3=Αντανακλάσεις +EXTRA_SETTING_4=Αλλαγή εικόνας παρασκηνίου +EXTRA_SETTING_5=Μήνυμα εκκίνησης εξώφυλλου +EXTRA_SETTING_6=Αλλαγή γραμματοσειράς +ADVANCED_SETTINGS=Ρυθμίσεις για προχωρημένους +SETTINGS_5=Επαναδημιουργία βάσης δεδομένων FPKG +HIDE_ADVANCED_SETTINGS=Απόκρυψη ρυθμίσεων για προχωρημένους +X_DL_COVER=Πατήστε το X για να κατεβάσετε τα εξώφυλλα +FAILED_TO_DOWNLOAD_COVER=Απέτυχε η λήψη εξωφύλλων +COVERS_UP_TO_DATE=Τα εξώφυλλα είναι πλέον ενημερωμένα! +IMAGE_APPLIED=Η εικόνα εφαρμόστηκε! + +[DUMPER] +DUMP_INFO=Πληροφορίες Dump +APP_NAME=Όνομα εφαρμογής: +TITLE_ID=TITLE_ID: +DUMPER_SC0=Dumping του περιεχομένου του sc0(sce_sys)... +DUMPING_TROPHIES=Dumping τροπαίων ... +CREATING_GP4=Δημιουργία του GP4 ... +DEC_BIN=Αποκρυπτογράφηση του Bin +DEL_SEM=Διαγραφή Semaphore ... +EXT_PATCH=Εξαγωγή αρχείων Patch παιχνιδιού +EXT_GAME_FILES=Εξαγωγή Base αρχείων του παιχνιδιού +PROCESSING=Επεξεργασία diff --git a/App-Media-Assets/langs/3/lang.ini b/App-Media-Assets/langs/3/lang.ini new file mode 100644 index 0000000..bab256d --- /dev/null +++ b/App-Media-Assets/langs/3/lang.ini @@ -0,0 +1,950 @@ +#strings for loader +[LOADER] +LOADER_FATAL=¡FATAL! +FATAL_JB=FATAL Jailbreak fallo con el codigo +FATAL_REJAIL=FATAL rejail_multi fallo con el codigo +SWU_ERROR=[SWU Error] Update IS Revoked para usar esta actualizacion desactive Secure Boot +RSA_LOAD=Comprobando RSA Sig... +RSA_FAILED=La comprobacion RSA ha fallado con el codigo de error +SECURE_FAIL=El arranque seguro esta activado pero no hemos podido descargar el archivo Sig de la CDN. +LOADER_ERROR=El cargador de itemzFlows ha encontrado un error +MORE_INFO=Para mas informacion, consulte: /mnt/usb0/itemzflow/loader.log La aplicacion se cerrara. +INI_FAIL=No se ha podido crear el archivo INI +STR_NOT_FOUND=Cadena no encontrada + +#strings IF +[ITEMZFLOW] +RSA_LOAD=Comprobando RSA Sig... +RSA_FAILED=La comprobacion RSA ha fallado con el codigo de error +OPT_UPDATE=Hay una actualizacion disponible, ¿Desea actualizar ahora? +SORT_OPTS=Ordenar aplicaciones +STR_NOT_FOUND=Cadena no encontrada +ITEMZ_SETTINGS=Configuracion de Itemzflow +RESORT=Resort Juegos/Apps +MISSING_EBOOT=[Internal] Falta eboot.bin en /data/app/ o /hostapp/app/ +MISSING_SFO=[Internal] falta param.sfo en /data/app/sce_sys o /hostapp/app/sce_sys +CORRUPT_SFO=el param.sfo esta dañado +ON2=ON +OFF2=OFF +TRUE2=Verdadero +FALSE2=Falso +STORAGE=Almacenamiento +ITEMZ_VER=Version de Itemzflow +SYS_VER=Version del sistema +OTHER=Otro +INSTALLING=Instalando... +SETTINGS=Ajustes +ID2=Id +NAME2=Nombre +DISC2=Disco +INSTALL_FAILED=Fallo de instalacion con codigo +INSTALL_OF=Instalacion de +COMPLETE=¡Ya esta completo! +FAILED_W_CODE=ha fallado con codigo +FATAL_ERROR=Error fatal +PRESS_OK_CLOSE=Por favor, cierre el programa despues de pulsar OK#strings for loader +[LOADER] +LOADER_FATAL=¡FATAL! +FATAL_JB=FATAL Jailbreak falló con el código +FATAL_REJAIL=FATAL rejail_multi falló con el código +SWU_ERROR=[SWU Error] Update IS Revoked para usar esta actualización desactive Secure Boot +RSA_LOAD=Comprobando firma RSA... +RSA_FAILED=La comprobación RSA ha fallado con el código de error +SECURE_FAIL=El arranque seguro está activado, pero no hemos podido descargar el archivo Sig del CDN. +LOADER_ERROR=El cargador de itemzFlows ha encontrado un error +MORE_INFO=Para más información, consulte: /mnt/usb0/itemzflow/loader.log La aplicación se cerrará. +INI_FAIL=No se ha podido crear el archivo INI +STR_NOT_FOUND=Cadena no encontrada + +#strings IF +[ITEMZFLOW] +RSA_LOAD=Comprobando firma RSA... +RSA_FAILED=La comprobación RSA ha fallado con el código de error +OPT_UPDATE=Hay una actualización disponible, ¿Desea actualizar ahora? +SORT_OPTS=Ordenar apps +STR_NOT_FOUND=Cadena no encontrada +ITEMZ_SETTINGS=Configuración de Itemzflow +RESORT=Reordenar Juegos/Apps +MISSING_EBOOT=[Interno] falta el eboot.bin de /data/app/ o /hostapp/app/ +MISSING_SFO=[Interno] falta el param.sfo de /data/app/sce_sys o /hostapp/app/sce_sys +CORRUPT_SFO=el param.sfo está dañado +ON2=Encendido +OFF2=Apagado +TRUE2=Verdadero +FALSE2=Falso +STORAGE=Almacenamiento +ITEMZ_VER=Versión de Itemzflow +SYS_VER=Versión del sistema +OTHER=Otro +INSTALLING=Instalando... +SETTINGS=Ajustes +ID2=Id +NAME2=Nombre +DISC2=Disco +INSTALL_FAILED=Fallo de instalación con código +INSTALL_OF=Instalación de +COMPLETE=se ha completado! +FAILED_W_CODE=ha fallado con código +FATAL_ERROR=Error fatal +PRESS_OK_CLOSE=Por favor, cierre el programa después de pulsar OK +WARNING2=Advertencia +FAILED_TTF=TTF falló al cargar desde +SWITCH_TO_EM=Cambiando a integrado +INI_ERROR=No se ha podido encontrar/abrir el archivo INI +FAILED_DAEMON=El daemon IF ha fallado +DAEMON_OFF=El inicio automatico de Daemon está desactivado +DAEMON_OFF2=Esto puede hacer que algunas cosas no funcionen +DL_CACHE=Descargando y almacenando en caché archivos del sitio web... +PIG_FAIL=Piglet falló al cargar con +NO_USB=No se ha detectado ningún USB, saliendo... +DUMP= Después de que el juego se inicie al pulsar OK, espere unos segundos, vuelva a la store y el juego empezará a volcarse. NO CIERRE EL JUEGO NI LA STORE HASTA QUE EL VOLCADO SE HAYA COMPLETADO. +UNINSTALL_UPDATE=Actualización desinstalada correctamente +UNINSTAL_UPDATE_FAILED=La desinstalación de la actualización ha fallado +UNINSTALL_SUCCESS=Juego desinstalado con éxito, las apps instaladas se volverá a cargar. +UNINSTALL_FAILED=Fallo en la desinstalación del juego +COMING_SOON=Próximamente +RELOAD_IAPPS=La lista de apps instaladas se recargará ahora +APP_REQ=Este lanzador requiere un minimo de 4 apps. Para usarlo necesitas instalar: +MORE_APPS=Más apps +DOWNLOADING_COVERS=Descargando cáratulas del servidor +DL_FAILED_W=La descarga ha fallado con código de estado: +STR_TOO_LONG=La cadena es demasiado larga o INVALIDA, Introduzca una entrada valida +INVAL_PATH=¡Ruta invalida! introduzca una ruta valida +INVAL_TTF=Ruta .ttf invalida Asegurese de que la extensión del archivo es .ttf +CACHE_CLEARED=Se han eliminado/borrado correctamente todas las imagenes almacenadas en caché. +CLEARING_CACHE=Borrando el contenido en caché +CACHE_FAILED=La limpieza de contenido en caché ha fallado +ITEMZ_FEATURE_DISABLED=esta función está desactivada, Motivo: El demonio ItemzFlow NO esta conectado +SAVE_ERROR=Error al guardar +SAVE_SUCCESS=Guardado correctamente +DL_FAILED2=Descarga fallida con código +OBJ_EXPECTED=Objeto esperado +CANT_OPEN=No se puede abrir +APP_DIED=La aplicación ha muerto con código de salida +PKG_TEAM=Si esto continua Contacte con el equipo de PKG-Zone +FATAL_DUMP_ERROR=El volcado del juego ha fallado, la app se recargará ahora Pulse OK para continuar +DUMP_OF=Volcado de +COMPLETE_WO_ERRORS=¡esta Completo sin Errores!: +DUMP_FAILED=Ha finalizado con problemas ¡NO se han volcado todos los archivos! Asegurese de que su proveedor de exploits tiene activados los parches MMAP. +EXCEED_LIMITS=El número de paginas excede el limite de la store +DL_ERROR_PAGE=No se ha podido descargar la pagina: +ERROR_DL_ASSETS=No se ha podido descargar el recurso: +APP_NOT_FOUND=app NO encontrada +APP_OPENED=la app ya se encuentra abierta +APP_CLOSED=app cerrada +APP_UNL=La app NO se puede iniciar +ID_NOT_VAILD=EL_ID_TiTULO NO ES VAILED +LAUNCH_ERROR=El lanzamiento de la aplicación ha fallado con un código de error +RELOAD_LIST=Cargar lista de aplicaciónes ... +SEARCHING=Buscar.... +WAITING_FOR_DAEMON=Esperando respuesta de bienvenida de los demonios (max. 1 min) +TRYING_TO_DL=Intentando descargar la portada de +DL_COVERS=Descarga de caratulas del servidor +STARTING_DUMPER=Puesta en marcha del Dumper... +UU=Desinstalar actualización +UG=Desinstalar juego +SETTINGS_1=Ruta del dump +SETTINGS_2=Comprobar actualizaciónes +SETTINGS_3=Ordenar apps por +SETTINGS_4=Panel por defecto +SETTINGS_5=Ruta de fuente +SETTINGS_6=Instalador de temas +SETTINGS_7=Ruta MP3 de fondo +SETTINGS_8=Mostrar controles de botones +SETTINGS_9=Abrir menu PS4 +SETTINGS_10=Instalador PKG +SETTINGS_11=Controles de energia +SETTINGS_12=Guardar ajustes +NA_SORT1=Aleatorio +TID_ALPHA_SORT1=Orden alfabetico por ID de titulo +TITLE_ALPHA_SORT1=Orden alfabetico por nombre de app +UNINSTALL_GAME1=Desinstalar juego/appp +UNINSTALL_PATCH1=Desinstalar parche +UNINSTALL_DLC1=Desinstalar DLC +UNINSTALL_NOTE=Seleccione una opcion de desinstalacion +SEL_DUMP_ALL1=Todo +SEL_BASE_GAME1=Juego base +SEL_GAME_PATCH1=Parche +SEL_REMASTER1=Remaster +SEL_DLC1=DLC +LAUNCH_GAME=Lanzar +DUMP_1=Dumpear +TRAINERS=Parches +UNINSTALL=Desinstalar +HIDE_APP=Ocultar app +CHANGE_ICON=Cambiar icono (PNG) +CHANGE_APP_NAME=Editar nombre app +CHANGE_TID=Cambiar ID de titulo +NAME_INFO=Cambia el nombre de la aplicación de PS4 en el XMB de PS4 (app.db) +IF_NOT_EFFECTED=Nota: No afecta a Itemzflow +TID_INFO=Cambia el ID del titulo de la aplicación en app.db +ICON_INFO=Escriba una ruta a un nuevo icono personalizado para la aplicación seleccionada +LAUNCH_INFO=Inicia el juego/aplicación seleccionado +TRAINER_INFO=Busca Entrenador(es) para el Juego Seleccionado +HIDE_INFO=Oculta el juego/aplicación en el app.db de PS4 +DUMP_OPT_INFO=Seleccionar para elegir una opcion de volcado +PLAYING_SINCE=Jugando desde +PNG_NOTE=Nota: Solo PNGs de 512x512 +SUSPEND_IF=Nota: Itemzflow sera Suspendido +HIDE_OPT_INFO=Nota: Tambien puede ocultarlo de Itemzflow a traves del menu Configuracion +SEL_DUMP_ALL_INFO=Dumpea TODO el juego y cualquier DLC y parche disponible. +SEL_BASE_GAME_INFO=Dumpea solo el juego base +SEL_GAME_PATCH_INFO=Dumpea solo el parche del juego +SEL_REMASTER_INFO=Dumpea solo las remasterizaciones disponibles +SEL_DLC_INFO=Dumpea solo DLC(s) disponible(s) +SETTINGS=Ajustes +FTP_NOT_RUNNING=FTP no en ejecucion (OFF) +FTP_RUNNING=FTP se esta ejecutando (ON) +DUMPER_PATH_DESC=Seleccione una ruta de volcado personalizada +REBUILD_DB_OPTION_DESC=Reconstruir la base de datos de aplicaciónes de PS4 (app.db) +SORT_BY_OPTION_DESC=Seleccionar como Itemzflow ordena las aplicaciónes (ralentiza la apertura SI) +HOME_MENU_OPTION_DESC=Redirige el boton de inicio de PS a esta aplicación +FTP_SERVICE_OPTION_DESC=Activar o desactivar temporalmente FTP +TTF_OPTION_DESC=Seleccionar una ruta de fuente TTF personalizada +BACKGROUND_MP3_OPTION_DESC=Seleccione un MP3 personalizado de 48 Hz para que se reproduzca en segundo plano. +SHOW_BUTTON_OPTION_DESC=Mostrar u ocultar controles de boton +OPEN_DEBUG_MENU_DESC=Abre el menu de depuracion o configuracion de PS4 +RDB=Reconstruir base de datos FPKG +RELOAD_APPS=Cargar aplicaciónes +#BUTTON INFO +BUTTON_X_INFO=Seleccionar +BUTTON_O_INFO=Atras/Cancelar +BUTTON_LEFT_RIGHT_INFO=Anterior/Siguiente +BUTTON_UP_DOWN_INFO=Arriba/Abajo +BUTTON_TRIANGLE=Recargar apps +BUTTON_CLOSE=Salir de ItemzFlow +BUTTON_CONFIRM_CLOSE=Confirmar cierre +CLOSE_GAME=Cerrar partida abierta +FAILED_MENU_OPEN=Fallo al abrir el menu +ERROR_CODE=código de error +SELECT_INTERACT=Pulsa X para interactuar +GAME_SAVE_OPTS=Opciones Savedata +BACKUP_SAVE=Backup de todos los archivos guardados +IMPORT_SAVE=Guardar importacion +SAVE_DELETE=Borrar todos los guardados +SHOW_APP=Hacer visible +HIDE_APP_OPT=Visibilidad de la app +PS4_REBOOT_REQ=Se necesita reiniciar para realizar cambios +PLEASE_WAIT=Por favor, espere... +APPS_RELOADED=aplicaciónes Recargadas +APPS_RELOADED_2=Lista de aplicaciónes actualizada +CON_DIS=Controlador desconectado +CON_DIS_2=Reconectar el controlador +REALLY_HOT=¡La PS4 esta muy caliente! +REALLY_HOT_2=PS4 por encima de 90C, considere una nueva pasta termica +NO_SAVES=No hay partidas guardadas disponibles +CANT_FIND_SAVE=No se ha encontrado un archivo guardado +SAVE_OPS_FAILED=Fallo la operacion de guardado +FAILED_INI_SD=Fallo al inicializar los datos guardados +FAILED_MOUNT_SD=Fallo al montar Guardar +SD_SAVED=Juego guardado en USB +SD_TRANSFER_FAIL=No se ha podido transferir el archivo guardado +SD_DELETED=Salvar partida borrada +CANT_DELETE_SD=No se ha podido eliminar +DECRYPTED_SD=No se encuentra el archivo descifrado +NO_AVAIL_SAVE=No hay archivos guardados disponibles +SAVE_IMPORTED=¡Salvar juego importado! +SAVE_IMPORT_2=Guardar titulo +NO_USERID=Error de no poder obtener el ID de usuario +UNSUPPORTED_FS=Sistema de archivos no soportado detectado +RETAILO=Solo PS4 al por menor +NO_GOLDHEN=¡Falta GoldHEN o ps4debug! +FAILED_SAVE_PATCHES=¡No se han podido aplicar los parches! +UNSUPPORTED_FW=Version de FW no soportada +MP3_PLAYING=MP3 en reproduccion +MP3_LOADED=MP3 cargado +FAILED_MP3=No se ha podido cargar el MP3 +TRAINER_LOADED=Entrenador cargado +TRAINER_FAILED=Fallo de carga del entrenador +TRAINER_ESRCH=No se han encontrado entrenadores +GAME_LAUCNHED=El juego ha sido lanzado +GAME_KILLED=El juego ha sido eliminado +GAME_RESUME=Reanudar partida +PLUG_MNG=Administrador de plugins +PLUG_LOADED=Plugin cargado +PLUG_FAILED=Fallo de carga del plugin +PLUG_ERROR=Error de Plugin +LANG_NOT_SUPPORTED=ItemzFlow no soporta su idioma +ENG_LOADED=Ingles cargado en lugar de ... +IF_UPDATE_SUCESS=¡Se ha actualizado Itemzflow! +FAILED_ICON=No se ha podido cambiar el icono +DAEMON_FAILED_NOTIFY=ItemzDaemon Ha fallado la conexion +DAEMON_FAILED_NOTIFY2=¡Algunas funciones se desactivaran! +PWR_OFF_SYS=Apagado del sistema +RESTRT_SYS=Reiniciar sistema +SUSPEND_SYS=Suspender sistema +NO_INTERNET=No se ha podido contactar con el servidor +BE_SURE_INTERNET=Asegurese de que Internet esta activado +SFO_OP_FAILED=¡Fallo de la operacion OFS! +ICON_OP_FAILED=¡Fallo la operacion de icono! +GAME_DUMP_FAILED=¡El volcado del juego ha fallado! +GAME_DUMP_FAILED2=Compruebe si hay problemas en el disco +UNABLE_TO_TRANFER=¡La transferencia ha fallado! +FTP_START_NOTIFY=FTP Plugin Iniciado +FTP_STOP_NOTIFY=FTP Plugin Detenido +FTP_ERROR=se ha producido un error FTP +REDIRECT_TURNED_ON=Redireccion del menu Inicio activada +REDIRECT_TURNED_OFF=Redireccion del menu Inicio desactivada +APP_DB_REBUILT=La base de datos de la aplicación ha sido reparada +APP_DB_ERROR=¡La reparacion de la base de datos de la aplicación ha fallado! +TTF_SUCCESS_NOTIFY=Se ha cargado el nuevo TTF +TTF_ERROR_NOTIFY=Fallo al cargar fuente TTF +TTF_ERROR_NOTIFY2=Cargado TTF por defecto +SETTING_APPLIED=Se ha aplicado la configuracion +PKG_INST_FAILED=¡Fallo la instalacion de PKG! +PKG_INST_FAILED1=Por favor, confirme el PKG +PKG_INST_SUCCESS=PKG instalado correctamente +USB_NOTIFY=Dispositivo USB insertado +USB_NOTIFY1=El USB esta listo para su uso +NOT_ENOUGH_FREE_SPACE=No hay suficiente espacio libre +UNHIDE_NOTIFY=Visibilidad cambiada +UNHIDE_SUCCESS_NOTIFY=La aplicación esta ahora visible +HIDE_SUCCESS_NOTIFY=La aplicación ya esta oculta +UNHIDE_FAILED_NOTIFY=No se ha podido cambiar la visibilidad +FAILED_TO_CLOSE=Fallo al cerrar la aplicación +OPT_NOT_PERMITTED=Opcion no disponible aqui +TITLE_ID_NOT_RIGHT=Titulo ID NO Valido +TILE_ID_CHANGED=Cambio de ID de hilera +TITLE_ID_FAILD=¡No se ha podido cambiar el ID del titulo! +PARAM_PATH_FAILED=¡El parcheo del SFO ha fallado! +TITLE_CHANGED=Cambio de titulo de la aplicación +FAILED_TITLE_CHANGE=Fallo al cambiar el titulo del juego +CONSIDER_SUPPORT=¡Apoyanos en Ko-fi! +DUMPER_PATH_NO_AVAIL=¡La ruta de descarga no es valida! +FS_SEL_FAILED=Fallo al abrir el selector de archivos +FS_SEL_ERROR1=No se puede abrir el selector FS +FS_SEL_ERROR2=Selector ya iniciado +ICON_CHANGED_SUCCESS=¡Icono cambiado! +ICON_CHANGE_FAILED=Fallo al cambiar el icono +PNG_NOT_VAILD=¡PNG no es valido! +FAILED_TO_COPY=Fallo de copia +FONT_CHANGED_SUCCESS=¡Fuente cambiada! +NEW_FONT_STRING=Fuente nueva +DUMPER_PATH_UPDATED=¡Ruta de descarga actualizada! +NEW_PATH_STRING=Nueva ruta +PKG_IS_INSTALLING=PKG se esta instalando... +PKG_IS_INSTALLED=La instalacion ha finalizado +VAR_IS_INSTALLED=ya esta instalado +FS_CONTROL_BUTTON_1=Introducir carpeta +FS_CONTROL_BUTTON_2=Carpeta anterior +FS_CONTROL_BUTTON_3=Cancelar/Salir +FS_CONTROL_BUTTON_4=Seleccionar archivo +FS_CONTROL_BUTTON_4_1=Seleccionar carpeta +FS_CONTROL_BUTTON_5=Cambiar paneles de archivos +FS_CONTROL_BUTTON_6=Nueva Carpeta +FS_CONTROL_BUTTON_7=Copiar/Pegar +FOLDER_MADE_SUCCESS=¡Carpeta creada! +FOLDER_MAKE_FAIL=¡Fallo en la creacion de la carpeta! +OP_CANNED=¡Operacion cancelada! +OP_CANNED_1=No se han aplicado cambios +MOVE_APP_OPT=Mover a USB +MOVE_APP_OPT_1=Mover aplicación/juego +MOVE_APP_OPT_2=Mover DLC +MOVE_APP_OPT_3=Mover parche +RESTORE_APP_OPT=Restaurar desde USB +RESTORE_APP_OPT_1=Restaurar aplicación/juego +RESTORE_APP_OPT_2=Restaurar DLC +RESTORE_APP_OPT_3=Restaurar parche +RETAIL=Minorista +RESTORE_SUCCESS=Restauracion correcta +MOVE_SUCCESSFULLY=Movido con exito +RESTORE_FAILED=Fallo de restauracion +MOVE_FAILED=Fallo en el movimiento +APP_MOVE_NOTIFY=aplicación movida con exito +SELECT_A_FOLDER=Seleccione una carpeta para continuar +SELECT_A_FILE=Seleccione un archivo para continuar +APP_MOVING_MESSAGE=La aplicación se traslada a +APP_NOT_MOVED=Nada que restaurar +BACKUP_FPKG=Backup FPKG +COPYING_FPKG=Copiando FPKG, Por favor espere... +FPKG_COPY_SUCCESS=FPKG Copiado con exito +FPKG_COPY_FAILED=¡FPKG no ha podido copiar! +EXT_MOVE_NOT_SUPPORTED=¡No se admiten aplicaciónes externas! +PATCH_MOVE_NOTIFY=Parche movido con exito +DLC_MOVE_NOTIFY=DLC Movido con exito +COPYING_FILE=Copiando archivo, por favor espere... +RESTORE_INFO_TEXT=Restaurar aplicaciónes digitales movidas con Itemzflow +MOVE_INFO_TEXT=Mover contenido descargado digitalmente a un USB +OPTION_DOESNT_SUPPORT_DISC=Esta opcion no admite discos +BACKUP_FPKG_INFO=Backup de los juegos FPKG para reinstalar mas tarde +GAME_CONTROL_INFO=Controles del juego: Reanudar o cerrar la aplicación +CLOSE_OPEN_APP_INFO=Cierra el juego o la aplicación abierta en ese momento +GAME_CONTROLS=Controles del juego +RESTORE_GAME_INFO=Importar y Resignar un dato de guardado descifrado del almacenamiento +BACKUP_GAME_INFO=Backup de TODAS las partidas guardadas del juego +DELETE_GAME_INFO=Eliminar TODAS las partidas guardadas de este juego +UNINSTALL_PATCH_INFO=Desinstalar cualquier parche instalado para este juego +UNINSTALL_GAME_INFO=Desinstalar juego/App y todo lo que contiene +SORT_RANDOM_INFO=Ordenar aplicaciónes/juegos aleatoriamente +SORT_ALPHA_NAME_INFO=Ordenar aplicaciónes/juegos por nombre alfabeticamente +SORT_ALPHA_TID_INFO=Ordenar alfabeticamente aplicaciónes/juegos por ID de titulo +THE_ITEM_IS_ALREADY_BP=El elemento seleccionado ya ha sido respaldado +IF_PKG_INSTALLER=Instalador de paquetes IF +IF_PKG_INSTALLER_INFO=Instalar PKGs desde una unidad USB +THEME_INSTALLER=Instalador de temas IF +THEME_NOT_VAILD=¡El tema no es válido! +THEME_INSTALLER_INFO=Instalar temas IF desde una unidad USB +THEME_INSTALL_SUCCESS=¡Tema instalado y aplicado! +THEME_FAILED_TO_APPLY=Fallo al aplicar el tema +FOUND_SAVE_MESSAGE=Datos de guardado del juego encontrado +FOUND_SAVE_MESSAGE_OVER_1=Datos de guardado encontrados, Mostrando 1... +USER_LANG=Usuario +NO_SAVES_LANG=Sin datos de guardado +DOWNLOAD_COVERS=¿Desea buscar y/o descargar carátulas ahora? +LOADING_GAME_LIST=Cargando lista de juegos ... +RESTORE_NOTICE=Al restaurar se borrarán todos los DLC y datos de guardado de este juego. +INSTALLING_THEME=Instalando y validando tema... +RESTART_STR=Reiniciar +SHUTDOWN_STR=Apagar +SUSPEND_STR=Suspender +ERROR_POWER_CONTROL=Error al ajustar el nivel de potencia +POWER_CONTROL_INFO=Opciones de energía de la consola +USB_DISCONNECTED=¡USB desconectado! +USB_DISCONNECTED1=Dispositivo USB desconectado +REINSTALL_APP_CONFIRMATION=Esta aplicación ya está instalada, ¿desea reinstalarla? (Se eliminarán todos los datos de juego) +THEME_RESET=Se ha establecido el tema por defecto +NO_DLC_AVAIL=No hay DLC disponible +NO_PATCH_AVAIL=No hay parches disponibles +RELAUCHING_IN_5=Recarga SI en 5 segundos... +CREATE_CUSTOM_DIR=Escriba un nuevo nombre de carpeta +FETCH_STATS=Obteniendo estadísticas de aplicación... +STATS_MINS=Minutos jugados +STATS_HOURS=Hora(s) +STATS_DAYS=Dia(s) +NO_STATS_AVAIL=No hay estadísticas de aplicación disponibles +SAVE_OP_ON_GOING=La operación de guardado está en curso, por favor espere... +NO_UPDATE_FOUND=No se han encontrado actualizaciones de ItemzFlow! +IF_UPDATE_FAILD=La actualización de ItemzFlow ha fallado al instalar! +NO_UPDATE_FOUND_INFO=¿Está habilitado Internet? +CHECH_UPDATE_IN_PROGRESS=Buscando actualizaciones... +CHECK_UPDATE_INFO=Comprobar actualizaciones de Itemzflow (actualización OTA) +PSV_MENU=Configuración de ahorro de energía +EJECT_DISK=Expulsar disco +EJECT_DISK_ERROR=Error expulsando disco +EJECT_DISK_SUCCESS=Disco expulsado correctamente +NO_DISC_INSERTED=No hay disco insertado +OVERWRITE_SAVE=¿Desea sobrescribir el guardado actual? +DUMPER_CANCELLED=La operación de volcado se ha cancelado +REBUILDING_FOR_FPKG=Reconstruyendo base de datos para los FPKGs +CURRENT_APP=Aplicación actual +TOTAL_NUM_OF_APPS=Número total de apps +NUMB_OF_FIXED_APPS=Número de apps reparadas +NOT_FIXED=No reparado +LAUNCH_FAILED_BC_NOT_FOUND=El lanzamiento ha fallado porque no se ha encontrado la aplicación en la base de datos de apps de PS4. +CONFIRMATION_2=¿Desea añadir esta aplicación a la base de datos de PS4? +IF_LAUNCH_TROUBLESHOOTER=IF Lanzar solucionador de problemas +GAME_INSERT_SUCCESSFUL=Agregado a la base de datos +GAME_INSERT_FAILED=¡Fallo al intentar añadir la aplicación a la base de datos de PS4! +FIX_BROKEN_SFO_DB=El lanzamiento ha fallado porque la información de la aplicación en la base de datos de PS4 está dañada. +CONFIRMATION_3=¿Desea intentar repararlo? +REPAIR_ATTEMPTED=¡Reparación Intentada! +REPAIR_ATTEMPTED1=Intenta lanzarlo de nuevo +PLACEHOLDER=Espacio reservado +PLACEHOLDER_NOT_ENTER=Los espacios reservados NO son interactivos +NO_PATCHES=No se han encontrado parches. +PATCH0_APPLIED=Parche aplicado: +PATCH1_APPLIED=Parches aplicados: +SUSPEND_FAILED=La suspensión crítica ha fallado +DAEMON_SUSPEND_FAILED=Fallo en la activación de la suspensión crítica +NO_PATCH_SELECTED=Sin parche seleccionado +NO_APP_OPENED_STR=La aplicación no está abierta +PATCH_NUM=Parche +PATCH_GAME_TITLE=Título del juego del parche: +PATCH_NAME=Nombre del parche: +PATCH_APP_VER=Versión del parche: +PATCH_AUTHOR=Autor del parche: +PATCH_NOTE=Nota del parche: +PATCH_VER=Versión del parche: +PATCH_ENABLED=Parche activado: +PATCH_SET0=Parche desactivado: +PATCH_SET1=Parche activado: +PATCH_DL_QUESTION=¿Desea descargar/actualizar la base de datos de parches? +PATCH_DL_QUESTION_NO=Ningún parche será descargado. +PATCH_DL_QUESTION_YES=Descargando base de datos de parches... +PATCH_DL_COMPLETE=Base de datos de parches descargada correctamente. +BUTTON_PATCH_TRI_INFO=Descargar/actualizar base de datos de parches +BUTTON_PATCH_SQUARE_INFO=Ver detalles del parche +CHANGE_CATEGORY=Cambiar categoría +SHOWING_CATEGORY=Mostrando categoría +RETAIL_GAMES=Juegos regulares +GAMES=Juegos +HOMEBREW=Homebrew +FPKG_STR=FPKGs +NONE=Nada +NO_TRAINERS=No se han encontrado trainers +UPDATED_CATEGORY=¡Categoría actualizada! +INC_CAT=Incluyendo con categoría +CAT_REBUILD_WARNING=La reconstrucción con una categoría seleccionada solo reconstruirá los juegos de esa categoría. ¿Desea continuar? +RESET_CAT=Restablecer categoría +NO_APPS_FOUND=¡No se han encontrado apps! +NON_EBOOT_NOT_SUPPORTED1=Encontrado parche de eboot no inicial para +NON_EBOOT_NOT_SUPPORTED2=aún no es compatible! +SKIPPING_MSG=Omitiendo... +#NEW STRINGS +EXTRA_SETTING_1=Descargar portadas +EXTRA_SETTING_2=Restablecer personalizaciones +EXTRA_SETTING_3=Reflejos +EXTRA_SETTING_4=Cambiar imagen de fondo +EXTRA_SETTING_5=Mensaje de portada de inicio +EXTRA_SETTING_6=Cambiar fuente +ADVANCED_SETTINGS=Configuración avanzada +SETTINGS_5=Reconstruir base de datos FPKG +HIDE_ADVANCED_SETTINGS=Ocultar configuración avanzada +X_DL_COVER=Presiona X para descargar carátulas +FAILED_TO_DOWNLOAD_COVER=Error al descargar carátulas +COVERS_UP_TO_DATE=¡Portadas actualizadas! +IMAGE_APPLIED=¡Imagen aplicada! +DISABLE_MUSIC=Desactivar música +REBUILD_DB_OPT_1=Reconstruir base de datos interna +REBUILD_DB_OPT_2=Reconstruir solo DLC (Inc. ext hdd) +REBUILD_DB_OPT_3=Reactivar ext. Contenido +REBUILD_DB_DESC_1=Restaurar juegos/aplicaciones/DLC XMB faltantes desde el almacenamiento interno (Inc. App2usb) +REBUILD_DB_DESC_2=Restaurar los DLC de almacenamiento interno y extendido de XMB que faltan +REBUILD_DB_DESC_3=Reactivar juegos/aplicaciones/DLC de almacenamiento extendido que se deshabilitaron +REBUILDING_ADDCONT=Reconstruyendo DLC +ADDCONT_REBUILT= ¡Los DLC se han reconstruido con éxito! +ADDCONT_REACTED=¡El contenido externo se ha reactivado correctamente! +ADDCONT_REACT_FAILED=Error, ¡el contenido externo no se ha reactivado! +ADDCONT_FAILED=Error, ¡Algunos DLC(s) no han sido agregados! +SHUTDOWN_DAEMON=Demonio de parada y salida +DB_MOD_WARNING=Esto modificará la base de datos de PS4. CUALQUIER inestabilidad o problema causado por esto queda a discreción de los usuarios. +SIGN_IN_USER_NOTIF=Perfil registrado +MUSIC_Q=Música en cola +PLAYING_NEXT=Reproduciendo a continuación +DELETING_GAME_FOLDER=El volcado ya existe, eliminando la carpeta del juego + + + + +[DUMPER] +DUMP_INFO=Información del volcado +APP_NAME=Nombre de la aplicación: +TITLE_ID=TITLE_ID: +DUMPER_SC0=Volcando contenido de sc0(sce_sys) ... +DUMPING_TROPHIES=Volcando trofeos ... +CREATING_GP4=Creando GP4 ... +DEC_BIN=Desencriptando Binario +DEL_SEM=Borrando Semáforo ... +EXT_PATCH=Extrayendo los archivos parches de juegos +EXT_GAME_FILES=Extrayendo los archivos del juego base +PROCESSING=Procesando +WARNING2=Aviso +FAILED_TTF=TTF Fallo al cargar desde +SWITCH_TO_EM=Cambiar a integrado +INI_ERROR=No se ha podido encontrar/abrir el archivo INI +FAILED_DAEMON=El demonio IF ha fallado +DAEMON_OFF=El inicio automatico de Daemon esta desactivado +DAEMON_OFF2=Esto puede hacer que algunas cosas no funcionen +DL_CACHE=Descarga y almacenamiento en cache de archivos del sitio web... +PIG_FAIL=Fallo de carga de Piglet (minorista) con +NO_USB=No se ha detectado ningun USB, saliendo... +DUMP= Despues de que el juego se inicie, cuando pulse OK, espere unos segundos y vuelva a la tienda para que el juego comience a descargarse. NO CIERRE EL JUEGO NI LA TIENDA HASTA QUE EL DUMP SE HAYA COMPLETADO. +UNINSTALL_UPDATE=Update del juego desinstalado correctamente +UNINSTAL_UPDATE_FAILED=Desinstalacion del update del juego +UNINSTALL_SUCCESS=Juego desinstalado con exito, la lista de aplicaciones instaladas se volvera a cargar. +UNINSTALL_FAILED=Fallo en la desinstalacion del juego +COMING_SOON=Proximamente +RELOAD_IAPPS=La lista de aplicaciones instaladas se recargara ahora +APP_REQ=Este Lanzador de Juegos tiene un Requerimiento de min. 4 Apps Para utilizarlo es necesario instalar: +MORE_APPS=Mas aplicaciones +DOWNLOADING_COVERS=Descarga de caratulas del servidor +DL_FAILED_W=Fallo de descarga con StatusCode: +STR_TOO_LONG=La cadena es demasiado larga o INVaLIDA Introduzca una entrada valida +INVAL_PATH=¡Ruta invalida! introduzca una ruta valida +INVAL_TTF=Ruta .ttf invalida Asegurese de que la extension del archivo es .ttf +CACHE_CLEARED=Se han eliminado/borrado correctamente todas las imagenes almacenadas en cache. +CLEARING_CACHE=Borrar el contenido de la cache +CACHE_FAILED=Fallo la limpieza del contenido en cache +ITEMZ_FEATURE_DISABLED=esta funcion esta desactivada, Razon: El demonio ItemzFlow NO esta conectado +SAVE_ERROR=Error al guardar +SAVE_SUCCESS=Guardado correctamente +DL_FAILED2=Descarga fallida con codigo +OBJ_EXPECTED=Objeto esperado +CANT_OPEN=No se puede abrir +APP_DIED=La aplicacion ha muerto con codigo de salida +PKG_TEAM=Si esto continua Contacte con el equipo PKG-Zone +FATAL_DUMP_ERROR=El volcado del juego ha fallado la aplicacion se recargara ahora Pulse OK para continuar +DUMP_OF=Volcado de +COMPLETE_WO_ERRORS=¡esta Completo sin Errores!: +DUMP_FAILED=Ha finalizado con problemas ¡NO se han volcado todos los archivos! Asegurese de que su proveedor de exploits tiene activados los parches MMAP. +EXCEED_LIMITS=¡El numero de paginas excede los limites del almacen! +DL_ERROR_PAGE=No se ha podido descargar la pagina: +ERROR_DL_ASSETS=No se ha podido descargar el activo: +APP_NOT_FOUND=Aplicacion NO encontrada +APP_OPENED=Aplicacion ya abierta +APP_CLOSED=Aplicacion cerrada +APP_UNL=La aplicacion NO se puede iniciar +ID_NOT_VAILD=EL_ID_TiTULO NO ES VAILED +LAUNCH_ERROR=El lanzamiento de la aplicacion ha fallado con un codigo de error +RELOAD_LIST=Cargar lista de aplicaciones ... +SEARCHING=Buscar.... +WAITING_FOR_DAEMON=Esperando respuesta de bienvenida de los demonios (max. 1 min) +TRYING_TO_DL=Intentando descargar la portada de +DL_COVERS=Descarga de caratulas del servidor +STARTING_DUMPER=Puesta en marcha del Dumper... +UU=Desinstalar actualizacion +UG=Desinstalar juego +SETTINGS_1=Ruta del dump +SETTINGS_2=Comprobar actualizaciones +SETTINGS_3=Ordenar aplicaciones por +SETTINGS_4=Configurar como Panel por defecto +SETTINGS_5=Ruta de fuente +SETTINGS_6=Instalador de temas +SETTINGS_7=Ruta MP3 de fondo +SETTINGS_8=Mostrar controles de botones +SETTINGS_9=Abrir menu PS4 +SETTINGS_10=Instalador PKG +SETTINGS_11=Controles de energia de la consola +SETTINGS_12=Guardar ajustes +NA_SORT1=Aleatorio +TID_ALPHA_SORT1=Orden alfabetico por ID de titulo +TITLE_ALPHA_SORT1=Orden alfabetico por nombre de aplicacion +UNINSTALL_GAME1=Desinstalar juego/appp +UNINSTALL_PATCH1=Desinstalar parche +UNINSTALL_DLC1=Desinstalar DLC +UNINSTALL_NOTE=Seleccione una opcion de desinstalacion +SEL_DUMP_ALL1=Todo +SEL_BASE_GAME1=Juego base +SEL_GAME_PATCH1=Parche +SEL_REMASTER1=Remaster +SEL_DLC1=DLC +LAUNCH_GAME=Lanzar +DUMP_1=Dumpear +TRAINERS=Parches +UNINSTALL=Desinstalar +HIDE_APP=Ocultar aplicacion +CHANGE_ICON=Cambiar icono (PNG) +CHANGE_APP_NAME=Cambiar nombre de aplicacion +CHANGE_TID=Cambiar ID de titulo +NAME_INFO=Cambia el nombre de la aplicacion de PS4 en el XMB de PS4 (app.db) +IF_NOT_EFFECTED=Nota: No afecta a Itemzflow +TID_INFO=Cambia el ID del titulo de la aplicacion en app.db +ICON_INFO=Escriba una ruta a un nuevo icono personalizado para la aplicacion seleccionada +LAUNCH_INFO=Inicia el juego/aplicacion seleccionado +TRAINER_INFO=Busca Entrenador(es) para el Juego Seleccionado +HIDE_INFO=Oculta el juego/aplicacion en el app.db de PS4 +DUMP_OPT_INFO=Seleccionar para elegir una opcion de volcado +PLAYING_SINCE=Jugando desde +PNG_NOTE=Nota: Solo PNGs de 512x512 +SUSPEND_IF=Nota: Itemzflow sera Suspendido +HIDE_OPT_INFO=Nota: Tambien puede ocultarlo de Itemzflow a traves del menu Configuracion +SEL_DUMP_ALL_INFO=Dumpea TODO el juego y cualquier DLC y parche disponible. +SEL_BASE_GAME_INFO=Dumpea solo el juego base +SEL_GAME_PATCH_INFO=Dumpea solo el parche del juego +SEL_REMASTER_INFO=Dumpea solo las remasterizaciones disponibles +SEL_DLC_INFO=Dumpea solo DLC(s) disponible(s) +SETTINGS=Ajustes +FTP_NOT_RUNNING=FTP no en ejecucion (OFF) +FTP_RUNNING=FTP se esta ejecutando (ON) +DUMPER_PATH_DESC=Seleccione una ruta de volcado personalizada +REBUILD_DB_OPTION_DESC=Reconstruir la base de datos de aplicaciones de PS4 (app.db) +SORT_BY_OPTION_DESC=Seleccionar como Itemzflow ordena las aplicaciones (ralentiza la apertura SI) +HOME_MENU_OPTION_DESC=Redirige el boton de inicio de PS a esta aplicacion +FTP_SERVICE_OPTION_DESC=Activar o desactivar temporalmente FTP +TTF_OPTION_DESC=Seleccionar una ruta de fuente TTF personalizada +BACKGROUND_MP3_OPTION_DESC=Seleccione un MP3 personalizado de 48 Hz para que se reproduzca en segundo plano. +SHOW_BUTTON_OPTION_DESC=Mostrar u ocultar controles de boton +OPEN_DEBUG_MENU_DESC=Abre el menu de depuracion o configuracion de PS4 +RDB=Reconstruir base de datos FPKG +RELOAD_APPS=Cargar aplicaciones +#BUTTON INFO +BUTTON_X_INFO=Seleccionar +BUTTON_O_INFO=Atras/Cancelar +BUTTON_LEFT_RIGHT_INFO=Anterior/Siguiente +BUTTON_UP_DOWN_INFO=Arriba/Abajo +BUTTON_TRIANGLE=Recargar aplicaciones +BUTTON_CLOSE=Salir de ItemzFlow +BUTTON_CONFIRM_CLOSE=Confirmar cierre +CLOSE_GAME=Cerrar partida abierta +FAILED_MENU_OPEN=Fallo al abrir el menu +ERROR_CODE=Codigo de error +SELECT_INTERACT=Pulsa X para interactuar +GAME_SAVE_OPTS=Opciones Savedata +BACKUP_SAVE=Backup de todos los archivos guardados +IMPORT_SAVE=Guardar importacion +SAVE_DELETE=Borrar todos los guardados +SHOW_APP=Hacer visible +HIDE_APP_OPT=Visibilidad de la app +PS4_REBOOT_REQ=Se necesita reiniciar para realizar cambios +PLEASE_WAIT=Por favor, espere... +APPS_RELOADED=Aplicaciones Recargadas +APPS_RELOADED_2=Lista de aplicaciones actualizada +CON_DIS=Controlador desconectado +CON_DIS_2=Reconectar el controlador +REALLY_HOT=¡La PS4 esta muy caliente! +REALLY_HOT_2=PS4 por encima de 90C, considere una nueva pasta termica +NO_SAVES=No hay partidas guardadas disponibles +CANT_FIND_SAVE=No se ha encontrado un archivo guardado +SAVE_OPS_FAILED=Fallo la operacion de guardado +FAILED_INI_SD=Fallo al inicializar los datos guardados +FAILED_MOUNT_SD=Fallo al montar Guardar +SD_SAVED=Juego guardado en USB +SD_TRANSFER_FAIL=No se ha podido transferir el archivo guardado +SD_DELETED=Salvar partida borrada +CANT_DELETE_SD=No se ha podido eliminar +DECRYPTED_SD=No se encuentra el archivo descifrado +NO_AVAIL_SAVE=No hay archivos guardados disponibles +SAVE_IMPORTED=¡Salvar juego importado! +SAVE_IMPORT_2=Guardar titulo +NO_USERID=Error de no poder obtener el ID de usuario +UNSUPPORTED_FS=Sistema de archivos no soportado detectado +RETAILO=Solo PS4 al por menor +NO_GOLDHEN=¡Falta GoldHEN o ps4debug! +FAILED_SAVE_PATCHES=¡No se han podido aplicar los parches! +UNSUPPORTED_FW=Version de FW no soportada +MP3_PLAYING=MP3 en reproduccion +MP3_LOADED=MP3 cargado +FAILED_MP3=No se ha podido cargar el MP3 +TRAINER_LOADED=Entrenador cargado +TRAINER_FAILED=Fallo de carga del entrenador +TRAINER_ESRCH=No se han encontrado entrenadores +GAME_LAUCNHED=El juego ha sido lanzado +GAME_KILLED=El juego ha sido eliminado +GAME_RESUME=Reanudar partida +PLUG_MNG=Administrador de plugins +PLUG_LOADED=Plugin cargado +PLUG_FAILED=Fallo de carga del plugin +PLUG_ERROR=Error de Plugin +LANG_NOT_SUPPORTED=ItemzFlow no soporta su idioma +ENG_LOADED=Ingles cargado en lugar de ... +IF_UPDATE_SUCESS=¡Se ha actualizado Itemzflow! +FAILED_ICON=No se ha podido cambiar el icono +DAEMON_FAILED_NOTIFY=ItemzDaemon Ha fallado la conexion +DAEMON_FAILED_NOTIFY2=¡Algunas funciones se desactivaran! +PWR_OFF_SYS=Apagado del sistema +RESTRT_SYS=Reiniciar sistema +SUSPEND_SYS=Suspender sistema +NO_INTERNET=No se ha podido contactar con el servidor +BE_SURE_INTERNET=Asegurese de que Internet esta activado +SFO_OP_FAILED=¡Fallo de la operacion OFS! +ICON_OP_FAILED=¡Fallo la operacion de icono! +GAME_DUMP_FAILED=¡El volcado del juego ha fallado! +GAME_DUMP_FAILED2=Compruebe si hay problemas en el disco +UNABLE_TO_TRANFER=¡La transferencia ha fallado! +FTP_START_NOTIFY=FTP Plugin Iniciado +FTP_STOP_NOTIFY=FTP Plugin Detenido +FTP_ERROR=se ha producido un error FTP +REDIRECT_TURNED_ON=Redireccion del menu Inicio activada +REDIRECT_TURNED_OFF=Redireccion del menu Inicio desactivada +APP_DB_REBUILT=La base de datos de la aplicacion ha sido reparada +APP_DB_ERROR=¡La reparacion de la base de datos de la aplicacion ha fallado! +TTF_SUCCESS_NOTIFY=Se ha cargado el nuevo TTF +TTF_ERROR_NOTIFY=Fallo al cargar fuente TTF +TTF_ERROR_NOTIFY2=Cargado TTF por defecto +SETTING_APPLIED=Se ha aplicado la configuracion +PKG_INST_FAILED=¡Fallo la instalacion de PKG! +PKG_INST_FAILED1=Por favor, confirme el PKG +PKG_INST_SUCCESS=PKG instalado correctamente +USB_NOTIFY=Dispositivo USB insertado +USB_NOTIFY1=El USB esta listo para su uso +NOT_ENOUGH_FREE_SPACE=No hay suficiente espacio libre +UNHIDE_NOTIFY=Visibilidad cambiada +UNHIDE_SUCCESS_NOTIFY=La aplicacion esta ahora visible +HIDE_SUCCESS_NOTIFY=La aplicacion ya esta oculta +UNHIDE_FAILED_NOTIFY=No se ha podido cambiar la visibilidad +FAILED_TO_CLOSE=Fallo al cerrar la aplicacion +OPT_NOT_PERMITTED=Opcion no disponible aqui +TITLE_ID_NOT_RIGHT=Titulo ID NO Valido +TILE_ID_CHANGED=Cambio de ID de hilera +TITLE_ID_FAILD=¡No se ha podido cambiar el ID del titulo! +PARAM_PATH_FAILED=¡El parcheo del SFO ha fallado! +TITLE_CHANGED=Cambio de titulo de la aplicacion +FAILED_TITLE_CHANGE=Fallo al cambiar el titulo del juego +CONSIDER_SUPPORT=¡Apoyanos en Ko-fi! +DUMPER_PATH_NO_AVAIL=¡La ruta de descarga no es valida! +FS_SEL_FAILED=Fallo al abrir el selector de archivos +FS_SEL_ERROR1=No se puede abrir el selector FS +FS_SEL_ERROR2=Selector ya iniciado +ICON_CHANGED_SUCCESS=¡Icono cambiado! +ICON_CHANGE_FAILED=Fallo al cambiar el icono +PNG_NOT_VAILD=¡PNG no es valido! +FAILED_TO_COPY=Fallo de copia +FONT_CHANGED_SUCCESS=¡Fuente cambiada! +NEW_FONT_STRING=Fuente nueva +DUMPER_PATH_UPDATED=¡Ruta de descarga actualizada! +NEW_PATH_STRING=Nueva ruta +PKG_IS_INSTALLING=PKG se esta instalando... +PKG_IS_INSTALLED=La instalacion ha finalizado +VAR_IS_INSTALLED=ya esta instalado +FS_CONTROL_BUTTON_1=Introducir carpeta +FS_CONTROL_BUTTON_2=Carpeta anterior +FS_CONTROL_BUTTON_3=Cancelar/Salir +FS_CONTROL_BUTTON_4=Seleccionar archivo +FS_CONTROL_BUTTON_4_1=Seleccionar carpeta +FS_CONTROL_BUTTON_5=Cambiar paneles de archivos +FS_CONTROL_BUTTON_6=Nueva Carpeta +FS_CONTROL_BUTTON_7=Copiar/Pegar +FOLDER_MADE_SUCCESS=¡Carpeta creada! +FOLDER_MAKE_FAIL=¡Fallo en la creacion de la carpeta! +OP_CANNED=¡Operacion cancelada! +OP_CANNED_1=No se han aplicado cambios +MOVE_APP_OPT=Mover a USB +MOVE_APP_OPT_1=Mover aplicacion/juego +MOVE_APP_OPT_2=Mover DLC +MOVE_APP_OPT_3=Mover parche +RESTORE_APP_OPT=Restaurar desde USB +RESTORE_APP_OPT_1=Restaurar aplicacion/juego +RESTORE_APP_OPT_2=Restaurar DLC +RESTORE_APP_OPT_3=Restaurar parche +RETAIL=Minorista +RESTORE_SUCCESS=Restauracion correcta +MOVE_SUCCESSFULLY=Movido con exito +RESTORE_FAILED=Fallo de restauracion +MOVE_FAILED=Fallo en el movimiento +APP_MOVE_NOTIFY=Aplicacion movida con exito +SELECT_A_FOLDER=Seleccione una carpeta para continuar +SELECT_A_FILE=Seleccione un archivo para continuar +APP_MOVING_MESSAGE=La aplicacion se traslada a +APP_NOT_MOVED=Nada que restaurar +BACKUP_FPKG=Backup FPKG +COPYING_FPKG=Copiando FPKG, Por favor espere... +FPKG_COPY_SUCCESS=FPKG Copiado con exito +FPKG_COPY_FAILED=¡FPKG no ha podido copiar! +EXT_MOVE_NOT_SUPPORTED=¡No se admiten aplicaciones externas! +PATCH_MOVE_NOTIFY=Parche movido con exito +DLC_MOVE_NOTIFY=DLC Movido con exito +COPYING_FILE=Copiando archivo, por favor espere... +RESTORE_INFO_TEXT=Restaurar aplicaciones digitales movidas con Itemzflow +MOVE_INFO_TEXT=Mover contenido descargado digitalmente a un USB +OPTION_DOESNT_SUPPORT_DISC=Esta opcion no admite discos +BACKUP_FPKG_INFO=Backup del (FPKG) para reinstalarlo mas tarde +GAME_CONTROL_INFO=Controles del juego: Reanudar o cerrar la aplicacion +CLOSE_OPEN_APP_INFO=Cierra el juego o la aplicacion abierta en ese momento +GAME_CONTROLS=Controles del juego +RESTORE_GAME_INFO=Importar y Resignar un Guardar Descifrado (Carpeta) del Almacenamiento +BACKUP_GAME_INFO=Backup de TODAS las partidas guardadas del juego +DELETE_GAME_INFO=Eliminar TODAS las partidas guardadas de este juego +UNINSTALL_PATCH_INFO=Desinstalar cualquier parche instalado para este juego +UNINSTALL_GAME_INFO=Desinstalar juego/App y todo lo que contiene +SORT_RANDOM_INFO=Ordenar aplicaciones/juegos aleatoriamente +SORT_ALPHA_NAME_INFO=Ordenar aplicaciones/juegos por nombre alfabeticamente +SORT_ALPHA_TID_INFO=Ordenar alfabeticamente aplicaciones/juegos por ID de titulo +THE_ITEM_IS_ALREADY_BP=El elemento seleccionado ya tiene copia de seguridad +IF_PKG_INSTALLER=Instalador de paquetes IF +IF_PKG_INSTALLER_INFO=Instalar PKGs desde una unidad USB +THEME_INSTALLER=Instalador de temas +THEME_NOT_VAILD=¡El tema no es valido! +THEME_INSTALLER_INFO=Instalar temas IF desde una unidad USB +THEME_INSTALL_SUCCESS=¡Tema instalado y aplicado! +THEME_FAILED_TO_APPLY=No se ha podido aplicar el tema +FOUND_SAVE_MESSAGE=Guardado del juego encontrado +FOUND_SAVE_MESSAGE_OVER_1=Guardados encontrados, Mostrando 1... +USER_LANG=Usuario +NO_SAVES_LANG=Sin guardados +DOWNLOAD_COVERS=¿Desea buscar y/o descargar caratulas ahora? +LOADING_GAME_LIST=Cargando lista de juegos ... +RESTORE_NOTICE=Al restaurar se borraran todos los DLC y datos de guardado de este juego. +INSTALLING_THEME=Instalacion y actualizacion del tema... +RESTART_STR=Inicio +SHUTDOWN_STR=Apagado +SUSPEND_STR=Suspender +ERROR_POWER_CONTROL=Error al ajustar el nivel de potencia +POWER_CONTROL_INFO=Opciones de energia de la consola +USB_DISCONNECTED=¡USB desconectado! +USB_DISCONNECTED1=Dispositivo USB desconectado +REINSTALL_APP_CONFIRMATION=Esta aplicacion ya esta instalada, ¿desea reinstalarla? (Se borraran todos los datos del juego) +THEME_RESET=Se ha establecido el tema por defecto +NO_DLC_AVAIL=No hay DLC disponible +NO_PATCH_AVAIL=No hay parches disponibles +RELAUCHING_IN_5=Recarga SI en 5 segundos... +CREATE_CUSTOM_DIR=Escriba un nuevo nombre de carpeta +FETCH_STATS=Buscando estadisticas de la aplicacion... +STATS_MINS=Minutos jugados +STATS_HOURS=Hora(s) +STATS_DAYS=Dia(s) +NO_STATS_AVAIL=No hay estadisticas de aplicacion disponibles +SAVE_OP_ON_GOING=La operacion de guardado esta en curso, por favor espere... +NO_UPDATE_FOUND=¡No se han encontrado actualizaciones de ItemzFlow! +IF_UPDATE_FAILD=¡No se ha podido instalar la actualizacion de ItemzFlow! +NO_UPDATE_FOUND_INFO=¿Esta habilitado Internet? +CHECH_UPDATE_IN_PROGRESS=Buscando actualizaciones... +CHECK_UPDATE_INFO=Comprobar actualizaciones de Itemzflow (actualizacion OTA) +PSV_MENU=Configuracion de ahorro de energia +EJECT_DISK=Expulsar disco +EJECT_DISK_ERROR=Error expulsando disco +EJECT_DISK_SUCCESS=Disco expulsado correctamente +NO_DISC_INSERTED=No hay disco +OVERWRITE_SAVE=¿Desea sobrescribir el guardado actual? +DUMPER_CANCELLED=La operacion de volcado se ha cancelado +REBUILDING_FOR_FPKG=Reconstruccion de la base de datos para los FPKG +CURRENT_APP=Aplicacion actual +TOTAL_NUM_OF_APPS=Numero total de aplicaciones +NUMB_OF_FIXED_APPS=Numero de aplicaciones fijas +NOT_FIXED=No fijo +LAUNCH_FAILED_BC_NOT_FOUND=El lanzamiento ha fallado porque no se ha encontrado la aplicacion en la base de datos de aplicaciones de PS4. +CONFIRMATION_2=¿Desea añadir esta aplicacion a la base de datos de PS4? +IF_LAUNCH_TROUBLESHOOTER=IF Lanzar solucionador de problemas +GAME_INSERT_SUCCESSFUL=Agregado a la base de datos +GAME_INSERT_FAILED=¡No se ha podido añadir la aplicacion a la base de datos de PS4! +FIX_BROKEN_SFO_DB=El lanzamiento ha fallado porque la informacion de la aplicacion en la base de datos de PS4 esta dañada. +CONFIRMATION_3=¿Desea intentar repararlo? +REPAIR_ATTEMPTED=¡Reparacion Intentada! +REPAIR_ATTEMPTED1=Intentar iniciar de nuevo +PLACEHOLDER=Asignatario de posicion +PLACEHOLDER_NOT_ENTER=Los marcadores de posicion NO son interactivos +NO_PATCHES=No se han encontrado parches. +PATCH0_APPLIED=Parche aplicado: +PATCH1_APPLIED=Parches aplicados: +SUSPEND_FAILED=Fallo de suspension critica +DAEMON_SUSPEND_FAILED=Fallo en la activacion de la suspension critica de Daemon +NO_PATCH_SELECTED=Sin parche seleccionado +NO_APP_OPENED_STR=La aplicacion no esta abierta +PATCH_NUM=Parche +PATCH_GAME_TITLE=Titulo del juego del parche: +PATCH_NAME=Nombre del parche: +PATCH_APP_VER=Version de la aplicacion: +PATCH_AUTHOR=Autor del parche: +PATCH_NOTE=Nota del parche: +PATCH_VER=Version del parche: +PATCH_ENABLED=Parche activado: +PATCH_SET0=Parche desactivado: +PATCH_SET1=Parche activado: +PATCH_DL_QUESTION=¿Desea descargar/actualizar la base de datos de parches? +PATCH_DL_QUESTION_NO=No se descargara ningun parche. +PATCH_DL_QUESTION_YES=Descargando base de datos de parches... +PATCH_DL_COMPLETE=Base de datos de parches descargada correctamente. +BUTTON_PATCH_TRI_INFO=Descargar/actualizar base de datos de parches +BUTTON_PATCH_SQUARE_INFO=Ver detalles del parche +CHANGE_CATEGORY=Cambiar categoria +SHOWING_CATEGORY=Categoria de presentacion +RETAIL_GAMES=Juegos al por menor +GAMES=Juegos +HOMEBREW=Homebrew +FPKG_STR=FPKGs +NONE=Ninguna +NO_TRAINERS=No se han encontrado entrenadores +UPDATED_CATEGORY=¡Categoria actualizada! +INC_CAT=Incluido con categoria +CAT_REBUILD_WARNING=La reconstruccion con una categoria seleccionada solo reconstruira los juegos de esa categoria. ¿Desea continuar? +RESET_CAT=Borrar categoria +NO_APPS_FOUND=¡No se han encontrado aplicaciones! +NON_EBOOT_NOT_SUPPORTED1=Encontrado parche de eboot no inicial para +NON_EBOOT_NOT_SUPPORTED2=¡aun no es compatible! +SKIPPING_MSG=Saltando... +#NEW STRINGS +EXTRA_SETTING_1=Descargar portadas +EXTRA_SETTING_2=Restablecer personalizaciones +EXTRA_SETTING_3=Reflejos +EXTRA_SETTING_4=Cambiar imagen de fondo +EXTRA_SETTING_5=Mensaje de portada de inicio +EXTRA_SETTING_6=Cambiar fuente +ADVANCED_SETTINGS=Configuración avanzada +SETTINGS_5=Reconstruir base de datos FPKG +HIDE_ADVANCED_SETTINGS=Ocultar configuración avanzada +X_DL_COVER=Presiona X para descargar carátulas +FAILED_TO_DOWNLOAD_COVER=Error al descargar carátulas +COVERS_UP_TO_DATE=¡Las portadas ya están actualizadas! +IMAGE_APPLIED=¡Imagen aplicada! + +[DUMPER] +DUMP_INFO=Informacion del dump +APP_NAME=Nombre de la aplicacion: +TITLE_ID=ID_TiTULO: +DUMPER_SC0=Dump del contenido de sc0(sce_sys) ... +DUMPING_TROPHIES=Dumpeando trofeos ... +CREATING_GP4=Creando GP4 ... +DEC_BIN=Desencriptando Bin +DEL_SEM=Borrarndo Semaforo ... +EXT_PATCH=Extraccion de archivos de parches de juegos +EXT_GAME_FILES=Extraccion de los archivos del juego base +PROCESSING=Procesamiento diff --git a/App-Media-Assets/langs/5/lang.ini b/App-Media-Assets/langs/5/lang.ini new file mode 100644 index 0000000..4df773c --- /dev/null +++ b/App-Media-Assets/langs/5/lang.ini @@ -0,0 +1,485 @@ +#strings for loader +[LOADER] +LOADER_FATAL=ERRORE! +FATAL_JB=Jailbreak fallito con il codice +FATAL_REJAIL=ERRORE rejail_multi non riuscito con il codice +SWU_ERROR=[Errore SWU] L'aggiornamento è stato revocato per utilizzare questo aggiornamento devi disattivare l'avvio protetto +RSA_LOAD=Verifica di RSA Sig... +RSA_FAILED=Verifica RSA non riuscita con codice di errore +SECURE_FAIL=Secure Boot è abilitato ma non è stato possibile scaricare il file Sig dalla CDN +LOADER_ERROR=Il caricatore ItemzFlows ha riscontrato un errore +MORE_INFO=Per maggiori informazioni controlla: /mnt/usb0/itemzflow/loader.log Ora l'app verrà chiusa +INI_FAIL=Impossibile creare il file INI +STR_NOT_FOUND=Stringa non trovata + +#strings IF +[ITEMZFLOW] +RSA_LOAD=Verifica RSA Sig... +RSA_FAILED=Verifica RSA non riuscita con codice di errore +OPT_UPDATE=È disponibile un aggiornamento, vuoi aggiornare ora? +SORT_OPTS=Ordina le app +STR_NOT_FOUND=Stringa non trovata +ITEMZ_SETTINGS=Impostazioni Itemzflow +RESORT=Resort Giochi/Apps +MISSING_EBOOT=[Interno] eboot.bin manca da /data/app/ o /hostapp/app/ +MISSING_SFO= [Interno] param.sfo manca da /data/app/sce_sys o /hostapp/app/sce_sys +CORRUPT_SFO=il param.sfo è danneggiato +ON2=ON +OFF2=OFF +TRUE2=Vero +FALSE2=Falso +STORAGE=Storage +ITEMZ_VER=Versione Itemzflow +SYS_VER=Versione di Sistema +OTHER=Altro +INSTALLING=Installazione in corso... +SETTINGS=Impostazioni +ID2=Id +NAME2=Nome +DISC2=Disco +INSTALL_FAILED=Installazione non riuscita con il codice +INSTALL_OF=Installazione di +COMPLETE=è ora completo! +FAILED_W_CODE=ha fallito con il codice +FATAL_ERROR=Errore Fatale +PRESS_OK_CLOSE=Chiudi il programma e dopo premi OK +WARNING2=Attenzione +FAILED_TTF=Caricamento TTF non riuscito da +SWITCH_TO_EM=Passaggio a Incorporato +INI_ERROR=IMPOSSIBILE trovare/aprire il file INI +FAILED_DAEMON=IF Daemon fallito +DAEMON_OFF=L'avvio automatico di Daemon è disattivato +DAEMON_OFF2=Ciò potrebbe causare il mancato funzionamento di alcune cose +DL_CACHE=Download e memorizzazione nella cache dei file del sito Web... +PIG_FAIL=Impossibile caricare Piglet (retail) con +NO_USB=Nessuna USB rilevata, uscita in corso... +DUMP=DOPO l'avvio del gioco quando premi OK attendi qualche secondo, quindi torna allo Store e il gioco inizierà a scaricarsi NON CHIUDERE IL GIOCO O LO STORE FINO A QUANDO IL DUMP NON È COMPLETO +UNINSTALL_UPDATE=Aggiornamento del gioco disinstallato con successo +UNINSTAL_UPDATE_FAILED=Disinstallazione aggiornamento gioco non riuscita +UNINSTALL_SUCCESS=Gioco disinstallato con successo, l'elenco delle app installate verrà ricaricato +UNINSTALL_FAILED=Disinstallazione del gioco non riuscita +COMING_SOON=Prossimamente +RELOAD_IAPPS=L'elenco delle app installate verrà ora ricaricato +APP_REQ=Questo Game Launcher ha un requisito di min. 4 App Per utilizzarla è necessario installare: +MORE_APPS=Più app +DOWNLOADING_COVERS=Download delle cover dal server +DL_FAILED_W=Download fallito con StatusCode: +STR_TOO_LONG=La stringa è troppo lunga o non VALIDA Inserisci una voce valida +INVAL_PATH=Percorso NON VALIDO! entrare in un percorso valido +INVAL_TTF=Percorso .ttf NON VALIDO. Assicurati che il file ext sia .ttf +CACHE_CLEARED=Pulite/cancellate con successo tutte le immagini memorizzate nella cache +CLEARING_CACHE=Cancellazione dei contenuti memorizzati nella cache +CACHE_FAILED=Cancellazione del contenuto memorizzata nella cache non riuscita +ITEMZ_FEATURE_DISABLED=questa funzione è disabilitata, MOTIVO: ItemzFlow Daemon NON è connesso +SAVE_ERROR=Salva errore +SAVE_SUCCESS=Salvato con successo +DL_FAILED2=Download fallito con il codice +OBJ_EXPECTED=Oggetto previsto +CANT_OPEN=Impossibile aprire +APP_DIED=L'app è morta con il codice di uscita +PKG_TEAM=Se continua, contatta il team PKG-Zone +FATAL_DUMP_ERROR=Il dump del gioco non è riuscito, l'app verrà ricaricata. Premi OK per continuare +DUMP_OF=Dump di +COMPLETE_WO_ERRORS=è completo senza errori!: +DUMP_FAILED=Completato con problemi. NON tutti i file sono stati scaricati! Assicurati che il tuo exploit hoster abbia le patch MMAP abilitate +EXCEED_LIMITS=Il numero di pagine supera i limiti dello STORE! +DL_ERROR_PAGE=Impossibile scaricare la pagina: +ERROR_DL_ASSETS=Impossibile scaricare la risorsa: +APP_NOT_FOUND=L'app NON è stata trovata +APP_OPENED=L'app è già aperta +APP_CLOSED=App chiusa +APP_UNL=L'app NON è avviabile +ID_NOT_VAILD=TITLE_ID NON VALIDO +LAUNCH_ERROR=L'avvio dell'app non è riuscito con codice di errore +RELOAD_LIST=Ricarica elenco app in corso... +SEARCHING=Ricerca in corso.... +WAITING_FOR_DAEMON=Aspettando la risposta di benvenuto da DAEMON (max 1 min) +TRYING_TO_DL=Sto cercando di scaricare la cover per +DL_COVERS=Download delle cover dal server +STARTING_DUMPER=Avvio del dumper... +UU=Disinstalla aggiornamento +UG=Disinstalla gioco +SETTINGS_1=Percorso dumper +SETTINGS_2=Verifica aggiornamenti +SETTINGS_3=Ordina app per +SETTINGS_4=Imposta come dashboard predefinita +SETTINGS_6=Programma di installazione del tema +SETTINGS_7=Percorso MP3 di sfondo +SETTINGS_8=Mostra i controlli dei pulsanti +SETTINGS_9=Apri il menu PS4 +SETTINGS_10=Installatore dei PKG +SETTINGS_11=Controlli alimentazione console +SETTINGS_12=Salva impostazioni +NA_SORT1=Casuale +TID_ALPHA_SORT1=Alfabetico per ID titolo +TITLE_ALPHA_SORT1=Alfabetico in base al nome dell'app +UNINSTALL_GAME1=Disinstalla Gioco/app +UNINSTALL_PATCH1=Disinstalla patch +UNINSTALL_DLC1=Disinstalla il DLC +UNINSTALL_NOTE=Seleziona per scegliere un'opzione di disinstallazione +SEL_DUMP_ALL1=Scarica TUTTO +SEL_BASE_GAME1=Scarica solo il gioco base +SEL_GAME_PATCH1=Scarica solo patch +SEL_REMASTER1=Scarica solo la rimasterizzazione +SEL_DLC1=Scarica solo DLC +LAUNCH_GAME=Lancia +DUMP_1=Dump +TRAINERS=Trainers +UNINSTALL=Disinstalla +HIDE_APP=Nascondi App +CHANGE_ICON=Cambia Icona (PNG) +CHANGE_APP_NAME=Cambia nome dell' App +CHANGE_TID=Change Title ID +NAME_INFO=Cambia il nome dell'app PS4 nell'XMB di PS4 (app.db) +IF_NOT_EFFECTED=Nota: non ha effetto su Itemzflow +TID_INFO=Modifica l'ID del titolo delle app in app.db +ICON_INFO=Digitare un percorso per una nuova Icon0 personalizzata per l'app selezionata +LAUNCH_INFO=Avvia il gioco/l'app selezionate +TRAINER_INFO=Recupera i Trainer(s) per il gioco selezionato +HIDE_INFO=Nasconde il gioco/l'app nell'app.db di PS4 +DUMP_OPT_INFO=Seleziona per scegliere un'opzione di dumping +PLAYING_SINCE=Playing Since +PNG_NOTE=Note: SOLO PNG DA 512x512! +SUSPEND_IF=Nota: Itemzflow sarà sospeso +HIDE_OPT_INFO=Nota: puoi anche nasconderlo da Itemzflow tramite il menu Impostazioni +SEL_DUMP_ALL_INFO=Scarica (tutto) il gioco e tutti i DLC e le patch disponibili +SEL_BASE_GAME_INFO=Scarica solo il gioco base +SEL_GAME_PATCH_INFO=Scarica solo la patch di gioco +SEL_REMASTER_INFO=Dump disponibili solo Remaster(s) +SEL_DLC_INFO=Scarica solo DLC disponibili +SETTINGS=Impostazioni +FTP_NOT_RUNNING=FTP non in esecuzione (OFF) +FTP_RUNNING=FTP è in esecuzione (ON) +DUMPER_PATH_DESC=Seleziona un percorso di dump personalizzato +REBUILD_DB_OPTION_DESC=Ricostruisci il database delle app PS4 (app.db) +SORT_BY_OPTION_DESC=Seleziona come Itemzflow ordina le app (rallenta l'apertura) +HOME_MENU_OPTION_DESC=Reindirizza il pulsante Home di PS a questa app +FTP_SERVICE_OPTION_DESC=Attiva o disattiva FTP temporaneamente +TTF_OPTION_DESC=Seleziona un percorso per il carattere TTF personalizzato +BACKGROUND_MP3_OPTION_DESC=Seleziona un MP3 personalizzato a 48 Hz da riprodurre in background +SHOW_BUTTON_OPTION_DESC=Mostra o nascondi i controlli dei pulsanti +OPEN_DEBUG_MENU_DESC=Apre il Debug o il menu Impostazioni della PS4 +RDB=Ricostruisci database FPKG +RELOAD_APPS=Ricarica le app +#BUTTON INFO +BUTTON_X_INFO=Seleziona/Conferma +BUTTON_O_INFO=Indietro/Cancella +BUTTON_LEFT_RIGHT_INFO=Prec./Avanti +BUTTON_UP_DOWN_INFO=Su/Giù +BUTTON_TRIANGLE=Ricarica app +BUTTON_CLOSE=Esci da ItemzFlow +BUTTON_CONFIRM_CLOSE=Conferma chiusura +CLOSE_GAME=Chiudi partita aperta +FAILED_MENU_OPEN=Impossibile aprire il menu +ERROR_CODE=Codice di errore +SELECT_INTERACT=Premi X per interagire +GAME_SAVE_OPTS=Opzioni di salvataggio del gioco +BACKUP_SAVE=Esegui il backup di tutti i salvataggi +IMPORT_SAVE=Importa Salvataggi +SAVE_DELETE=Elimina tutti i salvataggi +SHOW_APP=Scopri +HIDE_APP_OPT=Visibilità app +PS4_REBOOT_REQ=Riavvio richiesto per le modifiche +PLEASE_WAIT=Attendere prego... +APPS_RELOADED=App ricaricate +APPS_RELOADED_2=Elenco delle app aggiornato +CON_DIS=Controller disconnesso +CON_DIS_2=Ricollega il controller +REALLY_HOT=La PS4 è davvero calda! +REALLY_HOT_2=La PS4 è sopra i 90°C, considera di cambiare la pasta termica +NO_SAVES=Nessun salvataggio di gioco disponibile +CANT_FIND_SAVE=Impossibile trovare un salvataggio +SAVE_OPS_FAILED=Operazione di salvataggio fallita +FAILED_INI_SD=Impossibile inizializzare i dati di salvataggio +FAILED_MOUNT_SD=Impossibile montare il salvataggio +SD_SAVED=Salvataggio del gioco salvato su USB +SD_TRANSFER_FAIL=Impossibile trasferire il salvataggio +SD_DELETED=Salvataggio del gioco eliminato +CANT_DELETE_SD=Impossibile eliminare +DECRYPTED_SD=Impossibile trovare il salvataggio decrittografato +NO_AVAIL_SAVE=Nessun salvataggio disponibile +SAVE_IMPORTED=Salvataggio del gioco importato! +SAVE_IMPORT_2=Salva titolo +NO_USERID=Impossibile ottenere l'errore UserId +UNSUPPORTED_FS=Rilevato filesystem non supportato +RETAILO=Solo PS4 Retail +NO_GOLDHEN=Manca GoldHEN o ps4debug! +FAILED_SAVE_PATCHES=Impossibile applicare le patch di salvataggio! +UNSUPPORTED_FW=Versione firmware non supportata +MP3_PLAYING=MP3 in riproduzione +MP3_LOADED=MP3 caricato +FAILED_MP3=MP3 non è stato caricato +TRAINER_LOADED=Trainer caricato +TRAINER_FAILED=Impossibile caricare il trainer +TRAINER_ESRCH=Nessun Trainer Trovato +GAME_LAUCNHED=Il gioco è stato avviato +GAME_KILLED=Il gioco è stato bloccato +GAME_RESUME=Riprendi la partita +PLUG_MNG=Gestione Plugin +PLUG_LOADED=Plugin caricato +PLUG_FAILED=Impossibile caricare il Plugin +PLUG_ERROR=Errore del Plugin +LANG_NOT_SUPPORTED=ItemzFlow non riconosce il tuo linguaggio +ENG_LOADED=Caricamento Inglese in corso... +IF_UPDATE_SUCESS=Itemzflow è stato aggiornato! +FAILED_ICON=Impossibile modificare l'icona +DAEMON_FAILED_NOTIFY=ItemzDaemon non è riuscito a connettersi +DAEMON_FAILED_NOTIFY2=Alcune funzionalità saranno disabilitate! +PWR_OFF_SYS=Spegnere il sistema +RESTRT_SYS=Riavvia il sistema +SUSPEND_SYS=Sospendi sistema +NO_INTERNET=Impossibile contattare il server +BE_SURE_INTERNET=Assicurati che Internet sia abilitato +SFO_OP_FAILED=Operazione SFO fallita! +ICON_OP_FAILED=Operazione icona fallita! +GAME_DUMP_FAILED=Il dump del gioco è fallito! +GAME_DUMP_FAILED2=Controlla problemi sul disco +UNABLE_TO_TRANFER=Trasferimento fallito! +FTP_START_NOTIFY=Plugin FTP avviato +FTP_STOP_NOTIFY=Plugin FTP interrotto +FTP_ERROR=Si è verificato un errore FTP +REDIRECT_TURNED_ON=Reindirizzamento menu principale abilitato +REDIRECT_TURNED_OFF=Reindirizzamento menu principale disabilitato +APP_DB_REBUILT=Il DB dell'app è stato riparato +APP_DB_ERROR=La riparazione del DB dell'app non è riuscita! +TTF_SUCCESS_NOTIFY=Il nuovo TTF è stato caricato +TTF_ERROR_NOTIFY=Impossibile caricare il carattere TTF +TTF_ERROR_NOTIFY2=TTF predefinito caricato +SETTING_APPLIED=L'impostazione è stata applicata +PKG_INST_FAILED=Installazione PKG fallita! +PKG_INST_FAILED1=Convalida il PKG cortesemente +PKG_INST_SUCCESS=PKG installato correttamente +USB_NOTIFY=Dispositivo USB inserito +USB_NOTIFY1=USB pronto all'uso +NOT_ENOUGH_FREE_SPACE=Spazio libero insufficiente +UNHIDE_NOTIFY=Visibilità modificata +UNHIDE_SUCCESS_NOTIFY=L'app è ora visibile +HIDE_SUCCESS_NOTIFY=L'app ora è nascosta +UNHIDE_FAILED_NOTIFY=Impossibile modificare la visibilità +FAILED_TO_CLOSE=Chiusura dell'app fallita +OPT_NOT_PERMITTED=Opzione non disponibile qui +TITLE_ID_NOT_RIGHT=ID titolo NON valido +TILE_ID_CHANGED=ID intestazione modificato +TITLE_ID_FAILD=Impossibile modificare l'ID del titolo! +PARAM_PATH_FAILED=Patch SFO fallito! +TITLE_CHANGED=Titolo app cambiato +FAILED_TITLE_CHANGE=Impossibile modificare il titolo del gioco +CONSIDER_SUPPORT=Sostienici su Ko-fi! +DUMPER_PATH_NO_AVAIL=Il percorso del dumper non è valido! +FS_SEL_FAILED=Impossibile aprire il selettore di file +FS_SEL_ERROR1=Impossibile aprire il Selettore FS +FS_SEL_ERROR2=Selettore già avviato +ICON_CHANGED_SUCCESS=Icona cambiata! +ICON_CHANGE_FAILED=Cambiamento icona fallito +PNG_NOT_VAILD=PNG non valido! +FAILED_TO_COPY=Impossibile copiare +FONT_CHANGED_SUCCESS=Carattere cambiato! +NEW_FONT_STRING=Nuovo carattere +DUMPER_PATH_UPDATED=Percorso dumper aggiornato! +NEW_PATH_STRING=Nuovo percorso +PKG_IS_INSTALLING=Installazione PKG in corso... +PKG_IS_INSTALLED=L'installazione è stata completata +VAR_IS_INSTALLED=è ora installato +FS_CONTROL_BUTTON_1=Inserisci cartella +FS_CONTROL_BUTTON_2=Cartella precedente +FS_CONTROL_BUTTON_3=Annulla/Esci +FS_CONTROL_BUTTON_4=Seleziona file +FS_CONTROL_BUTTON_4_1=Seleziona cartella +FS_CONTROL_BUTTON_5=Cambia pannello file +FS_CONTROL_BUTTON_6=Nuova cartella +FS_CONTROL_BUTTON_7=Copia/Incolla +FOLDER_MADE_SUCCESS=Cartella creata! +FOLDER_MAKE_FAIL=Creazione cartella fallita! +OP_CANNED=Operazione annullata! +OP_CANNED_1=Nessuna modifica applicata +MOVE_APP_OPT=Sposta su USB +MOVE_APP_OPT_1=Sposta app/gioco +MOVE_APP_OPT_2=Sposta DLC +MOVE_APP_OPT_3=Sposta Patch +RESTORE_APP_OPT=Ripristina da USB +RESTORE_APP_OPT_1=Ripristina app/gioco +RESTORE_APP_OPT_2=Ripristina DLC +RESTORE_APP_OPT_3=Ripristina patch +RETAIL=Retail +RESTORE_SUCCESS=Ripristino riuscito +MOVE_SUCCESSFULLY=Spostato con successo +RESTORE_FAILED=Ripristino fallito +MOVE_FAILED=Impossibile spostare +APP_MOVE_NOTIFY=App spostata con successo +SELECT_A_FOLDER=Seleziona una cartella per continuare +SELECT_A_FILE=Seleziona un file per continuare +APP_MOVING_MESSAGE=L'app si sta spostando su +APP_NOT_MOVED=Niente da ripristinare +BACKUP_FPKG=Backup FPKG +COPYING_FPKG=Copia FPKG in corso, attendere prego... +FPKG_COPY_SUCCESS=FPKG copiato con successo +FPKG_COPY_FAILED=Il FPKG non è riuscito a copiare! +EXT_MOVE_NOT_SUPPORTED=App esterne non supportate! +PATCH_MOVE_NOTIFY=Patch spostata con successo +DLC_MOVE_NOTIFY=DLC spostato con successo +COPYING_FILE=Copia file, attendere prego... +RESTORE_INFO_TEXT=Ripristina le app digitali spostate con Itemzflow +MOVE_INFO_TEXT=Sposta il contenuto scaricato digitalmente su una USB +OPTION_DOESNT_SUPPORT_DISC=Questa opzione non supporta i dischi +BACKUP_FPKG_INFO=Effettua il backup del FPKG dei giochi per reinstallarlo in un secondo momento (solo FPKG) +GAME_CONTROL_INFO=Comandi di gioco: riprendi o chiudi l'app +CLOSE_OPEN_APP_INFO=Chiudi il gioco o l'app attualmente aperti +GAME_CONTROLS=Comandi di gioco +RESTORE_GAME_INFO=Importa e risigna un salvataggio (cartella) decrittografato dalla memoria +BACKUP_GAME_INFO=Decripta ed esegui il backup di TUTTI i salvataggi di gioco per questo gioco +DELETE_GAME_INFO=Elimina TUTTI i salvataggi di gioco per questo gioco +UNINSTALL_PATCH_INFO=Disinstalla eventuali patch installate per questo gioco +UNINSTALL_GAME_INFO=Disinstalla il gioco/l'app e tutto ciò che è collegato +SORT_RANDOM_INFO=Ordina app/giochi in modo casuale +SORT_ALPHA_NAME_INFO=Ordina app/giochi per nome in ordine alfabetico +SORT_ALPHA_TID_INFO=Ordina app/giochi per ID titolo in ordine alfabetico +THE_ITEM_IS_ALREADY_BP=L'elemento selezionato è già stato sottoposto a backup +IF_PKG_INSTALLER=Programma di installazione del pacchetto IF +IF_PKG_INSTALLER_INFO=Installa PKG da un'unità USB +THEME_INSTALLER=rogramma di installazione del tema IF +THEME_NOT_VAILD=Il tema non è valido! +THEME_INSTALLER_INFO=Installa i temi IF da un'unità USB +THEME_INSTALL_SUCCESS=Tema installato e applicato! +THEME_FAILED_TO_APPLY=Il tema non è stato applicato +FOUND_SAVE_MESSAGE=Salvataggio/i di gioco trovati +FOUND_SAVE_MESSAGE_OVER_1=Salvataggio/i di gioco trovati, Visualizzazione di 1... +USER_LANG=Utente +NO_SAVES_LANG=Nessun salvataggio +DOWNLOAD_COVERS=vuoi controllare e/o scaricare le cover ora? +LOADING_GAME_LIST=Caricamento elenco giochi in corso... +RESTORE_NOTICE=Il ripristino cancellerà tutti i DLC ei dati di salvataggio per questo gioco +INSTALLING_THEME=Installazione e convalida del tema... +RESTART_STR=Riavvia +SHUTDOWN_STR=Spegnimento +SUSPEND_STR=Sospendi +ERROR_POWER_CONTROL=Errore durante l'impostazione del livello di potenza +POWER_CONTROL_INFO=Opzioni risparmio energia della console +USB_DISCONNECTED=USB Disconnesso! +USB_DISCONNECTED1=Dispositivo USB scollegato +REINSTALL_APP_CONFIRMATION=Questa App è già installata vuoi reinstallarla? (Tutti i dati di gioco verranno eliminati!) +THEME_RESET=Il tema predefinito è stato impostato +NO_DLC_AVAIL=Nessun DLC disponibile +NO_PATCH_AVAIL=essuna patch disponibile +RELAUCHING_IN_5=Ricarica IF in 5 secondi.. +CREATE_CUSTOM_DIR=Digita un nuovo nome per la cartella +FETCH_STATS=Recupero delle statistiche dell'app in corso... +STATS_MINS=Minuti giocati +STATS_HOURS=Ora(e) +STATS_DAYS=Giorno(i) +NO_STATS_AVAIL=Nessuna statistica app disponibile +SAVE_OP_ON_GOING=L'operazione di salvataggio è in corso, attendere prego... +NO_UPDATE_FOUND=Nessun aggiornamento ItemzFlow trovato! +IF_UPDATE_FAILD=Installazione dell'aggiornamento ItemzFlow non riuscita! +NO_UPDATE_FOUND_INFO=Internet è abilitato? +CHECH_UPDATE_IN_PROGRESS=Verifica aggiornamenti in corso... +CHECK_UPDATE_INFO=Verifica aggiornamenti Itemzflow (aggiornamento OTA) +PSV_MENU=Impostazioni di risparmio energetico +EJECT_DISK=Espelli il disco +EJECT_DISK_ERROR=Errore durante l'espulsione del disco +EJECT_DISK_SUCCESS=Disco espulso con successo +NO_DISC_INSERTED=Nessun disco inserito +OVERWRITE_SAVE=Vuoi sovrascrivere il salvataggio corrente? +DUMPER_CANCELLED=L'operazione di dumping è stata annullata +REBUILDING_FOR_FPKG=Ricostruzione database per FPKG +CURRENT_APP=App attuale +TOTAL_NUM_OF_APPS=Numero totale di app +NUMB_OF_FIXED_APPS=Numero di app fixate +NOT_FIXED=Non fixate +LAUNCH_FAILED_BC_NOT_FOUND=Avvio fallito perché l'app non è stata trovata nel database delle app di PS4 +CONFIRMATION_2=Vuoi aggiungere questa app al database della PS4? +IF_LAUNCH_TROUBLESHOOTER=Avvia lo strumento IF di risoluzione dei problemi +GAME_INSERT_SUCCESSFUL=Aggiunto al database +GAME_INSERT_FAILED=Impossibile aggiungere l'app al database di PS4! +FIX_BROKEN_SFO_DB=L'avvio non è riuscito perché le informazioni sull'app nel database di PS4 sono danneggiate +CONFIRMATION_3=Vuoi tentare di ripararlo? +REPAIR_ATTEMPTED=Riparazione tentata! +REPAIR_ATTEMPTED1=Riprova ad avviare +PLACEHOLDER=Segnaposto +PLACEHOLDER_NOT_ENTER=I segnaposto NON sono interagibili +NO_PATCHES=Nessuna Patch Trovata. +PATCH0_APPLIED=Patch Applicata: +PATCH1_APPLIED=Patch Applicate: +SUSPEND_FAILED=Sospensione critica non riuscita +DAEMON_SUSPEND_FAILED=Daemon non ha attivato la sospensione critica +NO_PATCH_SELECTED=Nessuna patch selezionata +NO_APP_OPENED_STR=L'app non è aperta +PATCH_NUM=Patch +PATCH_GAME_TITLE=Patch Titolo del gioco: +PATCH_NAME=Nome patch: +PATCH_APP_VER=Versione applicazione patch: +PATCH_AUTHOR=Autore patch: +PATCH_NOTE=Nota sulla patch: +PATCH_VER=Versione patch: +PATCH_ENABLED=Patch abilitata: +PATCH_SET0=Patch disabilitata: +PATCH_SET1=Patch abilitata: +PATCH_DL_QUESTION=Vuoi scaricare/aggiornare il database delle patch? +PATCH_DL_QUESTION_NO=Nessuna patch verrà scaricata. +PATCH_DL_QUESTION_YES=Download del database delle patch in corso... +PATCH_DL_COMPLETE=Il database delle patch è stato scaricato correttamente. +BUTTON_PATCH_TRI_INFO=Scarica/aggiorna il database delle patch +BUTTON_PATCH_SQUARE_INFO=Visualizza i dettagli della patch +CHANGE_CATEGORY=Cambia Categoria +SHOWING_CATEGORY=Visualizza Categoria +RETAIL_GAMES=Giochi Retail +GAMES=Giochi +HOMEBREW=Homebrew +FPKG_STR=FPKG +NONE=Nessuno +NO_TRAINERS=Nessun Trainers Trovato +UPDATED_CATEGORY=Categoria AGGIORNATA! +INC_CAT=Compreso con Categoria +CAT_REBUILD_WARNING=La ricostruzione con una categoria selezionata ricostruirà solo i giochi di quella categoria. Vuoi continuare? +RESET_CAT=Cancella Categoria +NO_APPS_FOUND=Nessuna App TROVATA! +NON_EBOOT_NOT_SUPPORTED1=Trovata patch eboot non di avvio per +NON_EBOOT_NOT_SUPPORTED2=non è ancora supportato! +SKIPPING_MSG=Skipping in corso... +#NEW STRINGS +EXTRA_SETTING_1=Scarica cover +EXTRA_SETTING_2=Ripristina personalizzazioni +EXTRA_SETTING_3=Riflessioni +EXTRA_SETTING_4=Cambia immagine di sfondo +EXTRA_SETTING_5=Messaggio di cover di avvio +EXTRA_SETTING_6=Cambia carattere +ADVANCED_SETTINGS=Impostazioni avanzate +SETTINGS_5=Ricostruisci database FPKG +HIDE_ADVANCED_SETTINGS=Nascondi impostazioni avanzate +X_DL_COVER=Premi X per scaricare le cover +FAILED_TO_DOWNLOAD_COVER=Impossibile scaricare le cover +COVERS_UP_TO_DATE=Le cover sono ora aggiornate! +IMAGE_APPLIED=Immagine applicata! + +DISABLE_MUSIC=Disattiva musica +REBUILD_DB_OPT_1=Ricostruisci database interno +REBUILD_DB_OPT_2=Ricostruisci solo i DLC (incluso ext hdd) +REBUILD_DB_OPT_3=Riattiva ext. Contenuto +REBUILD_DB_DESC_1=Ripristina giochi/app/DLC XMB mancanti dalla memoria interna (Inc. App2usb) +REBUILD_DB_DESC_2=Ripristina i DLC di archiviazione interni ed estesi della XMB mancanti +REBUILD_DB_DESC_3=Riattiva giochi/app/DLC di archiviazione estesa che sono stati disabilitati +REBUILDING_ADDCONT=Ricostruzione DLC +ADDCONT_REBUILT= I DLC sono stati ricostruiti con successo! +ADDCONT_REACTED=Il contenuto esterno è stato riattivato con successo! +ADDCONT_REACT_FAILED=Errore, il contenuto esterno non è stato riattivato! +ADDCONT_FAILED=Fallimento, alcuni DLC non sono stati aggiunti! +SHUTDOWN_DAEMON=Arresta ed esci dal demone +DB_MOD_WARNING=Questo modificherà il database della PS4. QUALSIASI instabilità o problemi causati da ciò sono a discrezione degli utenti. +SIGN_IN_USER_NOTIF=Profilo registrato +MUSIC_Q=Musica in coda +PLAYING_NEXT=Riproduzione successiva +DELETING_GAME_FOLDER=Il dump esiste già, eliminando la cartella del gioco + +[DUMPER] +DUMP_INFO=Scarica info +APP_NAME=Nome app: +TITLE_ID=TITLE_ID: +DUMPER_SC0=Dumping del contenuto sc0(sce_sys) in corso... +DUMPING_TROPHIES=Dumping dei Trofei ... +CREATING_GP4=Creazione GP4 ... +DEC_BIN=Decrittografia Bin +DEL_SEM=Cancellazione Semaphore ... +EXT_PATCH=Estrazione dei file delle patch di gioco +EXT_GAME_FILES=Estrazione dei file del gioco di base +PROCESSING=Elaborazione in corso + +---------------------Translated into Italian by theheroGAC--------------------------------------------- diff --git a/App-Media-Assets/sce_sys/icon0.png b/App-Media-Assets/sce_sys/icon0.png new file mode 100644 index 0000000..c5c7fb2 Binary files /dev/null and b/App-Media-Assets/sce_sys/icon0.png differ diff --git a/App-Media-Assets/sce_sys/param.sfo b/App-Media-Assets/sce_sys/param.sfo new file mode 100644 index 0000000..a110f51 Binary files /dev/null and b/App-Media-Assets/sce_sys/param.sfo differ diff --git a/external/Jailbreak PRX/Makefile b/external/Jailbreak PRX/Makefile new file mode 100644 index 0000000..02e3e57 --- /dev/null +++ b/external/Jailbreak PRX/Makefile @@ -0,0 +1,70 @@ + +# Library metadata. +TARGET := jb.prx +# Libraries linked into the ELF. +LIBS := -lc -lc++ -lkernel + +# Additional compile flags. +#EXTRAFLAGS := + +# You likely won't need to touch anything below this point. + +# Root vars +TOOLCHAIN := $(OO_PS4_TOOLCHAIN) +PROJDIR := src +INTDIR := build + +# Define objects to build +CFILES := $(wildcard $(PROJDIR)/*.c) +CPPFILES := $(wildcard $(PROJDIR)/*.cpp) +COMMONFILES := $(wildcard $(COMMONDIR)/*.cpp) +OBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.o, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.o, $(CPPFILES)) $(patsubst $(COMMONDIR)/%.cpp, $(INTDIR)/%.o, $(COMMONFILES)) +STUBOBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.o, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.o.stub, $(CPPFILES)) $(patsubst $(COMMONDIR)/%.cpp, $(INTDIR)/%.o.stub, $(COMMONFILES)) + +# Define final C/C++ flags +CFLAGS := --target=x86_64-pc-freebsd12-elf -fPIC -funwind-tables -c $(EXTRAFLAGS) -isysroot $(TOOLCHAIN) -isystem $(TOOLCHAIN)/include -Iinclude +CXXFLAGS := $(CFLAGS) -isystem $(TOOLCHAIN)/include/c++/v1 -Iinclude +LDFLAGS := -m elf_x86_64 -pie --script $(TOOLCHAIN)/link.x --eh-frame-hdr -L$(TOOLCHAIN)/lib $(LIBS) $(TOOLCHAIN)/lib/crtlib.o + +# Create the intermediate directory incase it doesn't already exist. +_unused := $(shell mkdir -p $(INTDIR)) + +# Check for linux vs macOS and account for clang/ld path +UNAME_S := $(shell uname -s) + +ifeq ($(UNAME_S),Linux) + CC := clang + CCX := clang++ + LD := ld.lld + CDIR := linux +endif +ifeq ($(UNAME_S),Darwin) + CC := /usr/local/opt/llvm/bin/clang + CCX := /usr/local/opt/llvm/bin/clang++ + LD := /usr/local/opt/llvm/bin/ld.lld + CDIR := macos +endif + +$(TARGET): $(INTDIR) $(OBJS) + $(LD) $(INTDIR)/*.o -o $(INTDIR)/$(PROJDIR).elf $(LDFLAGS) + $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --lib=$(TARGET) --paid 0x3800000000000011 + +$(INTDIR)/%.o: $(PROJDIR)/%.c + $(CC) $(CFLAGS) -o $@ $< + +$(INTDIR)/%.o: $(PROJDIR)/%.cpp + $(CCX) $(CXXFLAGS) -o $@ $< + +$(INTDIR)/%.o.stub: $(PROJDIR)/%.c + $(CC) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(TOOLCHAIN)/include -o $@ $< + +$(INTDIR)/%.o.stub: $(PROJDIR)/%.cpp + $(CCX) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(TOOLCHAIN)/include -o $@ $< + +.PHONY: clean +.DEFAULT_GOAL := all + +all: $(TARGET) $(TARGETSTUB) + +clean: + rm -f $(TARGET) $(INTDIR)/$(PROJDIR).elf $(INTDIR)/$(PROJDIR)/oelf $(OBJS) diff --git a/external/Jailbreak PRX/README.md b/external/Jailbreak PRX/README.md new file mode 100644 index 0000000..7dd1a14 --- /dev/null +++ b/external/Jailbreak PRX/README.md @@ -0,0 +1,45 @@ +# Sample: Jailbreak PRX (OOSDK v0.5.2) + +## Directory structure +``` +Jailbreak PRX +|-- src + |- build // Object files / intermediate directory + |-- multi-jb.c // all the Jailbreak code for HEN + |-- multi-jb.h // Jailbreak Offsets +|-- jb.prx // final library file (not present until built) +|-- Makefile // Make rules for building on Linux +``` +The ELF, Orbis ELF (OELF), and object files will all be stored in the intermediate directory `src/build`. The final library prx and stub files will be found in the root directory. + + + +## Libraries used + +- Musl (-lc -lc++) +- libkernel + + + +## Building + +On Linux, a makefile has been included. + +To build this project, the developer will need clang, which is provided in the toolchain. The `OO_PS4_TOOLCHAIN` environment variable will also need to be set to the root directory of the SDK installation. + + +__Linux__ +Run the makefile. +``` +make +``` + +## Reference(s) used + +Libjbc - https://github.com/sleirsgoevy/ps4-libjbc + + +## Author(s) +- LM +- Sleirsgoevy +- Specter diff --git a/external/Jailbreak PRX/include/multi-jb.h b/external/Jailbreak PRX/include/multi-jb.h new file mode 100644 index 0000000..5718c11 --- /dev/null +++ b/external/Jailbreak PRX/include/multi-jb.h @@ -0,0 +1,65 @@ +#ifndef FW_DEFINES_H +#define FW_DEFINES_H + +#include +#include +#include + +#define AF_UNIX 1 +#define SOCK_STREAM 1 +#define MAX_PATH 1024 + +#define SYSCALL(nr, fn) __attribute__((naked)) fn\ +{\ + asm volatile("mov $" #nr ", %rax\nmov %rcx, %r10\nsyscall\nret");\ +} + +struct mount_in_sandbox_param +{ + const char* path; + const char* name; + int ans; +}; + +typedef enum KmemKind { USERSPACE, KERNEL_HEAP, KERNEL_TEXT } KmemKind; +enum { CWD_KEEP, CWD_ROOT, CWD_RESET }; + +struct jbc_cred +{ + uid_t uid; + uid_t ruid; + uid_t svuid; + gid_t rgid; + gid_t svgid; + uintptr_t prison; + uintptr_t cdir; + uintptr_t rdir; + uintptr_t jdir; + uint64_t sceProcType; + uint64_t sonyCred; + uint64_t sceProcCap; +}; + + +int socketpair(int domain, int type, int protocol, int* out); +ssize_t read(int fd, void* dst, size_t sz); +ssize_t write(int fd, const void* dst, size_t sz); +int close(int fd); +uint64_t jbc_krw_kcall(uint64_t fn, ...); +uintptr_t jbc_krw_get_td(void); +int jbc_krw_memcpy(uintptr_t dst, uintptr_t src, size_t sz, KmemKind kind); +uint64_t jbc_krw_read64(uintptr_t p, KmemKind kind); +int jbc_krw_write64(uintptr_t p, KmemKind kind, uintptr_t val); +uintptr_t jbc_get_prison0(void); +uintptr_t jbc_get_rootvnode(void); +int jbc_get_cred(struct jbc_cred*); +int jbc_jailbreak_cred(struct jbc_cred*); +int jbc_set_cred(const struct jbc_cred*); +void jbc_run_as_root(void(*fn)(void* arg), void* arg, int cwd_mode); +int jbc_mount_in_sandbox(const char* system_path, const char* mnt_name); +int jbc_unmount_in_sandbox(const char* mnt_name); +int jailbreak_multi(); + + + +#endif diff --git a/external/Jailbreak PRX/jb.prx b/external/Jailbreak PRX/jb.prx new file mode 100644 index 0000000..010d6d7 Binary files /dev/null and b/external/Jailbreak PRX/jb.prx differ diff --git a/external/Jailbreak PRX/src/multi-jb.c b/external/Jailbreak PRX/src/multi-jb.c new file mode 100644 index 0000000..137d1dc --- /dev/null +++ b/external/Jailbreak PRX/src/multi-jb.c @@ -0,0 +1,489 @@ +#include "multi-jb.h" +#include +#include +#include +#include +#include +#include +static uintptr_t prison0; +static uintptr_t rootvnode; +struct iovec { + void *iov_base; /* Base address. */ + size_t iov_len; /* Length. */ +}; + +SYSCALL(12, static int chdir(char* path)) +SYSCALL(22, static int unmount(const char* path, int flags)) +SYSCALL(136, static int mkdir(const char* path, int mode)) +SYSCALL(137, static int rmdir(const char* path)) +SYSCALL(326, static int getcwd(char* buf, size_t sz)) +SYSCALL(378, static int nmount(struct iovec* iov, unsigned int niov, int flags)) + + +void jbc_run_as_root(void(*fn)(void* arg), void* arg, int cwd_mode) +{ + struct jbc_cred cred; + jbc_get_cred(&cred); + struct jbc_cred root_cred = cred; + jbc_jailbreak_cred(&root_cred); + switch (cwd_mode) + { + case CWD_KEEP: + default: + root_cred.cdir = cred.cdir; + break; + case CWD_ROOT: + root_cred.cdir = cred.rdir; + break; + case CWD_RESET: + root_cred.cdir = root_cred.rdir; + break; + } + jbc_set_cred(&root_cred); + fn(arg); + jbc_set_cred(&cred); +} + +void build_iovec(struct iovec** iov, int* iovlen, const char* name, const void* val, size_t len) { + int i; + + if (*iovlen < 0) + return; + + i = *iovlen; + *iov = (struct iovec*)realloc((void*)(*iov), sizeof(struct iovec) * (i + 2)); + if (*iov == NULL) { + *iovlen = -1; + return; + } + + (*iov)[i].iov_base = strdup(name); + (*iov)[i].iov_len = strlen(name) + 1; + ++i; + + (*iov)[i].iov_base = (void*)val; + if (len == (size_t)-1) { + if (val != NULL) + len = strlen((const char*)val) + 1; + else + len = 0; + } + (*iov)[i].iov_len = (int)len; + + *iovlen = ++i; +} + + +int mount_NULL_fs(char* null_path, char* mountpoint, char* mode, unsigned int flags) { + struct iovec* iov = NULL; + int iovlen = 0; + int ret; + // + + mkdir(mountpoint, 0777); + + build_iovec(&iov, &iovlen, "fstype", "nullfs", (size_t)-1); + build_iovec(&iov, &iovlen, "fspath", null_path, (size_t)-1); // Where i want to add + build_iovec(&iov, &iovlen, "target", mountpoint, (size_t)-1); // What i want to add + build_iovec(&iov, &iovlen, "allow_other", "", (size_t)-1); // What i want to add + build_iovec(&iov, &iovlen, mode, "", (size_t)-1); + + + printf(" [I] Mounting %s (%s) to %s...\n", null_path, "nullfs", mountpoint); + ret = nmount(iov, iovlen, flags); + if (ret < 0) { + printf(" [E] Failed: %d (errno: %s).\n", ret, strerror(errno)); + goto error; + } + else { + printf(" [I] Success.\n"); + } + +error: + return ret; +} + +static void do_mount_in_sandbox(void* op) +{ + struct mount_in_sandbox_param* p = op; + mount_NULL_fs(p->path, p->name, "rw", 0777); +} + +int jbc_mount_in_sandbox(const char* system_path, const char* mnt_name) +{ + char buf[256]; + snprintf(buf, sizeof(buf), "/mnt/sandbox/ITEM00001_000%s", mnt_name); + struct mount_in_sandbox_param op = { + .path = system_path, + .name = buf, + .ans = 0, + }; + jbc_run_as_root(do_mount_in_sandbox, &op, CWD_ROOT); + return op.ans; +} + +int jbc_unmount_in_sandbox(const char* mnt_name) +{ + return jbc_mount_in_sandbox(0, mnt_name); +} + +static int k_kcall(void* td, uint64_t** uap) +{ + uint64_t* args = uap[1]; + args[0] = ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))args[0])(args[1], args[2], args[3], args[4], args[5], args[6]); + return 0; +} + +asm("kexec:\nmov $11, %rax\nmov %rcx, %r10\nsyscall\nret"); +void kexec(void*, void*); + +uint64_t jbc_krw_kcall(uint64_t fn, ...) +{ + va_list v; + va_start(v, fn); + uint64_t uap[7] = { fn }; + for (int i = 1; i <= 6; i++) + uap[i] = va_arg(v, uint64_t); + kexec(k_kcall, uap); + return uap[0]; +} + +asm("k_get_td:\nmov %gs:0, %rax\nret"); +extern char k_get_td[]; + +uintptr_t jbc_krw_get_td(void) +{ + return jbc_krw_kcall((uintptr_t)k_get_td); +} + +static int have_mira = -1; +static int mira_socket[2]; + +static int do_check_mira(void) +{ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, mira_socket)) + return 0; + if (write(mira_socket[1], (void*)jbc_krw_get_td(), 1) == 1) + { + char c; + read(mira_socket[0], &c, 1); + return 1; + } + return 0; +} + +static inline bool check_mira(void) +{ + if (have_mira < 0) + have_mira = do_check_mira(); + return (bool)have_mira; +} + +static inline bool check_ptr(uintptr_t p, KmemKind kind) +{ + if (kind == USERSPACE) + return p < 0x800000000000; + else if (kind == KERNEL_HEAP) + return p >= 0xffff800000000000 && p < 0xffffffff00000000; + else if (kind == KERNEL_TEXT) + return p >= 0xffffffff00000000 && p < 0xfffffffffffff000; + else + return false; +} + +static int kcpy_mira(uintptr_t dst, uintptr_t src, size_t sz) +{ + while (sz > 0) + { + size_t chk = (sz > 64 ? 64 : sz); + if (write(mira_socket[1], (void*)src, chk) != chk) + return -1; + if (read(mira_socket[0], (void*)dst, chk) != chk) + return -1; + dst += chk; + src += chk; + sz -= chk; + } + return 0; +} + +asm("k_kcpy:\nmov %rdx, %rcx\nrep movsb\nret"); +extern char k_kcpy[]; + +int jbc_krw_memcpy(uintptr_t dst, uintptr_t src, size_t sz, KmemKind kind) +{ + if (sz == 0) + return 0; + bool u1 = check_ptr(dst, USERSPACE) && check_ptr(dst + sz - 1, USERSPACE); + bool ok1 = check_ptr(dst, kind) && check_ptr(dst + sz - 1, kind); + bool u2 = check_ptr(src, USERSPACE) && check_ptr(src + sz - 1, USERSPACE); + bool ok2 = check_ptr(src, kind) && check_ptr(src + sz - 1, kind); + if (!((u1 || ok1) && (u2 || ok2))) + return -1; + if (u1 && u2) + return -1; + if (check_mira()) + return kcpy_mira(dst, src, sz); + jbc_krw_kcall((uintptr_t)k_kcpy, dst, src, sz); + return 0; +} + +uint64_t jbc_krw_read64(uintptr_t p, KmemKind kind) +{ + uint64_t ans; + if (jbc_krw_memcpy((uintptr_t)&ans, p, sizeof(ans), kind)) + return -1; + return ans; +} + +int jbc_krw_write64(uintptr_t p, KmemKind kind, uintptr_t val) +{ + return jbc_krw_memcpy(p, (uintptr_t)&val, sizeof(val), kind); +} + + +asm("open:\nmov $5, %rax\nmov %rcx, %r10\nsyscall\nret"); +asm("close:\nmov $6, %rax\nmov %rcx, %r10\nsyscall\nret"); + +int open(const char*, int, ...); +int close(int); + +static uintptr_t prison0; +static uintptr_t rootvnode; + +static int resolve(void) +{ +restart:; + uintptr_t td = jbc_krw_get_td(); + uintptr_t proc = jbc_krw_read64(td+8, KERNEL_HEAP); + for(;;) + { + int pid; + if(jbc_krw_memcpy((uintptr_t)&pid, proc+0xb0, sizeof(pid), KERNEL_HEAP)) + goto restart; + if(pid == 1) + break; + uintptr_t proc2 = jbc_krw_read64(proc, KERNEL_HEAP); + uintptr_t proc1 = jbc_krw_read64(proc2+8, KERNEL_HEAP); + if(proc1 != proc) + goto restart; + proc = proc2; + } + uintptr_t pid1_ucred = jbc_krw_read64(proc+0x40, KERNEL_HEAP); + uintptr_t pid1_fd = jbc_krw_read64(proc+0x48, KERNEL_HEAP); + if(jbc_krw_memcpy((uintptr_t)&prison0, pid1_ucred+0x30, sizeof(prison0), KERNEL_HEAP)) + return -1; + if(jbc_krw_memcpy((uintptr_t)&rootvnode, pid1_fd+0x18, sizeof(rootvnode), KERNEL_HEAP)) + { + prison0 = 0; + return -1; + } + return 0; +} + +uintptr_t jbc_get_prison0(void) +{ + if(!prison0) + resolve(); + return prison0; +} + +uintptr_t jbc_get_rootvnode(void) +{ + if(!rootvnode) + resolve(); + return rootvnode; +} + +static inline int ppcopyout(void* u1, void* u2, uintptr_t k) +{ + return jbc_krw_memcpy((uintptr_t)u1, k, (uintptr_t)u2-(uintptr_t)u1, KERNEL_HEAP); +} + +static inline int ppcopyin(const void* u1, const void* u2, uintptr_t k) +{ + return jbc_krw_memcpy(k, (uintptr_t)u1, (uintptr_t)u2-(uintptr_t)u1, KERNEL_HEAP); +} + +int jbc_get_cred(struct jbc_cred* ans) +{ + uintptr_t td = jbc_krw_get_td(); + uintptr_t proc = jbc_krw_read64(td + 8, KERNEL_HEAP); + uintptr_t ucred = jbc_krw_read64(proc + 0x40, KERNEL_HEAP); + uintptr_t fd = jbc_krw_read64(proc + 0x48, KERNEL_HEAP); + + if (ppcopyout(&ans->uid, 1 + &ans->svuid, ucred + 4) + || ppcopyout(&ans->rgid, 1 + &ans->svgid, ucred + 20) + || ppcopyout(&ans->prison, 1 + &ans->prison, ucred + 0x30) + || ppcopyout(&ans->cdir, 1 + &ans->jdir, fd + 0x10) + || ppcopyout(&ans->sceProcType, 1 + &ans->sceProcCap, ucred + 88)) + return -1; + + return 0; +} + +static int jbc_set_cred_internal(const struct jbc_cred* ans) +{ + uintptr_t td = jbc_krw_get_td(); + uintptr_t proc = jbc_krw_read64(td + 8, KERNEL_HEAP); + uintptr_t ucred = jbc_krw_read64(proc + 0x40, KERNEL_HEAP); + uintptr_t fd = jbc_krw_read64(proc + 0x48, KERNEL_HEAP); + + if (ppcopyin(&ans->uid, 1 + &ans->svuid, ucred + 4) + || ppcopyin(&ans->rgid, 1 + &ans->svgid, ucred + 20) + || ppcopyin(&ans->prison, 1 + &ans->prison, ucred + 0x30) + || ppcopyin(&ans->cdir, 1 + &ans->jdir, fd + 0x10) + || ppcopyin(&ans->sceProcType, 1 + &ans->sceProcCap, ucred + 88)) + return -1; + return 0; +} + +int jbc_jailbreak_cred(struct jbc_cred* ans) +{ + uintptr_t prison0 = jbc_get_prison0(); + if (!prison0) + return -1; + uintptr_t rootvnode = jbc_get_rootvnode(); + if (!rootvnode) + return -1; + + //without some modules wont load like Apputils + ans->sceProcCap = 0xffffffffffffffff; + ans->sceProcType = 0x3801000000000013; + ans->sonyCred = 0xffffffffffffffff; + + ans->uid = ans->ruid = ans->svuid = ans->rgid = ans->svgid = 0; + ans->prison = prison0; + ans->cdir = ans->rdir = ans->jdir = rootvnode; + return 0; +} + +static int jbc_open_this(const struct jbc_cred* cred0, uintptr_t vnode) +{ + if(!vnode) + return -1; + struct jbc_cred cred = *cred0; + jbc_jailbreak_cred(&cred); + cred.cdir = cred.rdir = cred.jdir = vnode; + jbc_set_cred_internal(&cred); + int ans = open("/", 0); + jbc_set_cred_internal(cred0); + return ans; +} + +static int swap64(uintptr_t p1, KmemKind k1, uintptr_t p2, KmemKind k2) +{ + uintptr_t v1 = jbc_krw_read64(p1, k1); + uintptr_t v2 = jbc_krw_read64(p2, k2); + if(ppcopyin(&v2, 1+&v2, p1) + || ppcopyin(&v1, 1+&v1, p2)) + return -1; + return 0; +} + +static int return0(void) +{ + return 0; +} + +static void* fake_vtable[16] = { + return0, return0, return0, return0, + return0, return0, return0, return0, + return0, return0, return0, return0, + return0, return0, return0, return0, +}; + +int jbc_set_cred(const struct jbc_cred* newp) +{ + struct jbc_cred old, neww = *newp; + if(jbc_get_cred(&old)) + return -1; + if(old.cdir && !neww.cdir) + neww.cdir = jbc_get_rootvnode(); + if(old.rdir && !neww.rdir) + neww.rdir = jbc_get_rootvnode(); + if(old.jdir && !neww.jdir) + neww.jdir = jbc_get_rootvnode(); + int cdir_fd = jbc_open_this(&old, neww.cdir); + int rdir_fd = jbc_open_this(&old, neww.rdir); + int jdir_fd = jbc_open_this(&old, neww.jdir); + struct jbc_cred elevated = neww; + elevated.cdir = old.cdir; + elevated.jdir = old.jdir; + elevated.rdir = old.rdir; + //this offset is the same in 5.05-9.60, probably safe to use + uint32_t rc; + if(elevated.prison) + { + if(jbc_krw_memcpy((uintptr_t)&rc, elevated.prison+0x14, sizeof(rc), KERNEL_HEAP) + && jbc_krw_memcpy((uintptr_t)&rc, elevated.prison+0x14, sizeof(rc), KERNEL_TEXT)) + return -1; + rc++; + if(jbc_krw_memcpy(elevated.prison+0x14, (uintptr_t)&rc, sizeof(rc), KERNEL_HEAP) + && jbc_krw_memcpy((uintptr_t)&rc, elevated.prison+0x14, sizeof(rc), KERNEL_TEXT)) + return -1; + } + if(jbc_set_cred_internal(&elevated)) + return -1; + if(old.prison) + { + if(jbc_krw_memcpy((uintptr_t)&rc, old.prison+0x14, sizeof(rc), KERNEL_HEAP) + && jbc_krw_memcpy((uintptr_t)&rc, old.prison+0x14, sizeof(rc), KERNEL_TEXT)) + return -1; + rc--; + if(jbc_krw_memcpy(old.prison+0x14, (uintptr_t)&rc, sizeof(rc), KERNEL_HEAP) + && jbc_krw_memcpy(old.prison+0x14, (uintptr_t)&rc, sizeof(rc), KERNEL_TEXT)) + return -1; + } + uintptr_t td = jbc_krw_get_td(); + uintptr_t proc = jbc_krw_read64(td + 8, KERNEL_HEAP); + uintptr_t ucred = jbc_krw_read64(proc + 0x40, KERNEL_HEAP); + uintptr_t fd = jbc_krw_read64(proc + 0x48, KERNEL_HEAP); + uintptr_t ofiles = jbc_krw_read64(fd, KERNEL_HEAP); + int fds[3] = {cdir_fd, rdir_fd, jdir_fd}; + for(int i = 0; i < 3; i++) + { + if(fds[i] < 0) + continue; + uintptr_t file = jbc_krw_read64(ofiles+8*fds[i], KERNEL_HEAP); + if(swap64(file, KERNEL_HEAP, fd+0x10+8*i, KERNEL_HEAP)) + return -1; + if(jbc_krw_read64(file, KERNEL_HEAP) == 0) + { + uintptr_t p = (uintptr_t)fake_vtable; + if(ppcopyin(&p, 1+&p, file+8)) + return -1; + } + close(fds[i]); + } + return 0; +} + +struct jbc_cred rejail; + +int jailbreak_multi() { + + struct jbc_cred ans; + jbc_get_cred(&rejail); + jbc_get_cred(&ans); + jbc_jailbreak_cred(&ans); + return jbc_set_cred(&ans); +} + +int rejail_multi() { + return jbc_set_cred(&rejail); +} + +int jailbreak_me(void) +{ + return jailbreak_multi(); +} + +int _fini(void) +{ + return 0; +} +int _init(void) +{ + return 0; +} \ No newline at end of file diff --git a/external/RSA PRX/Makefile b/external/RSA PRX/Makefile new file mode 100644 index 0000000..1b65ced --- /dev/null +++ b/external/RSA PRX/Makefile @@ -0,0 +1,69 @@ +TOOLCHAIN := $(OO_PS4_TOOLCHAIN) +PROJDIR := $(shell basename $(CURDIR)) +INTDIR := $(PROJDIR)/x64/Debug + +# Libraries linked into the ELF. +LIBS := -lSceLibcInternal -lkernel + +# Compiler options. You likely won't need to touch these. +UNAME_S := $(shell uname -s) +ifeq ($(UNAME_S),Linux) + CC := clang + LD := ld.lld + CDIR := linux +endif +ifeq ($(UNAME_S),Darwin) + CC := /usr/local/opt/llvm/bin/clang + LD := /usr/local/opt/llvm/bin/ld.lld + CDIR := macos +endif +ODIR := $(INTDIR) +SDIR := RSA +IDIRS := -I$(TOOLCHAIN)/include +LDIRS := -L$(TOOLCHAIN)/lib +CFLAGS := -cc1 -triple x86_64-scei-ps4-elf -munwind-tables $(IDIRS) -emit-obj +LFLAGS := -m elf_x86_64 -pie --script $(TOOLCHAIN)/link.x --eh-frame-hdr $(LDIRS) $(LIBS) $(TOOLCHAIN)/lib/crtlib.o + +CFILES := $(wildcard $(SDIR)/*.c) +CPPFILES := $(wildcard $(SDIR)/*.cpp) +OBJS := $(patsubst $(SDIR)/%.c, $(ODIR)/%.o, $(CFILES)) $(patsubst $(SDIR)/%.cpp, $(ODIR)/%.o, $(CPPFILES)) +STUBOBJS := $(patsubst $(SDIR)/%.c, $(ODIR)/%.o.stub, $(CFILES)) $(patsubst $(SDIR)/%.cpp, $(ODIR)/%.o.stub, $(CPPFILES)) + +TARGET = rsa.prx +TARGETSTUB = rsa.so + +# Create the intermediate directory incase it doesn't already exist. +_unused := $(shell mkdir -p $(INTDIR)) + +# Make rules +$(TARGET): $(ODIR) $(OBJS) + $(LD) $(ODIR)/*.o -o $(ODIR)/$(PROJDIR).elf $(LFLAGS) + $(TOOLCHAIN)/bin/$(CDIR)/create-lib -in=$(ODIR)/$(PROJDIR).elf -out=$(ODIR)/$(PROJDIR).oelf --paid 0x3800000000000011 + mv $(ODIR)/$(PROJDIR).prx $(TARGET) + +$(TARGETSTUB): $(ODIR) $(STUBOBJS) + $(CC) $(ODIR)/*.o.stub -o $(TARGETSTUB) -target x86_64-pc-linux-gnu -shared -fuse-ld=lld -ffreestanding -nostdlib -fno-builtin $(LDIRS) $(LIBS) + +$(ODIR)/%.o: $(SDIR)/%.c + $(CC) $(CFLAGS) -o $@ $< + +$(ODIR)/%.o: $(SDIR)/%.cpp + $(CC) $(CFLAGS) -o $@ $< + +$(ODIR)/%.o.stub: $(SDIR)/%.c + $(CC) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(IDIRS) -o $@ $< + +$(ODIR)/%.o.stub: $(SDIR)/%.cpp + $(CC) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(IDIRS) -o $@ $< + +$(ODIR): + @mkdir $@ + +.PHONY: clean +.DEFAULT_GOAL := all + +all: $(TARGET) $(TARGETSTUB) + +clean: + rm -f $(TARGET) $(ODIR)/*.o + rm -f $(TARGET) $(ODIR)/*.o.stub diff --git a/external/RSA PRX/README.md b/external/RSA PRX/README.md new file mode 100644 index 0000000..4cea4bc --- /dev/null +++ b/external/RSA PRX/README.md @@ -0,0 +1,59 @@ +# RSA (mbedtls) PRX + +[![Version](https://img.shields.io/badge/Version-1.00-brightgreen.svg)](https://github.com/Cryptogenic/OpenOrbis-PS4-Toolchain) + +This project contains code for creating a library with a RSA abilites. It will generate an output .prx (Playstation Relocatable Executable) for the PS4, as well as a stub .so shared object file for linking on the PC side. + +to Compile this PRX correctly you must replace your link.x with this one (from OO) here +`$OO_PS4_TOOLCHAIN/link.x` + +[Fix building libraries](https://github.com/sleirsgoevy/OpenOrbis-PS4-Toolchain/commit/f1cda6002d8e3af6f530cfaa5929c5d8b8167b0d) + +AND +Replace `$OO_PS4_TOOLCHAIN/bin/linux/create-lib` and `$OO_PS4_TOOLCHAIN/bin/linux/create-eboot` with these + +[Fix create-eboot generating non-contiguous relro and data segments #112 create-eboot/create-lib #45](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/actions/runs/503278524) + + +The ELF, Orbis ELF (OELF), and object files will all be stored in the intermediate directory `x64/Debug`. The final library prx and stub files will be found in the root directory. + + + +## Libraries used + +- libSceLibcInternal +- libkernel + + + +## Building + +On Linux, a makefile has been included. +To build this project, the developer will need clang, which is provided in the toolchain. The `OO_PS4_TOOLCHAIN` environment variable will also need to be set to the root directory of the SDK installation. +along with the following Linux Prerequisites + +__Ubuntu__ 20.04 LTS + +``` +sudo apt-get install -y libmbedtls-dev +sudo apt-get install gcc-multilib +sudo apt-get install lld +``` + + +__Linux__ +Run the makefile. +``` +make +``` + +## Reference(s) used + +ARMmbed - https://github.com/ARMmbed/mbedtls + + + +## Author(s) +- LM +- ARMmbed +- Specter diff --git a/external/RSA PRX/RSA/bignum.c b/external/RSA PRX/RSA/bignum.c new file mode 100644 index 0000000..c39adb8 --- /dev/null +++ b/external/RSA PRX/RSA/bignum.c @@ -0,0 +1,3010 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + // memset( v, ciL * n, sizeof ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char assign ) +{ + size_t i; + for( i = 0; i < n; i++ ) + dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( X != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + +/* + * Import X from unsigned binary data, little endian + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < buflen; i++ ) + X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + /* Avoid calling `memcpy` with NULL source argument, + * even if buflen is 0. */ + if( buf != NULL ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/** Decide if an integer is less than the other, without branches. + * + * \param x First integer. + * \param y Second integer. + * + * \return 1 if \p x is less than \p y, 0 otherwise + */ +static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 ); + + return (unsigned) ret; +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n Number of limbs of \p d and \p s. + * \param[in,out] d On input, the left operand. + * On output, the result of the subtraction: + * \param[in] s The right operand. + * + * \return 1 if `d < s`. + * 0 if `d >= s`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *s ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + carry = mpi_sub_hlp( n, X->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + --X->p[n]; + } + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi TA, TB; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t lz, lzt; + mbedtls_mpi TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( size ); + size_t const overhead = ( limbs * ciL ) - size; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + Xp = (unsigned char*) X->p; + f_rng( p_rng, Xp + overhead, size ); + + mpi_bigendian_to_host( X->p, limbs ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* + * In the past our key generation aimed for an error rate of at most + * 2^-80. Since this function is deprecated, aim for the same certainty + * here as well. + */ + return( mbedtls_mpi_is_prime_ext( X, 40, f_rng, p_rng ) ); +} +#endif + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/external/RSA PRX/RSA/common.h b/external/RSA PRX/RSA/common.h new file mode 100644 index 0000000..5845766 --- /dev/null +++ b/external/RSA PRX/RSA/common.h @@ -0,0 +1,53 @@ +/** + * \file common.h + * + * \brief Utility macros for internal use in the library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_LIBRARY_COMMON_H +#define MBEDTLS_LIBRARY_COMMON_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +/** Helper to define a function as static except when building invasive tests. + * + * If a function is only used inside its own source file and should be + * declared `static` to allow the compiler to optimize for code size, + * but that function has unit tests, define it with + * ``` + * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } + * ``` + * and declare it in a header in the `library/` directory with + * ``` + * #if defined(MBEDTLS_TEST_HOOKS) + * int mbedtls_foo(...); + * #endif + * ``` + */ +#if defined(MBEDTLS_TEST_HOOKS) +#define MBEDTLS_STATIC_TESTABLE +#else +#define MBEDTLS_STATIC_TESTABLE static +#endif + +#endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/external/RSA PRX/RSA/error.c b/external/RSA PRX/RSA/error.c new file mode 100644 index 0000000..901a369 --- /dev/null +++ b/external/RSA PRX/RSA/error.c @@ -0,0 +1,976 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#if defined(MBEDTLS_ERROR_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#include +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_ERROR_C) +#include "mbedtls/error.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +const char * mbedtls_high_level_strerr( int error_code ) +{ + int high_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the high-level part from the error code. */ + high_level_error_code = error_code & 0xFF80; + + switch( high_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_CIPHER_C) + case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE): + return( "CIPHER - The selected feature is not available" ); + case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA): + return( "CIPHER - Bad input parameters" ); + case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED): + return( "CIPHER - Failed to allocate memory" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING): + return( "CIPHER - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED): + return( "CIPHER - Decryption of block requires a full block" ); + case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED): + return( "CIPHER - Authentication failed (for AEAD modes)" ); + case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT): + return( "CIPHER - The context is invalid. For example, because it was freed" ); + case -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED): + return( "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA): + return( "DHM - Bad input parameters" ); + case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED): + return( "DHM - Reading of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED): + return( "DHM - Making of the DHM parameters failed" ); + case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED): + return( "DHM - Reading of the public values failed" ); + case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED): + return( "DHM - Making of the public value failed" ); + case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED): + return( "DHM - Calculation of the DHM secret failed" ); + case -(MBEDTLS_ERR_DHM_INVALID_FORMAT): + return( "DHM - The ASN.1 data is not formatted correctly" ); + case -(MBEDTLS_ERR_DHM_ALLOC_FAILED): + return( "DHM - Allocation of memory failed" ); + case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR): + return( "DHM - Read or write of file failed" ); + case -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED): + return( "DHM - DHM hardware accelerator failed" ); + case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED): + return( "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA): + return( "ECP - Bad input parameters to function" ); + case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL): + return( "ECP - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE): + return( "ECP - The requested feature is not available, for example, the requested curve is not supported" ); + case -(MBEDTLS_ERR_ECP_VERIFY_FAILED): + return( "ECP - The signature is not valid" ); + case -(MBEDTLS_ERR_ECP_ALLOC_FAILED): + return( "ECP - Memory allocation failed" ); + case -(MBEDTLS_ERR_ECP_RANDOM_FAILED): + return( "ECP - Generation of random value, such as ephemeral key, failed" ); + case -(MBEDTLS_ERR_ECP_INVALID_KEY): + return( "ECP - Invalid private or public key" ); + case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH): + return( "ECP - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED): + return( "ECP - The ECP hardware accelerator failed" ); + case -(MBEDTLS_ERR_ECP_IN_PROGRESS): + return( "ECP - Operation in progress, call again with the same parameters to continue" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE): + return( "MD - The selected feature is not available" ); + case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA): + return( "MD - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MD_ALLOC_FAILED): + return( "MD - Failed to allocate memory" ); + case -(MBEDTLS_ERR_MD_FILE_IO_ERROR): + return( "MD - Opening or reading of file failed" ); + case -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED): + return( "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT): + return( "PEM - No PEM header or footer found" ); + case -(MBEDTLS_ERR_PEM_INVALID_DATA): + return( "PEM - PEM string is not as expected" ); + case -(MBEDTLS_ERR_PEM_ALLOC_FAILED): + return( "PEM - Failed to allocate memory" ); + case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV): + return( "PEM - RSA IV is not in hex-format" ); + case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG): + return( "PEM - Unsupported key encryption algorithm" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED): + return( "PEM - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH): + return( "PEM - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE): + return( "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA): + return( "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + case -(MBEDTLS_ERR_PK_ALLOC_FAILED): + return( "PK - Memory allocation failed" ); + case -(MBEDTLS_ERR_PK_TYPE_MISMATCH): + return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA): + return( "PK - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PK_FILE_IO_ERROR): + return( "PK - Read/write of file failed" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION): + return( "PK - Unsupported key version" ); + case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT): + return( "PK - Invalid key tag or value" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG): + return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED): + return( "PK - Private key password can't be empty" ); + case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH): + return( "PK - Given private key password does not allow for correct decryption" ); + case -(MBEDTLS_ERR_PK_INVALID_PUBKEY): + return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + case -(MBEDTLS_ERR_PK_INVALID_ALG): + return( "PK - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE): + return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE): + return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH): + return( "PK - The buffer contains a valid signature followed by more data" ); + case -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED): + return( "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA): + return( "PKCS12 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE): + return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT): + return( "PKCS12 - PBE ASN.1 data not as expected" ); + case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH): + return( "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA): + return( "PKCS5 - Bad input parameters to function" ); + case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT): + return( "PKCS5 - Unexpected ASN.1 data" ); + case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE): + return( "PKCS5 - Requested encryption or digest alg not available" ); + case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH): + return( "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA): + return( "RSA - Bad input parameters to function" ); + case -(MBEDTLS_ERR_RSA_INVALID_PADDING): + return( "RSA - Input data contains invalid padding and is rejected" ); + case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED): + return( "RSA - Something failed during generation of a key" ); + case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED): + return( "RSA - Key failed to pass the validity check of the library" ); + case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED): + return( "RSA - The public key operation failed" ); + case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED): + return( "RSA - The private key operation failed" ); + case -(MBEDTLS_ERR_RSA_VERIFY_FAILED): + return( "RSA - The PKCS#1 verification failed" ); + case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE): + return( "RSA - The output buffer for decryption is not large enough" ); + case -(MBEDTLS_ERR_RSA_RNG_FAILED): + return( "RSA - The random generator failed to generate non-zeros" ); + case -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION): + return( "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + case -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED): + return( "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE): + return( "SSL - The requested feature is not available" ); + case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA): + return( "SSL - Bad input parameters to function" ); + case -(MBEDTLS_ERR_SSL_INVALID_MAC): + return( "SSL - Verification of the message MAC failed" ); + case -(MBEDTLS_ERR_SSL_INVALID_RECORD): + return( "SSL - An invalid SSL record was received" ); + case -(MBEDTLS_ERR_SSL_CONN_EOF): + return( "SSL - The connection indicated an EOF" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER): + return( "SSL - An unknown cipher was received" ); + case -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN): + return( "SSL - The server has no ciphersuites in common with the client" ); + case -(MBEDTLS_ERR_SSL_NO_RNG): + return( "SSL - No RNG was provided to the SSL module" ); + case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE): + return( "SSL - No client certification received from the client, but required by the authentication mode" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE): + return( "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + case -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED): + return( "SSL - The own certificate is not set, but needed by the server" ); + case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED): + return( "SSL - The own private key or pre-shared key is not set, but needed" ); + case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED): + return( "SSL - No CA Chain is set, but required to operate" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE): + return( "SSL - An unexpected message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE): + return( "SSL - A fatal alert message was received from our peer" ); + case -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED): + return( "SSL - Verification of our peer failed" ); + case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY): + return( "SSL - The peer notified us that the connection is going to be closed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO): + return( "SSL - Processing of the ClientHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO): + return( "SSL - Processing of the ServerHello handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE): + return( "SSL - Processing of the Certificate handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST): + return( "SSL - Processing of the CertificateRequest handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE): + return( "SSL - Processing of the ServerKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE): + return( "SSL - Processing of the ServerHelloDone handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE): + return( "SSL - Processing of the ClientKeyExchange handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS): + return( "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY): + return( "SSL - Processing of the CertificateVerify handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC): + return( "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED): + return( "SSL - Processing of the Finished handshake message failed" ); + case -(MBEDTLS_ERR_SSL_ALLOC_FAILED): + return( "SSL - Memory allocation failed" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED): + return( "SSL - Hardware acceleration function returned with error" ); + case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH): + return( "SSL - Hardware acceleration function skipped / left alone data" ); + case -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED): + return( "SSL - Processing of the compression / decompression failed" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION): + return( "SSL - Handshake protocol not within min/max boundaries" ); + case -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET): + return( "SSL - Processing of the NewSessionTicket handshake message failed" ); + case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED): + return( "SSL - Session ticket has expired" ); + case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH): + return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY): + return( "SSL - Unknown identity received (eg, PSK identity)" ); + case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR): + return( "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING): + return( "SSL - A counter would wrap (eg, too many messages exchanged)" ); + case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO): + return( "SSL - Unexpected message at ServerHello in renegotiation" ); + case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED): + return( "SSL - DTLS client must retry for hello verification" ); + case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL): + return( "SSL - A buffer is too small to receive or write a message" ); + case -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE): + return( "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + case -(MBEDTLS_ERR_SSL_WANT_READ): + return( "SSL - No data of requested type currently available on underlying transport" ); + case -(MBEDTLS_ERR_SSL_WANT_WRITE): + return( "SSL - Connection requires a write call" ); + case -(MBEDTLS_ERR_SSL_TIMEOUT): + return( "SSL - The operation timed out" ); + case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT): + return( "SSL - The client initiated a reconnect from the same port" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD): + return( "SSL - Record header looks valid but is not expected" ); + case -(MBEDTLS_ERR_SSL_NON_FATAL): + return( "SSL - The alert message received indicates a non-fatal error" ); + case -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH): + return( "SSL - Couldn't set the hash for verifying CertificateVerify" ); + case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING): + return( "SSL - Internal-only message signaling that further message-processing should be done" ); + case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS): + return( "SSL - The asynchronous operation is not completed yet" ); + case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE): + return( "SSL - Internal-only message signaling that a message arrived early" ); + case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID): + return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" ); + case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH): + return( "SSL - An operation failed due to an unexpected version or configuration" ); + case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS): + return( "SSL - A cryptographic operation is in progress. Try again later" ); + case -(MBEDTLS_ERR_SSL_BAD_CONFIG): + return( "SSL - Invalid value in SSL config" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE): + return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_OID): + return( "X509 - Requested OID is unknown" ); + case -(MBEDTLS_ERR_X509_INVALID_FORMAT): + return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + case -(MBEDTLS_ERR_X509_INVALID_VERSION): + return( "X509 - The CRT/CRL/CSR version element is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SERIAL): + return( "X509 - The serial tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_ALG): + return( "X509 - The algorithm tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_NAME): + return( "X509 - The name tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_DATE): + return( "X509 - The date tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE): + return( "X509 - The signature tag or value invalid" ); + case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS): + return( "X509 - The extension tag or value is invalid" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION): + return( "X509 - CRT/CRL/CSR has an unsupported version number" ); + case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG): + return( "X509 - Signature algorithm (oid) is unsupported" ); + case -(MBEDTLS_ERR_X509_SIG_MISMATCH): + return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED): + return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT): + return( "X509 - Format not recognized as DER or PEM" ); + case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA): + return( "X509 - Input invalid" ); + case -(MBEDTLS_ERR_X509_ALLOC_FAILED): + return( "X509 - Allocation of memory failed" ); + case -(MBEDTLS_ERR_X509_FILE_IO_ERROR): + return( "X509 - Read/write of file failed" ); + case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL): + return( "X509 - Destination buffer is too small" ); + case -(MBEDTLS_ERR_X509_FATAL_ERROR): + return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +const char * mbedtls_low_level_strerr( int error_code ) +{ + int low_level_error_code; + + if( error_code < 0 ) + error_code = -error_code; + + /* Extract the low-level part from the error code. */ + low_level_error_code = error_code & ~0xFF80; + + switch( low_level_error_code ) + { + /* Begin Auto-Generated Code. */ +#if defined(MBEDTLS_AES_C) + case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH): + return( "AES - Invalid key length" ); + case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH): + return( "AES - Invalid data input length" ); + case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA): + return( "AES - Invalid input data" ); + case -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE): + return( "AES - Feature not available. For example, an unsupported AES key size" ); + case -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED): + return( "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + case -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED): + return( "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA): + return( "ARIA - Bad input data" ); + case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH): + return( "ARIA - Invalid data input length" ); + case -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE): + return( "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + case -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED): + return( "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA): + return( "ASN1 - Out of data when parsing an ASN1 data structure" ); + case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG): + return( "ASN1 - ASN1 tag was of an unexpected value" ); + case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH): + return( "ASN1 - Error when trying to determine the length or invalid length" ); + case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH): + return( "ASN1 - Actual length differs from expected length" ); + case -(MBEDTLS_ERR_ASN1_INVALID_DATA): + return( "ASN1 - Data is invalid" ); + case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED): + return( "ASN1 - Memory allocation failed" ); + case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL): + return( "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL): + return( "BASE64 - Output buffer too small" ); + case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER): + return( "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR): + return( "BIGNUM - An error occurred while reading from or writing to a file" ); + case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA): + return( "BIGNUM - Bad input parameters to function" ); + case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER): + return( "BIGNUM - There is an invalid character in the digit string" ); + case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL): + return( "BIGNUM - The buffer is too small to write to" ); + case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE): + return( "BIGNUM - The input arguments are negative or result in illegal output" ); + case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO): + return( "BIGNUM - The input argument for division is zero, which is not allowed" ); + case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE): + return( "BIGNUM - The input arguments are not acceptable" ); + case -(MBEDTLS_ERR_MPI_ALLOC_FAILED): + return( "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + case -(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA): + return( "BLOWFISH - Bad input data" ); + case -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH): + return( "BLOWFISH - Invalid data input length" ); + case -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED): + return( "BLOWFISH - Blowfish hardware accelerator failed" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA): + return( "CAMELLIA - Bad input data" ); + case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH): + return( "CAMELLIA - Invalid data input length" ); + case -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED): + return( "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + case -(MBEDTLS_ERR_CCM_BAD_INPUT): + return( "CCM - Bad input parameters to the function" ); + case -(MBEDTLS_ERR_CCM_AUTH_FAILED): + return( "CCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED): + return( "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA): + return( "CHACHA20 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE): + return( "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED): + return( "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE): + return( "CHACHAPOLY - The requested operation is not permitted in the current state" ); + case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED): + return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + case -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED): + return( "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED): + return( "CTR_DRBG - The entropy source failed" ); + case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG): + return( "CTR_DRBG - The requested random buffer length is too big" ); + case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG): + return( "CTR_DRBG - The input (entropy + additional data) is too large" ); + case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR): + return( "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH): + return( "DES - The data input has an invalid length" ); + case -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED): + return( "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED): + return( "ENTROPY - Critical entropy source failure" ); + case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES): + return( "ENTROPY - No more sources can be added" ); + case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED): + return( "ENTROPY - No sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE): + return( "ENTROPY - No strong sources have been added to poll" ); + case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR): + return( "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_ERROR_C) + case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR): + return( "ERROR - Generic error" ); + case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED): + return( "ERROR - This is a bug in the library" ); +#endif /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_GCM_C) + case -(MBEDTLS_ERR_GCM_AUTH_FAILED): + return( "GCM - Authenticated decryption failed" ); + case -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED): + return( "GCM - GCM hardware accelerator failed" ); + case -(MBEDTLS_ERR_GCM_BAD_INPUT): + return( "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) + case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA): + return( "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG): + return( "HMAC_DRBG - Too many random requested in single call" ); + case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG): + return( "HMAC_DRBG - Input too large (Entropy + additional)" ); + case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR): + return( "HMAC_DRBG - Read/write error in file" ); + case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED): + return( "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + case -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED): + return( "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + case -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED): + return( "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + case -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED): + return( "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + case -(MBEDTLS_ERR_NET_SOCKET_FAILED): + return( "NET - Failed to open a socket" ); + case -(MBEDTLS_ERR_NET_CONNECT_FAILED): + return( "NET - The connection to the given server / port failed" ); + case -(MBEDTLS_ERR_NET_BIND_FAILED): + return( "NET - Binding of the socket failed" ); + case -(MBEDTLS_ERR_NET_LISTEN_FAILED): + return( "NET - Could not listen on the socket" ); + case -(MBEDTLS_ERR_NET_ACCEPT_FAILED): + return( "NET - Could not accept the incoming connection" ); + case -(MBEDTLS_ERR_NET_RECV_FAILED): + return( "NET - Reading information from the socket failed" ); + case -(MBEDTLS_ERR_NET_SEND_FAILED): + return( "NET - Sending information through the socket failed" ); + case -(MBEDTLS_ERR_NET_CONN_RESET): + return( "NET - Connection was reset by peer" ); + case -(MBEDTLS_ERR_NET_UNKNOWN_HOST): + return( "NET - Failed to get an IP address for the given hostname" ); + case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL): + return( "NET - Buffer is too small to hold the data" ); + case -(MBEDTLS_ERR_NET_INVALID_CONTEXT): + return( "NET - The context is invalid, eg because it was free()ed" ); + case -(MBEDTLS_ERR_NET_POLL_FAILED): + return( "NET - Polling the net context failed" ); + case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA): + return( "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + case -(MBEDTLS_ERR_OID_NOT_FOUND): + return( "OID - OID is not found" ); + case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL): + return( "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + case -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED): + return( "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_PLATFORM_C) + case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED): + return( "PLATFORM - Hardware accelerator failed" ); + case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED): + return( "PLATFORM - The requested feature is not supported by the platform" ); +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_POLY1305_C) + case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA): + return( "POLY1305 - Invalid input parameter(s)" ); + case -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE): + return( "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + case -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED): + return( "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + case -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED): + return( "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + case -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED): + return( "SHA1 - SHA-1 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA): + return( "SHA1 - SHA-1 input data was malformed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + case -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED): + return( "SHA256 - SHA-256 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA): + return( "SHA256 - SHA-256 input data was malformed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + case -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED): + return( "SHA512 - SHA-512 hardware accelerator failed" ); + case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA): + return( "SHA512 - SHA-512 input data was malformed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + case -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE): + return( "THREADING - The selected feature is not available" ); + case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA): + return( "THREADING - Bad input parameters to function" ); + case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR): + return( "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + case -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH): + return( "XTEA - The data input has an invalid length" ); + case -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED): + return( "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + /* End Auto-Generated Code. */ + + default: + break; + } + + return( NULL ); +} + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + const char * high_level_error_description = NULL; + const char * low_level_error_description = NULL; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // Translate high level error code. + high_level_error_description = mbedtls_high_level_strerr( ret ); + + if( high_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", high_level_error_description ); + +#if defined(MBEDTLS_SSL_TLS_C) + // Early return in case of a fatal error - do not try to translate low + // level code. + if(use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) + return; +#endif /* MBEDTLS_SSL_TLS_C */ + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Translate low level error code. + low_level_error_description = mbedtls_low_level_strerr( ret ); + + if( low_level_error_description == NULL ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret ); + else + mbedtls_snprintf( buf, buflen, "%s", low_level_error_description ); +} + +#else /* MBEDTLS_ERROR_C */ + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_C */ + +#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/external/RSA PRX/RSA/main.c b/external/RSA PRX/RSA/main.c new file mode 100644 index 0000000..02da70f --- /dev/null +++ b/external/RSA PRX/RSA/main.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include +#include + +// We need to provide an export to force the expected stub library to be generated +int VerifyRSA(const char* file, const char* pubkkey) +{ + return Check_rsa(file, pubkkey); + +} \ No newline at end of file diff --git a/external/RSA PRX/RSA/mbedtls/aes.h b/external/RSA PRX/RSA/mbedtls/aes.h new file mode 100644 index 0000000..63c0f67 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/aes.h @@ -0,0 +1,674 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/external/RSA PRX/RSA/mbedtls/aesni.h b/external/RSA PRX/RSA/mbedtls/aesni.h new file mode 100644 index 0000000..955b7c9 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/aesni.h @@ -0,0 +1,138 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, + int nr ); + +/** + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/external/RSA PRX/RSA/mbedtls/arc4.h b/external/RSA PRX/RSA/mbedtls/arc4.h new file mode 100644 index 0000000..acad623 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/arc4.h @@ -0,0 +1,146 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct mbedtls_arc4_context +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/external/RSA PRX/RSA/mbedtls/aria.h b/external/RSA PRX/RSA/mbedtls/aria.h new file mode 100644 index 0000000..a72a8c2 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/aria.h @@ -0,0 +1,370 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */ + +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */ + +/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used. + */ +#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */ + +/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */ + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char nr; /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/external/RSA PRX/RSA/mbedtls/asn1.h b/external/RSA PRX/RSA/mbedtls/asn1.h new file mode 100644 index 0000000..33b3004 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/asn1.h @@ -0,0 +1,609 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into Mbed TLS's \c mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_ENUMERATED 0x0A +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p On entry, \c *p points to the first byte of the length, + * i.e. immediately after the tag. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the element. + * Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * \param tag The expected tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start + * with the requested tag. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value (\c 0 or \c 1). + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BOOLEAN. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an enumerated ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 ENUMERATED. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param bs On success, ::mbedtls_asn1_bitstring information about + * the parsed value. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid BIT STRING. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs ); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * of the content of the BIT STRING. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On success, \c *len is the length of the content in bytes. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with + * a valid BIT STRING with a nonzero number of unused bits. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF ". + * Updates the pointer to immediately behind the full sequence tag. + * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * + * \note On error, this function may return a partial list in \p cur. + * You must set `cur->next = NULL` before calling this function! + * Otherwise it is impossible to distinguish a previously non-null + * pointer from a pointer to an object allocated by this function. + * + * \note If the sequence is empty, this function does not modify + * \c *cur. If the sequence is valid and non-empty, this + * function sets `cur->buf.tag` to \p tag. This allows + * callers to distinguish between an empty sequence and + * a one-element sequence. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param cur A ::mbedtls_asn1_sequence which this function fills. + * When this function returns, \c *cur is the head of a linked + * list. Each node in this list is allocated with + * mbedtls_calloc() apart from \p cur itself, and should + * therefore be freed with mbedtls_free(). + * The list describes the content of the sequence. + * The head of the list (i.e. \c *cur itself) describes the + * first element, `*cur->next` describes the second element, etc. + * For each element, `buf.tag == tag`, `buf.len` is the length + * of the content of the content of the element, and `buf.p` + * points to the first byte of the content (i.e. immediately + * past the length of the element). + * Note that list elements may be allocated even on error. + * \param tag Each element of the sequence must have this tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param X On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + * \return An MPI error code if the parsed value is too large. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * \param params The buffer to receive the parameters. + * This is zeroized if there are no parameters. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list. + * + * \param head Pointer to the head of the list of named data entries to free. + * This function calls mbedtls_asn1_free_named_data() and + * mbedtls_free() on each list element and + * sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/external/RSA PRX/RSA/mbedtls/asn1write.h b/external/RSA PRX/RSA/mbedtls/asn1write.h new file mode 100644 index 0000000..0bce28e --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/asn1write.h @@ -0,0 +1,372 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( ret = (f) ) < 0 ) \ + return( ret ); \ + else \ + (g) += ret; \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, + size_t len ); +/** + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, + const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, + int boolean ); + +/** + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief This function writes a named bitstring tag + * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. + * + * As stated in RFC 5280 Appendix B, trailing zeroes are + * omitted when encoding named bitstrings in DER. + * + * \note This function works backwards within the data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer which is used for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + unsigned char *start, + const unsigned char *buf, + size_t bits ); + +/** + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The associated data to store. If this is \c NULL, + * no data is copied to the new or existing buffer. + * \param val_len The minimum length of the data buffer needed. + * If this is 0, do not allocate a buffer for the associated + * data. + * If the OID was already present, enlarge, shrink or free + * the existing buffer to fit \p val_len. + * + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/external/RSA PRX/RSA/mbedtls/base64.h b/external/RSA PRX/RSA/mbedtls/base64.h new file mode 100644 index 0000000..07ae3bf --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/base64.h @@ -0,0 +1,98 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/external/RSA PRX/RSA/mbedtls/bignum.h b/external/RSA PRX/RSA/mbedtls/bignum.h new file mode 100644 index 0000000..1d00c56 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/bignum.h @@ -0,0 +1,1019 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) || \ + defined(__aarch64__) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Import X from unsigned binary data, little endian + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param _RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p _RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p _RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Perform a Miller-Rabin primality test with error + * probability of 2-80. + * + * \deprecated Superseded by mbedtls_mpi_is_prime_ext() which allows + * specifying the number of Miller-Rabin rounds. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use a + * context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/external/RSA PRX/RSA/mbedtls/blowfish.h b/external/RSA PRX/RSA/mbedtls/blowfish.h new file mode 100644 index 0000000..1e5dba3 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/blowfish.h @@ -0,0 +1,287 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +/** + * \brief Blowfish context structure + */ +typedef struct mbedtls_blowfish_context +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +/** + * \brief Initialize a Blowfish context. + * + * \param ctx The Blowfish context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear a Blowfish context. + * + * \param ctx The Blowfish context to be cleared. + * This may be \c NULL, in which case this function + * returns immediately. If it is not \c NULL, it must + * point to an initialized Blowfish context. + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Perform a Blowfish key schedule operation. + * + * \param ctx The Blowfish context to perform the key schedule on. + * \param key The encryption key. This must be a readable buffer of + * length \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be between + * \c 32 and \c 448 and a multiple of \c 8. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a Blowfish-ECB block encryption/decryption operation. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param input The input block. This must be a readable buffer + * of size \c 8 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 8 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a Blowfish-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be + * multiple of \c 8. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 8 Bytes. It is updated by this function. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a Blowfish CFB buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. Possible values are + * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or + * #MBEDTLS_BLOWFISH_DECRYPT for decryption. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in the initialiation vector. + * The value pointed to must be smaller than \c 8 Bytes. + * It is updated by this function to support the aforementioned + * streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of size \c 8 Bytes. It is updated after use. + * \param input The input data. This must be a readable buffer of length + * \p length Bytes. + * \param output The output data. This must be a writable buffer of length + * \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a Blowfish-CTR buffer encryption/decryption operation. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The Blowfish context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data in Bytes. + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer + * should be \c 0 at the start of a stream and must be + * smaller than \c 8. It is updated by this function. + * \param nonce_counter The 64-bit nonce and counter. This must point to a + * read/write buffer of length \c 8 Bytes. + * \param stream_block The saved stream-block for resuming. This must point to + * a read/write buffer of length \c 8 Bytes. + * \param input The input data. This must be a readable buffer of + * length \p length Bytes. + * \param output The output data. This must be a writable buffer of + * length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#endif /* blowfish.h */ diff --git a/external/RSA PRX/RSA/mbedtls/bn_mul.h b/external/RSA PRX/RSA/mbedtls/bn_mul.h new file mode 100644 index 0000000..163869a --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/bn_mul.h @@ -0,0 +1,940 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__aarch64__) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr x4, [%2], #8 \n\t" \ + "ldr x5, [%1] \n\t" \ + "mul x6, x4, %3 \n\t" \ + "umulh x7, x4, %3 \n\t" \ + "adds x5, x5, x6 \n\t" \ + "adc x7, x7, xzr \n\t" \ + "adds x5, x5, %0 \n\t" \ + "adc %0, x7, xzr \n\t" \ + "str x5, [%1], #8 \n\t" + +#define MULADDC_STOP \ + : "+r" (c), "+r" (d), "+r" (s) \ + : "r" (b) \ + : "x4", "x5", "x6", "x7", "cc" \ + ); + +#endif /* Aarch64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/external/RSA PRX/RSA/mbedtls/camellia.h b/external/RSA PRX/RSA/mbedtls/camellia.h new file mode 100644 index 0000000..a832454 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/camellia.h @@ -0,0 +1,326 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 ) +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */ + +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ + +/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief Perform a CAMELLIA key schedule operation for encryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA key schedule operation for decryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. + * + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. + * + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ccm.h b/external/RSA PRX/RSA/mbedtls/ccm.h new file mode 100644 index 0000000..ceac36c --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ccm.h @@ -0,0 +1,310 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} +mbedtls_ccm_context; + +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. This must not be \c NULL. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. If \p add_len is greater than + * zero, \p add must be a readable buffer of at least that + * length. + * \param add_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer + * of at least that \p add_len Bytes.. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param add The additional data field. This must be a readable buffer of + * at least that \p add_len Bytes. + * \param add_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/external/RSA PRX/RSA/mbedtls/chacha20.h b/external/RSA PRX/RSA/mbedtls/chacha20.h new file mode 100644 index 0000000..243ae63 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/chacha20.h @@ -0,0 +1,226 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t state[16]; /*! The state (before round operations). */ + uint8_t keystream8[64]; /*! Leftover keystream bytes. */ + size_t keystream_bytes_used; /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/external/RSA PRX/RSA/mbedtls/chachapoly.h b/external/RSA PRX/RSA/mbedtls/chachapoly.h new file mode 100644 index 0000000..3d842ef --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/chachapoly.h @@ -0,0 +1,358 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* for shared error codes */ +#include "mbedtls/poly1305.h" + +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "mbedtls/chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */ + mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */ + uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */ + int state; /**< The current state of the context. */ + mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/external/RSA PRX/RSA/mbedtls/check_config.h b/external/RSA PRX/RSA/mbedtls/check_config.h new file mode 100644 index 0000000..ae7469e --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/check_config.h @@ -0,0 +1,567 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +#error "Mbed Crypto is no longer being updated. Please use Mbed TLS instead. See README.md." +#endif +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Mbed Crypto is no longer being updated. Please use Mbed TLS instead. See README.md." +#endif + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.py. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif + +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_TIMING_C) +#error "The TIMING module is not available for mbed OS - please use the timing functions provided by Mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ! defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT" +#endif + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \ + defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + !( defined(MBEDTLS_CTR_DRBG_C) && \ + defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + ! defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) && \ + !defined(MBEDTLS_FS_IO) +#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/external/RSA PRX/RSA/mbedtls/cipher.h b/external/RSA PRX/RSA/mbedtls/cipher.h new file mode 100644 index 0000000..96efd93 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/cipher.h @@ -0,0 +1,926 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ + +/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ + MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ + MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ + MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in Bytes. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /** Indicates whether the cipher operations should be performed + * by Mbed TLS' own crypto library or an external implementation + * of the PSA Crypto API. + * This is unset if the cipher context was established through + * mbedtls_cipher_setup(), and set if it was established through + * mbedtls_cipher_setup_psa(). + */ + unsigned char psa_enabled; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported + * by the generic cipher module. + * + * For any cipher identifier in the returned list, you can + * obtain the corresponding generic cipher information structure + * via mbedtls_cipher_info_from_type(), which can then be used + * to prepare a cipher context via mbedtls_cipher_setup(). + * + * + * \return A statically-allocated array of cipher identifiers + * of type cipher_type_t. The last entry is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes a cipher context for + * use with the given cipher primitive. + * + * \param ctx The context to initialize. This must be initialized. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. + * + * \param ctx The context to initialize. May not be \c NULL. + * \param cipher_info The cipher to use. + * \param taglen For AEAD ciphers, the length in bytes of the + * authentication tag to use. Subsequent uses of + * mbedtls_cipher_auth_encrypt() or + * mbedtls_cipher_auth_decrypt() must provide + * the same tag length. + * For non-AEAD ciphers, the value must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The block size of the underlying cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->cipher_info == NULL ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->cipher_info == NULL ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called exactly once, after + * mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad in Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, + size_t ilen, unsigned char *output, + size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer for the authentication tag. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The desired length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. This must be initialized and + * and bound to a key. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. This must be a + * readable buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * This must be able to hold at least \p ilen Bytes. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * \param tag The buffer holding the authentication tag. This must be + * a readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/external/RSA PRX/RSA/mbedtls/cipher_internal.h b/external/RSA PRX/RSA/mbedtls/cipher_internal.h new file mode 100644 index 0000000..5930f0e --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/cipher_internal.h @@ -0,0 +1,152 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +typedef enum +{ + MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, + MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ + /* use raw key material internally imported */ + /* as a volatile key, and which hence need */ + /* to destroy that key when the context is */ + /* freed. */ + MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ + /* which use a key provided by the */ + /* user, and which hence will not be */ + /* destroyed when the context is freed. */ +} mbedtls_cipher_psa_key_ownership; + +typedef struct +{ + psa_algorithm_t alg; + psa_key_handle_t slot; + mbedtls_cipher_psa_key_ownership slot_state; +} mbedtls_cipher_context_psa; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/external/RSA PRX/RSA/mbedtls/cmac.h b/external/RSA PRX/RSA/mbedtls/cmac.h new file mode 100644 index 0000000..792fbdc --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/cmac.h @@ -0,0 +1,213 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. + * + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. + * + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/external/RSA PRX/RSA/mbedtls/compat-1.3.h b/external/RSA PRX/RSA/mbedtls/compat-1.3.h new file mode 100644 index 0000000..361cf56 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/compat-1.3.h @@ -0,0 +1,2531 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN ( ( ( MBEDTLS_SSL_IN_BUFFER_LEN ) < ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) \ + ? ( MBEDTLS_SSL_IN_BUFFER_LEN ) : ( MBEDTLS_SSL_OUT_BUFFER_LEN ) ) +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/external/RSA PRX/RSA/mbedtls/config.h b/external/RSA PRX/RSA/mbedtls/config.h new file mode 100644 index 0000000..585d087 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/config.h @@ -0,0 +1,2145 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/** + * \def MBEDTLS_CHECK_PARAMS + * + * This configuration option controls whether the library validates more of + * the parameters passed to it. + * + * When this flag is not defined, the library only attempts to validate an + * input parameter if: (1) they may come from the outside world (such as the + * network, the filesystem, etc.) or (2) not validating them could result in + * internal memory errors such as overflowing a buffer controlled by the + * library. On the other hand, it doesn't attempt to validate parameters whose + * values are fully controlled by the application (such as pointers). + * + * When this flag is defined, the library additionally attempts to validate + * parameters that are fully controlled by the application, and should always + * be valid if the application code is fully correct and trusted. + * + * For example, when a function accepts as input a pointer to a buffer that may + * contain untrusted data, and its documentation mentions that this pointer + * must not be NULL: + * - The pointer is checked to be non-NULL only if this option is enabled. + * - The content of the buffer is always validated. + * + * When this flag is defined, if a library function receives a parameter that + * is invalid: + * 1. The function will invoke the macro MBEDTLS_PARAM_FAILED(). + * 2. If MBEDTLS_PARAM_FAILED() did not terminate the program, the function + * will immediately return. If the function returns an Mbed TLS error code, + * the error code in this case is MBEDTLS_ERR_xxx_BAD_INPUT_DATA. + * + * When defining this flag, you also need to arrange a definition for + * MBEDTLS_PARAM_FAILED(). You can do this by any of the following methods: + * - By default, the library defines MBEDTLS_PARAM_FAILED() to call a + * function mbedtls_param_failed(), but the library does not define this + * function. If you do not make any other arrangements, you must provide + * the function mbedtls_param_failed() in your application. + * See `platform_util.h` for its prototype. + * - If you enable the macro #MBEDTLS_CHECK_PARAMS_ASSERT, then the + * library defines MBEDTLS_PARAM_FAILED(\c cond) to be `assert(cond)`. + * You can still supply an alternative definition of + * MBEDTLS_PARAM_FAILED(), which may call `assert`. + * - If you define a macro MBEDTLS_PARAM_FAILED() before including `config.h` + * or you uncomment the definition of MBEDTLS_PARAM_FAILED() in `config.h`, + * the library will call the macro that you defined and will not supply + * its own version. Note that if MBEDTLS_PARAM_FAILED() calls `assert`, + * you need to enable #MBEDTLS_CHECK_PARAMS_ASSERT so that library source + * files include ``. + * + * Uncomment to enable validation of application-controlled parameters. + */ +//#define MBEDTLS_CHECK_PARAMS + +/** + * \def MBEDTLS_CHECK_PARAMS_ASSERT + * + * Allow MBEDTLS_PARAM_FAILED() to call `assert`, and make it default to + * `assert`. This macro is only used if #MBEDTLS_CHECK_PARAMS is defined. + * + * If this macro is not defined, then MBEDTLS_PARAM_FAILED() defaults to + * calling a function mbedtls_param_failed(). See the documentation of + * #MBEDTLS_CHECK_PARAMS for details. + * + * Uncomment to allow MBEDTLS_PARAM_FAILED() to call `assert`. + */ +//#define MBEDTLS_CHECK_PARAMS_ASSERT + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overridden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * This module is required to support the TLS ciphersuites that use the NULL + * cipher. + * + * Uncomment this macro to enable the NULL cipher + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in Mbed TLS's SSL module, + * MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in order + * to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum number + * of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT + * and MBEDTLS_ECDH_LEGACY_CONTEXT. + */ +//#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDH_LEGACY_CONTEXT + * + * Use a backward compatible ECDH context. + * + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + * + * Define this macro if you enable MBEDTLS_ECP_RESTARTABLE or if you + * want to access ECDH context fields directly. Otherwise you should + * comment out this macro definition. + * + * This option has no effect if #MBEDTLS_ECDH_C is not enabled. + * + * \note This configuration option is experimental. Future versions of the + * library may modify the way the ECDH context layout is configured + * and may modify the layout of the new context type. + */ +#define MBEDTLS_ECDH_LEGACY_CONTEXT + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + * + * In PSA key storage, encode the owner of the key. + * + * This is only meaningful when building the library as part of a + * multi-client service. When you activate this option, you must provide + * an implementation of the type psa_key_owner_id_t and a translation + * from psa_key_file_id_t to file name in all the storage backends that + * you wish to support. + * + * Note that this option is meant for internal use only and may be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_PSA_CRYPTO_SPM + * + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure + * Partition Manager) integration which separates the code into two parts: a + * NSPE (Non-Secure Process Environment) and an SPE (Secure Process + * Environment). + * + * Module: library/psa_crypto.c + * Requires: MBEDTLS_PSA_CRYPTO_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SPM + +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SHA512_SMALLER + * + * Enable an implementation of SHA-512 that has lower ROM footprint but also + * lower performance. + * + * Uncomment to enable the smaller implementation of SHA512. + */ +//#define MBEDTLS_SHA512_SMALLER + +/** + * \def MBEDTLS_SHA512_NO_SHA384 + * + * Disable the SHA-384 option of the SHA-512 module. Use this to save some + * code size on devices that don't use SHA-384. + * + * Requires: MBEDTLS_SHA512_C + * + * Uncomment to disable SHA-384 + */ +//#define MBEDTLS_SHA512_NO_SHA384 + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_USE_PSA_CRYPTO + * + * Make the X.509 and TLS library use PSA for cryptographic operations, and + * enable new APIs for using keys handled by PSA Crypto. + * + * \note Development of this option is currently in progress, and parts of Mbed + * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts + * will still continue to work as usual, so enabling this option should not + * break backwards compatibility. + * + * \warning Support for PSA is still an experimental feature. + * Any public API that depends on this option may change + * at any time until this warning is removed. + * + * \warning This option enables new Mbed TLS APIs that are dependent on the + * PSA Crypto API, so can't come with the same stability guarantees as the + * rest of the Mbed TLS APIs. You're welcome to experiment with them, but for + * now, access to these APIs is opt-in (via enabling the present option), in + * order to clearly differentiate them from the stable Mbed TLS APIs. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * Uncomment this to enable internal use of PSA Crypto and new associated APIs. + */ +//#define MBEDTLS_USE_PSA_CRYPTO + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module is required to support the TLS ciphersuites that use the AES + * cipher. + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module is required to support the TLS ciphersuites that use the ARC4 + * cipher. + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module is required to support the TLS ciphersuites that use the + * Camellia cipher. + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module is required to support the TLS ciphersuites that use the + * ARIA cipher. + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module is required to support AES-CCM ciphersuites in TLS. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module is required to support the TLS ciphersuites that use the DES + * cipher. + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM). + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C + * + * This module is required to support the TLS ciphersuites that use GCM. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_PSA_CRYPTO_C + * + * Enable the Platform Security Architecture cryptography API. + * + * \warning The PSA Crypto API is still beta status. While you're welcome to + * experiment using it, incompatible API changes are still possible, and some + * parts may not have reached the same quality as the rest of Mbed TLS yet. + * + * Module: library/psa_crypto.c + * + * Requires: MBEDTLS_CTR_DRBG_C, MBEDTLS_ENTROPY_C + * + */ +#define MBEDTLS_PSA_CRYPTO_C + +/** + * \def MBEDTLS_PSA_CRYPTO_SE_C + * + * Enable secure element support in the Platform Security Architecture + * cryptography API. + * + * \warning This feature is not yet suitable for production. It is provided + * for API evaluation and testing purposes only. + * + * Module: library/psa_crypto_se.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SE_C + +/** + * \def MBEDTLS_PSA_CRYPTO_STORAGE_C + * + * Enable the Platform Security Architecture persistent key storage. + * + * Module: library/psa_crypto_storage.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, + * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of + * the PSA ITS interface + */ +#define MBEDTLS_PSA_CRYPTO_STORAGE_C + +/** + * \def MBEDTLS_PSA_ITS_FILE_C + * + * Enable the emulation of the Platform Security Architecture + * Internal Trusted Storage (PSA ITS) over files. + * + * Module: library/psa_its_file.c + * + * Requires: MBEDTLS_FS_IO + */ +#define MBEDTLS_PSA_ITS_FILE_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by Mbed + * TLS's \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and + * provide your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** + * \brief This macro is invoked by the library when an invalid parameter + * is detected that is only checked with #MBEDTLS_CHECK_PARAMS + * (see the documentation of that option for context). + * + * When you leave this undefined here, the library provides + * a default definition. If the macro #MBEDTLS_CHECK_PARAMS_ASSERT + * is defined, the default definition is `assert(cond)`, + * otherwise the default definition calls a function + * mbedtls_param_failed(). This function is declared in + * `platform_util.h` for the benefit of the library, but + * you need to define in your application. + * + * When you define this here, this replaces the default + * definition in platform_util.h (which no longer declares the + * function mbedtls_param_failed()) and it is your responsibility + * to make sure this macro expands to something suitable (in + * particular, that all the necessary declarations are visible + * from within the library - you can ensure that by providing + * them in this file next to the macro definition). + * If you define this macro to call `assert`, also define + * #MBEDTLS_CHECK_PARAMS_ASSERT so that library source files + * include ``. + * + * Note that you may define this macro to expand to nothing, in + * which case you don't have to worry about declarations or + * definitions. However, you will then be notified about invalid + * parameters only in non-void functions, and void function will + * just silently return early on invalid parameters, which + * partially negates the benefits of enabling + * #MBEDTLS_CHECK_PARAMS in the first place, so is discouraged. + * + * \param cond The expression that should evaluate to true, but doesn't. + */ +//#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/** + * Enable the verified implementations of ECDH primitives from Project Everest + * (currently only Curve25519). This feature changes the layout of ECDH + * contexts and therefore is a compatibility break for applications that access + * fields of a mbedtls_ecdh_context structure directly. See also + * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. + */ +//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/external/RSA PRX/RSA/mbedtls/ctr_drbg.h b/external/RSA PRX/RSA/mbedtls/ctr_drbg.h new file mode 100644 index 0000000..234e6a0 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ctr_drbg.h @@ -0,0 +1,562 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * + * The security strength as defined in NIST SP 800-90A is + * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * kept at its default value (and not overridden in config.h) and that the + * DRBG instance is set up with default parameters. + * See the documentation of mbedtls_ctr_drbg_seed() for more + * information. + */ +/* + * Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them using the compiler command + * line. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + */ +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer in bytes. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** The default length of the nonce read from the entropy source. + * + * This is \c 0 because a single read from the entropy source is sufficient + * to include a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 +#else +/** The default length of the nonce read from the entropy source. + * + * This is half of the default entropy length because a single read from + * the entropy source does not provide enough material to form a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2 +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. + * This is the number of requests that have + * been made since the last (re)seeding, + * minus one. + * Before the initial seeding, this field + * contains the amount of entropy in bytes + * to use as a nonce for the initial seeding, + * or -1 if no nonce length has been explicitly + * set (see mbedtls_ctr_drbg_set_nonce_len()). + */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int reseed_interval; /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * The entropy nonce length is: + * - \c 0 if the entropy length is at least 3/2 times the entropy length, + * which guarantees that the security strength is the maximum permitted + * by the key size and entropy length according to NIST SP 800-90A §10.2.1; + * - Half the entropy length otherwise. + * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). + * With the default entropy length, the entropy nonce length is + * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. + * + * You can provide a nonce and personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * See SP 800-90A §8.6.7 for more details about nonces. + * + * The _seed_material_ value passed to the derivation function in + * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the following strings: + * - A string obtained by calling \p f_entropy function for the entropy + * length. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 +/** + * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string + * obtained by calling \p f_entropy function for the specified length. + */ +#else +/** + * - A string obtained by calling \p f_entropy function for the entropy nonce + * length. If the entropy nonce length is \c 0, this function does not + * make a second call to \p f_entropy. + */ +#endif +/** + * - The \p custom string. + * + * \note To achieve the nominal security strength permitted + * by CTR_DRBG, the entropy length must be: + * - at least 16 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 32 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * In addition, if you do not pass a nonce in \p custom, + * the sum of the entropy length + * and the entropy nonce length must be: + * - at least 24 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 48 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the amount of entropy grabbed + * as a nonce for the initial seeding. + * + * Call this function before calling mbedtls_ctr_drbg_seed() to read + * a nonce from the entropy source during the initial seeding. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab for the nonce, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is + * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * if the initial seeding has already taken place. + */ +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \deprecated Superseded by mbedtls_ctr_drbg_update_ret() + * in 2.16.0. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + */ +MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( + mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/external/RSA PRX/RSA/mbedtls/des.h b/external/RSA PRX/RSA/mbedtls/des.h new file mode 100644 index 0000000..1c80b53 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/des.h @@ -0,0 +1,356 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/external/RSA PRX/RSA/mbedtls/dhm.h b/external/RSA PRX/RSA/mbedtls/dhm.h new file mode 100644 index 0000000..831cfd7 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/dhm.h @@ -0,0 +1,1093 @@ +/** + * \file dhm.h + * + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "mbedtls/bignum.h" + +/* + * DHM Error codes + */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read or write of file failed. */ + +/* MBEDTLS_ERR_DHM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_DHM_HW_ACCEL_FAILED -0x3500 /**< DHM hardware accelerator failed. */ + +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 /**< Setting the modulus and generator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context +{ + size_t len; /*!< The size of \p P in Bytes. */ + mbedtls_mpi P; /*!< The prime modulus. */ + mbedtls_mpi G; /*!< The generator. */ + mbedtls_mpi X; /*!< Our secret value. */ + mbedtls_mpi GX; /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi GY; /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi K; /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi RP; /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi Vi; /*!< The blinding value. */ + mbedtls_mpi Vf; /*!< The unblinding value. */ + mbedtls_mpi pX; /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). + * + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. + * + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function sets the prime modulus and generator. + * + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). + * + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. + * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function frees and clears the components + * of a DHM context. + * + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of Diffie-Hellman + * groups, some of which are included here for use by Mbed TLS's SSL/TLS module + * and the user's convenience when configuring the Diffie-Hellman parameters by + * hand through Mbed TLS's \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/** + * \warning The origin of the primes in RFC 5114 is not documented and + * their use therefore constitutes a security risk! + * + * \deprecated The hex-encoded primes from RFC 5114 are deprecated and are + * likely to be removed in a future version of the library without + * replacement. + */ + +/** + * The hexadecimal presentation of the prime underlying the + * 2048-bit MODP Group with 224-bit Prime Order Subgroup, as defined + * in RFC-5114: Additional Diffie-Hellman Groups for Use with + * IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ + "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ + "CF9DE5384E71B81C0AC4DFFE0C10E64F" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group with 224-bit Prime Order Subgroup, as defined in RFC-5114: + * Additional Diffie-Hellman Groups for Use with IETF Standards. + */ +#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" \ + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" \ + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" \ + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" \ + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" \ + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" \ + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" \ + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" \ + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" \ + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" \ + "81BC087F2A7065B384B890D3191F2BFA" ) + +/** + * The hexadecimal presentation of the prime underlying the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + * + * \deprecated The hex-encoded primes from RFC 3625 are deprecated and + * superseded by the corresponding macros providing them as + * binary constants. Their hex-encoded constants are likely + * to be removed in a future version of the library. + * + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AACAA68FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 2048-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_2048_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 3072-bit MODP + * Group, as defined in RFC-3072: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 3072-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_3072_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +/** + * The hexadecimal presentation of the prime underlying the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( \ + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ + "FFFFFFFFFFFFFFFF" ) + +/** + * The hexadecimal presentation of the chosen generator of the 4096-bit MODP + * Group, as defined in RFC-3526: More Modular Exponential (MODP) + * Diffie-Hellman groups for Internet Key Exchange (IKE). + */ +#define MBEDTLS_DHM_RFC3526_MODP_4096_G \ + MBEDTLS_DEPRECATED_STRING_CONSTANT( "02" ) + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ecdh.h b/external/RSA PRX/RSA/mbedtls/ecdh.h new file mode 100644 index 0000000..3948d7c --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ecdh.h @@ -0,0 +1,448 @@ +/** + * \file ecdh.h + * + * \brief This file contains ECDH definitions and functions. + * + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#include "everest/everest.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key. + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ +} mbedtls_ecdh_side; + +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ +#endif +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group grp; /*!< The elliptic curve used. */ + mbedtls_mpi d; /*!< The private key. */ + mbedtls_ecp_point Q; /*!< The public key. */ + mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */ + mbedtls_mpi z; /*!< The shared secret. */ + int point_format; /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point Vi; /*!< The blinding value. */ + mbedtls_ecp_point Vf; /*!< The unblinding value. */ + mbedtls_mpi _d; /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t point_format; /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */ + mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed mbed_ecdh; +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + mbedtls_ecdh_context_everest everest_ecdh; +#endif + } ctx; /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +} +mbedtls_ecdh_context; + +/** + * \brief Check whether a given group can be used for ECDH. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results during the ECP computations is + * not needed (discouraged). See the documentation of + * mbedtls_ecp_mul() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. This must not be \c NULL. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. + * + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. + * + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. + * + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function, for blinding purposes. This may + * b \c NULL if blinding isn't needed. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ecdsa.h b/external/RSA PRX/RSA/mbedtls/ecdsa.h new file mode 100644 index 0000000..b009e73 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ecdsa.h @@ -0,0 +1,628 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +/** + * \brief Maximum ECDSA signature size for a given curve bit size + * + * \param bits Curve size in bits + * \return Maximum signature size in bytes + * + * \note This macro returns a compile-time constant if its argument + * is one. It may evaluate its argument multiple times. + */ +/* + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * For each of r and s, the value (V) may include an extra initial "0" bit. + */ +#define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \ + ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \ + /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \ + /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) ) + +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function checks whether a given group can be used + * for ECDSA. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is used only for blinding and may be set to \c NULL, but + * doing so is DEPRECATED. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param md_alg The message digest that was used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets up an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ecjpake.h b/external/RSA PRX/RSA/mbedtls/ecjpake.h new file mode 100644 index 0000000..97387c3 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ecjpake.h @@ -0,0 +1,277 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +#if !defined(MBEDTLS_ECJPAKE_ALT) +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct mbedtls_ecjpake_context +{ + const mbedtls_md_info_t *md_info; /**< Hash to use */ + mbedtls_ecp_group grp; /**< Elliptic curve */ + mbedtls_ecjpake_role role; /**< Are we client or server? */ + int point_format; /**< Format for point export */ + + mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + +/** + * \brief Initialize an ECJPAKE context. + * + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up an ECJPAKE context for use. + * + * \note Currently the only values for hash/curve allowed by the + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Check if an ECJPAKE context is ready for use. + * + * \param ctx The ECJPAKE context to check. This must be + * initialized. + * + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. + * + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ecjpake.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ecp.h b/external/RSA PRX/RSA/mbedtls/ecp.h new file mode 100644 index 0000000..d04cc49 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ecp.h @@ -0,0 +1,1185 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_ECP_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ + +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + * + * \note Montgomery curves are currently excluded. + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/* + * Curve types + */ +typedef enum +{ + MBEDTLS_ECP_TYPE_NONE = 0, + MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} mbedtls_ecp_curve_type; + +/** + * Curve information, for use by other modules. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations must keep the group IDs distinct. If + * two group structures have the same ID, then they must be + * identical. + * + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h, or define them using the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation mentions + * they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * `MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS` for functions in the + * Mbed TLS SSL module). For functions that accept a "restart + * context" argument, passing NULL disables restart and makes + * the function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts an + * "ECDH context" argument and mbedtls_ecdh_enable_restart() + * was previously called on that context. For function in the + * Mbed TLS SSL module, restart is only enabled for specific + * sides and key exchanges (currently only for clients and + * ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ); + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to the point at infinity. + * + * \param pt The point to set. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is the point at infinity. + * + * \param pt The point to test. This must be initialized. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * (For groups without these formats, this parameter is + * ignored. But it still has to be either of the above + * values.) + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * or the export for the given group is not implemented. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the + * given group is not implemented. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); + +/** + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. + * + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This may be \c NULL if randomization + * of intermediate results isn't desired (discouraged). + * \param p_rng The RNG context to be passed to \p p_rng. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function reads an elliptic curve private key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param buf The the buffer containing the binary representation of the + * key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is + * invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ); +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, + const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/external/RSA PRX/RSA/mbedtls/ecp_internal.h b/external/RSA PRX/RSA/mbedtls/ecp_internal.h new file mode 100644 index 0000000..3b6fbf1 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ecp_internal.h @@ -0,0 +1,299 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright (C) 2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* ECP_MONTGOMERY */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/external/RSA PRX/RSA/mbedtls/entropy.h b/external/RSA PRX/RSA/mbedtls/entropy.h new file mode 100644 index 0000000..06aaffa --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/entropy.h @@ -0,0 +1,289 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "mbedtls/sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "mbedtls/sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int accumulator_started; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/external/RSA PRX/RSA/mbedtls/entropy_poll.h b/external/RSA PRX/RSA/mbedtls/entropy_poll.h new file mode 100644 index 0000000..ba42805 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/entropy_poll.h @@ -0,0 +1,110 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/external/RSA PRX/RSA/mbedtls/error.h b/external/RSA PRX/RSA/mbedtls/error.h new file mode 100644 index 0000000..82b0188 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/error.h @@ -0,0 +1,134 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) + * + * Module Nr Codes assigned + * ERROR 2 0x006E 0x0001 + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 2 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 1 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 24 (Started from top, plus 0x6000) + * SSL 7 32 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /**< Generic error */ +#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /**< This is a bug in the library */ + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/external/RSA PRX/RSA/mbedtls/gcm.h b/external/RSA PRX/RSA/mbedtls/gcm.h new file mode 100644 index 0000000..a71a2af --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/gcm.h @@ -0,0 +1,326 @@ +/** + * \file gcm.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ + +/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */ + +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ + uint64_t HL[16]; /*!< Precalculated HTable low. */ + uint64_t HH[16]; /*!< Precalculated HTable high. */ + uint64_t len; /*!< The total length of the encrypted data. */ + uint64_t add_len; /*!< The total length of the additional data. */ + unsigned char base_ectr[16]; /*!< The first ECTR for tag. */ + unsigned char y[16]; /*!< The Y working value. */ + unsigned char buf[16]; /*!< The buf working value. */ + int mode; /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * ` The function expects input to be a multiple of 16 + * Bytes. Only the last call before calling + * mbedtls_gcm_finish() can be less than 16 Bytes. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the input data. This must be a multiple of + * 16 except in the last call before mbedtls_gcm_finish(). + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is + * greater than zero, this must be a writable buffer of at + * least that size in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ diff --git a/external/RSA PRX/RSA/mbedtls/havege.h b/external/RSA PRX/RSA/mbedtls/havege.h new file mode 100644 index 0000000..acd7e48 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/havege.h @@ -0,0 +1,82 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief HAVEGE state structure + */ +typedef struct mbedtls_havege_state +{ + uint32_t PT1, PT2, offset[2]; + uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; + uint32_t WALK[8192]; +} +mbedtls_havege_state; + +/** + * \brief HAVEGE initialization + * + * \param hs HAVEGE state to be initialized + */ +void mbedtls_havege_init( mbedtls_havege_state *hs ); + +/** + * \brief Clear HAVEGE state + * + * \param hs HAVEGE state to be cleared + */ +void mbedtls_havege_free( mbedtls_havege_state *hs ); + +/** + * \brief HAVEGE rand function + * + * \param p_rng A HAVEGE state + * \param output Buffer to fill + * \param len Length of buffer + * + * \return 0 + */ +int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* havege.h */ diff --git a/external/RSA PRX/RSA/mbedtls/hkdf.h b/external/RSA PRX/RSA/mbedtls/hkdf.h new file mode 100644 index 0000000..77a99ab --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/hkdf.h @@ -0,0 +1,141 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright (C) 2018-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +/** + * \name HKDF Error codes + * \{ + */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/external/RSA PRX/RSA/mbedtls/hmac_drbg.h b/external/RSA PRX/RSA/mbedtls/hmac_drbg.h new file mode 100644 index 0000000..00be9df --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/hmac_drbg.h @@ -0,0 +1,415 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright (C) 2006-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct mbedtls_hmac_drbg_context +{ + /* Working state: the key K is not stored explicitly, + * but is implied by the HMAC context */ + mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ + unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int reseed_counter; /*!< reseed counter */ + + /* Administrative state */ + size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ + int prediction_resistance; /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int reseed_interval; /*!< reseed interval */ + + /* Callbacks */ + int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ + void *p_entropy; /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + * + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + * + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief Free an HMAC_DRBG context + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() + * in 2.16.0. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + */ +MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( + mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/external/RSA PRX/RSA/mbedtls/md.h b/external/RSA PRX/RSA/mbedtls/md.h new file mode 100644 index 0000000..0b0ec91 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/md.h @@ -0,0 +1,474 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ + +/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/external/RSA PRX/RSA/mbedtls/md2.h b/external/RSA PRX/RSA/mbedtls/md2.h new file mode 100644 index 0000000..df1d5f7 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/md2.h @@ -0,0 +1,306 @@ +/** + * \file md2.h + * + * \brief MD2 message digest algorithm (hash function) + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD2_ALT) +// Regular implementation +// + +/** + * \brief MD2 context structure + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md2_context +{ + unsigned char cksum[16]; /*!< checksum of the data block */ + unsigned char state[48]; /*!< intermediate digest state */ + unsigned char buffer[16]; /*!< data block being processed */ + size_t left; /*!< amount of data in buffer */ +} +mbedtls_md2_context; + +#else /* MBEDTLS_MD2_ALT */ +#include "md2_alt.h" +#endif /* MBEDTLS_MD2_ALT */ + +/** + * \brief Initialize MD2 context + * + * \param ctx MD2 context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_init( mbedtls_md2_context *ctx ); + +/** + * \brief Clear MD2 context + * + * \param ctx MD2 context to be cleared + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_free( mbedtls_md2_context *ctx ); + +/** + * \brief Clone (the state of) an MD2 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md2_clone( mbedtls_md2_context *dst, + const mbedtls_md2_context *src ); + +/** + * \brief MD2 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_update_ret( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \param ctx MD2 context + * + * \return 0 if successful + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md2_process( mbedtls_md2_context *ctx ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD2 context setup + * + * \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx ); + +/** + * \brief MD2 process buffer + * + * \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD2 final digest + * + * \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0 + * + * \param ctx MD2 context + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD2 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0 + * + * \param ctx MD2 context + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD2( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD2( input buffer ) + * + * \deprecated Superseded by mbedtls_md2_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD2 checksum result + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD2 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md2_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md2.h */ diff --git a/external/RSA PRX/RSA/mbedtls/md4.h b/external/RSA PRX/RSA/mbedtls/md4.h new file mode 100644 index 0000000..e7accd4 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/md4.h @@ -0,0 +1,311 @@ +/** + * \file md4.h + * + * \brief MD4 message digest algorithm (hash function) + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message digests + * instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD4_ALT) +// Regular implementation +// + +/** + * \brief MD4 context structure + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md4_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md4_context; + +#else /* MBEDTLS_MD4_ALT */ +#include "md4_alt.h" +#endif /* MBEDTLS_MD4_ALT */ + +/** + * \brief Initialize MD4 context + * + * \param ctx MD4 context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_init( mbedtls_md4_context *ctx ); + +/** + * \brief Clear MD4 context + * + * \param ctx MD4 context to be cleared + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_free( mbedtls_md4_context *ctx ); + +/** + * \brief Clone (the state of) an MD4 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md4_clone( mbedtls_md4_context *dst, + const mbedtls_md4_context *src ); + +/** + * \brief MD4 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + */ +int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_update_ret( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD4 context setup + * + * \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx ); + +/** + * \brief MD4 process buffer + * + * \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD4 final digest + * + * \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0 + * + * \param ctx MD4 context + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD4 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0 + * + * \param ctx MD4 context + * \param data buffer holding one block of data + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD4( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \return 0 if successful + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD4( input buffer ) + * + * \deprecated Superseded by mbedtls_md4_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD4 checksum result + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD4 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md4_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md4.h */ diff --git a/external/RSA PRX/RSA/mbedtls/md5.h b/external/RSA PRX/RSA/mbedtls/md5.h new file mode 100644 index 0000000..4206c1f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/md5.h @@ -0,0 +1,311 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/external/RSA PRX/RSA/mbedtls/md_internal.h b/external/RSA PRX/RSA/mbedtls/md_internal.h new file mode 100644 index 0000000..0922dff --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/md_internal.h @@ -0,0 +1,92 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Name of the message digest */ + const char * name; + + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Output length of the digest function in bytes */ + unsigned char size; + + /** Block length of the digest function in bytes */ + unsigned char block_size; +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/external/RSA PRX/RSA/mbedtls/memory_buffer_alloc.h b/external/RSA PRX/RSA/mbedtls/memory_buffer_alloc.h new file mode 100644 index 0000000..8e77f6f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,151 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/external/RSA PRX/RSA/mbedtls/nist_kw.h b/external/RSA PRX/RSA/mbedtls/nist_kw.h new file mode 100644 index 0000000..b39406f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/nist_kw.h @@ -0,0 +1,184 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright (C) 2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/external/RSA PRX/RSA/mbedtls/oid.h b/external/RSA PRX/RSA/mbedtls/oid.h new file mode 100644 index 0000000..59ce020 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/oid.h @@ -0,0 +1,649 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" + +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/external/RSA PRX/RSA/mbedtls/padlock.h b/external/RSA PRX/RSA/mbedtls/padlock.h new file mode 100644 index 0000000..513d72f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/padlock.h @@ -0,0 +1,126 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param feature The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/external/RSA PRX/RSA/mbedtls/pem.h b/external/RSA PRX/RSA/mbedtls/pem.h new file mode 100644 index 0000000..f7bf1a6 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/pem.h @@ -0,0 +1,146 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/external/RSA PRX/RSA/mbedtls/pk.h b/external/RSA PRX/RSA/mbedtls/pk.h new file mode 100644 index 0000000..99e7a55 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/pk.h @@ -0,0 +1,881 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ + +/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in pk_wrap will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ + void * rs_ctx; /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC key pair + * (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC key + * pairs (that is, ECC keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key handle). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign()) + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \note Only ECDSA keys are supported so far. Signing with the + * specified hash is the only allowed use of that key. + * + * \param pk Input: the EC key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param handle Output: a PSA key handle. + * It's the caller's responsibility to call + * psa_destroy_key() on that handle after calling + * mbedtls_pk_free() on the PK context. + * \param hash_alg The hash algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_handle_t *handle, + psa_algorithm_t hash_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/external/RSA PRX/RSA/mbedtls/pk_internal.h b/external/RSA PRX/RSA/mbedtls/pk_internal.h new file mode 100644 index 0000000..7ef6322 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/pk_internal.h @@ -0,0 +1,142 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/external/RSA PRX/RSA/mbedtls/pkcs12.h b/external/RSA PRX/RSA/mbedtls/pkcs12.h new file mode 100644 index 0000000..9d42d7f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/pkcs12.h @@ -0,0 +1,130 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/asn1.h" + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/external/RSA PRX/RSA/mbedtls/pkcs5.h b/external/RSA PRX/RSA/mbedtls/pkcs5.h new file mode 100644 index 0000000..bbec7e7 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/pkcs5.h @@ -0,0 +1,109 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/asn1.h" +#include "mbedtls/md.h" + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/external/RSA PRX/RSA/mbedtls/platform.h b/external/RSA PRX/RSA/mbedtls/platform.h new file mode 100644 index 0000000..b402f8f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/platform.h @@ -0,0 +1,419 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 /**< Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 /**< The requested feature is not supported by the platform */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* The older Microsoft Windows common runtime provides non-conforming + * implementations of some standard library functions, including snprintf + * and vsnprintf. This affects MSVC and MinGW builds. + */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF +#endif + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for vsnprintf + * + * The vsnprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ); +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#include +extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg ); + +/** + * \brief Set your own snprintf function pointer + * + * \param vsnprintf_func The \c vsnprintf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, va_list arg ) ); +#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO +#else +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/external/RSA PRX/RSA/mbedtls/platform_time.h b/external/RSA PRX/RSA/mbedtls/platform_time.h new file mode 100644 index 0000000..fe484fd --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/platform_time.h @@ -0,0 +1,82 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/external/RSA PRX/RSA/mbedtls/platform_util.h b/external/RSA PRX/RSA/mbedtls/platform_util.h new file mode 100644 index 0000000..cf0130a --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/platform_util.h @@ -0,0 +1,196 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) + +#if defined(MBEDTLS_CHECK_PARAMS_ASSERT) +/* Allow the user to define MBEDTLS_PARAM_FAILED to something like assert + * (which is what our config.h suggests). */ +#include +#endif /* MBEDTLS_CHECK_PARAMS_ASSERT */ + +#if defined(MBEDTLS_PARAM_FAILED) +/** An alternative definition of MBEDTLS_PARAM_FAILED has been set in config.h. + * + * This flag can be used to check whether it is safe to assume that + * MBEDTLS_PARAM_FAILED() will expand to a call to mbedtls_param_failed(). + */ +#define MBEDTLS_PARAM_FAILED_ALT + +#elif defined(MBEDTLS_CHECK_PARAMS_ASSERT) +#define MBEDTLS_PARAM_FAILED( cond ) assert( cond ) +#define MBEDTLS_PARAM_FAILED_ALT + +#else /* MBEDTLS_PARAM_FAILED */ +#define MBEDTLS_PARAM_FAILED( cond ) \ + mbedtls_param_failed( #cond, __FILE__, __LINE__ ) + +/** + * \brief User supplied callback function for parameter validation failure. + * See #MBEDTLS_CHECK_PARAMS for context. + * + * This function will be called unless an alternative treatement + * is defined through the #MBEDTLS_PARAM_FAILED macro. + * + * This function can return, and the operation will be aborted, or + * alternatively, through use of setjmp()/longjmp() can resume + * execution in the application code. + * + * \param failure_condition The assertion that didn't hold. + * \param file The file where the assertion failed. + * \param line The line in the file where the assertion failed. + */ +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ); +#endif /* MBEDTLS_PARAM_FAILED */ + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return( ret ); \ + } \ + } while( 0 ) + +/* Internal macro meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE( cond ) \ + do { \ + if( !(cond) ) \ + { \ + MBEDTLS_PARAM_FAILED( cond ); \ + return; \ + } \ + } while( 0 ) + +#else /* MBEDTLS_CHECK_PARAMS */ + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#endif /* MBEDTLS_CHECK_PARAMS */ + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +/* Deliberately don't (yet) export MBEDTLS_DEPRECATED here + * to avoid conflict with other headers which define and use + * it, too. We might want to move all these definitions here at + * some point for uniformity. */ +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#undef MBEDTLS_DEPRECATED +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/external/RSA PRX/RSA/mbedtls/poly1305.h b/external/RSA PRX/RSA/mbedtls/poly1305.h new file mode 100644 index 0000000..05866a2 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/poly1305.h @@ -0,0 +1,192 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 /**< Invalid input parameter(s). */ + +/* MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE -0x0059 /**< Feature not available. For example, s part of the API is not implemented. */ + +/* MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED -0x005B /**< Poly1305 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t r[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t s[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t acc[5]; /** The accumulator number. */ + uint8_t queue[16]; /** The current partial block of data. */ + size_t queue_len; /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/external/RSA PRX/RSA/mbedtls/psa_util.h b/external/RSA PRX/RSA/mbedtls/psa_util.h new file mode 100644 index 0000000..513bc5f --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/psa_util.h @@ -0,0 +1,422 @@ +/** + * \file psa_util.h + * + * \brief Utility functions for the use of the PSA Crypto library. + * + * \warning This function is not part of the public API and may + * change at any time. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PSA_UTIL_H +#define MBEDTLS_PSA_UTIL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" + +#include + +/* Translations for symmetric crypto. */ + +static inline psa_key_type_t mbedtls_psa_translate_cipher_type( + mbedtls_cipher_type_t cipher ) +{ + switch( cipher ) + { + case MBEDTLS_CIPHER_AES_128_CCM: + case MBEDTLS_CIPHER_AES_192_CCM: + case MBEDTLS_CIPHER_AES_256_CCM: + case MBEDTLS_CIPHER_AES_128_GCM: + case MBEDTLS_CIPHER_AES_192_GCM: + case MBEDTLS_CIPHER_AES_256_GCM: + case MBEDTLS_CIPHER_AES_128_CBC: + case MBEDTLS_CIPHER_AES_192_CBC: + case MBEDTLS_CIPHER_AES_256_CBC: + return( PSA_KEY_TYPE_AES ); + + /* ARIA not yet supported in PSA. */ + /* case MBEDTLS_CIPHER_ARIA_128_CCM: + case MBEDTLS_CIPHER_ARIA_192_CCM: + case MBEDTLS_CIPHER_ARIA_256_CCM: + case MBEDTLS_CIPHER_ARIA_128_GCM: + case MBEDTLS_CIPHER_ARIA_192_GCM: + case MBEDTLS_CIPHER_ARIA_256_GCM: + case MBEDTLS_CIPHER_ARIA_128_CBC: + case MBEDTLS_CIPHER_ARIA_192_CBC: + case MBEDTLS_CIPHER_ARIA_256_CBC: + return( PSA_KEY_TYPE_ARIA ); */ + + default: + return( 0 ); + } +} + +static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( + mbedtls_cipher_mode_t mode, size_t taglen ) +{ + switch( mode ) + { + case MBEDTLS_MODE_GCM: + return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) ); + case MBEDTLS_MODE_CCM: + return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_CCM, taglen ) ); + case MBEDTLS_MODE_CBC: + if( taglen == 0 ) + return( PSA_ALG_CBC_NO_PADDING ); + /* Intentional fallthrough for taglen != 0 */ + /* fallthrough */ + default: + return( 0 ); + } +} + +static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation( + mbedtls_operation_t op ) +{ + switch( op ) + { + case MBEDTLS_ENCRYPT: + return( PSA_KEY_USAGE_ENCRYPT ); + case MBEDTLS_DECRYPT: + return( PSA_KEY_USAGE_DECRYPT ); + default: + return( 0 ); + } +} + +/* Translations for hashing. */ + +static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg ) +{ + switch( md_alg ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( PSA_ALG_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( PSA_ALG_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( PSA_ALG_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( PSA_ALG_SHA_1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( PSA_ALG_SHA_224 ); + case MBEDTLS_MD_SHA256: + return( PSA_ALG_SHA_256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( PSA_ALG_SHA_384 ); + case MBEDTLS_MD_SHA512: + return( PSA_ALG_SHA_512 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( PSA_ALG_RIPEMD160 ); +#endif + case MBEDTLS_MD_NONE: /* Intentional fallthrough */ + default: + return( 0 ); + } +} + +/* Translations for ECC. */ + +static inline int mbedtls_psa_get_ecc_oid_from_id( + psa_ecc_curve_t curve, size_t bits, + char const **oid, size_t *oid_len ) +{ + switch( curve ) + { + case PSA_ECC_CURVE_SECP_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_SECP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case 521: + *oid = MBEDTLS_OID_EC_GRP_SECP521R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + } + break; + case PSA_ECC_CURVE_SECP_K1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + } + break; + case PSA_ECC_CURVE_BRAINPOOL_P_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_BP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_BP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case 512: + *oid = MBEDTLS_OID_EC_GRP_BP512R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + } + break; + } + (void) oid; + (void) oid_len; + return( -1 ); +} + +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +/* Translations for PK layer */ + +static inline int mbedtls_psa_err_translate_pk( psa_status_t status ) +{ + switch( status ) + { + case PSA_SUCCESS: + return( 0 ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + case PSA_ERROR_BAD_STATE: + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + /* All other failures */ + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + case PSA_ERROR_CORRUPTION_DETECTED: + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + default: /* We return the same as for the 'other failures', + * but list them separately nonetheless to indicate + * which failure conditions we have considered. */ + return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED ); + } +} + +/* Translations for ECC */ + +/* This function transforms an ECC group identifier from + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * into a PSA ECC group identifier. */ +#if defined(MBEDTLS_ECP_C) +static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( + uint16_t tls_ecc_grp_reg_id, size_t *bits ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id ); + if( curve_info == NULL ) + return( 0 ); + return( PSA_KEY_TYPE_ECC_KEY_PAIR( + mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) ); +} +#endif /* MBEDTLS_ECP_C */ + +/* This function takes a buffer holding an EC public key + * exported through psa_export_public_key(), and converts + * it into an ECPoint structure to be put into a ClientKeyExchange + * message in an ECDHE exchange. + * + * Both the present and the foreseeable future format of EC public keys + * used by PSA have the ECPoint structure contained in the exported key + * as a subbuffer, and the function merely selects this subbuffer instead + * of making a copy. + */ +static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src, + size_t srclen, + unsigned char **dst, + size_t *dstlen ) +{ + *dst = src; + *dstlen = srclen; + return( 0 ); +} + +/* This function takes a buffer holding an ECPoint structure + * (as contained in a TLS ServerKeyExchange message for ECDHE + * exchanges) and converts it into a format that the PSA key + * agreement API understands. + */ +static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, + size_t srclen, + unsigned char *dst, + size_t dstlen, + size_t *olen ) +{ + if( srclen > dstlen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( dst, src, srclen ); + *olen = srclen; + return( 0 ); +} + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/external/RSA PRX/RSA/mbedtls/ripemd160.h b/external/RSA PRX/RSA/mbedtls/ripemd160.h new file mode 100644 index 0000000..3c1f5bf --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/ripemd160.h @@ -0,0 +1,237 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED -0x0031 /**< RIPEMD160 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[5]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160_alt.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief RIPEMD-160 context setup + * + * \deprecated Superseded by mbedtls_ripemd160_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_starts( + mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \deprecated Superseded by mbedtls_ripemd160_update_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_update( + mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \deprecated Superseded by mbedtls_ripemd160_finish_ret() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_finish( + mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_ripemd160_process() in 2.7.0 + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160_process( + mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \deprecated Superseded by mbedtls_ripemd160_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + */ +MBEDTLS_DEPRECATED void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/external/RSA PRX/RSA/mbedtls/rsa.h b/external/RSA PRX/RSA/mbedtls/rsa.h new file mode 100644 index 0000000..ec8d0d8 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/rsa.h @@ -0,0 +1,1277 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ + +/* MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION is deprecated and should not be used. + */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ + +/* MBEDTLS_ERR_RSA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct mbedtls_rsa_context +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ + + mbedtls_mpi RN; /*!< cached R^2 mod N. */ + + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of ::mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. It is unused + * otherwise. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is discouraged + * and deprecated to pass \c NULL here, in which case + * blinding will be omitted. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is mandatory for PKCS#1 v2.1 padding + * encoding, and for PKCS#1 v1.5 padding encoding when used + * with \p mode set to #MBEDTLS_RSA_PUBLIC. For PKCS#1 v1.5 + * padding encoding and \p mode set to #MBEDTLS_RSA_PRIVATE, + * it is used for blinding and should be provided in this + * case; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng is \c NULL or if \p f_rng doesn't + * need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is needed for padding generation + * if \p mode is #MBEDTLS_RSA_PUBLIC. If \p mode is + * #MBEDTLS_RSA_PRIVATE (discouraged), it is used for + * blinding and should be provided; see mbedtls_rsa_private(). + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng is \c NULL or if \p f_rng + * doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and must be provided. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. If the padding mode is PKCS#1 v2.1, + * this must be provided. If the padding mode is PKCS#1 v1.5 and + * \p mode is #MBEDTLS_RSA_PRIVATE, it is used for blinding + * and should be provided; see mbedtls_rsa_private() for more + * more. It is ignored otherwise. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. If \p mode is + * #MBEDTLS_RSA_PUBLIC, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng is \c NULL or doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PRIVATE or #MBEDTLS_RSA_PUBLIC (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * Ths is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE (deprecated). + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param f_rng The RNG function to use. If \p mode is #MBEDTLS_RSA_PRIVATE, + * this is used for blinding and should be provided; see + * mbedtls_rsa_private() for more. Otherwise, it is ignored. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a context. + * \param mode The mode of operation. This must be either + * #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. + * This is only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest or raw data. + * If \p md_alg is #MBEDTLS_MD_NONE, this must be a readable + * buffer of length \p hashlen Bytes. If \p md_alg is not + * #MBEDTLS_MD_NONE, it must be a readable buffer of length + * the size of the hash corresponding to \p md_alg. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/external/RSA PRX/RSA/mbedtls/rsa_internal.h b/external/RSA PRX/RSA/mbedtls/rsa_internal.h new file mode 100644 index 0000000..c1c844e --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/rsa_internal.h @@ -0,0 +1,226 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/external/RSA PRX/RSA/mbedtls/sha1.h b/external/RSA PRX/RSA/mbedtls/sha1.h new file mode 100644 index 0000000..988d2f9 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/sha1.h @@ -0,0 +1,352 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/external/RSA PRX/RSA/mbedtls/sha256.h b/external/RSA PRX/RSA/mbedtls/sha256.h new file mode 100644 index 0000000..1c59740 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/sha256.h @@ -0,0 +1,297 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/external/RSA PRX/RSA/mbedtls/sha512.h b/external/RSA PRX/RSA/mbedtls/sha512.h new file mode 100644 index 0000000..8e54ce0 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/sha512.h @@ -0,0 +1,316 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 /**< SHA-512 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +#endif +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512 or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of length \c 128 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. This must be a + * readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. This must + * be a writable buffer of length \c 64 Bytes. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA512_NO_SHA384 is defined, \p is384 must + * be \c 0, or the function will fail to work. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/external/RSA PRX/RSA/mbedtls/threading.h b/external/RSA PRX/RSA/mbedtls/threading.h new file mode 100644 index 0000000..cab40f7 --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/threading.h @@ -0,0 +1,122 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE is deprecated and should not be + * used. */ +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ + +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/external/RSA PRX/RSA/mbedtls/timing.h b/external/RSA PRX/RSA/mbedtls/timing.h new file mode 100644 index 0000000..b264a5a --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/timing.h @@ -0,0 +1,153 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/external/RSA PRX/RSA/mbedtls/version.h b/external/RSA PRX/RSA/mbedtls/version.h new file mode 100644 index 0000000..35af4cc --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/version.h @@ -0,0 +1,112 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * This set of compile-time defines and run-time variables can be used to + * determine the version number of the mbed TLS library used. + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 21 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02150000 +#define MBEDTLS_VERSION_STRING "2.21.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.21.0" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/external/RSA PRX/RSA/mbedtls/xtea.h b/external/RSA PRX/RSA/mbedtls/xtea.h new file mode 100644 index 0000000..2dc0afc --- /dev/null +++ b/external/RSA PRX/RSA/mbedtls/xtea.h @@ -0,0 +1,139 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_XTEA_ENCRYPT 1 +#define MBEDTLS_XTEA_DECRYPT 0 + +#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ + +/* MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED -0x0029 /**< XTEA hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_XTEA_ALT) +// Regular implementation +// + +/** + * \brief XTEA context structure + */ +typedef struct mbedtls_xtea_context +{ + uint32_t k[4]; /*!< key */ +} +mbedtls_xtea_context; + +#else /* MBEDTLS_XTEA_ALT */ +#include "xtea_alt.h" +#endif /* MBEDTLS_XTEA_ALT */ + +/** + * \brief Initialize XTEA context + * + * \param ctx XTEA context to be initialized + */ +void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); + +/** + * \brief Clear XTEA context + * + * \param ctx XTEA context to be cleared + */ +void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); + +/** + * \brief XTEA key schedule + * + * \param ctx XTEA context to be initialized + * \param key the secret key + */ +void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); + +/** + * \brief XTEA cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, + int mode, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief XTEA CBC cipher function + * + * \param ctx XTEA context + * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT + * \param length the length of input, multiple of 8 + * \param iv initialization vector for CBC mode + * \param input input block + * \param output output block + * + * \return 0 if successful, + * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 + */ +int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_xtea_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* xtea.h */ diff --git a/external/RSA PRX/RSA/md.c b/external/RSA PRX/RSA/md.c new file mode 100644 index 0000000..03ea532 --- /dev/null +++ b/external/RSA PRX/RSA/md.c @@ -0,0 +1,910 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/md2.h" +#include "mbedtls/md4.h" +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_MD2_C) +const mbedtls_md_info_t mbedtls_md2_info = { + "MD2", + MBEDTLS_MD_MD2, + 16, + 16, +}; +#endif + +#if defined(MBEDTLS_MD4_C) +const mbedtls_md_info_t mbedtls_md4_info = { + "MD4", + MBEDTLS_MD_MD4, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_MD5_C) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA1_C) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA256_C) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; + +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif + +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#if !defined(MBEDTLS_SHA512_NO_SHA384) + MBEDTLS_MD_SHA384, +#endif +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); +#endif + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + { + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free( ctx->md_ctx ); + } + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + switch( src->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + mbedtls_md2_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + mbedtls_md4_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +#define ALLOC( type ) \ + do { \ + ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \ + if( ctx->md_ctx == NULL ) \ + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \ + mbedtls_##type##_init( ctx->md_ctx ); \ + } \ + while( 0 ) + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info = md_info; + ctx->md_ctx = NULL; + ctx->hmac_ctx = NULL; + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + ALLOC( md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + ALLOC( md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + ALLOC( md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + ALLOC( ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + ALLOC( sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + ALLOC( sha512 ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + mbedtls_md_free( ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + return( 0 ); +} +#undef ALLOC + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_starts_ret( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_starts_ret( ctx->md_ctx, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_starts_ret( ctx->md_ctx, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_update_ret( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_update_ret( ctx->md_ctx, input, ilen ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_finish_ret( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_finish_ret( ctx->md_ctx, output ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_md2_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_md4_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_ret( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +#if defined(MBEDTLS_FS_IO) + +#include + +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + int bytes = -1; + + + printf("Verifying %s....\n", path); + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + + mbedtls_md_init( &ctx ); + + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + + + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + goto cleanup; + + + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + { + bytes+=n; + if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 ) + goto cleanup; + } + + printf("Bytes read %i\n", bytes); + + + ret = mbedtls_md_finish( &ctx, output ); + + //printf("here ret %x, %s\n", ret, strerror(errno)); + // printf(mbedtls_high_level_strerr(ret)); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( mbedtls_md_update( ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( mbedtls_md_finish( ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( mbedtls_internal_md2_process( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( mbedtls_internal_md4_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_internal_md5_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + case MBEDTLS_MD_SHA256: + return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA512_C) +#if !defined(MBEDTLS_SHA512_NO_SHA384) + case MBEDTLS_MD_SHA384: +#endif + case MBEDTLS_MD_SHA512: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/external/RSA PRX/RSA/md5.c b/external/RSA PRX/RSA/md5.c new file mode 100644 index 0000000..1e702b4 --- /dev/null +++ b/external/RSA PRX/RSA/md5.c @@ -0,0 +1,492 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) \ + ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) + +#define P(a,b,c,d,k,s,t) \ + do \ + { \ + (a) += F((b),(c),(d)) + X[(k)] + (t); \ + (a) = S((a),(s)) + (b); \ + } while( 0 ) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((x) | ~(z))) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/external/RSA PRX/RSA/oid.c b/external/RSA PRX/RSA/oid.c new file mode 100644 index 0000000..19c8ac2 --- /dev/null +++ b/external/RSA PRX/RSA/oid.c @@ -0,0 +1,767 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + { ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" }, + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { ADD_LEN( MBEDTLS_OID_WISUN_FAN ), "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) + +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + { ADD_LEN( MBEDTLS_OID_ANY_POLICY ), "anyPolicy", "Any Policy" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_RIPEMD160_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ), "id-ripemd160", "RIPEMD-160" }, + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_RIPEMD160_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%u", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/external/RSA PRX/RSA/pkcs11.c b/external/RSA PRX/RSA/pkcs11.c new file mode 100644 index 0000000..4deccf3 --- /dev/null +++ b/external/RSA PRX/RSA/pkcs11.c @@ -0,0 +1,238 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); +} + +int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + unsigned char *cert_blob = NULL; + size_t cert_blob_size = 0; + + if( cert == NULL ) + { + ret = 2; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, + &cert_blob_size ) != CKR_OK ) + { + ret = 3; + goto cleanup; + } + + cert_blob = mbedtls_calloc( 1, cert_blob_size ); + if( NULL == cert_blob ) + { + ret = 4; + goto cleanup; + } + + if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, + &cert_blob_size ) != CKR_OK ) + { + ret = 5; + goto cleanup; + } + + if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) + { + ret = 6; + goto cleanup; + } + + ret = 0; + +cleanup: + if( NULL != cert_blob ) + mbedtls_free( cert_blob ); + + return( ret ); +} + + +int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, + pkcs11h_certificate_t pkcs11_cert ) +{ + int ret = 1; + mbedtls_x509_crt cert; + + mbedtls_x509_crt_init( &cert ); + + if( priv_key == NULL ) + goto cleanup; + + if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) + goto cleanup; + + priv_key->len = mbedtls_pk_get_len( &cert.pk ); + priv_key->pkcs11h_cert = pkcs11_cert; + + ret = 0; + +cleanup: + mbedtls_x509_crt_free( &cert ); + + return( ret ); +} + +void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) +{ + if( NULL != priv_key ) + pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); +} + +int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + size_t input_len, output_len; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + output_len = input_len = ctx->len; + + if( input_len < 16 || input_len > output_max_len ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Determine size of output buffer */ + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, NULL, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( output_len > output_max_len ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, + input_len, output, &output_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + *olen = output_len; + return( 0 ); +} + +int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t sig_len = 0, asn_len = 0, oid_size = 0; + unsigned char *p = sig; + const char *oid; + + if( NULL == ctx ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( MBEDTLS_RSA_PRIVATE != mode ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + asn_len = 10 + oid_size; + } + + sig_len = ctx->len; + if( hashlen > sig_len || asn_len > sig_len || + hashlen + asn_len > sig_len ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char) ( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = oid_size & 0xFF; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = hashlen; + } + + memcpy( p, hash, hashlen ); + + if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, + asn_len + hashlen, sig, &sig_len ) != CKR_OK ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/external/RSA PRX/RSA/platform.c b/external/RSA PRX/RSA/platform.c new file mode 100644 index 0000000..e742fde --- /dev/null +++ b/external/RSA PRX/RSA/platform.c @@ -0,0 +1,386 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + va_list argp; + + va_start( argp, fmt ); + ret = mbedtls_vsnprintf( s, n, fmt, argp ); + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + +#if defined(_TRUNCATE) + ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg ); +#else + ret = vsnprintf( s, n, fmt, arg ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_vsnprintf_uninit( char * s, size_t n, + const char * format, va_list arg ) +{ + ((void) s); + ((void) n); + ((void) format); + ((void) arg); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ + +int (*mbedtls_vsnprintf)( char * s, size_t n, + const char * format, + va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF; + +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, + va_list arg ) ) +{ + mbedtls_vsnprintf = vsnprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/external/RSA PRX/RSA/platform_util.c b/external/RSA PRX/RSA/platform_util.c new file mode 100644 index 0000000..879328a --- /dev/null +++ b/external/RSA PRX/RSA/platform_util.c @@ -0,0 +1,133 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +//static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); + + if( len > 0 ) + memset( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_s( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ diff --git a/external/RSA PRX/RSA/ripemd160.c b/external/RSA PRX/RSA/ripemd160.c new file mode 100644 index 0000000..603b6ba --- /dev/null +++ b/external/RSA PRX/RSA/ripemd160.c @@ -0,0 +1,553 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include "common.h" + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts_ret( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + mbedtls_ripemd160_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + + A = Ap = ctx->state[0]; + B = Bp = ctx->state[1]; + C = Cp = ctx->state[2]; + D = Dp = ctx->state[3]; + E = Ep = ctx->state[4]; + +#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) +#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) +#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) +#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) +#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) + +#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + do \ + { \ + (a) += f( (b), (c), (d) ) + X[r] + (k); \ + (a) = S( (a), (s) ) + (e); \ + (c) = S( (c), 10 ); \ + } while( 0 ) + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + do \ + { \ + P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, \ + (rp), (sp), Fp, Kp ); \ + } while( 0 ) + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( A, B, C, D, E, 0, 11, 5, 8 ); + P2( E, A, B, C, D, 1, 14, 14, 9 ); + P2( D, E, A, B, C, 2, 15, 7, 9 ); + P2( C, D, E, A, B, 3, 12, 0, 11 ); + P2( B, C, D, E, A, 4, 5, 9, 13 ); + P2( A, B, C, D, E, 5, 8, 2, 15 ); + P2( E, A, B, C, D, 6, 7, 11, 15 ); + P2( D, E, A, B, C, 7, 9, 4, 5 ); + P2( C, D, E, A, B, 8, 11, 13, 7 ); + P2( B, C, D, E, A, 9, 13, 6, 7 ); + P2( A, B, C, D, E, 10, 14, 15, 8 ); + P2( E, A, B, C, D, 11, 15, 8, 11 ); + P2( D, E, A, B, C, 12, 6, 1, 14 ); + P2( C, D, E, A, B, 13, 7, 10, 14 ); + P2( B, C, D, E, A, 14, 9, 3, 12 ); + P2( A, B, C, D, E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( E, A, B, C, D, 7, 7, 6, 9 ); + P2( D, E, A, B, C, 4, 6, 11, 13 ); + P2( C, D, E, A, B, 13, 8, 3, 15 ); + P2( B, C, D, E, A, 1, 13, 7, 7 ); + P2( A, B, C, D, E, 10, 11, 0, 12 ); + P2( E, A, B, C, D, 6, 9, 13, 8 ); + P2( D, E, A, B, C, 15, 7, 5, 9 ); + P2( C, D, E, A, B, 3, 15, 10, 11 ); + P2( B, C, D, E, A, 12, 7, 14, 7 ); + P2( A, B, C, D, E, 0, 12, 15, 7 ); + P2( E, A, B, C, D, 9, 15, 8, 12 ); + P2( D, E, A, B, C, 5, 9, 12, 7 ); + P2( C, D, E, A, B, 2, 11, 4, 6 ); + P2( B, C, D, E, A, 14, 7, 9, 15 ); + P2( A, B, C, D, E, 11, 13, 1, 13 ); + P2( E, A, B, C, D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( D, E, A, B, C, 3, 11, 15, 9 ); + P2( C, D, E, A, B, 10, 13, 5, 7 ); + P2( B, C, D, E, A, 14, 6, 1, 15 ); + P2( A, B, C, D, E, 4, 7, 3, 11 ); + P2( E, A, B, C, D, 9, 14, 7, 8 ); + P2( D, E, A, B, C, 15, 9, 14, 6 ); + P2( C, D, E, A, B, 8, 13, 6, 6 ); + P2( B, C, D, E, A, 1, 15, 9, 14 ); + P2( A, B, C, D, E, 2, 14, 11, 12 ); + P2( E, A, B, C, D, 7, 8, 8, 13 ); + P2( D, E, A, B, C, 0, 13, 12, 5 ); + P2( C, D, E, A, B, 6, 6, 2, 14 ); + P2( B, C, D, E, A, 13, 5, 10, 13 ); + P2( A, B, C, D, E, 11, 12, 0, 13 ); + P2( E, A, B, C, D, 5, 7, 4, 7 ); + P2( D, E, A, B, C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( C, D, E, A, B, 1, 11, 8, 15 ); + P2( B, C, D, E, A, 9, 12, 6, 5 ); + P2( A, B, C, D, E, 11, 14, 4, 8 ); + P2( E, A, B, C, D, 10, 15, 1, 11 ); + P2( D, E, A, B, C, 0, 14, 3, 14 ); + P2( C, D, E, A, B, 8, 15, 11, 14 ); + P2( B, C, D, E, A, 12, 9, 15, 6 ); + P2( A, B, C, D, E, 4, 8, 0, 14 ); + P2( E, A, B, C, D, 13, 9, 5, 6 ); + P2( D, E, A, B, C, 3, 14, 12, 9 ); + P2( C, D, E, A, B, 7, 5, 2, 12 ); + P2( B, C, D, E, A, 15, 6, 13, 9 ); + P2( A, B, C, D, E, 14, 8, 9, 12 ); + P2( E, A, B, C, D, 5, 6, 7, 5 ); + P2( D, E, A, B, C, 6, 5, 10, 15 ); + P2( C, D, E, A, B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( B, C, D, E, A, 4, 9, 12, 8 ); + P2( A, B, C, D, E, 0, 15, 15, 5 ); + P2( E, A, B, C, D, 5, 5, 10, 12 ); + P2( D, E, A, B, C, 9, 11, 4, 9 ); + P2( C, D, E, A, B, 7, 6, 1, 12 ); + P2( B, C, D, E, A, 12, 8, 5, 5 ); + P2( A, B, C, D, E, 2, 13, 8, 14 ); + P2( E, A, B, C, D, 10, 12, 7, 6 ); + P2( D, E, A, B, C, 14, 5, 6, 8 ); + P2( C, D, E, A, B, 1, 12, 2, 13 ); + P2( B, C, D, E, A, 3, 13, 13, 6 ); + P2( A, B, C, D, E, 8, 14, 14, 5 ); + P2( E, A, B, C, D, 11, 11, 0, 15 ); + P2( D, E, A, B, C, 6, 8, 3, 13 ); + P2( C, D, E, A, B, 15, 5, 9, 11 ); + P2( B, C, D, E, A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + C = ctx->state[1] + C + Dp; + ctx->state[1] = ctx->state[2] + D + Ep; + ctx->state[2] = ctx->state[3] + E + Ap; + ctx->state[3] = ctx->state[4] + A + Bp; + ctx->state[4] = ctx->state[0] + B + Cp; + ctx->state[0] = C; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_ripemd160_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update_ret( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_ripemd160_update_ret( ctx, input, ilen ); +} +#endif + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish_ret( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, msglen, 0 ); + PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update_ret( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update_ret( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + mbedtls_ripemd160_finish_ret( ctx, output ); +} +#endif + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_ripemd160_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160_ret( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/external/RSA PRX/RSA/rsa.c b/external/RSA PRX/RSA/rsa.c new file mode 100644 index 0000000..183e78d --- /dev/null +++ b/external/RSA PRX/RSA/rsa.c @@ -0,0 +1,2762 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + + + + + +#if defined(MBEDTLS_PKCS1_V15) +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id ) +{ + RSA_VALIDATE( ctx != NULL ); + RSA_VALIDATE( padding == MBEDTLS_RSA_PKCS_V15 || + padding == MBEDTLS_RSA_PKCS_V21 ); + + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + if( *olen != 0 ) + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, plaintext_max_size; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; + + if( mode == MBEDTLS_RSA_PRIVATE ) + { + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + } + else + { + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); + } + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if( output_max_len != 0 ) + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + size_t slen, min_slen, hlen, offset = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + /* Calculate the largest possible salt length. Normally this is the hash + * length, which is the maximum length the salt can have. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_platform_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( mode == MBEDTLS_RSA_PRIVATE || + mode == MBEDTLS_RSA_PUBLIC ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->ver = src->ver; + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/external/RSA PRX/RSA/rsa_check.c b/external/RSA PRX/RSA/rsa_check.c new file mode 100644 index 0000000..3fb04ba --- /dev/null +++ b/external/RSA PRX/RSA/rsa_check.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include "mbedtls/config.h" +#include "mbedtls/rsa.h" +#include "mbedtls/md.h" +#include "rsa_check.h" +#include + + + +void logshit(char* format, ...) +{ + + char buff[1024]; + + memset(buff, 0, 1024); + + va_list args; + va_start(args, format); + vsprintf(buff, format, args); + va_end(args); + + printf(buff); + + int fd = sceKernelOpen("/data/Loader_Logs.txt", O_WRONLY | O_CREAT | O_APPEND, 0777); + if (fd >= 0) + { + + sceKernelWrite(fd, buff, strlen(buff)); + sceKernelClose(fd); + } +} + + +int Check_rsa(const char * path, const char * pubkey) +{ + FILE *f; + int ret = 1; + unsigned c; + int exit_code = -1; + size_t i; + mbedtls_rsa_context rsa; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + char filename[512]; + + logshit("[%s:%i] ----- INIT ARMmbed with RSA_PKCS_V15 ---\n", __FUNCTION__, __LINE__); + + + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + + logshit("[%s:%i] ----- Reading public key from %s (rsa.pub) ---\n", __FUNCTION__, __LINE__, pubkey); + + if( ( f = fopen( pubkey, "rb" ) ) == NULL ) + { + logshit("[%s:%i] ----- failed to read rsa.pub ---\n", __FUNCTION__, __LINE__); + goto exit; + } + + + + if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 || + ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) + { + + logshit("[%s:%i] ----- mbedtls_mpi_read_file returned %d ---\n", __FUNCTION__, __LINE__, ret); + fclose( f ); + exit_code = -ret; + goto exit; + } + + + rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3; + + fclose( f ); + + /* + * Extract the RSA signature from the text file + */ + + snprintf(filename, sizeof(filename), "%s.sig", path); + if( ( f = fopen( filename, "rb" ) ) == NULL ) + { + logshit("[%s:%i] ----- Could NOT open sigfile ---\n", __FUNCTION__, __LINE__); + goto exit; + } + + i = 0; + while( fscanf( f, "%02X", (unsigned int*) &c ) > 0 && + i < (int) sizeof( buf ) ) + buf[i++] = (unsigned char) c; + + fclose( f ); + + if( i != rsa.len ) + { + logshit("[%s:%i] ----- Invaild RSA Sign format ---\n", __FUNCTION__, __LINE__); + exit_code = 0x999; + goto exit; + } + + /* + * Compute the SHA-256 hash of the input file and + * verify the signature + */ + + logshit("[%s:%i] ----- Verifying the RSA/SHA-256 signature ---\n", __FUNCTION__, __LINE__); + + + if( ( ret = mbedtls_md_file( + mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), + path, hash ) ) != 0 ) + { + logshit("[%s:%i] ----- could not read file ---\n", __FUNCTION__, __LINE__); + // fflush( stdout ); + goto exit; + } + + if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 20, hash, buf ) ) != 0 ) + { + + + logshit("[%s:%i] ----- mbedtls_rsa_pkcs1_verify returned -0x%0x ---\n", __FUNCTION__, __LINE__, -ret); + exit_code = -ret; + goto exit; + } + + + logshit("[%s:%i] ----- Success the signature is valid ---\n", __FUNCTION__, __LINE__); + + + + exit_code = 0; + +exit: + + mbedtls_rsa_free( &rsa ); + + return exit_code; + +} \ No newline at end of file diff --git a/external/RSA PRX/RSA/rsa_check.h b/external/RSA PRX/RSA/rsa_check.h new file mode 100644 index 0000000..ca18a25 --- /dev/null +++ b/external/RSA PRX/RSA/rsa_check.h @@ -0,0 +1,2 @@ +#pragma once +int Check_rsa(const char * path, const char * pubkey); \ No newline at end of file diff --git a/external/RSA PRX/RSA/rsa_internal.c b/external/RSA PRX/RSA/rsa_internal.c new file mode 100644 index 0000000..d6ba97a --- /dev/null +++ b/external/RSA PRX/RSA/rsa_internal.c @@ -0,0 +1,486 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/external/RSA PRX/RSA/sha1.c b/external/RSA PRX/RSA/sha1.c new file mode 100644 index 0000000..593f795 --- /dev/null +++ b/external/RSA PRX/RSA/sha1.c @@ -0,0 +1,568 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE_RET( ctx != NULL ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + temp = W[( (t) - 3 ) & 0x0F] ^ W[( (t) - 8 ) & 0x0F] ^ \ + W[( (t) - 14 ) & 0x0F] ^ W[ (t) & 0x0F], \ + ( W[(t) & 0x0F] = S(temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + mbedtls_sha1_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/external/RSA PRX/RSA/sha256.c b/external/RSA PRX/RSA/sha256.c new file mode 100644 index 0000000..e8b25e3 --- /dev/null +++ b/external/RSA PRX/RSA/sha256.c @@ -0,0 +1,509 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + SHA256_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) +{ + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + W[t] = S1(W[(t) - 2]) + W[(t) - 7] + \ + S0(W[(t) - 15]) + W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += temp1; (h) = temp1 + temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + + + return 0; +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/external/RSA PRX/RSA/sha512.c b/external/RSA PRX/RSA/sha512.c new file mode 100644 index 0000000..0a4632f --- /dev/null +++ b/external/RSA PRX/RSA/sha512.c @@ -0,0 +1,599 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +#if defined(MBEDTLS_SHA512_SMALLER) +static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i ) +{ + PUT_UINT64_BE(n, b, i); +} +#else +#define sha512_put_uint64_be PUT_UINT64_BE +#endif /* MBEDTLS_SHA512_SMALLER */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + SHA512_VALIDATE_RET( ctx != NULL ); +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { +#if defined(MBEDTLS_SHA512_NO_SHA384) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA512_NO_SHA384 */ + } + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + ctx->is384 = is384; +#endif + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += temp1; (h) = temp1 + temp2; \ + } while( 0 ) + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA512_SMALLER) + for( i = 0; i < 80; i++ ) + { + if( i < 16 ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + else + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA512_SMALLER */ + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + i = 0; + do + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); i++; + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i], K[i] ); i++; + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i], K[i] ); i++; + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i], K[i] ); i++; + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i], K[i] ); i++; + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i], K[i] ); i++; + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i], K[i] ); i++; + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i], K[i] ); i++; + } + while( i < 80 ); +#endif /* MBEDTLS_SHA512_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + sha512_put_uint64_be( high, ctx->buffer, 112 ); + sha512_put_uint64_be( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + sha512_put_uint64_be( ctx->state[0], output, 0 ); + sha512_put_uint64_be( ctx->state[1], output, 8 ); + sha512_put_uint64_be( ctx->state[2], output, 16 ); + sha512_put_uint64_be( ctx->state[3], output, 24 ); + sha512_put_uint64_be( ctx->state[4], output, 32 ); + sha512_put_uint64_be( ctx->state[5], output, 40 ); + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + if( ctx->is384 == 0 ) +#endif + { + sha512_put_uint64_be( ctx->state[6], output, 48 ); + sha512_put_uint64_be( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; + +#if !defined(MBEDTLS_SHA512_NO_SHA384) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[][64] = +{ +#if !defined(MBEDTLS_SHA512_NO_SHA384) + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* !MBEDTLS_SHA512_NO_SHA384 */ + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + + + return 0; +} + +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/external/curl prx/Makefile b/external/curl prx/Makefile new file mode 100644 index 0000000..da50b15 --- /dev/null +++ b/external/curl prx/Makefile @@ -0,0 +1,70 @@ + +# Library metadata. +TARGET := curl.prx +# Libraries linked into the ELF. +LIBS := -lcurl -lpolarssl -lSceNet -lc -lc++ -lkernel + +# Additional compile flags. +#EXTRAFLAGS := + +# You likely won't need to touch anything below this point. + +# Root vars +TOOLCHAIN := $(OO_PS4_TOOLCHAIN) +PROJDIR := src +INTDIR := build + +# Define objects to build +CFILES := $(wildcard $(PROJDIR)/*.c) +CPPFILES := $(wildcard $(PROJDIR)/*.cpp) +COMMONFILES := $(wildcard $(COMMONDIR)/*.cpp) +OBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.c.obj, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.c.obj, $(CPPFILES)) $(patsubst $(COMMONDIR)/%.cpp, $(INTDIR)/%.c.obj, $(COMMONFILES)) +STUBOBJS := $(patsubst $(PROJDIR)/%.c, $(INTDIR)/%.c.obj, $(CFILES)) $(patsubst $(PROJDIR)/%.cpp, $(INTDIR)/%.c.obj.stub, $(CPPFILES)) $(patsubst $(COMMONDIR)/%.cpp, $(INTDIR)/%.c.obj.stub, $(COMMONFILES)) + +# Define final C/C++ flags +CFLAGS := --target=x86_64-pc-freebsd12-elf -fdeclspec -fPIC -funwind-tables -c $(EXTRAFLAGS) -isysroot $(TOOLCHAIN) -isystem $(TOOLCHAIN)/include -Iinclude +CXXFLAGS := $(CFLAGS) -DBUILDING_LIBCURL=1 -D__PS4__ -DUSE_MBEDTLS=1 -DUSE_UNIX_SOCKETS=0 -DENABLE_THREADED_RESOLVER=0 -DENABLE_IPV6=0 -D__OPENORBIS__ -D__ORBIS__ -isystem $(TOOLCHAIN)/include/c++/v1 -Iinclude +LDFLAGS := -m elf_x86_64 -pie --script $(TOOLCHAIN)/link.x --eh-frame-hdr -L$(TOOLCHAIN)/lib $(LIBS) $(TOOLCHAIN)/lib/crtlib.o + +# Create the intermediate directory incase it doesn't already exist. +_unused := $(shell mkdir -p $(INTDIR)) + +# Check for linux vs macOS and account for clang/ld path +UNAME_S := $(shell uname -s) + +ifeq ($(UNAME_S),Linux) + CC := clang + CCX := clang++ + LD := ld.lld + CDIR := linux +endif +ifeq ($(UNAME_S),Darwin) + CC := /usr/local/opt/llvm/bin/clang + CCX := /usr/local/opt/llvm/bin/clang++ + LD := /usr/local/opt/llvm/bin/ld.lld + CDIR := macos +endif + +$(TARGET): $(INTDIR) $(OBJS) + $(LD) $(INTDIR)/*.c.obj -o $(INTDIR)/$(PROJDIR).elf $(LDFLAGS) + $(TOOLCHAIN)/bin/$(CDIR)/create-fself -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --lib=$(TARGET) --paid 0x3800000000000011 + +$(INTDIR)/%.c.obj: $(PROJDIR)/%.c + $(CC) $(CFLAGS) -o $@ $< + +$(INTDIR)/%.c.obj: $(PROJDIR)/%.cpp + $(CCX) $(CXXFLAGS) -o $@ $< + +$(INTDIR)/%.c.obj.stub: $(PROJDIR)/%.c + $(CC) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(TOOLCHAIN)/include -o $@ $< + +$(INTDIR)/%.c.obj.stub: $(PROJDIR)/%.cpp + $(CCX) -target x86_64-pc-linux-gnu -ffreestanding -nostdlib -fno-builtin -fPIC -c $(TOOLCHAIN)/include -o $@ $< + +.PHONY: clean +.DEFAULT_GOAL := all + +all: $(TARGET) $(TARGETSTUB) + +clean: + rm -f $(TARGET) $(INTDIR)/$(PROJDIR).elf $(INTDIR)/$(PROJDIR)/oelf $(OBJS) diff --git a/external/curl prx/build/curl.c.obj b/external/curl prx/build/curl.c.obj new file mode 100644 index 0000000..8116ca7 Binary files /dev/null and b/external/curl prx/build/curl.c.obj differ diff --git a/external/curl prx/build/easy.c.obj b/external/curl prx/build/easy.c.obj new file mode 100644 index 0000000..6fa472c Binary files /dev/null and b/external/curl prx/build/easy.c.obj differ diff --git a/external/curl prx/build/escape.c.obj b/external/curl prx/build/escape.c.obj new file mode 100644 index 0000000..9ee250e Binary files /dev/null and b/external/curl prx/build/escape.c.obj differ diff --git a/external/curl prx/build/setopt.c.obj b/external/curl prx/build/setopt.c.obj new file mode 100644 index 0000000..92db56f Binary files /dev/null and b/external/curl prx/build/setopt.c.obj differ diff --git a/external/curl prx/build/src.oelf.i64 b/external/curl prx/build/src.oelf.i64 new file mode 100644 index 0000000..a287188 Binary files /dev/null and b/external/curl prx/build/src.oelf.i64 differ diff --git a/external/curl prx/build/strerror.c.obj b/external/curl prx/build/strerror.c.obj new file mode 100644 index 0000000..12db293 Binary files /dev/null and b/external/curl prx/build/strerror.c.obj differ diff --git a/external/curl prx/build/version.c.obj b/external/curl prx/build/version.c.obj new file mode 100644 index 0000000..c66419e Binary files /dev/null and b/external/curl prx/build/version.c.obj differ diff --git a/external/curl prx/curl.prx b/external/curl prx/curl.prx new file mode 100644 index 0000000..31b6bf6 Binary files /dev/null and b/external/curl prx/curl.prx differ diff --git a/external/curl prx/include/altsvc.h b/external/curl prx/include/altsvc.h new file mode 100644 index 0000000..eefb45b --- /dev/null +++ b/external/curl prx/include/altsvc.h @@ -0,0 +1,77 @@ +#ifndef HEADER_CURL_ALTSVC_H +#define HEADER_CURL_ALTSVC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_ALTSVC) +#include +#include "llist.h" + +enum alpnid { + ALPN_none, + ALPN_h1, + ALPN_h2, + ALPN_h2c, + ALPN_h3 +}; + +struct altsvc { + char *srchost; + char *dsthost; + unsigned short srcport; + unsigned short dstport; + enum alpnid srcalpnid; + enum alpnid dstalpnid; + time_t expires; + bool persist; + int prio; + struct curl_llist_element node; +}; + +struct altsvcinfo { + char *filename; + struct curl_llist list; /* list of entries */ + size_t num; /* number of alt-svc entries */ + long flags; /* the publicly set bitmask */ +}; + +const char *Curl_alpnid2str(enum alpnid id); +struct altsvcinfo *Curl_altsvc_init(void); +CURLcode Curl_altsvc_load(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_save(struct altsvcinfo *asi, const char *file); +CURLcode Curl_altsvc_ctrl(struct altsvcinfo *asi, const long ctrl); +void Curl_altsvc_cleanup(struct altsvcinfo *altsvc); +CURLcode Curl_altsvc_parse(struct Curl_easy *data, + struct altsvcinfo *altsvc, const char *value, + enum alpnid srcalpn, const char *srchost, + unsigned short srcport); +bool Curl_altsvc_lookup(struct altsvcinfo *asi, + enum alpnid srcalpnid, const char *srchost, + int srcport, + enum alpnid *dstalpnid, const char **dsthost, + int *dstport); +#else +/* disabled */ +#define Curl_altsvc_save(a,b) +#endif /* CURL_DISABLE_HTTP || USE_ALTSVC */ +#endif /* HEADER_CURL_ALTSVC_H */ diff --git a/external/curl prx/include/amigaos.h b/external/curl prx/include/amigaos.h new file mode 100644 index 0000000..c776c9c --- /dev/null +++ b/external/curl prx/include/amigaos.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_AMIGAOS_H +#define HEADER_CURL_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL) + +bool Curl_amiga_init(); +void Curl_amiga_cleanup(); + +#else + +#define Curl_amiga_init() 1 +#define Curl_amiga_cleanup() Curl_nop_stmt + +#endif + +#ifdef USE_AMISSL +#include +void Curl_amiga_X509_free(X509 *a); +#endif /* USE_AMISSL */ + +#endif /* HEADER_CURL_AMIGAOS_H */ + diff --git a/external/curl prx/include/arpa_telnet.h b/external/curl prx/include/arpa_telnet.h new file mode 100644 index 0000000..232680e --- /dev/null +++ b/external/curl prx/include/arpa_telnet.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_ARPA_TELNET_H +#define HEADER_CURL_ARPA_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +/* + * Telnet option defines. Add more here if in need. + */ +#define CURL_TELOPT_BINARY 0 /* binary 8bit data */ +#define CURL_TELOPT_ECHO 1 /* just echo! */ +#define CURL_TELOPT_SGA 3 /* Suppress Go Ahead */ +#define CURL_TELOPT_EXOPL 255 /* EXtended OPtions List */ +#define CURL_TELOPT_TTYPE 24 /* Terminal TYPE */ +#define CURL_TELOPT_NAWS 31 /* Negotiate About Window Size */ +#define CURL_TELOPT_XDISPLOC 35 /* X DISPlay LOCation */ + +#define CURL_TELOPT_NEW_ENVIRON 39 /* NEW ENVIRONment variables */ +#define CURL_NEW_ENV_VAR 0 +#define CURL_NEW_ENV_VALUE 1 + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * The telnet options represented as strings + */ +static const char * const telnetoptions[]= +{ + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", + "NAME", "STATUS", "TIMING MARK", "RCTE", + "NAOL", "NAOP", "NAOCRD", "NAOHTS", + "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", + "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DE TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", + "TERM TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", + "TTYLOC", "3270 REGIME", "X3 PAD", "NAWS", + "TERM SPEED", "LFLOW", "LINEMODE", "XDISPLOC", + "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON" +}; +#endif + +#define CURL_TELOPT_MAXIMUM CURL_TELOPT_NEW_ENVIRON + +#define CURL_TELOPT_OK(x) ((x) <= CURL_TELOPT_MAXIMUM) +#define CURL_TELOPT(x) telnetoptions[x] + +#define CURL_NTELOPTS 40 + +/* + * First some defines + */ +#define CURL_xEOF 236 /* End Of File */ +#define CURL_SE 240 /* Sub negotiation End */ +#define CURL_NOP 241 /* No OPeration */ +#define CURL_DM 242 /* Data Mark */ +#define CURL_GA 249 /* Go Ahead, reverse the line */ +#define CURL_SB 250 /* SuBnegotiation */ +#define CURL_WILL 251 /* Our side WILL use this option */ +#define CURL_WONT 252 /* Our side WON'T use this option */ +#define CURL_DO 253 /* DO use this option! */ +#define CURL_DONT 254 /* DON'T use this option! */ +#define CURL_IAC 255 /* Interpret As Command */ + +#ifndef CURL_DISABLE_VERBOSE_STRINGS +/* + * Then those numbers represented as strings: + */ +static const char * const telnetcmds[]= +{ + "EOF", "SUSP", "ABORT", "EOR", "SE", + "NOP", "DMARK", "BRK", "IP", "AO", + "AYT", "EC", "EL", "GA", "SB", + "WILL", "WONT", "DO", "DONT", "IAC" +}; +#endif + +#define CURL_TELCMD_MINIMUM CURL_xEOF /* the first one */ +#define CURL_TELCMD_MAXIMUM CURL_IAC /* surprise, 255 is the last one! ;-) */ + +#define CURL_TELQUAL_IS 0 +#define CURL_TELQUAL_SEND 1 +#define CURL_TELQUAL_INFO 2 +#define CURL_TELQUAL_NAME 3 + +#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ + ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) +#define CURL_TELCMD(x) telnetcmds[(x)-CURL_TELCMD_MINIMUM] + +#endif /* CURL_DISABLE_TELNET */ + +#endif /* HEADER_CURL_ARPA_TELNET_H */ diff --git a/external/curl prx/include/asyn.h b/external/curl prx/include/asyn.h new file mode 100644 index 0000000..ccd4b1f --- /dev/null +++ b/external/curl prx/include/asyn.h @@ -0,0 +1,184 @@ +#ifndef HEADER_CURL_ASYN_H +#define HEADER_CURL_ASYN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "curl_addrinfo.h" + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; +struct Curl_dns_entry; + +/* + * This header defines all functions in the internal asynch resolver interface. + * All asynch resolvers need to provide these functions. + * asyn-ares.c and asyn-thread.c are the current implementations of asynch + * resolver backends. + */ + +/* + * Curl_resolver_global_init() + * + * Called from curl_global_init() to initialize global resolver environment. + * Returning anything else than CURLE_OK fails curl_global_init(). + */ +int Curl_resolver_global_init(void); + +/* + * Curl_resolver_global_cleanup() + * Called from curl_global_cleanup() to destroy global resolver environment. + */ +void Curl_resolver_global_cleanup(void); + +/* + * Curl_resolver_init() + * Called from curl_easy_init() -> Curl_open() to initialize resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should fill the passed pointer by the initialized handler. + * Returning anything else than CURLE_OK fails curl_easy_init() with the + * correspondent code. + */ +CURLcode Curl_resolver_init(struct Curl_easy *easy, void **resolver); + +/* + * Curl_resolver_cleanup() + * Called from curl_easy_cleanup() -> Curl_close() to cleanup resolver + * URL-state specific environment ('resolver' member of the UrlState + * structure). Should destroy the handler and free all resources connected to + * it. + */ +void Curl_resolver_cleanup(void *resolver); + +/* + * Curl_resolver_duphandle() + * Called from curl_easy_duphandle() to duplicate resolver URL-state specific + * environment ('resolver' member of the UrlState structure). Should + * duplicate the 'from' handle and pass the resulting handle to the 'to' + * pointer. Returning anything else than CURLE_OK causes failed + * curl_easy_duphandle() call. + */ +CURLcode Curl_resolver_duphandle(struct Curl_easy *easy, void **to, + void *from); + +/* + * Curl_resolver_cancel(). + * + * It is called from inside other functions to cancel currently performing + * resolver request. Should also free any temporary resources allocated to + * perform a request. This never waits for resolver threads to complete. + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_cancel(struct connectdata *conn); + +/* + * Curl_resolver_kill(). + * + * This acts like Curl_resolver_cancel() except it will block until any threads + * associated with the resolver are complete. This never blocks for resolvers + * that do not use threads. This is intended to be the "last chance" function + * that cleans up an in-progress resolver completely (before its owner is about + * to die). + * + * It is safe to call this when conn is in any state. + */ +void Curl_resolver_kill(struct connectdata *conn); + +/* Curl_resolver_getsock() + * + * This function is called from the multi_getsock() function. 'sock' is a + * pointer to an array to hold the file descriptors, with 'numsock' being the + * size of that array (in number of entries). This function is supposed to + * return bitmask indicating what file descriptors (referring to array indexes + * in the 'sock' array) to wait for, read/write. + */ +int Curl_resolver_getsock(struct connectdata *conn, curl_socket_t *sock, + int numsocks); + +/* + * Curl_resolver_is_resolved() + * + * Called repeatedly to check if a previous name resolve request has + * completed. It should also make sure to time-out if the operation seems to + * take too long. + * + * Returns normal CURLcode errors. + */ +CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +/* + * Curl_resolver_wait_resolv() + * + * Waits for a resolve to finish. This function should be avoided since using + * this risk getting the multi interface to "hang". + * + * If 'entry' is non-NULL, make it point to the resolved dns entry + * + * Returns CURLE_COULDNT_RESOLVE_HOST if the host was not resolved, + * CURLE_OPERATION_TIMEDOUT if a time-out occurred, or other errors. + */ +CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + struct Curl_dns_entry **dnsentry); + +/* + * Curl_resolver_getaddrinfo() - when using this resolver + * + * Returns name information about the given hostname and port number. If + * successful, the 'hostent' is returned and the forth argument will point to + * memory we need to free after use. That memory *MUST* be freed with + * Curl_freeaddrinfo(), nothing else. + * + * Each resolver backend must of course make sure to return data in the + * correct format to comply with this. + */ +Curl_addrinfo *Curl_resolver_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +#ifndef CURLRES_ASYNCH +/* convert these functions if an asynch resolver isn't used */ +#define Curl_resolver_cancel(x) Curl_nop_stmt +#define Curl_resolver_kill(x) Curl_nop_stmt +#define Curl_resolver_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_wait_resolv(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_resolver_getsock(x,y,z) 0 +#define Curl_resolver_duphandle(x,y,z) CURLE_OK +#define Curl_resolver_init(x,y) CURLE_OK +#define Curl_resolver_global_init() CURLE_OK +#define Curl_resolver_global_cleanup() Curl_nop_stmt +#define Curl_resolver_cleanup(x) Curl_nop_stmt +#endif + +#ifdef CURLRES_ASYNCH +#define Curl_resolver_asynch() 1 +#else +#define Curl_resolver_asynch() 0 +#endif + + +/********** end of generic resolver interface functions *****************/ +#endif /* HEADER_CURL_ASYN_H */ diff --git a/external/curl prx/include/config-amigaos.h b/external/curl prx/include/config-amigaos.h new file mode 100644 index 0000000..31cfc3a --- /dev/null +++ b/external/curl prx/include/config-amigaos.h @@ -0,0 +1,166 @@ +#ifndef HEADER_CURL_CONFIG_AMIGAOS_H +#define HEADER_CURL_CONFIG_AMIGAOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for AmigaOS */ +/* ================================================================ */ + +#ifdef __AMIGA__ /* Any AmigaOS flavour */ + +#define HAVE_ARPA_INET_H 1 +#define HAVE_CLOSESOCKET_CAMEL 1 +#define HAVE_ERRNO_H 1 +#define HAVE_GETHOSTBYADDR 1 +#define HAVE_INET_ADDR 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_IOCTLSOCKET_CAMEL 1 +#define HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1 +#define HAVE_LIBCRYPTO 1 +#define HAVE_LIBSSL 1 +#define HAVE_LIBZ 1 +#define HAVE_LONGLONG 1 +#define HAVE_MALLOC_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_OPENSSL_CRYPTO_H 1 +#define HAVE_OPENSSL_ERR_H 1 +#define HAVE_OPENSSL_PEM_H 1 +#define HAVE_OPENSSL_RSA_H 1 +#define HAVE_OPENSSL_SSL_H 1 +#define HAVE_OPENSSL_X509_H 1 +#define HAVE_PERROR 1 +#define HAVE_PWD_H 1 +#define HAVE_RAND_EGD 1 +#define HAVE_RAND_STATUS 1 +#define HAVE_SELECT 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SGTTY_H 1 +#define HAVE_SIGNAL 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 +#define HAVE_SOCKET 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRDUP 1 +#define HAVE_STRFTIME 1 +#define HAVE_STRICMP 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRSTR 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SOCKIO_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNAME 1 +#define HAVE_UNISTD_H 1 +#define HAVE_UTIME 1 +#define HAVE_UTIME_H 1 +#define HAVE_WRITABLE_ARGV 1 +#define HAVE_ZLIB_H 1 +#define HAVE_SYS_IOCTL_H 1 + +#define NEED_MALLOC_H 1 + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define USE_MANUAL 1 +#define USE_OPENSSL 1 +#define CURL_DISABLE_LDAP 1 + +#define OS "AmigaOS" + +#define PACKAGE "curl" +#define PACKAGE_BUGREPORT "a suitable mailing list: https://curl.haxx.se/mail/" +#define PACKAGE_NAME "curl" +#define PACKAGE_STRING "curl -" +#define PACKAGE_TARNAME "curl" +#define PACKAGE_VERSION "-" +#define CURL_CA_BUNDLE "s:curl-ca-bundle.crt" + +#define RETSIGTYPE void +#define SELECT_TYPE_ARG1 int +#define SELECT_TYPE_ARG234 (fd_set *) +#define SELECT_TYPE_ARG5 (struct timeval *) + +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +#define in_addr_t int + +#ifndef F_OK +# define F_OK 0 +#endif + +#ifndef O_RDONLY +# define O_RDONLY 0x0000 +#endif + +#ifndef LONG_MAX +# define LONG_MAX 0x7fffffffL +#endif + +#ifndef LONG_MIN +# define LONG_MIN (-0x7fffffffL-1) +#endif + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 long +#define RECV_TYPE_ARG2 char * +#define RECV_TYPE_ARG3 long +#define RECV_TYPE_ARG4 long +#define RECV_TYPE_RETV long + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 long +#define RECVFROM_TYPE_ARG2 char +#define RECVFROM_TYPE_ARG3 long +#define RECVFROM_TYPE_ARG4 long +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 long +#define RECVFROM_TYPE_RETV long + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 char * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#endif /* __AMIGA__ */ +#endif /* HEADER_CURL_CONFIG_AMIGAOS_H */ diff --git a/external/curl prx/include/config-dos.h b/external/curl prx/include/config-dos.h new file mode 100644 index 0000000..3e973de --- /dev/null +++ b/external/curl prx/include/config-dos.h @@ -0,0 +1,183 @@ +#ifndef HEADER_CURL_CONFIG_DOS_H +#define HEADER_CURL_CONFIG_DOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* ================================================================ */ +/* lib/config-dos.h - Hand crafted config file for DOS */ +/* ================================================================ */ + +#if defined(DJGPP) + #define OS "MSDOS/djgpp" +#elif defined(__HIGHC__) + #define OS "MSDOS/HighC" +#elif defined(__WATCOMC__) + #define OS "MSDOS/Watcom" +#else + #define OS "MSDOS/?" +#endif + +#define PACKAGE "curl" + +#define HAVE_ARPA_INET_H 1 +#define HAVE_ASSERT_H 1 +#define HAVE_ERRNO_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_FREEADDRINFO 1 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETNAMEINFO 1 +#define HAVE_GETPROTOBYNAME 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_IO_H 1 +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 +#define HAVE_IOCTLSOCKET 1 +#define HAVE_IOCTLSOCKET_FIONBIO 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LONGLONG 1 +#define HAVE_MEMORY_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_NETINET_TCP_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_PROCESS_H 1 +#define HAVE_RECV 1 +#define HAVE_RECVFROM 1 +#define HAVE_SELECT 1 +#define HAVE_SEND 1 +#define HAVE_SETJMP_H 1 +#define HAVE_SETLOCALE 1 +#define HAVE_SETMODE 1 +#define HAVE_SIGNAL 1 +#define HAVE_SOCKET 1 +#define HAVE_STRDUP 1 +#define HAVE_STRICMP 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRUCT_TIMEVAL 1 +#define HAVE_STRUCT_IN6_ADDR 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UNISTD_H 1 + +#define NEED_MALLOC_H 1 + +#define RETSIGTYPE void +#define SIZEOF_INT 4 +#define SIZEOF_LONG 4 +#define SIZEOF_LONG_DOUBLE 16 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 +#define SIZEOF_CURL_OFF_T 4 +#define STDC_HEADERS 1 +#define TIME_WITH_SYS_TIME 1 + +/* Qualifiers for send(), recv(), recvfrom() and getnameinfo(). */ + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 int +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV int + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 int +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV int + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 int +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV int +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 int +#define GETNAMEINFO_TYPE_ARG46 int +#define GETNAMEINFO_TYPE_ARG7 int + +#define BSD + +/* CURLDEBUG definition enables memory tracking */ +/* #define CURLDEBUG */ + +/* USE_ZLIB on cmd-line */ +#ifdef USE_ZLIB + #define HAVE_ZLIB_H 1 + #define HAVE_LIBZ 1 +#endif + +/* USE_OPENSSL on cmd-line */ +#ifdef USE_OPENSSL + #define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + #define HAVE_OPENSSL_ENGINE_H 1 + #define OPENSSL_NO_KRB5 1 +#endif + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +#define in_addr_t u_long + +#if defined(__HIGHC__) || \ + (defined(__GNUC__) && (__GNUC__ < 4)) + #define ssize_t int +#endif + +#define CURL_CA_BUNDLE getenv("CURL_CA_BUNDLE") + +/* Target HAVE_x section */ + +#if defined(DJGPP) + #define HAVE_BASENAME 1 + #define HAVE_STRCASECMP 1 + #define HAVE_SIGACTION 1 + #define HAVE_SIGSETJMP 1 + #define HAVE_SYS_TIME_H 1 + #define HAVE_TERMIOS_H 1 + #define HAVE_VARIADIC_MACROS_GCC 1 + +#elif defined(__WATCOMC__) + #define HAVE_STRCASECMP 1 + +#elif defined(__HIGHC__) + #define HAVE_SYS_TIME_H 1 + #define strerror(e) strerror_s_((e)) +#endif + +#ifdef MSDOS /* Watt-32 */ + #define HAVE_CLOSE_S 1 +#endif + +#undef word +#undef byte + +#endif /* HEADER_CURL_CONFIG_DOS_H */ diff --git a/external/curl prx/include/config-mac.h b/external/curl prx/include/config-mac.h new file mode 100644 index 0000000..3c12bdf --- /dev/null +++ b/external/curl prx/include/config-mac.h @@ -0,0 +1,125 @@ +#ifndef HEADER_CURL_CONFIG_MAC_H +#define HEADER_CURL_CONFIG_MAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =================================================================== */ +/* Hand crafted config file for Mac OS 9 */ +/* =================================================================== */ +/* On Mac OS X you must run configure to generate curl_config.h file */ +/* =================================================================== */ + +#define OS "mac" + +/* Define if you want the built-in manual */ +#define USE_MANUAL 1 + +#define HAVE_ERRNO_H 1 +#define HAVE_NETINET_IN_H 1 +#define HAVE_SYS_SOCKET_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_ARPA_INET_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_NET_IF_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_FCNTL_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_TIME_H 1 +#define HAVE_UTIME_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_UTIME_H 1 + +#define TIME_WITH_SYS_TIME 1 + +#define HAVE_ALARM 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_UTIME 1 +#define HAVE_SETVBUF 1 +#define HAVE_STRFTIME 1 +#define HAVE_INET_ADDR 1 +#define HAVE_MEMCPY 1 +#define HAVE_SELECT 1 +#define HAVE_SOCKET 1 +#define HAVE_STRUCT_TIMEVAL 1 + +#define HAVE_SIGACTION 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_SIG_ATOMIC_T 1 + +#ifdef MACOS_SSL_SUPPORT +# define USE_OPENSSL 1 +#endif + +#define CURL_DISABLE_LDAP 1 + +#define HAVE_RAND_STATUS 1 +#define HAVE_RAND_EGD 1 + +#define HAVE_IOCTL 1 +#define HAVE_IOCTL_FIONBIO 1 + +#define RETSIGTYPE void + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 4 + +#define HAVE_GETNAMEINFO 1 +#define GETNAMEINFO_QUAL_ARG1 const +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * +#define GETNAMEINFO_TYPE_ARG2 socklen_t +#define GETNAMEINFO_TYPE_ARG46 size_t +#define GETNAMEINFO_TYPE_ARG7 int + +#define HAVE_RECV 1 +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define HAVE_RECVFROM 1 +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 int +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define HAVE_SEND 1 +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 size_T +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + +#define HAVE_EXTRA_STRICMP_H 1 +#define HAVE_EXTRA_STRDUP_H 1 + +#endif /* HEADER_CURL_CONFIG_MAC_H */ diff --git a/external/curl prx/include/config-os400.h b/external/curl prx/include/config-os400.h new file mode 100644 index 0000000..bde4f0b --- /dev/null +++ b/external/curl prx/include/config-os400.h @@ -0,0 +1,572 @@ +#ifndef HEADER_CURL_CONFIG_OS400_H +#define HEADER_CURL_CONFIG_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for OS/400 */ +/* ================================================================ */ + +#pragma enum(int) + +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "OS/400" + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#define HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its + * prototype is incompatible with the "standard" one (1st argument is not + * const). However, getaddrinfo() is supported (ASCII version defined as + * a local wrapper in setup-os400.h) in a threadsafe way: we can then + * configure getaddrinfo() as such and get rid of gethostbyname_r() without + * loss of threadsafeness. */ +#undef HAVE_GETHOSTBYNAME_R +#undef HAVE_GETHOSTBYNAME_R_3 +#undef HAVE_GETHOSTBYNAME_R_5 +#undef HAVE_GETHOSTBYNAME_R_6 +#define HAVE_GETADDRINFO +#define HAVE_GETADDRINFO_THREADSAFE + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `geteuid' function. */ +#define HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#define HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define if you have the `getpwuid' function. */ +#define HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#define HAVE_GETSERVBYNAME + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have GSS API. */ +#define HAVE_GSSAPI + +/* Define if you have the GNU gssapi libraries */ +#undef HAVE_GSSGNU + +/* Define if you have the Heimdal gssapi libraries */ +#define HAVE_GSSHEIMDAL + +/* Define if you have the MIT gssapi libraries */ +#undef HAVE_GSSMIT + +/* Define if you have the `ucb' library (-lucb). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#define HAVE_PERROR + +/* Define if you have the header file. */ +#define HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#define HAVE_SETVBUF + +/* Define if you have the header file. */ +#undef HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#define HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#undef HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + + +/* The following define is needed on OS400 to enable strcmpi(), stricmp() and + strdup(). */ +#define __cplusplus__strings__ + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#define HAVE_STRCMPI + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the header file. */ +#define HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the header file. */ +#undef HAVE_STROPTS_H + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL /* Allows ASCII compile on V5R1. */ + +/* Define if you have the header file. */ +#define HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#define HAVE_SYS_UN_H + +/* Define if you have the header file. */ +#define HAVE_SYS_IOCTL_H + +/* Define if you have the `tcgetattr' function. */ +#undef HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#undef HAVE_TCSETATTR + +/* Define if you have the header file. */ +#undef HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#define HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#undef HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of a `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 8 + +/* Define if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG + +/* The size of a `long long', as computed by sizeof. */ +#define SIZEOF_LONG_LONG 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `curl_off_t', as computed by sizeof. */ +#define SIZEOF_CURL_OFF_T 8 + +/* Whether long long constants must be suffixed by LL. */ + +#define HAVE_LL + +/* Define this if you have struct sockaddr_storage */ +#define HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS + +/* Define if you can safely include both and . */ +#define TIME_WITH_SYS_TIME + +/* Define to enable alt-svc support (experimental) */ +#undef USE_ALTSVC + +/* Version number of package */ +#undef VERSION + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#define _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* type to use in place of in_addr_t if not defined */ +#define in_addr_t unsigned long + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* Define if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR + +/* To disable LDAP */ +#undef CURL_DISABLE_LDAP + +/* Definition to make a library symbol externally visible. */ +#define CURL_EXTERN_SYMBOL + +/* Define if you have the ldap_url_parse procedure. */ +/* #define HAVE_LDAP_URL_PARSE */ /* Disabled because of an IBM bug. */ + +/* Define if you have the getnameinfo function. */ +/* OS400 has no ASCII version of this procedure: wrapped in setup-os400.h. */ +#define HAVE_GETNAMEINFO + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 socklen_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* Define to use the GSKit package. */ +#define USE_GSKIT + +/* Define to use the OS/400 crypto library. */ +#define USE_OS400CRYPTO + +/* Define to use Unix sockets. */ +#define USE_UNIX_SOCKETS + +/* Use the system keyring as the default CA bundle. */ +#define CURL_CA_BUNDLE "/QIBM/UserData/ICSS/Cert/Server/DEFAULT.KDB" + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* The following must be defined BEFORE system header files inclusion. */ + +#define __ptr128 /* No teraspace. */ +#define qadrt_use_fputc_inline /* Generate fputc() wrapper inline. */ +#define qadrt_use_fread_inline /* Generate fread() wrapper inline. */ +#define qadrt_use_fwrite_inline /* Generate fwrite() wrapper inline. */ + +#endif /* HEADER_CURL_CONFIG_OS400_H */ diff --git a/external/curl prx/include/config-riscos.h b/external/curl prx/include/config-riscos.h new file mode 100644 index 0000000..0379524 --- /dev/null +++ b/external/curl prx/include/config-riscos.h @@ -0,0 +1,513 @@ +#ifndef HEADER_CURL_CONFIG_RISCOS_H +#define HEADER_CURL_CONFIG_RISCOS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for RISC OS */ +/* ================================================================ */ + +/* Name of this package! */ +#undef PACKAGE + +/* Version number of this archive. */ +#undef VERSION + +/* Define if you have the getpass function. */ +#undef HAVE_GETPASS + +/* Define cpu-machine-OS */ +#define OS "ARM-RISC OS" + +/* Define if you want the built-in manual */ +#define USE_MANUAL + +/* Define if you have the gethostbyaddr_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYADDR_R_5 + +/* Define if you have the gethostbyaddr_r() function with 7 arguments */ +#undef HAVE_GETHOSTBYADDR_R_7 + +/* Define if you have the gethostbyaddr_r() function with 8 arguments */ +#undef HAVE_GETHOSTBYADDR_R_8 + +/* Define if you have the gethostbyname_r() function with 3 arguments */ +#undef HAVE_GETHOSTBYNAME_R_3 + +/* Define if you have the gethostbyname_r() function with 5 arguments */ +#undef HAVE_GETHOSTBYNAME_R_5 + +/* Define if you have the gethostbyname_r() function with 6 arguments */ +#undef HAVE_GETHOSTBYNAME_R_6 + +/* Define if you need the _REENTRANT define for some functions */ +#undef NEED_REENTRANT + +/* Define if you have the Kerberos4 libraries (including -ldes) */ +#undef HAVE_KRB4 + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define this to 'int' if ssize_t is not an available typedefed type */ +#undef ssize_t + +/* Define this as a suitable file to read random data from */ +#undef RANDOM_FILE + +/* Define this to your Entropy Gathering Daemon socket pathname */ +#undef EGD_SOCKET + +/* Define if you want to enable IPv6 support */ +#undef ENABLE_IPV6 + +/* Define if you have the alarm function. */ +#define HAVE_ALARM + +/* Define if you have the header file. */ +#define HAVE_ALLOCA_H + +/* Define if you have the header file. */ +#define HAVE_ARPA_INET_H + +/* Define if you have the `closesocket' function. */ +#undef HAVE_CLOSESOCKET + +/* Define if you have the header file. */ +#undef HAVE_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_DES_H + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H + +/* Define if you have the header file. */ +#undef HAVE_ERR_H + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H + +/* Define if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO + +/* Define if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR + +/* Define if you have the `gethostbyaddr_r' function. */ +#undef HAVE_GETHOSTBYADDR_R + +/* Define if you have the `gethostbyname_r' function. */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define if you have the `gethostname' function. */ +#define HAVE_GETHOSTNAME + +/* Define if you have the header file. */ +#define HAVE_GETOPT_H + +/* Define if you have the `getpass_r' function. */ +#undef HAVE_GETPASS_R + +/* Define if you have the `getpwuid' function. */ +#undef HAVE_GETPWUID + +/* Define if you have the `getservbyname' function. */ +#undef HAVE_GETSERVBYNAME + +/* Define if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY + +/* Define if you have the `timeval' struct. */ +#define HAVE_STRUCT_TIMEVAL + +/* Define if you have the `inet_addr' function. */ +#undef HAVE_INET_ADDR + +/* Define if you have the header file. */ +#define HAVE_INTTYPES_H + +/* Define if you have the header file. */ +#undef HAVE_IO_H + +/* Define if you have the `krb_get_our_ip_for_realm' function. */ +#undef HAVE_KRB_GET_OUR_IP_FOR_REALM + +/* Define if you have the header file. */ +#undef HAVE_KRB_H + +/* Define if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define if you have the `resolve' library (-lresolve). */ +#undef HAVE_LIBRESOLVE + +/* Define if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the `ssl' library (-lssl). */ +#undef HAVE_LIBSSL + +/* Define if you have the `ucb' library (-lucb). */ +#undef HAVE_LIBUCB + +/* Define if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define if you have the header file. */ +#define HAVE_MALLOC_H + +/* Define if you need the malloc.h header file even with stdlib.h */ +/* #define NEED_MALLOC_H 1 */ + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#define HAVE_NETDB_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IF_ETHER_H + +/* Define if you have the header file. */ +#define HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#define HAVE_NET_IF_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_CRYPTO_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_ERR_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_PEM_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_RSA_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_OPENSSL_X509_H + +/* Define if you have the header file. */ +#undef HAVE_PEM_H + +/* Define if you have the `perror' function. */ +#undef HAVE_PERROR + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the `RAND_egd' function. */ +#undef HAVE_RAND_EGD + +/* Define if you have the `RAND_screen' function. */ +#undef HAVE_RAND_SCREEN + +/* Define if you have the `RAND_status' function. */ +#undef HAVE_RAND_STATUS + +/* Define if you have the header file. */ +#undef HAVE_RSA_H + +/* Define if you have the `select' function. */ +#define HAVE_SELECT + +/* Define if you have the `setvbuf' function. */ +#undef HAVE_SETVBUF + +/* Define if you have the header file. */ +#define HAVE_SGTTY_H + +/* Define if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define if you have the `signal' function. */ +#define HAVE_SIGNAL + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T + +/* Define if sig_atomic_t is already defined as volatile. */ +#undef HAVE_SIG_ATOMIC_T_VOLATILE + +/* Define if you have the `socket' function. */ +#define HAVE_SOCKET + +/* Define if you have the header file. */ +#undef HAVE_SSL_H + +/* Define if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H + +/* Define if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the `strcmpi' function. */ +#undef HAVE_STRCMPI + +/* Define if you have the `strdup' function. */ +#define HAVE_STRDUP + +/* Define if you have the `strftime' function. */ +#define HAVE_STRFTIME + +/* Define if you have the `stricmp' function. */ +#define HAVE_STRICMP + +/* Define if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define if you have the header file. */ +#define HAVE_STRING_H + +/* Define if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define if you have the `strstr' function. */ +#define HAVE_STRSTR + +/* Define if you have the `strtok_r' function. */ +#undef HAVE_STRTOK_R + +/* Define if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H + +/* Define if you have the `tcgetattr' function. */ +#define HAVE_TCGETATTR + +/* Define if you have the `tcsetattr' function. */ +#define HAVE_TCSETATTR + +/* Define if you have the header file. */ +#define HAVE_TERMIOS_H + +/* Define if you have the header file. */ +#undef HAVE_TERMIO_H + +/* Define if you have the header file. */ +#undef HAVE_TIME_H + +/* Define if you have the `uname' function. */ +#define HAVE_UNAME + +/* Define if you have the header file. */ +#define HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_WINSOCK_H + +/* Define if you have the header file. */ +#undef HAVE_X509_H + +/* Name of package */ +#undef PACKAGE + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#undef SIZEOF_LONG_DOUBLE + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define if you have the ioctl function. */ +#define HAVE_IOCTL + +/* Define if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV ssize_t + +/* Define 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV ssize_t + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV ssize_t + +#endif /* HEADER_CURL_CONFIG_RISCOS_H */ diff --git a/external/curl prx/include/config-symbian.h b/external/curl prx/include/config-symbian.h new file mode 100644 index 0000000..d23de33 --- /dev/null +++ b/external/curl prx/include/config-symbian.h @@ -0,0 +1,808 @@ +#ifndef HEADER_CURL_CONFIG_SYMBIAN_H +#define HEADER_CURL_CONFIG_SYMBIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for Symbian */ +/* ================================================================ */ + +/* Location of default ca bundle */ +/* #define CURL_CA_BUNDLE "/etc/pki/tls/certs/ca-bundle.crt"*/ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #define CURL_DISABLE_VERBOSE_STRINGS 1*/ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ALLOCA_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_ARPA_TFTP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/*#define HAVE_BASENAME 1*/ + +/* Define to 1 if bool is an available type. */ +/*#define HAVE_BOOL_T 1*/ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/*#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/*#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/*#define HAVE_FORK 1*/ + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/*#define HAVE_GETRLIMIT 1*/ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/*#define HAVE_IDNA_STRERROR 1*/ + +/* Define to 1 if you have the `idn_free' function. */ +/*#define HAVE_IDN_FREE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_IDN_FREE_H 1*/ + +/* Define to 1 if you have the `inet_addr' function. */ +/*#define HAVE_INET_ADDR 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/*#define HAVE_INET_NTOP 1*/ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/*#define HAVE_INET_PTON 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/*#define HAVE_LBER_H 1*/ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/*#define HAVE_LDAP_H 1*/ + +/* Use LDAPS implementation */ +/*#define HAVE_LDAP_SSL 1*/ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/*#define HAVE_LDAP_URL_PARSE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBGEN_H 1*/ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/*#define HAVE_LIBIDN 1*/ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/*#define HAVE_LIBSSH2 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_LIBSSH2_H 1*/ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/*#define HAVE_LIBSSL 1*/ + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +/*#define HAVE_MALLOC_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/*#define HAVE_MSG_NOSIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_NETINET_TCP_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/*#define HAVE_NI_WITHSCOPEID 1*/ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_CRYPTO_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ENGINE_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_ERR_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PEM_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_PKCS12_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_RSA_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_SSL_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_OPENSSL_X509_H 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/*#define HAVE_POLL 1*/ + +/* If you have a fine poll */ +/*#define HAVE_POLL_FINE 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_POLL_H 1*/ + +/* we have a POSIX-style strerror_r() */ +#define HAVE_POSIX_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/*#define HAVE_RAND_STATUS 1*/ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +/* #undef HAVE_SETMODE */ + +/* Define to 1 if you have the `setrlimit' function. */ +/*#define HAVE_SETRLIMIT 1*/ + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SGTTY_H 1*/ + +/* Define to 1 if you have the `sigaction' function. */ +/*#define HAVE_SIGACTION 1*/ + +/* Define to 1 if you have the `siginterrupt' function. */ +/*#define HAVE_SIGINTERRUPT 1*/ + +/* Define to 1 if you have the `signal' function. */ +/*#define HAVE_SIGNAL 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* If you have sigsetjmp */ +/*#define HAVE_SIGSETJMP 1*/ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +/*#define HAVE_SIG_ATOMIC_T 1*/ + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +/*#define HAVE_SSL_GET_SHUTDOWN 1*/ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +#define HAVE_STRLCPY 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_SYS_POLL_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIOS_H 1*/ + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TERMIO_H 1*/ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/*#define HAVE_TLD_H 1*/ + +/* Define to 1 if you have the `tld_strerror' function. */ +/*#define HAVE_TLD_STRERROR 1*/ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +/*#define HAVE_VARIADIC_MACROS_GCC 1*/ + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/*#define HAVE_WRITABLE_ARGV 1*/ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#ifdef __WINS__ +#define OS "i386-pc-epoc32" +#elif __MARM__ +#define OS "arm-unknown-epoc32" +#else +/* This won't happen on any current Symbian version */ +#define OS "unknown-unknown-epoc32" +#endif + +/* Name of package */ +/*#define PACKAGE "curl"*/ + +/* Define to the address where bug reports for this package should be sent. */ +/*#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => https://curl.haxx.se/mail/"*/ + +/* Define to the full name of this package. */ +/*#define PACKAGE_NAME "curl"*/ + +/* Define to the full name and version of this package. */ +/*#define PACKAGE_STRING "curl -"*/ + +/* Define to the one symbol short name of this package. */ +/*#define PACKAGE_TARNAME "curl"*/ + +/* Define to the version of this package. */ +/*#define PACKAGE_VERSION "-"*/ + +/* a suitable file to read random data from */ +/*#define RANDOM_FILE "/dev/urandom"*/ + +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void * +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t + +#define RECVFROM_TYPE_ARG1 int +#define RECVFROM_TYPE_ARG2 void +#define RECVFROM_TYPE_ARG3 size_t +#define RECVFROM_TYPE_ARG4 int +#define RECVFROM_TYPE_ARG5 struct sockaddr +#define RECVFROM_TYPE_ARG6 size_t +#define RECVFROM_TYPE_RETV ssize_t +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +#define SEND_TYPE_ARG1 int +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG2 void * +#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t + + +/* Define as the return type of signal handlers (`int' or `void'). */ +/*#define RETSIGTYPE void*/ + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/*#define USE_LIBSSH2 1*/ + +/* If you want to build curl with the built-in manual */ +/*#define USE_MANUAL 1*/ + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Version number of package */ +/*#define VERSION "7.18.2-CVS"*/ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Enabling curl debug mode when building in Symbian debug mode would work */ +/* except that debug mode introduces new exports that must be frozen. */ +#ifdef _DEBUG +/* #define CURLDEBUG */ +#endif + +/* sys/cdefs.h fails to define this for WINSCW prior to Symbian OS ver. 9.4 */ +#ifndef __LONG_LONG_SUPPORTED +#define __LONG_LONG_SUPPORTED +#endif + +/* Enable appropriate header only when zlib support is enabled */ +#ifdef HAVE_LIBZ +#define HAVE_ZLIB_H 1 +#endif + +#endif /* HEADER_CURL_CONFIG_SYMBIAN_H */ diff --git a/external/curl prx/include/config-tpf.h b/external/curl prx/include/config-tpf.h new file mode 100644 index 0000000..778d983 --- /dev/null +++ b/external/curl prx/include/config-tpf.h @@ -0,0 +1,772 @@ +#ifndef HEADER_CURL_CONFIG_TPF_H +#define HEADER_CURL_CONFIG_TPF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for TPF */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* FEATURES, FUNCTIONS, and DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* NOTE: Refer also to the .mak file for some of the flags below */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +/* #undef CURL_DISABLE_FTP */ + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +/* #undef CURL_DISABLE_LDAP */ + +/* to disable TELNET */ +/* #undef CURL_DISABLE_TELNET */ + +/* to disable TFTP */ +/* #undef CURL_DISABLE_TFTP */ + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* lber dynamic library file */ +/* #undef DL_LBER_FILE */ + +/* ldap dynamic library file */ +/* #undef DL_LDAP_FILE */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +/* #undef ENABLE_IPV6 */ + +/* Define if struct sockaddr_in6 has the sin6_scope_id member */ +/* #undef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 */ + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +#define HAVE_BASENAME 1 + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +/* #undef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ +#define HAVE_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ +#define HAVE_DES_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +/* #undef HAVE_ENGINE_LOAD_BUILTIN_ENGINES */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ +#define HAVE_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +/* #undef HAVE_FORK */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if getaddrinfo exists and works */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `gethostbyaddr' function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* If you have gethostbyname */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 1 */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO */ + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getprotobyname' function. */ +/* #undef HAVE_GETPROTOBYNAME */ + +/* Define to 1 if you have the `getpwuid' function. */ +#define HAVE_GETPWUID 1 + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* we have a glibc-style strerror_r() */ +/* #undef HAVE_GLIBC_STRERROR_R */ +#define HAVE_GLIBC_STRERROR_R 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `iconv' functions. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO + function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IO_H */ + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H 1 */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +/* #undef HAVE_LIBZ */ + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +/* undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define if NI_WITHSCOPEID exists and works */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* we have no strerror_r() proto */ +/* #undef HAVE_NO_STRERROR_R_DECL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_CRYPTO_H */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ENGINE_H */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_ERR_H */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PEM_H */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_PKCS12_H */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_RSA_H */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_SSL_H */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_OPENSSL_X509_H */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ +#define HAVE_PEM_H 1 + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* we have a POSIX-style strerror_r() */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `RAND_egd' function. */ +/* #undef HAVE_RAND_EGD */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +/* #undef HAVE_RAND_STATUS */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ +#define HAVE_RSA_H 1 + +/* Define to 1 if you have the `select' function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +/* #undef HAVE_SETSOCKOPT */ + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H 1 */ + +/* Define to 1 if you have the `sigaction' function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the `siginterrupt' function. */ +/* #undef HAVE_SIGINTERRUPT */ + +/* Define to 1 if you have the `signal' function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* If you have sigsetjmp */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ +#define HAVE_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcmpi' function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `stricmp' function. */ +/* #undef HAVE_STRICMP */ +#define HAVE_STRICMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtok_r' function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* if struct sockaddr_storage is defined */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_FILIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ +#define HAVE_SYS_SOCKIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_UTIME_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TERMIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +/* #undef HAVE_WRITABLE_ARGV */ + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +/* #undef HAVE_ZLIB_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* cpu-machine-OS */ +#define OS "s390x-ibm-tpf" + +/* Name of package */ +#define PACKAGE "curl" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT \ + "a suitable curl mailing list => https://curl.haxx.se/mail/" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "curl" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "curl -" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "curl" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "-" + +/* a suitable file to read random data from */ +/* #undef RANDOM_FILE */ + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type of arg 1 for `select'. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#define SELECT_TYPE_ARG234 (fd_set *) + +/* Define to the type of arg 5 for `select'. */ +#define SELECT_TYPE_ARG5 (struct timeval *) + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define if you want to enable ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* If you want to build curl with the built-in manual */ +/* #undef USE_MANUAL */ + +/* if OpenSSL is in use */ +/* #undef USE_OPENSSL */ + +/* if SSL is enabled */ +/* #undef USE_OPENSSL */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Version number of package */ +#define VERSION "not-used" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* type to use in place of in_addr_t if not defined */ +/* #undef in_addr_t */ + +/* Define to `unsigned' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +/* Define to 1 if you have the getnameinfo function. */ +/* #undef HAVE_GETNAMEINFO 1 */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_QUAL_ARG1 const */ + +/* Define to the type of arg 1 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG1 struct sockaddr * */ + +/* Define to the type of arg 2 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG2 socklen_t */ + +/* Define to the type of args 4 and 6 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG46 size_t */ + +/* Define to the type of arg 7 for getnameinfo. */ +/* #undef GETNAMEINFO_TYPE_ARG7 int */ + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +#define CURL_DOES_CONVERSIONS +#ifndef CURL_ICONV_CODESET_OF_HOST +#define CURL_ICONV_CODESET_OF_HOST "IBM-1047" +#endif + + +#endif /* HEADER_CURL_CONFIG_TPF_H */ diff --git a/external/curl prx/include/config-vxworks.h b/external/curl prx/include/config-vxworks.h new file mode 100644 index 0000000..8790f82 --- /dev/null +++ b/external/curl prx/include/config-vxworks.h @@ -0,0 +1,919 @@ +#ifndef HEADER_CURL_CONFIG_VXWORKS_H +#define HEADER_CURL_CONFIG_VXWORKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* =============================================================== */ +/* Hand crafted config file for VxWorks */ +/* =============================================================== */ + +/* Location of default ca bundle */ +/* #undef CURL_CA_BUNDLE */ + +/* Location of default ca path */ +/* #undef CURL_CA_PATH */ + +/* to disable cookies support */ +/* #undef CURL_DISABLE_COOKIES */ + +/* to disable cryptographic authentication */ +/* #undef CURL_DISABLE_CRYPTO_AUTH */ + +/* to disable DICT */ +/* #undef CURL_DISABLE_DICT */ + +/* to disable FILE */ +/* #undef CURL_DISABLE_FILE */ + +/* to disable FTP */ +#define CURL_DISABLE_FTP 1 + +/* to disable HTTP */ +/* #undef CURL_DISABLE_HTTP */ + +/* to disable LDAP */ +#define CURL_DISABLE_LDAP 1 + +/* to disable LDAPS */ +#define CURL_DISABLE_LDAPS 1 + +/* to disable NTLM authentication */ +#define CURL_DISABLE_NTLM 1 + +/* to disable proxies */ +/* #undef CURL_DISABLE_PROXY */ + +/* to disable TELNET */ +#define CURL_DISABLE_TELNET 1 + +/* to disable TFTP */ +#define CURL_DISABLE_TFTP 1 + +/* to disable verbose strings */ +/* #undef CURL_DISABLE_VERBOSE_STRINGS */ + +/* Definition to make a library symbol externally visible. */ +/* #undef CURL_EXTERN_SYMBOL */ + +/* Use Windows LDAP implementation */ +/* #undef USE_WIN32_LDAP */ + +/* your Entropy Gathering Daemon socket pathname */ +/* #undef EGD_SOCKET */ + +/* Define if you want to enable IPv6 support */ +#define ENABLE_IPV6 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have the alarm function. */ +#define HAVE_ALARM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_TFTP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `basename' function. */ +/* #undef HAVE_BASENAME */ + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +/* #undef HAVE_CLOCK_GETTIME_MONOTONIC */ + +/* Define to 1 if you have the `closesocket' function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the `CRYPTO_cleanup_all_ex_data' function. */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CRYPTO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DES_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ENGINE_load_builtin_engines' function. */ +#define HAVE_ENGINE_LOAD_BUILTIN_ENGINES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ERR_H */ + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have the freeifaddrs function. */ +#define HAVE_FREEIFADDRS 1 + +/* Define to 1 if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `geteuid' function. */ +/* #undef HAVE_GETEUID */ + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyaddr_r function. */ +#define HAVE_GETHOSTBYADDR_R 1 + +/* gethostbyaddr_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYADDR_R_5 */ + +/* gethostbyaddr_r() takes 7 args */ +/* #undef HAVE_GETHOSTBYADDR_R_7 */ + +/* gethostbyaddr_r() takes 8 args */ +#define HAVE_GETHOSTBYADDR_R_8 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostbyname_r function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* gethostbyname_r() takes 3 args */ +/* #undef HAVE_GETHOSTBYNAME_R_3 */ + +/* gethostbyname_r() takes 5 args */ +/* #undef HAVE_GETHOSTBYNAME_R_5 */ + +/* gethostbyname_r() takes 6 args */ +/* #undef HAVE_GETHOSTBYNAME_R_6 */ + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have a working getifaddrs function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the `getpass_r' function. */ +/* #undef HAVE_GETPASS_R */ + +/* Define to 1 if you have the `getppid' function. */ +#define HAVE_GETPPID 1 + +/* Define to 1 if you have the `getprotobyname' function. */ +#define HAVE_GETPROTOBYNAME 1 + +/* Define to 1 if you have the `getpwuid' function. */ +/* #undef HAVE_GETPWUID */ + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the getservbyport_r function. */ +/* #undef HAVE_GETSERVBYPORT_R */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have a working glibc-style strerror_r function. */ +/* #undef HAVE_GLIBC_STRERROR_R */ + +/* Define to 1 if you have a working gmtime_r function. */ +#define HAVE_GMTIME_R 1 + +/* if you have the gssapi libraries */ +/* #undef HAVE_GSSAPI */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_GENERIC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_KRB5_H */ + +/* if you have the GNU gssapi libraries */ +/* #undef HAVE_GSSGNU */ + +/* if you have the Heimdal gssapi libraries */ +/* #undef HAVE_GSSHEIMDAL */ + +/* if you have the MIT gssapi libraries */ +/* #undef HAVE_GSSMIT */ + +/* Define to 1 if you have the `idna_strerror' function. */ +/* #undef HAVE_IDNA_STRERROR */ + +/* Define to 1 if you have the `idn_free' function. */ +/* #undef HAVE_IDN_FREE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IDN_FREE_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_addr' function. */ +#define HAVE_INET_ADDR 1 + +/* Define to 1 if you have the inet_ntoa_r function. */ +/* #undef HAVE_INET_NTOA_R */ + +/* inet_ntoa_r() takes 2 args */ +/* #undef HAVE_INET_NTOA_R_2 */ + +/* inet_ntoa_r() takes 3 args */ +/* #undef HAVE_INET_NTOA_R_3 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +/* #undef HAVE_INET_NTOP */ + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +/* #undef HAVE_INET_PTON */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. + */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IO_H 1 + +/* if you have the Kerberos4 libraries (including -ldes) */ +/* #undef HAVE_KRB4 */ + +/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */ +/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_KRB_H */ + +/* Define to 1 if you have the lber.h header file. */ +/* #undef HAVE_LBER_H */ + +/* Define to 1 if you have the ldapssl.h header file. */ +/* #undef HAVE_LDAPSSL_H */ + +/* Define to 1 if you have the ldap.h header file. */ +/* #undef HAVE_LDAP_H */ + +/* Use LDAPS implementation */ +/* #undef HAVE_LDAP_SSL */ + +/* Define to 1 if you have the ldap_ssl.h header file. */ +/* #undef HAVE_LDAP_SSL_H */ + +/* Define to 1 if you have the `ldap_url_parse' function. */ +/* #undef HAVE_LDAP_URL_PARSE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBGEN_H */ + +/* Define to 1 if you have the `idn' library (-lidn). */ +/* #undef HAVE_LIBIDN */ + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +/* #undef HAVE_LIBRESOLV */ + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the `socket' library (-lsocket). */ +/* #undef HAVE_LIBSOCKET */ + +/* Define to 1 if you have the `ssh2' library (-lssh2). */ +/* #undef HAVE_LIBSSH2 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_LIBSSH2_H */ + +/* Define to 1 if you have the `libssh2_version' function. */ +/* #undef HAVE_LIBSSH2_VERSION */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +#define HAVE_LIBSSL 1 + +/* if zlib is available */ +#define HAVE_LIBZ 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if you have a working localtime_r function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +/* #undef HAVE_MSG_NOSIGNAL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if NI_WITHSCOPEID exists and works. */ +/* #undef HAVE_NI_WITHSCOPEID */ + +/* if you have an old MIT gssapi library, lacking GSS_C_NT_HOSTBASED_SERVICE + */ +/* #undef HAVE_OLD_GSSMIT */ + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_CRYPTO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ENGINE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_ERR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PEM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_PKCS12_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_RSA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_SSL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_OPENSSL_X509_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PEM_H */ + +/* Define to 1 if you have the `perror' function. */ +#define HAVE_PERROR 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have a working poll function. */ +/* #undef HAVE_POLL */ + +/* If you have a fine poll */ +/* #undef HAVE_POLL_FINE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have a working POSIX-style strerror_r function. */ +/* #undef HAVE_POSIX_STRERROR_R */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PWD_H */ + +/* Define to 1 if you have the `RAND_egd' function. */ +#define HAVE_RAND_EGD 1 + +/* Define to 1 if you have the `RAND_screen' function. */ +/* #undef HAVE_RAND_SCREEN */ + +/* Define to 1 if you have the `RAND_status' function. */ +#define HAVE_RAND_STATUS 1 + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_RSA_H */ + +/* Define to 1 if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the `setmode' function. */ +#define HAVE_SETMODE 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SGTTY_H */ + +/* Define to 1 if you have the sigaction function. */ +#define HAVE_SIGACTION 1 + +/* Define to 1 if you have the siginterrupt function. */ +#define HAVE_SIGINTERRUPT 1 + +/* Define to 1 if you have the signal function. */ +#define HAVE_SIGNAL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the sigsetjmp function or macro. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the `socket' function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the `SSL_get_shutdown' function. */ +#define HAVE_SSL_GET_SHUTDOWN 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SSL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the strerror_r function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STROPTS_H */ + +/* Define to 1 if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the strtok_r function. */ +#define HAVE_STRTOK_R 1 + +/* Define to 1 if you have the strtoll function. */ +/* #undef HAVE_STRTOLL */ + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_PARAM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_UTIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_TLD_H */ + +/* Define to 1 if you have the `tld_strerror' function. */ +/* #undef HAVE_TLD_STRERROR */ + +/* Define to 1 if you have the `uname' function. */ +#define HAVE_UNAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if compiler supports C99 variadic macro style. */ +#define HAVE_VARIADIC_MACROS_C99 1 + +/* Define to 1 if compiler supports old gcc variadic macro style. */ +#define HAVE_VARIADIC_MACROS_GCC 1 + +/* Define to 1 if you have a working vxworks-style strerror_r function. */ +#define HAVE_VXWORKS_STRERROR_R 1 + +/* Define to 1 if you have the winber.h header file. */ +/* #undef HAVE_WINBER_H */ + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winldap.h header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define this symbol if your OS supports changing the contents of argv */ +#define HAVE_WRITABLE_ARGV 1 + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_X509_H */ + +/* if you have the zlib.h header file */ +#define HAVE_ZLIB_H 1 + +/* Define to 1 if you need the lber.h header file even with ldap.h */ +/* #undef NEED_LBER_H */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to 1 if the open function requires three arguments. */ +#define OPEN_NEEDS_ARG3 1 + +/* cpu-machine-OS */ +#define OS "unknown-unknown-vxworks" + +/* Name of package */ +#define PACKAGE "curl" + +/* a suitable file to read random data from */ +#define RANDOM_FILE "/dev/urandom" + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 5 for select. */ +#define SELECT_QUAL_ARG5 + +/* Define to the type of arg 1 for select. */ +#define SELECT_TYPE_ARG1 int + +/* Define to the type of args 2, 3 and 4 for select. */ +#define SELECT_TYPE_ARG234 fd_set * + +/* Define to the type of arg 5 for select. */ +#define SELECT_TYPE_ARG5 struct timeval * + +/* Define to the function return type for select. */ +#define SELECT_TYPE_RETV int + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to the type of arg 3 for strerror_r. */ +/* #undef STRERROR_R_TYPE_ARG3 */ + +/* Define to 1 if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define if you want to enable c-ares support */ +/* #undef USE_ARES */ + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* if GnuTLS is enabled */ +/* #undef USE_GNUTLS */ + +/* if libSSH2 is in use */ +/* #undef USE_LIBSSH2 */ + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +/* if NSS is enabled */ +/* #undef USE_NSS */ + +/* if OpenSSL is in use */ +#define USE_OPENSSL 1 + +/* Define to 1 if you are building a Windows target without large file + support. */ +/* #undef USE_WIN32_LARGE_FILES */ + +/* to enable SSPI support */ +/* #undef USE_WINDOWS_SSPI */ + +/* Define to 1 if using yaSSL in OpenSSL compatibility mode. */ +/* #undef USE_YASSLEMUL */ + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* # undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ + +#endif /* HEADER_CURL_CONFIG_VXWORKS_H */ diff --git a/external/curl prx/include/config-win32.h b/external/curl prx/include/config-win32.h new file mode 100644 index 0000000..76b00b9 --- /dev/null +++ b/external/curl prx/include/config-win32.h @@ -0,0 +1,743 @@ +#ifndef HEADER_CURL_CONFIG_WIN32_H +#define HEADER_CURL_CONFIG_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* Hand crafted config file for Windows */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__POCC__) +#define HAVE_GETOPT_H 1 +#endif + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_INTTYPES_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define if you need header even with header file. */ +#if !defined(__SALFORDC__) && !defined(__POCC__) +#define NEED_MALLOC_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_PROCESS_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define to 1 if you have the header file. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_STDBOOL_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if you have the header file. */ +#ifndef __BORLANDC__ +#define HAVE_SYS_UTIME_H 1 +#endif + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__POCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WINSOCK2_H 1 +#endif + +/* Define if you have the header file. */ +#ifndef __SALFORDC__ +#define HAVE_WS2TCPIP_H 1 +#endif + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* Define to 1 if bool is an available type. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1800) +#define HAVE_BOOL_T 1 +#endif + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the ftruncate function. */ +#define HAVE_FTRUNCATE 1 + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the getprotobyname function. */ +#define HAVE_GETPROTOBYNAME + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL. */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the `CRYPTO_cleanup_all_ex_data' function. + This is present in OpenSSL versions after 0.9.6b */ +#define HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setlocale function. */ +#define HAVE_SETLOCALE 1 + +/* Define if you have the setmode function. */ +#define HAVE_SETMODE 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the strftime function. */ +#define HAVE_STRFTIME 1 + +/* Define if you have the stricmp function. */ +#define HAVE_STRICMP 1 + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +#define HAVE_STRNICMP 1 + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__POCC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1800)) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function. */ +#ifndef __BORLANDC__ +#define HAVE_UTIME 1 +#endif + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define if in_addr_t is not an available 'typedefed' type. */ +#define in_addr_t unsigned long + +/* Define to the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define if ssize_t is not an available 'typedefed' type. */ +#ifndef _SSIZE_T_DEFINED +# if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \ + defined(__POCC__) || \ + defined(__MINGW32__) +# elif defined(_WIN64) +# define _SSIZE_T_DEFINED +# define ssize_t __int64 +# else +# define _SSIZE_T_DEFINED +# define ssize_t int +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* Define to the size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* Define to the size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* Define to the size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* Define to the size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* Define to the size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* Define to the size of `curl_off_t', as computed by sizeof. */ +#define SIZEOF_CURL_OFF_T 8 + +/* ---------------------------------------------------------------- */ +/* BSD-style lwIP TCP/IP stack SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to use BSD-style lwIP TCP/IP stack. */ +/* #define USE_LWIPSOCK 1 */ + +#ifdef USE_LWIPSOCK +# undef USE_WINSOCK +# undef HAVE_WINSOCK_H +# undef HAVE_WINSOCK2_H +# undef HAVE_WS2TCPIP_H +# undef HAVE_ERRNO_H +# undef HAVE_GETHOSTNAME +# undef HAVE_GETNAMEINFO +# undef LWIP_POSIX_SOCKETS_IO_NAMES +# undef RECV_TYPE_ARG1 +# undef RECV_TYPE_ARG3 +# undef SEND_TYPE_ARG1 +# undef SEND_TYPE_ARG3 +# define HAVE_FREEADDRINFO +# define HAVE_GETADDRINFO +# define HAVE_GETHOSTBYNAME +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GETHOSTBYNAME_R_6 +# define LWIP_POSIX_SOCKETS_IO_NAMES 0 +# define RECV_TYPE_ARG1 int +# define RECV_TYPE_ARG3 size_t +# define SEND_TYPE_ARG1 int +# define SEND_TYPE_ARG3 size_t +#endif + +/* ---------------------------------------------------------------- */ +/* Watt-32 tcp/ip SPECIFIC */ +/* ---------------------------------------------------------------- */ + +#ifdef USE_WATT32 + #include + #undef byte + #undef word + #undef USE_WINSOCK + #undef HAVE_WINSOCK_H + #undef HAVE_WINSOCK2_H + #undef HAVE_WS2TCPIP_H + #define HAVE_GETADDRINFO + #define HAVE_GETNAMEINFO + #define HAVE_SYS_IOCTL_H + #define HAVE_SYS_SOCKET_H + #define HAVE_NETINET_IN_H + #define HAVE_NETDB_H + #define HAVE_ARPA_INET_H + #define HAVE_FREEADDRINFO + #define SOCKET int +#endif + + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Define to nothing if compiler does not support 'const' qualifier. */ +/* #define const */ + +/* Define to nothing if compiler does not support 'volatile' qualifier. */ +/* #define volatile */ + +/* Windows should not have HAVE_GMTIME_R defined */ +/* #undef HAVE_GMTIME_R */ + +/* Define if the compiler supports C99 variadic macro style. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define HAVE_VARIADIC_MACROS_C99 1 +#endif + +/* Define if the compiler supports the 'long long' data type. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || \ + (defined(_MSC_VER) && (_MSC_VER >= 1310)) || \ + (defined(__BORLANDC__) && (__BORLANDC__ >= 0x561)) +#define HAVE_LONGLONG 1 +#endif + +/* Define to avoid VS2005 complaining about portable C functions. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later default size for time_t is 64-bit, unless + _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* Define some minimum and default build targets for Visual Studio */ +#if defined(_MSC_VER) + /* Officially, Microsoft's Windows SDK versions 6.X does not support Windows + 2000 as a supported build target. VS2008 default installations provides + an embedded Windows SDK v6.0A along with the claim that Windows 2000 is a + valid build target for VS2008. Popular belief is that binaries built with + VS2008 using Windows SDK versions v6.X and Windows 2000 as a build target + are functional. */ +# define VS2008_MIN_TARGET 0x0500 + + /* The minimum build target for VS2012 is Vista unless Update 1 is installed + and the v110_xp toolset is chosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_MIN_TARGET 0x0501 +# else +# define VS2012_MIN_TARGET 0x0600 +# endif + + /* VS2008 default build target is Windows Vista. We override default target + to be Windows XP. */ +# define VS2008_DEF_TARGET 0x0501 + + /* VS2012 default build target is Windows Vista unless Update 1 is installed + and the v110_xp toolset is chosen. */ +# if defined(_USING_V110_SDK71_) +# define VS2012_DEF_TARGET 0x0501 +# else +# define VS2012_DEF_TARGET 0x0600 +# endif +#endif + +/* VS2008 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER <= 1600) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2008_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2008_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET) +# error VS2008 does not support Windows build targets prior to Windows 2000 +# endif +#endif + +/* VS2012 default target settings and minimum build target check. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT VS2012_DEF_TARGET +# endif +# ifndef WINVER +# define WINVER VS2012_DEF_TARGET +# endif +# if (_WIN32_WINNT < VS2012_MIN_TARGET) || (WINVER < VS2012_MIN_TARGET) +# if defined(_USING_V110_SDK71_) +# error VS2012 does not support Windows build targets prior to Windows XP +# else +# error VS2012 does not support Windows build targets prior to Windows \ +Vista +# endif +# endif +#endif + +/* When no build target is specified Pelles C 5.00 and later default build + target is Windows Vista. We override default target to be Windows 2000. */ +#if defined(__POCC__) && (__POCC__ >= 500) +# ifndef _WIN32_WINNT +# define _WIN32_WINNT 0x0500 +# endif +# ifndef WINVER +# define WINVER 0x0500 +# endif +#endif + +/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is + quite convoluted, compiler dependent and even build target dependent. */ +#if defined(HAVE_WS2TCPIP_H) +# if defined(__POCC__) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# elif defined(_MSC_VER) && (_MSC_VER >= 1200) +# define HAVE_FREEADDRINFO 1 +# define HAVE_GETADDRINFO 1 +# define HAVE_GETADDRINFO_THREADSAFE 1 +# define HAVE_GETNAMEINFO 1 +# endif +#endif + +#if defined(__POCC__) +# ifndef _MSC_VER +# error Microsoft extensions /Ze compiler option is required +# endif +# ifndef __POCC__OLDNAMES +# error Compatibility names /Go compiler option is required +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define if you have struct sockaddr_storage. */ +#if !defined(__SALFORDC__) && !defined(__BORLANDC__) +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#endif + +/* Define if you have struct timeval. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define if struct sockaddr_in6 has the sin6_scope_id member. */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +#if defined(HAVE_WINSOCK2_H) && defined(_WIN32_WINNT) && \ + (_WIN32_WINNT >= 0x0600) +#define HAVE_STRUCT_POLLFD 1 +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if defined(__MINGW32__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__WATCOMC__) && !defined(USE_WIN32_LARGE_FILES) +# define USE_WIN32_LARGE_FILES +#endif + +#if defined(__POCC__) +# undef USE_WIN32_LARGE_FILES +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* DNS RESOLVER SPECIALTY */ +/* ---------------------------------------------------------------- */ + +/* + * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. + */ + +/* Define to enable c-ares asynchronous DNS lookups. */ +/* #define USE_ARES 1 */ + +/* Default define to enable threaded asynchronous DNS lookups. */ +#if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ + !defined(USE_THREADS_WIN32) +# define USE_THREADS_WIN32 1 +#endif + +#if defined(USE_ARES) && defined(USE_THREADS_WIN32) +# error "Only one DNS lookup specialty may be defined at most" +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_SSL_H 1 +#define HAVE_LDAP_URL_PARSE 1 +#elif defined(CURL_HAS_OPENLDAP_LDAPSDK) +#undef USE_WIN32_LDAP +#define HAVE_LDAP_URL_PARSE 1 +#else +#undef HAVE_LDAP_URL_PARSE +#define HAVE_LDAP_SSL 1 +#define USE_WIN32_LDAP 1 +#endif + +#if defined(__WATCOMC__) && defined(USE_WIN32_LDAP) +#if __WATCOMC__ < 1280 +#define WINBERAPI __declspec(cdecl) +#define WINLDAPAPI __declspec(cdecl) +#endif +#endif + +#if defined(__POCC__) && defined(USE_WIN32_LDAP) +# define CURL_DISABLE_LDAP 1 +#endif + +/* Define to use the Windows crypto library. */ +#define USE_WIN32_CRYPTO + +/* Define to use Unix sockets. */ +#if defined(_MSC_VER) && _MSC_VER >= 1900 +/* #define USE_UNIX_SOCKETS */ +#endif + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ +#define OS "i386-pc-win32" +#elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (MSVC >=2005 or gcc) */ +#define OS "x86_64-pc-win32" +#elif defined(_M_IA64) /* Itanium */ +#define OS "ia64-pc-win32" +#else +#define OS "unknown-pc-win32" +#endif + +/* Name of package */ +#define PACKAGE "curl" + +/* If you want to build curl with the built-in manual */ +#define USE_MANUAL 1 + +#if defined(__POCC__) || defined(USE_IPV6) +# define ENABLE_IPV6 1 +#endif + +#endif /* HEADER_CURL_CONFIG_WIN32_H */ diff --git a/external/curl prx/include/config-win32ce.h b/external/curl prx/include/config-win32ce.h new file mode 100644 index 0000000..1820522 --- /dev/null +++ b/external/curl prx/include/config-win32ce.h @@ -0,0 +1,448 @@ +#ifndef HEADER_CURL_CONFIG_WIN32CE_H +#define HEADER_CURL_CONFIG_WIN32CE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* ================================================================ */ +/* lib/config-win32ce.h - Hand crafted config file for windows ce */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/* HEADER FILES */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the header file. */ +/* #define HAVE_ARPA_INET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ASSERT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_CRYPTO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERRNO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_ERR_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_GETOPT_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_IO_H 1 + +/* Define if you need the malloc.h header header file even with stdlib.h */ +#define NEED_MALLOC_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_NETDB_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_NETINET_IN_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_SGTTY_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SSL_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_PROCESS_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_PARAM_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SELECT_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKET_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_SOCKIO_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define if you have the header file */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_SYS_TYPES_H 1 */ + +/* Define if you have the header file */ +#define HAVE_SYS_UTIME_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_TERMIO_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_TERMIOS_H 1 */ + +/* Define if you have the header file. */ +#define HAVE_TIME_H 1 + +/* Define if you have the header file. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the header file. */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the header file. */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the header file. */ +/* #define HAVE_WINSOCK2_H 1 */ + +/* Define if you have the header file. */ +/* #define HAVE_WS2TCPIP_H 1 */ + +/* ---------------------------------------------------------------- */ +/* OTHER HEADER INFO */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both and . */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* ---------------------------------------------------------------- */ +/* FUNCTIONS */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the closesocket function. */ +#define HAVE_CLOSESOCKET 1 + +/* Define if you don't have vprintf but do have _doprnt. */ +/* #define HAVE_DOPRNT 1 */ + +/* Define if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the getpass function. */ +/* #define HAVE_GETPASS 1 */ + +/* Define if you have the getservbyname function. */ +#define HAVE_GETSERVBYNAME 1 + +/* Define if you have the gettimeofday function. */ +/* #define HAVE_GETTIMEOFDAY 1 */ + +/* Define if you have the inet_addr function. */ +#define HAVE_INET_ADDR 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the perror function. */ +#define HAVE_PERROR 1 + +/* Define if you have the RAND_screen function when using SSL */ +#define HAVE_RAND_SCREEN 1 + +/* Define if you have the `RAND_status' function when using SSL. */ +#define HAVE_RAND_STATUS 1 + +/* Define if you have the select function. */ +#define HAVE_SELECT 1 + +/* Define if you have the setvbuf function. */ +#define HAVE_SETVBUF 1 + +/* Define if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +/* #define HAVE_STRDUP 1 */ + +/* Define if you have the strftime function. */ +/* #define HAVE_STRFTIME 1 */ + +/* Define if you have the stricmp function. */ +/* #define HAVE_STRICMP 1 */ + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +/* #define HAVE_STRNICMP 1 */ + +/* Define if you have the strstr function. */ +#define HAVE_STRSTR 1 + +/* Define if you have the strtoll function. */ +#if defined(__MINGW32__) || defined(__WATCOMC__) +#define HAVE_STRTOLL 1 +#endif + +/* Define if you have the tcgetattr function. */ +/* #define HAVE_TCGETATTR 1 */ + +/* Define if you have the tcsetattr function. */ +/* #define HAVE_TCSETATTR 1 */ + +/* Define if you have the utime function */ +#define HAVE_UTIME 1 + +/* Define if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 DWORD + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 int + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* ---------------------------------------------------------------- */ +/* TYPEDEF REPLACEMENTS */ +/* ---------------------------------------------------------------- */ + +/* Define this if in_addr_t is not an available 'typedefed' type */ +#define in_addr_t unsigned long + +/* Define as the return type of signal handlers (int or void). */ +#define RETSIGTYPE void + +/* Define ssize_t if it is not an available 'typedefed' type */ +#if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || defined(__POCC__) +#elif defined(_WIN64) +#define ssize_t __int64 +#else +#define ssize_t int +#endif + +/* ---------------------------------------------------------------- */ +/* TYPE SIZES */ +/* ---------------------------------------------------------------- */ + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 16 + +/* The size of `long long', as computed by sizeof. */ +/* #define SIZEOF_LONG_LONG 8 */ + +/* The size of `short', as computed by sizeof. */ +#define SIZEOF_SHORT 2 + +/* Define to the size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `size_t', as computed by sizeof. */ +#if defined(_WIN64) +# define SIZEOF_SIZE_T 8 +#else +# define SIZEOF_SIZE_T 4 +#endif + +/* ---------------------------------------------------------------- */ +/* STRUCT RELATED */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have struct sockaddr_storage */ +/* #define HAVE_STRUCT_SOCKADDR_STORAGE 1 */ + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define this if struct sockaddr_in6 has the sin6_scope_id member */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* ---------------------------------------------------------------- */ +/* COMPILER SPECIFIC */ +/* ---------------------------------------------------------------- */ + +/* Undef keyword 'const' if it does not work. */ +/* #undef const */ + +/* Define to avoid VS2005 complaining about portable C functions */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* VS2005 and later default size for time_t is 64-bit, unless */ +/* _USE_32BIT_TIME_T has been defined to get a 32-bit time_t. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +# ifndef _USE_32BIT_TIME_T +# define SIZEOF_TIME_T 8 +# else +# define SIZEOF_TIME_T 4 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* LARGE FILE SUPPORT */ +/* ---------------------------------------------------------------- */ + +#if defined(_MSC_VER) && !defined(_WIN32_WCE) +# if (_MSC_VER >= 900) && (_INTEGRAL_MAX_BITS >= 64) +# define USE_WIN32_LARGE_FILES +# else +# define USE_WIN32_SMALL_FILES +# endif +#endif + +#if !defined(USE_WIN32_LARGE_FILES) && !defined(USE_WIN32_SMALL_FILES) +# define USE_WIN32_SMALL_FILES +#endif + +/* ---------------------------------------------------------------- */ +/* LDAP SUPPORT */ +/* ---------------------------------------------------------------- */ + +#define USE_WIN32_LDAP 1 +#undef HAVE_LDAP_URL_PARSE + +/* ---------------------------------------------------------------- */ +/* ADDITIONAL DEFINITIONS */ +/* ---------------------------------------------------------------- */ + +/* Define cpu-machine-OS */ +#undef OS +#define OS "i386-pc-win32ce" + +/* Name of package */ +#define PACKAGE "curl" + +/* ---------------------------------------------------------------- */ +/* WinCE */ +/* ---------------------------------------------------------------- */ + +#ifndef UNICODE +# define UNICODE +#endif + +#ifndef _UNICODE +# define _UNICODE +#endif + +#define CURL_DISABLE_FILE 1 +#define CURL_DISABLE_TELNET 1 +#define CURL_DISABLE_LDAP 1 + +#define ENOSPC 1 +#define ENOMEM 2 +#define EAGAIN 3 + +extern int stat(const char *path, struct stat *buffer); + +#endif /* HEADER_CURL_CONFIG_WIN32CE_H */ diff --git a/external/curl prx/include/conncache.h b/external/curl prx/include/conncache.h new file mode 100644 index 0000000..0df6d47 --- /dev/null +++ b/external/curl prx/include/conncache.h @@ -0,0 +1,87 @@ +#ifndef HEADER_CURL_CONNCACHE_H +#define HEADER_CURL_CONNCACHE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 2012 - 2014, Linus Nielsen Feltzing, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * All accesses to struct fields and changing of data in the connection cache + * and connectbundles must be done with the conncache LOCKED. The cache might + * be shared. + */ + +struct conncache { + struct curl_hash hash; + size_t num_conn; + long next_connection_id; + struct curltime last_cleanup; + /* handle used for closing cached connections */ + struct Curl_easy *closure_handle; +}; + +#define BUNDLE_NO_MULTIUSE -1 +#define BUNDLE_UNKNOWN 0 /* initial value */ +#define BUNDLE_PIPELINING 1 +#define BUNDLE_MULTIPLEX 2 + +struct connectbundle { + int multiuse; /* supports multi-use */ + size_t num_connections; /* Number of connections in the bundle */ + struct curl_llist conn_list; /* The connectdata members of the bundle */ +}; + +/* returns 1 on error, 0 is fine */ +int Curl_conncache_init(struct conncache *, int size); +void Curl_conncache_destroy(struct conncache *connc); + +/* return the correct bundle, to a host or a proxy */ +struct connectbundle *Curl_conncache_find_bundle(struct connectdata *conn, + struct conncache *connc); +void Curl_conncache_unlock(struct Curl_easy *data); +/* returns number of connections currently held in the connection cache */ +size_t Curl_conncache_size(struct Curl_easy *data); +size_t Curl_conncache_bundle_size(struct connectdata *conn); + +bool Curl_conncache_return_conn(struct connectdata *conn); +CURLcode Curl_conncache_add_conn(struct conncache *connc, + struct connectdata *conn) WARN_UNUSED_RESULT; +void Curl_conncache_remove_conn(struct Curl_easy *data, + struct connectdata *conn, + bool lock); +bool Curl_conncache_foreach(struct Curl_easy *data, + struct conncache *connc, + void *param, + int (*func)(struct connectdata *conn, + void *param)); + +struct connectdata * +Curl_conncache_find_first_connection(struct conncache *connc); + +struct connectdata * +Curl_conncache_extract_bundle(struct Curl_easy *data, + struct connectbundle *bundle); +struct connectdata * +Curl_conncache_extract_oldest(struct Curl_easy *data); +void Curl_conncache_close_all_connections(struct conncache *connc); +void Curl_conncache_print(struct conncache *connc); + +#endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/external/curl prx/include/connect.h b/external/curl prx/include/connect.h new file mode 100644 index 0000000..6a5c755 --- /dev/null +++ b/external/curl prx/include/connect.h @@ -0,0 +1,144 @@ +#ifndef HEADER_CURL_CONNECT_H +#define HEADER_CURL_CONNECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include "nonblock.h" /* for curlx_nonblock(), formerly Curl_nonblock() */ +#include "sockaddr.h" +#include "timeval.h" + +CURLcode Curl_is_connected(struct connectdata *conn, + int sockindex, + bool *connected); + +CURLcode Curl_connecthost(struct connectdata *conn, + const struct Curl_dns_entry *host); + +/* generic function that returns how much time there's left to run, according + to the timeouts set */ +timediff_t Curl_timeleft(struct Curl_easy *data, + struct curltime *nowp, + bool duringconnect); + +#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ + +/* + * Used to extract socket and connectdata struct for the most recent + * transfer on the given Curl_easy. + * + * The returned socket will be CURL_SOCKET_BAD in case of failure! + */ +curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, + struct connectdata **connp); + +/* + * Check if a connection seems to be alive. + */ +bool Curl_connalive(struct connectdata *conn); + +#ifdef USE_WINSOCK +/* When you run a program that uses the Windows Sockets API, you may + experience slow performance when you copy data to a TCP server. + + https://support.microsoft.com/kb/823764 + + Work-around: Make the Socket Send Buffer Size Larger Than the Program Send + Buffer Size + +*/ +void Curl_sndbufset(curl_socket_t sockfd); +#else +#define Curl_sndbufset(y) Curl_nop_stmt +#endif + +void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd); +void Curl_persistconninfo(struct connectdata *conn); +int Curl_closesocket(struct connectdata *conn, curl_socket_t sock); + +/* + * The Curl_sockaddr_ex structure is basically libcurl's external API + * curl_sockaddr structure with enough space available to directly hold any + * protocol-specific address structures. The variable declared here will be + * used to pass / receive data to/from the fopensocket callback if this has + * been set, before that, it is initialized from parameters. + */ +struct Curl_sockaddr_ex { + int family; + int socktype; + int protocol; + unsigned int addrlen; + union { + struct sockaddr addr; + struct Curl_sockaddr_storage buff; + } _sa_ex_u; +}; +#define sa_addr _sa_ex_u.addr + +/* + * Create a socket based on info from 'conn' and 'ai'. + * + * Fill in 'addr' and 'sockfd' accordingly if OK is returned. If the open + * socket callback is set, used that! + * + */ +CURLcode Curl_socket(struct connectdata *conn, + const Curl_addrinfo *ai, + struct Curl_sockaddr_ex *addr, + curl_socket_t *sockfd); + +/* + * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' + * argument specifies if it is the end of a connection or a stream. + * + * For stream-based protocols (such as HTTP/2), a stream close will not cause + * a connection close. Other protocols will close the connection for both + * cases. + * + * It sets the bit.close bit to TRUE (with an explanation for debug builds), + * when the connection will close. + */ + +#define CONNCTRL_KEEP 0 /* undo a marked closure */ +#define CONNCTRL_CONNECTION 1 +#define CONNCTRL_STREAM 2 + +void Curl_conncontrol(struct connectdata *conn, + int closeit +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) + , const char *reason +#endif + ); + +#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y) +#else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */ +#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM) +#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION) +#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) +#endif + +bool Curl_conn_data_pending(struct connectdata *conn, int sockindex); + +#endif /* HEADER_CURL_CONNECT_H */ diff --git a/external/curl prx/include/content_encoding.h b/external/curl prx/include/content_encoding.h new file mode 100644 index 0000000..4cd52be --- /dev/null +++ b/external/curl prx/include/content_encoding.h @@ -0,0 +1,55 @@ +#ifndef HEADER_CURL_CONTENT_ENCODING_H +#define HEADER_CURL_CONTENT_ENCODING_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* Decoding writer. */ +typedef struct contenc_writer_s contenc_writer; +typedef struct content_encoding_s content_encoding; + +struct contenc_writer_s { + const content_encoding *handler; /* Encoding handler. */ + contenc_writer *downstream; /* Downstream writer. */ + void *params; /* Encoding-specific storage (variable length). */ +}; + +/* Content encoding writer. */ +struct content_encoding_s { + const char *name; /* Encoding name. */ + const char *alias; /* Encoding name alias. */ + CURLcode (*init_writer)(struct connectdata *conn, contenc_writer *writer); + CURLcode (*unencode_write)(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); + void (*close_writer)(struct connectdata *conn, contenc_writer *writer); + size_t paramsize; +}; + + +CURLcode Curl_build_unencoding_stack(struct connectdata *conn, + const char *enclist, int maybechunked); +CURLcode Curl_unencode_write(struct connectdata *conn, contenc_writer *writer, + const char *buf, size_t nbytes); +void Curl_unencode_cleanup(struct connectdata *conn); +char *Curl_all_content_encodings(void); + +#endif /* HEADER_CURL_CONTENT_ENCODING_H */ diff --git a/external/curl prx/include/cookie.h b/external/curl prx/include/cookie.h new file mode 100644 index 0000000..6ac4a6a --- /dev/null +++ b/external/curl prx/include/cookie.h @@ -0,0 +1,121 @@ +#ifndef HEADER_CURL_COOKIE_H +#define HEADER_CURL_COOKIE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#include + +struct Cookie { + struct Cookie *next; /* next in the chain */ + char *name; /* = value */ + char *value; /* name = */ + char *path; /* path = which is in Set-Cookie: */ + char *spath; /* sanitized cookie path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ + bool tailmatch; /* whether we do tail-matching of the domain name */ + + /* RFC 2109 keywords. Version=1 means 2109-compliant cookie sending */ + char *version; /* Version = */ + char *maxage; /* Max-Age = */ + + bool secure; /* whether the 'secure' keyword was used */ + bool livecookie; /* updated from a server, not a stored file */ + bool httponly; /* true if the httponly directive is present */ + int creationtime; /* time when the cookie was written */ + unsigned char prefix; /* bitmap fields indicating which prefix are set */ +}; + +/* + * Available cookie prefixes, as defined in + * draft-ietf-httpbis-rfc6265bis-02 + */ +#define COOKIE_PREFIX__SECURE (1<<0) +#define COOKIE_PREFIX__HOST (1<<1) + +#define COOKIE_HASH_SIZE 256 + +struct CookieInfo { + /* linked list of cookies we know of */ + struct Cookie *cookies[COOKIE_HASH_SIZE]; + + char *filename; /* file we read from/write to */ + bool running; /* state info, for cookie adding information */ + long numcookies; /* number of cookies in the "jar" */ + bool newsession; /* new session, discard session cookies on load */ + int lastct; /* last creation-time used in the jar */ +}; + +/* This is the maximum line length we accept for a cookie line. RFC 2109 + section 6.3 says: + + "at least 4096 bytes per cookie (as measured by the size of the characters + that comprise the cookie non-terminal in the syntax description of the + Set-Cookie header)" + + We allow max 5000 bytes cookie header. Max 4095 bytes length per cookie + name and value. Name + value may not exceed 4096 bytes. + +*/ +#define MAX_COOKIE_LINE 5000 + +/* This is the maximum length of a cookie name or content we deal with: */ +#define MAX_NAME 4096 +#define MAX_NAME_TXT "4095" + +struct Curl_easy; +/* + * Add a cookie to the internal list of cookies. The domain and path arguments + * are only used if the header boolean is TRUE. + */ + +struct Cookie *Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *, bool header, bool noexpiry, + char *lineptr, + const char *domain, const char *path, + bool secure); + +struct Cookie *Curl_cookie_getlist(struct CookieInfo *, const char *, + const char *, bool); +void Curl_cookie_freelist(struct Cookie *cookies); +void Curl_cookie_clearall(struct CookieInfo *cookies); +void Curl_cookie_clearsess(struct CookieInfo *cookies); +char *Curl_get_line(char *buf, int len, FILE *input); + +#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) +#define Curl_cookie_list(x) NULL +#define Curl_cookie_loadfiles(x) Curl_nop_stmt +#define Curl_cookie_init(x,y,z,w) NULL +#define Curl_cookie_cleanup(x) Curl_nop_stmt +#define Curl_flush_cookies(x,y) Curl_nop_stmt +#else +void Curl_flush_cookies(struct Curl_easy *data, int cleanup); +void Curl_cookie_cleanup(struct CookieInfo *); +struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, + const char *, struct CookieInfo *, bool); +struct curl_slist *Curl_cookie_list(struct Curl_easy *data); +void Curl_cookie_loadfiles(struct Curl_easy *data); +#endif + +#endif /* HEADER_CURL_COOKIE_H */ diff --git a/external/curl prx/include/curl_addrinfo.h b/external/curl prx/include/curl_addrinfo.h new file mode 100644 index 0000000..205e121 --- /dev/null +++ b/external/curl prx/include/curl_addrinfo.h @@ -0,0 +1,107 @@ +#ifndef HEADER_CURL_ADDRINFO_H +#define HEADER_CURL_ADDRINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_NETINET_IN_H +# include +#endif +#ifdef HAVE_NETDB_H +# include +#endif +#ifdef HAVE_ARPA_INET_H +# include +#endif + +#ifdef __VMS +# include +# include +# include +#endif + + +/* + * Curl_addrinfo is our internal struct definition that we use to allow + * consistent internal handling of this data. We use this even when the + * system provides an addrinfo structure definition. And we use this for + * all sorts of IPv4 and IPV6 builds. + */ + +struct Curl_addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + curl_socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */ + char *ai_canonname; + struct sockaddr *ai_addr; + struct Curl_addrinfo *ai_next; +}; +typedef struct Curl_addrinfo Curl_addrinfo; + +void +Curl_freeaddrinfo(Curl_addrinfo *cahead); + +#ifdef HAVE_GETADDRINFO +int +Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + Curl_addrinfo **result); +#endif + +Curl_addrinfo * +Curl_he2ai(const struct hostent *he, int port); + +Curl_addrinfo * +Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); + +Curl_addrinfo *Curl_str2addr(char *dotted, int port); + +#ifdef USE_UNIX_SOCKETS +Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, bool abstract); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ + defined(HAVE_FREEADDRINFO) +void +curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); +#endif + +#if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) +int +curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, struct addrinfo **result, + int line, const char *source); +#endif + +#ifdef HAVE_GETADDRINFO +#ifdef USE_RESOLVE_ON_IPS +void Curl_addrinfo_set_port(Curl_addrinfo *addrinfo, int port); +#else +#define Curl_addrinfo_set_port(x,y) +#endif +#endif + +#endif /* HEADER_CURL_ADDRINFO_H */ diff --git a/external/curl prx/include/curl_base64.h b/external/curl prx/include/curl_base64.h new file mode 100644 index 0000000..7e9fc26 --- /dev/null +++ b/external/curl prx/include/curl_base64.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_BASE64_H +#define HEADER_CURL_BASE64_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_base64_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); +CURLcode Curl_base64url_encode(struct Curl_easy *data, + const char *inputbuff, size_t insize, + char **outptr, size_t *outlen); + +CURLcode Curl_base64_decode(const char *src, + unsigned char **outptr, size_t *outlen); + +#endif /* HEADER_CURL_BASE64_H */ diff --git a/external/curl prx/include/curl_ctype.h b/external/curl prx/include/curl_ctype.h new file mode 100644 index 0000000..6e94bb1 --- /dev/null +++ b/external/curl prx/include/curl_ctype.h @@ -0,0 +1,81 @@ +#ifndef HEADER_CURL_CTYPE_H +#define HEADER_CURL_CTYPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +/* + * Uppercase macro versions of ANSI/ISO is*() functions/macros which + * avoid negative number inputs with argument byte codes > 127. + * + * For non-ASCII platforms the C library character classification routines + * are used despite being locale-dependent, because this is better than + * not to work at all. + */ +#include + +#define ISSPACE(x) (isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (isascii((int) ((unsigned char)x))) + +#else + +int Curl_isspace(int c); +int Curl_isdigit(int c); +int Curl_isalnum(int c); +int Curl_isxdigit(int c); +int Curl_isgraph(int c); +int Curl_isprint(int c); +int Curl_isalpha(int c); +int Curl_isupper(int c); +int Curl_islower(int c); +int Curl_iscntrl(int c); + +#define ISSPACE(x) (Curl_isspace((int) ((unsigned char)x))) +#define ISDIGIT(x) (Curl_isdigit((int) ((unsigned char)x))) +#define ISALNUM(x) (Curl_isalnum((int) ((unsigned char)x))) +#define ISXDIGIT(x) (Curl_isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x) (Curl_isgraph((int) ((unsigned char)x))) +#define ISALPHA(x) (Curl_isalpha((int) ((unsigned char)x))) +#define ISPRINT(x) (Curl_isprint((int) ((unsigned char)x))) +#define ISUPPER(x) (Curl_isupper((int) ((unsigned char)x))) +#define ISLOWER(x) (Curl_islower((int) ((unsigned char)x))) +#define ISCNTRL(x) (Curl_iscntrl((int) ((unsigned char)x))) +#define ISASCII(x) (((x) >= 0) && ((x) <= 0x80)) + +#endif + +#define ISBLANK(x) (int)((((unsigned char)x) == ' ') || \ + (((unsigned char)x) == '\t')) + +#endif /* HEADER_CURL_CTYPE_H */ diff --git a/external/curl prx/include/curl_des.h b/external/curl prx/include/curl_des.h new file mode 100644 index 0000000..129060f --- /dev/null +++ b/external/curl prx/include/curl_des.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_DES_H +#define HEADER_CURL_DES_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) && !defined(USE_OPENSSL) + +/* Applies odd parity to the given byte array */ +void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); + +#endif /* USE_NTLM && !USE_OPENSSL */ + +#endif /* HEADER_CURL_DES_H */ diff --git a/external/curl prx/include/curl_endian.h b/external/curl prx/include/curl_endian.h new file mode 100644 index 0000000..4f345a6 --- /dev/null +++ b/external/curl prx/include/curl_endian.h @@ -0,0 +1,46 @@ +#ifndef HEADER_CURL_ENDIAN_H +#define HEADER_CURL_ENDIAN_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Converts a 16-bit integer from little endian */ +unsigned short Curl_read16_le(const unsigned char *buf); + +/* Converts a 32-bit integer from little endian */ +unsigned int Curl_read32_le(const unsigned char *buf); + +/* Converts a 16-bit integer from big endian */ +unsigned short Curl_read16_be(const unsigned char *buf); + +/* Converts a 32-bit integer to little endian */ +void Curl_write32_le(const int value, unsigned char *buffer); + +#if (CURL_SIZEOF_CURL_OFF_T > 4) +/* Converts a 64-bit integer to little endian */ +#if defined(HAVE_LONGLONG) +void Curl_write64_le(const long long value, unsigned char *buffer); +#else +void Curl_write64_le(const __int64 value, unsigned char *buffer); +#endif +#endif + +#endif /* HEADER_CURL_ENDIAN_H */ diff --git a/external/curl prx/include/curl_fnmatch.h b/external/curl prx/include/curl_fnmatch.h new file mode 100644 index 0000000..69ffe39 --- /dev/null +++ b/external/curl prx/include/curl_fnmatch.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_FNMATCH_H +#define HEADER_CURL_FNMATCH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define CURL_FNMATCH_MATCH 0 +#define CURL_FNMATCH_NOMATCH 1 +#define CURL_FNMATCH_FAIL 2 + +/* default pattern matching function + * ================================= + * Implemented with recursive backtracking, if you want to use Curl_fnmatch, + * please note that there is not implemented UTF/UNICODE support. + * + * Implemented features: + * '?' notation, does not match UTF characters + * '*' can also work with UTF string + * [a-zA-Z0-9] enumeration support + * + * keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space + * and upper (use as "[[:alnum:]]") + */ +int Curl_fnmatch(void *ptr, const char *pattern, const char *string); + +#endif /* HEADER_CURL_FNMATCH_H */ diff --git a/external/curl prx/include/curl_gethostname.h b/external/curl prx/include/curl_gethostname.h new file mode 100644 index 0000000..07517c5 --- /dev/null +++ b/external/curl prx/include/curl_gethostname.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_GETHOSTNAME_H +#define HEADER_CURL_GETHOSTNAME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Hostname buffer size */ +#define HOSTNAME_MAX 1024 + +/* This returns the local machine's un-qualified hostname */ +int Curl_gethostname(char *name, GETHOSTNAME_TYPE_ARG2 namelen); + +#endif /* HEADER_CURL_GETHOSTNAME_H */ diff --git a/external/curl prx/include/curl_gssapi.h b/external/curl prx/include/curl_gssapi.h new file mode 100644 index 0000000..88f68db --- /dev/null +++ b/external/curl prx/include/curl_gssapi.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_GSSAPI_H +#define HEADER_CURL_GSSAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2011 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#ifdef HAVE_GSSAPI +extern gss_OID_desc Curl_spnego_mech_oid; +extern gss_OID_desc Curl_krb5_mech_oid; + +/* Common method for using GSS-API */ +OM_uint32 Curl_gss_init_sec_context( + struct Curl_easy *data, + OM_uint32 *minor_status, + gss_ctx_id_t *context, + gss_name_t target_name, + gss_OID mech_type, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_buffer_t output_token, + const bool mutual_auth, + OM_uint32 *ret_flags); + +/* Helper to log a GSS-API error status */ +void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, + OM_uint32 major, OM_uint32 minor); + +/* Provide some definitions missing in old headers */ +#ifdef HAVE_OLD_GSSMIT +#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name +#define NCOMPAT 1 +#endif + +/* Define our privacy and integrity protection values */ +#define GSSAUTH_P_NONE 1 +#define GSSAUTH_P_INTEGRITY 2 +#define GSSAUTH_P_PRIVACY 4 + +#endif /* HAVE_GSSAPI */ +#endif /* HEADER_CURL_GSSAPI_H */ diff --git a/external/curl prx/include/curl_hmac.h b/external/curl prx/include/curl_hmac.h new file mode 100644 index 0000000..756dc9e --- /dev/null +++ b/external/curl prx/include/curl_hmac.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_HMAC_H +#define HEADER_CURL_HMAC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +typedef void (* HMAC_hinit_func)(void *context); +typedef void (* HMAC_hupdate_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* HMAC_hfinal_func)(unsigned char *result, void *context); + + +/* Per-hash function HMAC parameters. */ + +typedef struct { + HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */ + HMAC_hupdate_func hmac_hupdate; /* Update context with data. */ + HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */ + unsigned int hmac_ctxtsize; /* Context structure size. */ + unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */ + unsigned int hmac_resultlen; /* Result length (bytes). */ +} HMAC_params; + + +/* HMAC computation context. */ + +typedef struct { + const HMAC_params *hmac_hash; /* Hash function definition. */ + void *hmac_hashctxt1; /* Hash function context 1. */ + void *hmac_hashctxt2; /* Hash function context 2. */ +} HMAC_context; + + +/* Prototypes. */ + +HMAC_context * Curl_HMAC_init(const HMAC_params *hashparams, + const unsigned char *key, + unsigned int keylen); +int Curl_HMAC_update(HMAC_context *context, + const unsigned char *data, + unsigned int len); +int Curl_HMAC_final(HMAC_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_HMAC_H */ diff --git a/external/curl prx/include/curl_ldap.h b/external/curl prx/include/curl_ldap.h new file mode 100644 index 0000000..94c0029 --- /dev/null +++ b/external/curl prx/include/curl_ldap.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_LDAP_H +#define HEADER_CURL_LDAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_LDAP +extern const struct Curl_handler Curl_handler_ldap; + +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) +extern const struct Curl_handler Curl_handler_ldaps; +#endif + +#endif +#endif /* HEADER_CURL_LDAP_H */ diff --git a/external/curl prx/include/curl_md4.h b/external/curl prx/include/curl_md4.h new file mode 100644 index 0000000..e069041 --- /dev/null +++ b/external/curl prx/include/curl_md4.h @@ -0,0 +1,35 @@ +#ifndef HEADER_CURL_MD4_H +#define HEADER_CURL_MD4_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \ + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) + +void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len); + +#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) || + (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */ + +#endif /* HEADER_CURL_MD4_H */ diff --git a/external/curl prx/include/curl_md5.h b/external/curl prx/include/curl_md5.h new file mode 100644 index 0000000..5f70c96 --- /dev/null +++ b/external/curl prx/include/curl_md5.h @@ -0,0 +1,63 @@ +#ifndef HEADER_CURL_MD5_H +#define HEADER_CURL_MD5_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH +#include "curl_hmac.h" + +#define MD5_DIGEST_LEN 16 + +typedef void (* Curl_MD5_init_func)(void *context); +typedef void (* Curl_MD5_update_func)(void *context, + const unsigned char *data, + unsigned int len); +typedef void (* Curl_MD5_final_func)(unsigned char *result, void *context); + +typedef struct { + Curl_MD5_init_func md5_init_func; /* Initialize context procedure */ + Curl_MD5_update_func md5_update_func; /* Update context with data */ + Curl_MD5_final_func md5_final_func; /* Get final result procedure */ + unsigned int md5_ctxtsize; /* Context structure size */ + unsigned int md5_resultlen; /* Result length (bytes) */ +} MD5_params; + +typedef struct { + const MD5_params *md5_hash; /* Hash function definition */ + void *md5_hashctx; /* Hash function context */ +} MD5_context; + +extern const MD5_params Curl_DIGEST_MD5[1]; +extern const HMAC_params Curl_HMAC_MD5[1]; + +void Curl_md5it(unsigned char *output, + const unsigned char *input); + +MD5_context * Curl_MD5_init(const MD5_params *md5params); +int Curl_MD5_update(MD5_context *context, + const unsigned char *data, + unsigned int len); +int Curl_MD5_final(MD5_context *context, unsigned char *result); + +#endif + +#endif /* HEADER_CURL_MD5_H */ diff --git a/external/curl prx/include/curl_memory.h b/external/curl prx/include/curl_memory.h new file mode 100644 index 0000000..fccf468 --- /dev/null +++ b/external/curl prx/include/curl_memory.h @@ -0,0 +1,156 @@ +#ifndef HEADER_CURL_MEMORY_H +#define HEADER_CURL_MEMORY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Nasty internal details ahead... + * + * File curl_memory.h must be included by _all_ *.c source files + * that use memory related functions strdup, malloc, calloc, realloc + * or free, and given source file is used to build libcurl library. + * It should be included immediately before memdebug.h as the last files + * included to avoid undesired interaction with other memory function + * headers in dependent libraries. + * + * There is nearly no exception to above rule. All libcurl source + * files in 'lib' subdirectory as well as those living deep inside + * 'packages' subdirectories and linked together in order to build + * libcurl library shall follow it. + * + * File lib/strdup.c is an exception, given that it provides a strdup + * clone implementation while using malloc. Extra care needed inside + * this one. TODO: revisit this paragraph and related code. + * + * The need for curl_memory.h inclusion is due to libcurl's feature + * of allowing library user to provide memory replacement functions, + * memory callbacks, at runtime with curl_global_init_mem() + * + * Any *.c source file used to build libcurl library that does not + * include curl_memory.h and uses any memory function of the five + * mentioned above will compile without any indication, but it will + * trigger weird memory related issues at runtime. + * + * OTOH some source files from 'lib' subdirectory may additionally be + * used directly as source code when using some curlx_ functions by + * third party programs that don't even use libcurl at all. When using + * these source files in this way it is necessary these are compiled + * with CURLX_NO_MEMORY_CALLBACKS defined, in order to ensure that no + * attempt of calling libcurl's memory callbacks is done from code + * which can not use this machinery. + * + * Notice that libcurl's 'memory tracking' system works chaining into + * the memory callback machinery. This implies that when compiling + * 'lib' source files with CURLX_NO_MEMORY_CALLBACKS defined this file + * disengages usage of libcurl's 'memory tracking' system, defining + * MEMDEBUG_NODEFINES and overriding CURLDEBUG purpose. + * + * CURLX_NO_MEMORY_CALLBACKS takes precedence over CURLDEBUG. This is + * done in order to allow building a 'memory tracking' enabled libcurl + * and at the same time allow building programs which do not use it. + * + * Programs and libraries in 'tests' subdirectories have specific + * purposes and needs, and as such each one will use whatever fits + * best, depending additionally whether it links with libcurl or not. + * + * Caveat emptor. Proper curlx_* separation is a work in progress + * the same as CURLX_NO_MEMORY_CALLBACKS usage, some adjustments may + * still be required. IOW don't use them yet, there are sharp edges. + */ + +#ifdef HEADER_CURL_MEMDEBUG_H +#error "Header memdebug.h shall not be included before curl_memory.h" +#endif + +#ifndef CURLX_NO_MEMORY_CALLBACKS + +#ifndef CURL_DID_MEMORY_FUNC_TYPEDEFS /* only if not already done */ +/* + * The following memory function replacement typedef's are COPIED from + * curl/curl.h and MUST match the originals. We copy them to avoid having to + * include curl/curl.h here. We avoid that include since it includes stdio.h + * and other headers that may get messed up with defines done here. + */ +typedef void *(*curl_malloc_callback)(size_t size); +typedef void (*curl_free_callback)(void *ptr); +typedef void *(*curl_realloc_callback)(void *ptr, size_t size); +typedef char *(*curl_strdup_callback)(const char *str); +typedef void *(*curl_calloc_callback)(size_t nmemb, size_t size); +#define CURL_DID_MEMORY_FUNC_TYPEDEFS +#endif + +extern curl_malloc_callback Curl_cmalloc; +extern curl_free_callback Curl_cfree; +extern curl_realloc_callback Curl_crealloc; +extern curl_strdup_callback Curl_cstrdup; +extern curl_calloc_callback Curl_ccalloc; +#if defined(WIN32) && defined(UNICODE) +extern curl_wcsdup_callback Curl_cwcsdup; +#endif + +#ifndef CURLDEBUG + +/* + * libcurl's 'memory tracking' system defines strdup, malloc, calloc, + * realloc and free, along with others, in memdebug.h in a different + * way although still using memory callbacks forward declared above. + * When using the 'memory tracking' system (CURLDEBUG defined) we do + * not define here the five memory functions given that definitions + * from memdebug.h are the ones that shall be used. + */ + +#undef strdup +#define strdup(ptr) Curl_cstrdup(ptr) +#undef malloc +#define malloc(size) Curl_cmalloc(size) +#undef calloc +#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) +#undef realloc +#define realloc(ptr,size) Curl_crealloc(ptr, size) +#undef free +#define free(ptr) Curl_cfree(ptr) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _wcsdup +# define _wcsdup(ptr) Curl_cwcsdup(ptr) +# undef _tcsdup +# define _tcsdup(ptr) Curl_cwcsdup(ptr) +# else +# undef _tcsdup +# define _tcsdup(ptr) Curl_cstrdup(ptr) +# endif +#endif + +#endif /* CURLDEBUG */ + +#else /* CURLX_NO_MEMORY_CALLBACKS */ + +#ifndef MEMDEBUG_NODEFINES +#define MEMDEBUG_NODEFINES +#endif + +#endif /* CURLX_NO_MEMORY_CALLBACKS */ + +#endif /* HEADER_CURL_MEMORY_H */ diff --git a/external/curl prx/include/curl_memrchr.h b/external/curl prx/include/curl_memrchr.h new file mode 100644 index 0000000..747509c --- /dev/null +++ b/external/curl prx/include/curl_memrchr.h @@ -0,0 +1,44 @@ +#ifndef HEADER_CURL_MEMRCHR_H +#define HEADER_CURL_MEMRCHR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_MEMRCHR + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#else /* HAVE_MEMRCHR */ + +void *Curl_memrchr(const void *s, int c, size_t n); + +#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) + +#endif /* HAVE_MEMRCHR */ + +#endif /* HEADER_CURL_MEMRCHR_H */ diff --git a/external/curl prx/include/curl_multibyte.h b/external/curl prx/include/curl_multibyte.h new file mode 100644 index 0000000..615f5c0 --- /dev/null +++ b/external/curl prx/include/curl_multibyte.h @@ -0,0 +1,92 @@ +#ifndef HEADER_CURL_MULTIBYTE_H +#define HEADER_CURL_MULTIBYTE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP)) && defined(UNICODE)) + + /* + * MultiByte conversions using Windows kernel32 library. + */ + +wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); +char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); + +#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ + + +#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_WIN32_LDAP) + +/* + * Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() + * and Curl_unicodefree() main purpose is to minimize the number of + * preprocessor conditional directives needed by code using these + * to differentiate UNICODE from non-UNICODE builds. + * + * When building with UNICODE defined, this two macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return a pointer to a newly allocated memory area holding result. + * When the result is no longer needed, allocated memory is intended + * to be free'ed with Curl_unicodefree(). + * + * When building without UNICODE defined, this macros + * Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() + * return the pointer received as argument. Curl_unicodefree() does + * no actual free'ing of this pointer it is simply set to NULL. + */ + +#ifdef UNICODE + +#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) +#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) +#define Curl_unicodefree(ptr) \ + do {if((ptr)) {free((ptr)); (ptr) = NULL;}} WHILE_FALSE + +typedef union { + unsigned short *tchar_ptr; + const unsigned short *const_tchar_ptr; + unsigned short *tbyte_ptr; + const unsigned short *const_tbyte_ptr; +} xcharp_u; + +#else + +#define Curl_convert_UTF8_to_tchar(ptr) (ptr) +#define Curl_convert_tchar_to_UTF8(ptr) (ptr) +#define Curl_unicodefree(ptr) \ + do {(ptr) = NULL;} WHILE_FALSE + +typedef union { + char *tchar_ptr; + const char *const_tchar_ptr; + unsigned char *tbyte_ptr; + const unsigned char *const_tbyte_ptr; +} xcharp_u; + +#endif /* UNICODE */ + +#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */ + +#endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/external/curl prx/include/curl_ntlm_core.h b/external/curl prx/include/curl_ntlm_core.h new file mode 100644 index 0000000..07ef5de --- /dev/null +++ b/external/curl prx/include/curl_ntlm_core.h @@ -0,0 +1,107 @@ +#ifndef HEADER_CURL_NTLM_CORE_H +#define HEADER_CURL_NTLM_CORE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_NTLM) + +/* If NSS is the first available SSL backend (see order in curl_ntlm_core.c) + then it must be initialized to be used by NTLM. */ +#if !defined(USE_OPENSSL) && \ + !defined(USE_GNUTLS_NETTLE) && \ + !defined(USE_GNUTLS) && \ + defined(USE_NSS) +#define NTLM_NEEDS_NSS_INIT +#endif + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +#ifdef USE_OPENSSL +# include +#endif + +/* Define USE_NTRESPONSES in order to make the type-3 message include + * the NT response message. */ +#if !defined(USE_OPENSSL) || !defined(OPENSSL_NO_MD4) +#define USE_NTRESPONSES +#endif + +/* Define USE_NTLM2SESSION in order to make the type-3 message include the + NTLM2Session response message, requires USE_NTRESPONSES defined to 1 and a + Crypto engine that we have curl_ssl_md5sum() for. */ +#if defined(USE_NTRESPONSES) && !defined(USE_WIN32_CRYPTO) +#define USE_NTLM2SESSION +#endif + +/* Define USE_NTLM_V2 in order to allow the type-3 message to include the + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 + and support for 64-bit integers. */ +#if defined(USE_NTRESPONSES) && (CURL_SIZEOF_CURL_OFF_T > 4) +#define USE_NTLM_V2 +#endif + +void Curl_ntlm_core_lm_resp(const unsigned char *keys, + const unsigned char *plaintext, + unsigned char *results); + +CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data, + const char *password, + unsigned char *lmbuffer /* 21 bytes */); + +#ifdef USE_NTRESPONSES +CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + const char *password, + unsigned char *ntbuffer /* 21 bytes */); + +#if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) + +CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output); + +CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + const char *domain, size_t domlen, + unsigned char *ntlmhash, + unsigned char *ntlmv2hash); + +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len); + +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp); + +#endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */ + +#endif /* USE_NTRESPONSES */ + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_CORE_H */ diff --git a/external/curl prx/include/curl_ntlm_wb.h b/external/curl prx/include/curl_ntlm_wb.h new file mode 100644 index 0000000..aba3d46 --- /dev/null +++ b/external/curl prx/include/curl_ntlm_wb.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_NTLM_WB_H +#define HEADER_CURL_NTLM_WB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + +/* this is for creating ntlm header output by delegating challenge/response + to Samba's winbind daemon helper ntlm_auth */ +CURLcode Curl_output_ntlm_wb(struct connectdata *conn, bool proxy); + +void Curl_ntlm_wb_cleanup(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM && NTLM_WB_ENABLED */ + +#endif /* HEADER_CURL_NTLM_WB_H */ diff --git a/external/curl prx/include/curl_path.h b/external/curl prx/include/curl_path.h new file mode 100644 index 0000000..636c37f --- /dev/null +++ b/external/curl prx/include/curl_path.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_PATH_H +#define HEADER_CURL_PATH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "urldata.h" + +#ifdef WIN32 +# undef PATH_MAX +# define PATH_MAX MAX_PATH +# ifndef R_OK +# define R_OK 4 +# endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 /* just an extra precaution since there are systems that + have their definition hidden well */ +#endif + +CURLcode Curl_getworkingpath(struct connectdata *conn, + char *homedir, + char **path); + +CURLcode Curl_get_pathname(const char **cpp, char **path, char *homedir); +#endif /* HEADER_CURL_PATH_H */ diff --git a/external/curl prx/include/curl_printf.h b/external/curl prx/include/curl_printf.h new file mode 100644 index 0000000..0d37b8e --- /dev/null +++ b/external/curl prx/include/curl_printf.h @@ -0,0 +1,48 @@ +#ifndef HEADER_CURL_PRINTF_H +#define HEADER_CURL_PRINTF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * This header should be included by ALL code in libcurl that uses any + * *rintf() functions. + */ + +#include + +# undef printf +# undef fprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsnprintf +# undef aprintf +# undef vaprintf +# define printf curl_mprintf +# define fprintf curl_mfprintf +# define msnprintf curl_msnprintf +# define vprintf curl_mvprintf +# define vfprintf curl_mvfprintf +# define mvsnprintf curl_mvsnprintf +# define aprintf curl_maprintf +# define vaprintf curl_mvaprintf +#endif /* HEADER_CURL_PRINTF_H */ diff --git a/external/curl prx/include/curl_range.h b/external/curl prx/include/curl_range.h new file mode 100644 index 0000000..2350df9 --- /dev/null +++ b/external/curl prx/include/curl_range.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_RANGE_H +#define HEADER_CURL_RANGE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +CURLcode Curl_range(struct connectdata *conn); + +#endif /* HEADER_CURL_RANGE_H */ diff --git a/external/curl prx/include/curl_rtmp.h b/external/curl prx/include/curl_rtmp.h new file mode 100644 index 0000000..3306e22 --- /dev/null +++ b/external/curl prx/include/curl_rtmp.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_RTMP_H +#define HEADER_CURL_RTMP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010, Howard Chu, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifdef USE_LIBRTMP +extern const struct Curl_handler Curl_handler_rtmp; +extern const struct Curl_handler Curl_handler_rtmpt; +extern const struct Curl_handler Curl_handler_rtmpe; +extern const struct Curl_handler Curl_handler_rtmpte; +extern const struct Curl_handler Curl_handler_rtmps; +extern const struct Curl_handler Curl_handler_rtmpts; +#endif + +#endif /* HEADER_CURL_RTMP_H */ diff --git a/external/curl prx/include/curl_sasl.h b/external/curl prx/include/curl_sasl.h new file mode 100644 index 0000000..7647a48 --- /dev/null +++ b/external/curl prx/include/curl_sasl.h @@ -0,0 +1,143 @@ +#ifndef HEADER_CURL_SASL_H +#define HEADER_CURL_SASL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; +struct connectdata; + +/* Authentication mechanism flags */ +#define SASL_MECH_LOGIN (1 << 0) +#define SASL_MECH_PLAIN (1 << 1) +#define SASL_MECH_CRAM_MD5 (1 << 2) +#define SASL_MECH_DIGEST_MD5 (1 << 3) +#define SASL_MECH_GSSAPI (1 << 4) +#define SASL_MECH_EXTERNAL (1 << 5) +#define SASL_MECH_NTLM (1 << 6) +#define SASL_MECH_XOAUTH2 (1 << 7) +#define SASL_MECH_OAUTHBEARER (1 << 8) + +/* Authentication mechanism values */ +#define SASL_AUTH_NONE 0 +#define SASL_AUTH_ANY ~0U +#define SASL_AUTH_DEFAULT (SASL_AUTH_ANY & ~SASL_MECH_EXTERNAL) + +/* Authentication mechanism strings */ +#define SASL_MECH_STRING_LOGIN "LOGIN" +#define SASL_MECH_STRING_PLAIN "PLAIN" +#define SASL_MECH_STRING_CRAM_MD5 "CRAM-MD5" +#define SASL_MECH_STRING_DIGEST_MD5 "DIGEST-MD5" +#define SASL_MECH_STRING_GSSAPI "GSSAPI" +#define SASL_MECH_STRING_EXTERNAL "EXTERNAL" +#define SASL_MECH_STRING_NTLM "NTLM" +#define SASL_MECH_STRING_XOAUTH2 "XOAUTH2" +#define SASL_MECH_STRING_OAUTHBEARER "OAUTHBEARER" + +/* SASL machine states */ +typedef enum { + SASL_STOP, + SASL_PLAIN, + SASL_LOGIN, + SASL_LOGIN_PASSWD, + SASL_EXTERNAL, + SASL_CRAMMD5, + SASL_DIGESTMD5, + SASL_DIGESTMD5_RESP, + SASL_NTLM, + SASL_NTLM_TYPE2MSG, + SASL_GSSAPI, + SASL_GSSAPI_TOKEN, + SASL_GSSAPI_NO_DATA, + SASL_OAUTH2, + SASL_OAUTH2_RESP, + SASL_CANCEL, + SASL_FINAL +} saslstate; + +/* Progress indicator */ +typedef enum { + SASL_IDLE, + SASL_INPROGRESS, + SASL_DONE +} saslprogress; + +/* Protocol dependent SASL parameters */ +struct SASLproto { + const char *service; /* The service name */ + int contcode; /* Code to receive when continuation is expected */ + int finalcode; /* Code to receive upon authentication success */ + size_t maxirlen; /* Maximum initial response length */ + CURLcode (*sendauth)(struct connectdata *conn, + const char *mech, const char *ir); + /* Send authentication command */ + CURLcode (*sendcont)(struct connectdata *conn, const char *contauth); + /* Send authentication continuation */ + void (*getmessage)(char *buffer, char **outptr); + /* Get SASL response message */ +}; + +/* Per-connection parameters */ +struct SASL { + const struct SASLproto *params; /* Protocol dependent parameters */ + saslstate state; /* Current machine state */ + unsigned int authmechs; /* Accepted authentication mechanisms */ + unsigned int prefmech; /* Preferred authentication mechanism */ + unsigned int authused; /* Auth mechanism used for the connection */ + bool resetprefs; /* For URL auth option parsing. */ + bool mutual_auth; /* Mutual authentication enabled (GSSAPI only) */ + bool force_ir; /* Protocol always supports initial response */ +}; + +/* This is used to test whether the line starts with the given mechanism */ +#define sasl_mech_equal(line, wordlen, mech) \ + (wordlen == (sizeof(mech) - 1) / sizeof(char) && \ + !memcmp(line, mech, wordlen)) + +/* This is used to cleanup any libraries or curl modules used by the sasl + functions */ +void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused); + +/* Convert a mechanism name to a token */ +unsigned int Curl_sasl_decode_mech(const char *ptr, + size_t maxlen, size_t *len); + +/* Parse the URL login options */ +CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, + const char *value, size_t len); + +/* Initializes an SASL structure */ +void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params); + +/* Check if we have enough auth data and capabilities to authenticate */ +bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn); + +/* Calculate the required login details for SASL authentication */ +CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn, + bool force_ir, saslprogress *progress); + +/* Continue an SASL authentication */ +CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, + int code, saslprogress *progress); + +#endif /* HEADER_CURL_SASL_H */ diff --git a/external/curl prx/include/curl_sec.h b/external/curl prx/include/curl_sec.h new file mode 100644 index 0000000..7bdde26 --- /dev/null +++ b/external/curl prx/include/curl_sec.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_SECURITY_H +#define HEADER_CURL_SECURITY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +struct Curl_sec_client_mech { + const char *name; + size_t size; + int (*init)(void *); + int (*auth)(void *, struct connectdata *); + void (*end)(void *); + int (*check_prot)(void *, int); + int (*overhead)(void *, int, int); + int (*encode)(void *, const void *, int, int, void **); + int (*decode)(void *, void *, int, int, struct connectdata *); +}; + +#define AUTH_OK 0 +#define AUTH_CONTINUE 1 +#define AUTH_ERROR 2 + +#ifdef HAVE_GSSAPI +int Curl_sec_read_msg(struct connectdata *conn, char *, + enum protection_level); +void Curl_sec_end(struct connectdata *); +CURLcode Curl_sec_login(struct connectdata *); +int Curl_sec_request_prot(struct connectdata *conn, const char *level); + +extern struct Curl_sec_client_mech Curl_krb5_client_mech; +#endif + +#endif /* HEADER_CURL_SECURITY_H */ diff --git a/external/curl prx/include/curl_setup.h b/external/curl prx/include/curl_setup.h new file mode 100644 index 0000000..e9adefa --- /dev/null +++ b/external/curl prx/include/curl_setup.h @@ -0,0 +1,844 @@ +#ifndef HEADER_CURL_SETUP_H +#define HEADER_CURL_SETUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define HAVE_NETINET_IN_H 1 +#define HAVE_NETDB_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_PARAM_H 1 +#define RECV_TYPE_ARG1 int +#define RECV_TYPE_ARG2 void* +#define RECV_TYPE_ARG3 size_t +#define RECV_TYPE_ARG4 int +#define RECV_TYPE_RETV ssize_t +#define SEND_TYPE_ARG1 int +#define SEND_TYPE_ARG2 void* +#define SEND_QUAL_ARG2 const +#define SEND_TYPE_ARG3 size_t +#define SEND_TYPE_ARG4 int +#define SEND_TYPE_RETV ssize_t +#define HAVE_IOCTL_FIONBIO 1 +#define HAVE_SYS_SELECT_H 1 +#define MBEDTLS_NO_UDBL_DIVISION 1 +#if defined(BUILDING_LIBCURL) && !defined(CURL_NO_OLDIES) +#define CURL_NO_OLDIES +#endif + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) && \ + !defined(__SYMBIAN32__) +#define WIN32 +#endif + +#ifdef WIN32 +/* + * Don't include unneeded stuff in Windows headers to avoid compiler + * warnings and macro clashes. + * Make sure to define this macro before including any Windows headers. + */ +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# ifndef NOGDI +# define NOGDI +# endif +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H + +#include "curl_config.h" + +#else /* HAVE_CONFIG_H */ + +#ifdef _WIN32_WCE +# include "config-win32ce.h" +#else +# ifdef WIN32 +# include "config-win32.h" +# endif +#endif + +#if defined(macintosh) && defined(__MRC__) +# include "config-mac.h" +#endif + +#ifdef __riscos__ +# include "config-riscos.h" +#endif + +#ifdef __AMIGA__ +# include "config-amigaos.h" +#endif + +#ifdef __SYMBIAN32__ +# include "config-symbian.h" +#endif + +#ifdef __OS400__ +# include "config-os400.h" +#endif + +#ifdef TPF +# include "config-tpf.h" +#endif + +#ifdef __VXWORKS__ +# include "config-vxworks.h" +#endif + +#endif /* HAVE_CONFIG_H */ + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler */ +/* behavior or generated code characteristics must be done here, */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +# ifndef _THREAD_SAFE +# define _THREAD_SAFE +# endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +/* Solaris needs this to get a POSIX-conformant getpwuid_r */ +#if defined(sun) || defined(__sun) +# ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +# endif +#endif + +/* ================================================================ */ +/* If you need to include a system header file for your platform, */ +/* please, do it beyond the point further indicated in this file. */ +/* ================================================================ */ + +#include + +#define CURL_SIZEOF_CURL_OFF_T SIZEOF_CURL_OFF_T + +/* + * Disable other protocols when http is the only one desired. + */ + +#ifdef HTTP_ONLY +# ifndef CURL_DISABLE_TFTP +# define CURL_DISABLE_TFTP +# endif +# ifndef CURL_DISABLE_FTP +# define CURL_DISABLE_FTP +# endif +# ifndef CURL_DISABLE_LDAP +# define CURL_DISABLE_LDAP +# endif +# ifndef CURL_DISABLE_TELNET +# define CURL_DISABLE_TELNET +# endif +# ifndef CURL_DISABLE_DICT +# define CURL_DISABLE_DICT +# endif +# ifndef CURL_DISABLE_FILE +# define CURL_DISABLE_FILE +# endif +# ifndef CURL_DISABLE_RTSP +# define CURL_DISABLE_RTSP +# endif +# ifndef CURL_DISABLE_POP3 +# define CURL_DISABLE_POP3 +# endif +# ifndef CURL_DISABLE_IMAP +# define CURL_DISABLE_IMAP +# endif +# ifndef CURL_DISABLE_SMTP +# define CURL_DISABLE_SMTP +# endif +# ifndef CURL_DISABLE_GOPHER +# define CURL_DISABLE_GOPHER +# endif +# ifndef CURL_DISABLE_SMB +# define CURL_DISABLE_SMB +# endif +#endif + +/* + * When http is disabled rtsp is not supported. + */ + +#if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) +# define CURL_DISABLE_RTSP +#endif + +/* ================================================================ */ +/* No system header file shall be included in this file before this */ +/* point. The only allowed ones are those included from curl/system.h */ +/* ================================================================ */ + +/* + * OS/400 setup file includes some system headers. + */ + +#ifdef __OS400__ +# include "setup-os400.h" +#endif + +/* + * VMS setup file includes some system headers. + */ + +#ifdef __VMS +# include "setup-vms.h" +#endif + +/* + * Use getaddrinfo to resolve the IPv4 address literal. If the current network + * interface doesn't support IPv4, but supports IPv6, NAT64, and DNS64, + * performing this task will result in a synthesized IPv6 address. + */ +#ifdef __APPLE__ +#define USE_RESOLVE_ON_IPS 1 +#endif + +/* + * Include header files for windows builds before redefining anything. + * Use this preprocessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block. Under Cygwin things work + * just as under linux (e.g. ) and the winsock headers should + * never be included when __CYGWIN__ is defined. configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +# if defined(UNICODE) && !defined(_UNICODE) +# define _UNICODE +# endif +# if defined(_UNICODE) && !defined(UNICODE) +# define UNICODE +# endif +# include +# include +# ifdef HAVE_WINSOCK2_H +# include +# ifdef HAVE_WS2TCPIP_H +# include +# endif +# else +# ifdef HAVE_WINSOCK_H +# include +# endif +# endif +# include +# ifdef UNICODE + typedef wchar_t *(*curl_wcsdup_callback)(const wchar_t *str); +# endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +# define USE_WINSOCK 2 +#else +# ifdef HAVE_WINSOCK_H +# define USE_WINSOCK 1 +# endif +#endif + +#ifdef USE_LWIPSOCK +# include +# include +# include +#endif + +#ifdef HAVE_EXTRA_STRICMP_H +# include +#endif + +#ifdef HAVE_EXTRA_STRDUP_H +# include +#endif + +#ifdef TPF +# include /* for bzero, strcasecmp, and strncasecmp */ +# include /* for strcpy and strlen */ +# include /* for rand and srand */ +# include /* for select and ioctl*/ +# include /* for in_addr_t definition */ +# include /* for tpf_process_signals */ + /* change which select is used for libcurl */ +# define select(a,b,c,d,e) tpf_select_libcurl(a,b,c,d,e) +#endif + +#ifdef __VXWORKS__ +# include /* for generic BSD socket functions */ +# include /* for basic I/O interface functions */ +#endif + +#ifdef __AMIGA__ +# include +# include +# include +# include +# ifdef HAVE_PROTO_BSDSOCKET_H +# include /* ensure bsdsocket.library use */ +# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# endif +#endif + +#include +#ifdef HAVE_ASSERT_H +#include +#endif + +#ifdef __TANDEM /* for nsr-tandem-nsk systems */ +#include +#endif + +#ifndef STDC_HEADERS /* no standard C headers! */ +#include +#endif + +#ifdef __POCC__ +# include +# include +# define sys_nerr EILSEQ +#endif + +/* + * Salford-C kludge section (mostly borrowed from wxWidgets). + */ +#ifdef __SALFORDC__ + #pragma suppress 353 /* Possible nested comments */ + #pragma suppress 593 /* Define not used */ + #pragma suppress 61 /* enum has no name */ + #pragma suppress 106 /* unnamed, unused parameter */ + #include +#endif + +/* + * Large file (>2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_LARGE_FILES +# include +# include +# include +# undef lseek +# define lseek(fdes,offset,whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes,stp) _fstati64(fdes, stp) +# undef stat +# define stat(fname,stp) _stati64(fname, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 +#endif + +/* + * Small file (<2Gb) support using WIN32 functions. + */ + +#ifdef USE_WIN32_SMALL_FILES +# include +# include +# include +# ifndef _WIN32_WCE +# undef lseek +# define lseek(fdes,offset,whence) _lseek(fdes, (long)offset, whence) +# define fstat(fdes,stp) _fstat(fdes, stp) +# define stat(fname,stp) _stat(fname, stp) +# define struct_stat struct _stat +# endif +# define LSEEK_ERROR (long)-1 +#endif + +#ifndef struct_stat +# define struct_stat struct stat +#endif + +#ifndef LSEEK_ERROR +# define LSEEK_ERROR (off_t)-1 +#endif + +#ifndef SIZEOF_TIME_T +/* assume default size of time_t to be 32 bit */ +#define SIZEOF_TIME_T 4 +#endif + +/* + * Default sizeof(off_t) in case it hasn't been defined in config file. + */ + +#ifndef SIZEOF_OFF_T +# if defined(__VMS) && !defined(__VAX) +# if defined(_LARGEFILE) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__OS400__) && defined(__ILEC400__) +# if defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__MVS__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# elif defined(__370__) && defined(__IBMC__) +# if defined(_LP64) || defined(_LARGE_FILES) +# define SIZEOF_OFF_T 8 +# endif +# endif +# ifndef SIZEOF_OFF_T +# define SIZEOF_OFF_T 4 +# endif +#endif + +#if (SIZEOF_CURL_OFF_T == 4) +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFF) +#else + /* assume CURL_SIZEOF_CURL_OFF_T == 8 */ +# define CURL_OFF_T_MAX CURL_OFF_T_C(0x7FFFFFFFFFFFFFFF) +#endif +#define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - CURL_OFF_T_C(1)) + +#if (SIZEOF_TIME_T == 4) +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX UINT_MAX +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX INT_MAX +# define TIME_T_MIN INT_MIN +# endif +#else +# ifdef HAVE_TIME_T_UNSIGNED +# define TIME_T_MAX 0xFFFFFFFFFFFFFFFF +# define TIME_T_MIN 0 +# else +# define TIME_T_MAX 0x7FFFFFFFFFFFFFFF +# define TIME_T_MIN (-TIME_T_MAX - 1) +# endif +#endif + +#ifndef SIZE_T_MAX +/* some limits.h headers have this defined, some don't */ +#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) +#define SIZE_T_MAX 18446744073709551615U +#else +#define SIZE_T_MAX 4294967295U +#endif +#endif + +/* + * Arg 2 type for gethostname in case it hasn't been defined in config file. + */ + +#ifndef GETHOSTNAME_TYPE_ARG2 +# ifdef USE_WINSOCK +# define GETHOSTNAME_TYPE_ARG2 int +# else +# define GETHOSTNAME_TYPE_ARG2 size_t +# endif +#endif + +/* Below we define some functions. They should + + 4. set the SIGALRM signal timeout + 5. set dir/file naming defines + */ + +#ifdef WIN32 + +# define DIR_CHAR "\\" +# define DOT_CHAR "_" + +#else /* WIN32 */ + +# ifdef MSDOS /* Watt-32 */ + +# include +# define select(n,r,w,x,t) select_s(n,r,w,x,t) +# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# include +# ifdef word +# undef word +# endif +# ifdef byte +# undef byte +# endif + +# endif /* MSDOS */ + +# ifdef __minix + /* Minix 3 versions up to at least 3.1.3 are missing these prototypes */ + extern char *strtok_r(char *s, const char *delim, char **last); + extern struct tm *gmtime_r(const time_t * const timep, struct tm *tmp); +# endif + +# define DIR_CHAR "/" +# ifndef DOT_CHAR +# define DOT_CHAR "." +# endif + +# ifdef MSDOS +# undef DOT_CHAR +# define DOT_CHAR "_" +# endif + +# ifndef fileno /* sunos 4 have this as a macro! */ + int fileno(FILE *stream); +# endif + +#endif /* WIN32 */ + +/* + * msvc 6.0 requires PSDK in order to have INET6_ADDRSTRLEN + * defined in ws2tcpip.h as well as to provide IPv6 support. + * Does not apply if lwIP is used. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(USE_LWIPSOCK) +# if !defined(HAVE_WS2TCPIP_H) || \ + ((_MSC_VER < 1300) && !defined(INET6_ADDRSTRLEN)) +# undef HAVE_GETADDRINFO_THREADSAFE +# undef HAVE_FREEADDRINFO +# undef HAVE_GETADDRINFO +# undef HAVE_GETNAMEINFO +# undef ENABLE_IPV6 +# endif +#endif + +/* ---------------------------------------------------------------- */ +/* resolver specialty compile-time defines */ +/* CURLRES_* defines to use in the host*.c sources */ +/* ---------------------------------------------------------------- */ + +/* + * lcc-win32 doesn't have _beginthreadex(), lacks threads support. + */ + +#if defined(__LCC__) && defined(WIN32) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * MSVC threads support requires a multi-threaded runtime library. + * _beginthreadex() is not available in single-threaded ones. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) && !defined(_MT) +# undef USE_THREADS_POSIX +# undef USE_THREADS_WIN32 +#endif + +/* + * Mutually exclusive CURLRES_* definitions. + */ + +#ifdef USE_ARES +# define CURLRES_ASYNCH +# define CURLRES_ARES +/* now undef the stock libc functions just to avoid them being used */ +# undef HAVE_GETADDRINFO +# undef HAVE_FREEADDRINFO +# undef HAVE_GETHOSTBYNAME +#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +# define CURLRES_ASYNCH +# define CURLRES_THREADED +#else +# define CURLRES_SYNCH +#endif + +#ifdef ENABLE_IPV6 +# define CURLRES_IPV6 +#else +# define CURLRES_IPV4 +#endif + +/* ---------------------------------------------------------------- */ + +/* + * When using WINSOCK, TELNET protocol requires WINSOCK2 API. + */ + +#if defined(USE_WINSOCK) && (USE_WINSOCK != 2) +# define CURL_DISABLE_TELNET 1 +#endif + +/* + * msvc 6.0 does not have struct sockaddr_storage and + * does not define IPPROTO_ESP in winsock2.h. But both + * are available if PSDK is properly installed. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINSOCK2_H) || ((_MSC_VER < 1300) && !defined(IPPROTO_ESP)) +# undef HAVE_STRUCT_SOCKADDR_STORAGE +# endif +#endif + +/* + * Intentionally fail to build when using msvc 6.0 without PSDK installed. + * The brave of heart can circumvent this, defining ALLOW_MSVC6_WITHOUT_PSDK + * in lib/config-win32.h although absolutely discouraged and unsupported. + */ + +#if defined(_MSC_VER) && !defined(__POCC__) +# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_)) +# if !defined(ALLOW_MSVC6_WITHOUT_PSDK) +# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. \ + "Windows Server 2003 PSDK" +# else +# define CURL_DISABLE_LDAP 1 +# endif +# endif +#endif + +#ifdef NETWARE +int netware_init(void); +#ifndef __NOVELL_LIBC__ +#include +#include +#endif +#endif + +#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN) +/* The lib and header are present */ +#define USE_LIBIDN2 +#endif + +#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN) +#error "Both libidn2 and WinIDN are enabled, choose one." +#endif + +#define LIBIDN_REQUIRED_VERSION "0.4.1" + +#if defined(USE_GNUTLS) || defined(USE_OPENSSL) || defined(USE_NSS) || \ + defined(USE_POLARSSL) || defined(USE_MBEDTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) || \ + defined(USE_SECTRANSP) || defined(USE_GSKIT) || defined(USE_MESALINK) +#define USE_SSL /* SSL support has been enabled */ +#endif + +/* Single point where USE_SPNEGO definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_SPNEGO +#endif + +/* Single point where USE_KERBEROS5 definition might be defined */ +#if !defined(CURL_DISABLE_CRYPTO_AUTH) && \ + (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) +#define USE_KERBEROS5 +#endif + +/* Single point where USE_NTLM definition might be defined */ +#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) +#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \ + defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_SECTRANSP) || \ + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ + defined(USE_MBEDTLS) + +#define USE_NTLM + +# if defined(USE_MBEDTLS) +/* Get definition of MBEDTLS_MD4_C */ +# include +# endif + +#endif +#endif + +#ifdef CURL_WANTS_CA_BUNDLE_ENV +#error "No longer supported. Set CURLOPT_CAINFO at runtime instead." +#endif + +/* + * Provide a mechanism to silence picky compilers, such as gcc 4.6+. + * Parameters should of course normally not be unused, but for example when + * we have multiple implementations of the same interface it may happen. + */ + +#if defined(__GNUC__) && ((__GNUC__ >= 3) || \ + ((__GNUC__ == 2) && defined(__GNUC_MINOR__) && (__GNUC_MINOR__ >= 7))) +# define UNUSED_PARAM __attribute__((__unused__)) +# define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define UNUSED_PARAM /*NOTHING*/ +# define WARN_UNUSED_RESULT +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef HEADER_CURL_SETUP_ONCE_H +#include "curl_setup_once.h" +#endif + +/* + * Definition of our NOP statement Object-like macro + */ + +#ifndef Curl_nop_stmt +# define Curl_nop_stmt do { } WHILE_FALSE +#endif + +/* + * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. + */ + +#if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) +# if defined(SOCKET) || \ + defined(USE_WINSOCK) || \ + defined(HAVE_WINSOCK_H) || \ + defined(HAVE_WINSOCK2_H) || \ + defined(HAVE_WS2TCPIP_H) +# error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" +# endif +#endif + +/* + * Portable symbolic names for Winsock shutdown() mode flags. + */ + +#ifdef USE_WINSOCK +# define SHUT_RD 0x00 +# define SHUT_WR 0x01 +# define SHUT_RDWR 0x02 +#endif + +/* Define S_ISREG if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#endif + +/* Define S_ISDIR if not defined by system headers, f.e. MSVC */ +#if !defined(S_ISDIR) && defined(S_IFMT) && defined(S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +/* In Windows the default file mode is text but an application can override it. +Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 +*/ +#if defined(WIN32) || defined(MSDOS) +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" +#define FOPEN_APPENDTEXT "at" +#elif defined(__CYGWIN__) +/* Cygwin has specific behavior we need to address when WIN32 is not defined. +https://cygwin.com/cygwin-ug-net/using-textbinary.html +For write we want our output to have line endings of LF and be compatible with +other Cygwin utilities. For read we want to handle input that may have line +endings either CRLF or LF so 't' is appropriate. +*/ +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#else +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" +#define FOPEN_APPENDTEXT "a" +#endif + +/* WinSock destroys recv() buffer when send() failed. + * Enabled automatically for Windows and for Cygwin as Cygwin sockets are + * wrappers for WinSock sockets. https://github.com/curl/curl/issues/657 + * Define DONT_USE_RECV_BEFORE_SEND_WORKAROUND to force disable workaround. + */ +#if !defined(DONT_USE_RECV_BEFORE_SEND_WORKAROUND) +# if defined(WIN32) || defined(__CYGWIN__) +# define USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#else /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ +# ifdef USE_RECV_BEFORE_SEND_WORKAROUND +# undef USE_RECV_BEFORE_SEND_WORKAROUND +# endif +#endif /* DONT_USE_RECV_BEFORE_SEND_WORKAROUND */ + +/* Detect Windows App environment which has a restricted access + * to the Win32 APIs. */ +# if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ + defined(WINAPI_FAMILY) +# include +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ + !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +# define CURL_WINDOWS_APP +# endif +# endif + +/* for systems that don't detect this in configure, use a sensible default */ +#ifndef CURL_SA_FAMILY_T +#define CURL_SA_FAMILY_T unsigned short +#endif + +/* Some convenience macros to get the larger/smaller value out of two given. + We prefix with CURL to prevent name collisions. */ +#define CURLMAX(x,y) ((x)>(y)?(x):(y)) +#define CURLMIN(x,y) ((x)<(y)?(x):(y)) + +/* Some versions of the Android SDK is missing the declaration */ +#if defined(HAVE_GETPWUID_R) && defined(HAVE_DECL_GETPWUID_R_MISSING) +struct passwd; +int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, + size_t buflen, struct passwd **result); +#endif + +#ifdef DEBUGBUILD +#define UNITTEST +#else +#define UNITTEST static +#endif + +#endif /* HEADER_CURL_SETUP_H */ diff --git a/external/curl prx/include/curl_setup_once.h b/external/curl prx/include/curl_setup_once.h new file mode 100644 index 0000000..ffa5fd8 --- /dev/null +++ b/external/curl prx/include/curl_setup_once.h @@ -0,0 +1,483 @@ +#ifndef HEADER_CURL_SETUP_ONCE_H +#define HEADER_CURL_SETUP_ONCE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* + * Inclusion of common header files. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NEED_MALLOC_H +#include +#endif + +#ifdef NEED_MEMORY_H +#include +#endif + +#include +#include +#include + +#ifdef WIN32 +#include +#endif + +#include +#include + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef _APP32_64BIT_OFF_T +# define OLD_APP32_64BIT_OFF_T _APP32_64BIT_OFF_T +# undef _APP32_64BIT_OFF_T +# else +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +#include + +#ifdef __hpux +# if !defined(_XOPEN_SOURCE_EXTENDED) || defined(_KERNEL) +# ifdef OLD_APP32_64BIT_OFF_T +# define _APP32_64BIT_OFF_T OLD_APP32_64BIT_OFF_T +# undef OLD_APP32_64BIT_OFF_T +# endif +# endif +#endif + +/* + * Definition of timeval struct for platforms that don't have it. + */ +#define HAVE_STRUCT_TIMEVAL 1 +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + + +/* + * If we have the MSG_NOSIGNAL define, make sure we use + * it as the fourth argument of function send() + */ + +#ifdef HAVE_MSG_NOSIGNAL +#define SEND_4TH_ARG MSG_NOSIGNAL +#else +#define SEND_4TH_ARG 0 +#endif + + +#if defined(__minix) +/* Minix doesn't support recv on TCP sockets */ +#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z)) + +#elif defined(HAVE_RECV) +/* + * The definitions for the return type and arguments types + * of functions recv() and send() belong and come from the + * configuration file. Do not define them in any other place. + * + * HAVE_RECV is defined if you have a function named recv() + * which is used to read incoming data from sockets. If your + * function has another name then don't define HAVE_RECV. + * + * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, + * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also + * be defined. + * + * HAVE_SEND is defined if you have a function named send() + * which is used to write outgoing data on a connected socket. + * If yours has another name then don't define HAVE_SEND. + * + * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, + * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and + * SEND_TYPE_RETV must also be defined. + */ + +#if !defined(RECV_TYPE_ARG1) || \ + !defined(RECV_TYPE_ARG2) || \ + !defined(RECV_TYPE_ARG3) || \ + !defined(RECV_TYPE_ARG4) || \ + !defined(RECV_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recv + /* */ +#else +#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z), \ + (RECV_TYPE_ARG4)(0)) +#endif +#else /* HAVE_RECV */ +#endif /* HAVE_RECV */ + + +#if defined(__minix) +/* Minix doesn't support send on TCP sockets */ +#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z)) + +#elif defined(HAVE_SEND) +#if !defined(SEND_TYPE_ARG1) || \ + !defined(SEND_QUAL_ARG2) || \ + !defined(SEND_TYPE_ARG2) || \ + !defined(SEND_TYPE_ARG3) || \ + !defined(SEND_TYPE_ARG4) || \ + !defined(SEND_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_send + /* */ +#else +#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ + (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \ + (SEND_TYPE_ARG3)(z), \ + (SEND_TYPE_ARG4)(SEND_4TH_ARG)) +#endif +#else /* HAVE_SEND */ +#endif /* HAVE_SEND */ + + +#if 0 +#if defined(HAVE_RECVFROM) +/* + * Currently recvfrom is only used on udp sockets. + */ +#if !defined(RECVFROM_TYPE_ARG1) || \ + !defined(RECVFROM_TYPE_ARG2) || \ + !defined(RECVFROM_TYPE_ARG3) || \ + !defined(RECVFROM_TYPE_ARG4) || \ + !defined(RECVFROM_TYPE_ARG5) || \ + !defined(RECVFROM_TYPE_ARG6) || \ + !defined(RECVFROM_TYPE_RETV) + /* */ + Error Missing_definition_of_return_and_arguments_types_of_recvfrom + /* */ +#else +#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1) (s), \ + (RECVFROM_TYPE_ARG2 *)(b), \ + (RECVFROM_TYPE_ARG3) (bl), \ + (RECVFROM_TYPE_ARG4) (0), \ + (RECVFROM_TYPE_ARG5 *)(f), \ + (RECVFROM_TYPE_ARG6 *)(fl)) +#endif +#else /* HAVE_RECVFROM */ +#ifndef sreadfrom + /* */ + Error Missing_definition_of_macro_sreadfrom + /* */ +#endif +#endif /* HAVE_RECVFROM */ + + +#ifdef RECVFROM_TYPE_ARG6_IS_VOID +# define RECVFROM_ARG6_T int +#else +# define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 +#endif +#endif /* if 0 */ + + +/* + * Function-like macro definition used to close a socket. + */ + +#if defined(HAVE_CLOSESOCKET) +# define sclose(x) closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +# define sclose(x) CloseSocket((x)) +#elif defined(HAVE_CLOSE_S) +# define sclose(x) close_s((x)) +#elif defined(USE_LWIPSOCK) +# define sclose(x) lwip_close((x)) +#else +# define sclose(x) close((x)) +#endif + +/* + * Stack-independent version of fcntl() on sockets: + */ +#if defined(USE_LWIPSOCK) +# define sfcntl lwip_fcntl +#else +# define sfcntl fcntl +#endif + +#define TOLOWER(x) (tolower((int) ((unsigned char)x))) + + +/* + * 'bool' stuff compatible with HP-UX headers. + */ + +#if defined(__hpux) && !defined(HAVE_BOOL_T) + typedef int bool; +# define false 0 +# define true 1 +# define HAVE_BOOL_T +#endif + + +/* + * 'bool' exists on platforms with , i.e. C99 platforms. + * On non-C99 platforms there's no bool, so define an enum for that. + * On C99 platforms 'false' and 'true' also exist. Enum uses a + * global namespace though, so use bool_false and bool_true. + */ +#define HAVE_BOOL_T 1 +#ifndef HAVE_BOOL_T + typedef enum { + bool_false = 0, + bool_true = 1 + } bool; + +/* + * Use a define to let 'true' and 'false' use those enums. There + * are currently no use of true and false in libcurl proper, but + * there are some in the examples. This will cater for any later + * code happening to use true and false. + */ +# define false false +# define true true +# define HAVE_BOOL_T +#endif + + +/* + * Redefine TRUE and FALSE too, to catch current use. With this + * change, 'bool found = 1' will give a warning on MIPSPro, but + * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, + * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. + */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#include "curl_ctype.h" + +/* + * Macro WHILE_FALSE may be used to build single-iteration do-while loops, + * avoiding compiler warnings. Mostly intended for other macro definitions. + */ + +#define WHILE_FALSE while(0) + +#if defined(_MSC_VER) && !defined(__POCC__) +# undef WHILE_FALSE +# if (_MSC_VER < 1500) +# define WHILE_FALSE while(1, 0) +# else +# define WHILE_FALSE \ +__pragma(warning(push)) \ +__pragma(warning(disable:4127)) \ +while(0) \ +__pragma(warning(pop)) +# endif +#endif + + +/* + * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. + */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +#define HAVE_SIG_ATOMIC_T +#endif + + +/* + * Convenience SIG_ATOMIC_T definition + */ + +#ifdef HAVE_SIG_ATOMIC_T_VOLATILE +#define SIG_ATOMIC_T static sig_atomic_t +#else +#define SIG_ATOMIC_T static volatile sig_atomic_t +#endif + + +/* + * Default return type for signal handlers. + */ + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#endif + + +/* + * Macro used to include code only in debug builds. + */ + +#ifdef DEBUGBUILD +#define DEBUGF(x) x +#else +#define DEBUGF(x) do { } WHILE_FALSE +#endif + + +/* + * Macro used to include assertion code only in debug builds. + */ + +#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) do { } WHILE_FALSE +#endif + + +/* + * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef USE_WINSOCK +#define SOCKERRNO ((int)WSAGetLastError()) +#define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) +#else +#define SOCKERRNO (errno) +#define SET_SOCKERRNO(x) (errno = (x)) +#endif + + +/* + * Portable error number symbolic names defined to Winsock error codes. + */ + +#ifdef USE_WINSOCK +#undef EBADF /* override definition in errno.h */ +#define EBADF WSAEBADF +#undef EINTR /* override definition in errno.h */ +#define EINTR WSAEINTR +#undef EINVAL /* override definition in errno.h */ +#define EINVAL WSAEINVAL +#undef EWOULDBLOCK /* override definition in errno.h */ +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINPROGRESS /* override definition in errno.h */ +#define EINPROGRESS WSAEINPROGRESS +#undef EALREADY /* override definition in errno.h */ +#define EALREADY WSAEALREADY +#undef ENOTSOCK /* override definition in errno.h */ +#define ENOTSOCK WSAENOTSOCK +#undef EDESTADDRREQ /* override definition in errno.h */ +#define EDESTADDRREQ WSAEDESTADDRREQ +#undef EMSGSIZE /* override definition in errno.h */ +#define EMSGSIZE WSAEMSGSIZE +#undef EPROTOTYPE /* override definition in errno.h */ +#define EPROTOTYPE WSAEPROTOTYPE +#undef ENOPROTOOPT /* override definition in errno.h */ +#define ENOPROTOOPT WSAENOPROTOOPT +#undef EPROTONOSUPPORT /* override definition in errno.h */ +#define EPROTONOSUPPORT WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT +#undef EOPNOTSUPP /* override definition in errno.h */ +#define EOPNOTSUPP WSAEOPNOTSUPP +#define EPFNOSUPPORT WSAEPFNOSUPPORT +#undef EAFNOSUPPORT /* override definition in errno.h */ +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#undef EADDRINUSE /* override definition in errno.h */ +#define EADDRINUSE WSAEADDRINUSE +#undef EADDRNOTAVAIL /* override definition in errno.h */ +#define EADDRNOTAVAIL WSAEADDRNOTAVAIL +#undef ENETDOWN /* override definition in errno.h */ +#define ENETDOWN WSAENETDOWN +#undef ENETUNREACH /* override definition in errno.h */ +#define ENETUNREACH WSAENETUNREACH +#undef ENETRESET /* override definition in errno.h */ +#define ENETRESET WSAENETRESET +#undef ECONNABORTED /* override definition in errno.h */ +#define ECONNABORTED WSAECONNABORTED +#undef ECONNRESET /* override definition in errno.h */ +#define ECONNRESET WSAECONNRESET +#undef ENOBUFS /* override definition in errno.h */ +#define ENOBUFS WSAENOBUFS +#undef EISCONN /* override definition in errno.h */ +#define EISCONN WSAEISCONN +#undef ENOTCONN /* override definition in errno.h */ +#define ENOTCONN WSAENOTCONN +#define ESHUTDOWN WSAESHUTDOWN +#define ETOOMANYREFS WSAETOOMANYREFS +#undef ETIMEDOUT /* override definition in errno.h */ +#define ETIMEDOUT WSAETIMEDOUT +#undef ECONNREFUSED /* override definition in errno.h */ +#define ECONNREFUSED WSAECONNREFUSED +#undef ELOOP /* override definition in errno.h */ +#define ELOOP WSAELOOP +#ifndef ENAMETOOLONG /* possible previous definition in errno.h */ +#define ENAMETOOLONG WSAENAMETOOLONG +#endif +#define EHOSTDOWN WSAEHOSTDOWN +#undef EHOSTUNREACH /* override definition in errno.h */ +#define EHOSTUNREACH WSAEHOSTUNREACH +#ifndef ENOTEMPTY /* possible previous definition in errno.h */ +#define ENOTEMPTY WSAENOTEMPTY +#endif +#define EPROCLIM WSAEPROCLIM +#define EUSERS WSAEUSERS +#define EDQUOT WSAEDQUOT +#define ESTALE WSAESTALE +#define EREMOTE WSAEREMOTE +#endif + +/* + * Macro argv_item_t hides platform details to code using it. + */ + +#ifdef __VMS +#define argv_item_t __char_ptr32 +#else +#define argv_item_t char * +#endif + + +/* + * We use this ZERO_NULL to avoid picky compiler warnings, + * when assigning a NULL pointer to a function pointer var. + */ + +#define ZERO_NULL 0 + + +#endif /* HEADER_CURL_SETUP_ONCE_H */ diff --git a/external/curl prx/include/curl_sha256.h b/external/curl prx/include/curl_sha256.h new file mode 100644 index 0000000..6db4b04 --- /dev/null +++ b/external/curl prx/include/curl_sha256.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SHA256_H +#define HEADER_CURL_SHA256_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Florin Petriuc, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_CRYPTO_AUTH + +void Curl_sha256it(unsigned char *outbuffer, + const unsigned char *input); + +#endif + +#endif /* HEADER_CURL_SHA256_H */ diff --git a/external/curl prx/include/curl_sspi.h b/external/curl prx/include/curl_sspi.h new file mode 100644 index 0000000..2bbf947 --- /dev/null +++ b/external/curl prx/include/curl_sspi.h @@ -0,0 +1,350 @@ +#ifndef HEADER_CURL_SSPI_H +#define HEADER_CURL_SSPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_WINDOWS_SSPI + +#include + +/* + * When including the following three headers, it is mandatory to define either + * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. + */ + +#undef SECURITY_WIN32 +#undef SECURITY_KERNEL +#define SECURITY_WIN32 1 +#include +#include +#include + +CURLcode Curl_sspi_global_init(void); +void Curl_sspi_global_cleanup(void); + +/* This is used to populate the domain in a SSPI identity structure */ +CURLcode Curl_override_sspi_http_realm(const char *chlg, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to generate an SSPI identity structure */ +CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, + SEC_WINNT_AUTH_IDENTITY *identity); + +/* This is used to free an SSPI identity structure */ +void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity); + +/* Forward-declaration of global variables defined in curl_sspi.c */ +extern HMODULE s_hSecDll; +extern PSecurityFunctionTable s_pSecFn; + +/* Provide some definitions missing in old headers */ +#define SP_NAME_DIGEST "WDigest" +#define SP_NAME_NTLM "NTLM" +#define SP_NAME_NEGOTIATE "Negotiate" +#define SP_NAME_KERBEROS "Kerberos" + +#ifndef ISC_REQ_USE_HTTP_STYLE +#define ISC_REQ_USE_HTTP_STYLE 0x01000000 +#endif + +#ifndef ISC_RET_REPLAY_DETECT +#define ISC_RET_REPLAY_DETECT 0x00000004 +#endif + +#ifndef ISC_RET_SEQUENCE_DETECT +#define ISC_RET_SEQUENCE_DETECT 0x00000008 +#endif + +#ifndef ISC_RET_CONFIDENTIALITY +#define ISC_RET_CONFIDENTIALITY 0x00000010 +#endif + +#ifndef ISC_RET_ALLOCATED_MEMORY +#define ISC_RET_ALLOCATED_MEMORY 0x00000100 +#endif + +#ifndef ISC_RET_STREAM +#define ISC_RET_STREAM 0x00008000 +#endif + +#ifndef SEC_E_INSUFFICIENT_MEMORY +# define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L) +#endif +#ifndef SEC_E_INVALID_HANDLE +# define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L) +#endif +#ifndef SEC_E_UNSUPPORTED_FUNCTION +# define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L) +#endif +#ifndef SEC_E_TARGET_UNKNOWN +# define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L) +#endif +#ifndef SEC_E_INTERNAL_ERROR +# define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L) +#endif +#ifndef SEC_E_SECPKG_NOT_FOUND +# define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L) +#endif +#ifndef SEC_E_NOT_OWNER +# define SEC_E_NOT_OWNER ((HRESULT)0x80090306L) +#endif +#ifndef SEC_E_CANNOT_INSTALL +# define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L) +#endif +#ifndef SEC_E_INVALID_TOKEN +# define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L) +#endif +#ifndef SEC_E_CANNOT_PACK +# define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L) +#endif +#ifndef SEC_E_QOP_NOT_SUPPORTED +# define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL) +#endif +#ifndef SEC_E_NO_IMPERSONATION +# define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL) +#endif +#ifndef SEC_E_LOGON_DENIED +# define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL) +#endif +#ifndef SEC_E_UNKNOWN_CREDENTIALS +# define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL) +#endif +#ifndef SEC_E_NO_CREDENTIALS +# define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL) +#endif +#ifndef SEC_E_MESSAGE_ALTERED +# define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) +#endif +#ifndef SEC_E_OUT_OF_SEQUENCE +# define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) +#endif +#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY +# define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L) +#endif +#ifndef SEC_E_BAD_PKGID +# define SEC_E_BAD_PKGID ((HRESULT)0x80090316L) +#endif +#ifndef SEC_E_CONTEXT_EXPIRED +# define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) +#endif +#ifndef SEC_E_INCOMPLETE_MESSAGE +# define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L) +#endif +#ifndef SEC_E_INCOMPLETE_CREDENTIALS +# define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L) +#endif +#ifndef SEC_E_BUFFER_TOO_SMALL +# define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) +#endif +#ifndef SEC_E_WRONG_PRINCIPAL +# define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L) +#endif +#ifndef SEC_E_TIME_SKEW +# define SEC_E_TIME_SKEW ((HRESULT)0x80090324L) +#endif +#ifndef SEC_E_UNTRUSTED_ROOT +# define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L) +#endif +#ifndef SEC_E_ILLEGAL_MESSAGE +# define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L) +#endif +#ifndef SEC_E_CERT_UNKNOWN +# define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L) +#endif +#ifndef SEC_E_CERT_EXPIRED +# define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L) +#endif +#ifndef SEC_E_ENCRYPT_FAILURE +# define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L) +#endif +#ifndef SEC_E_DECRYPT_FAILURE +# define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L) +#endif +#ifndef SEC_E_ALGORITHM_MISMATCH +# define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L) +#endif +#ifndef SEC_E_SECURITY_QOS_FAILED +# define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L) +#endif +#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED +# define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L) +#endif +#ifndef SEC_E_NO_TGT_REPLY +# define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L) +#endif +#ifndef SEC_E_NO_IP_ADDRESSES +# define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L) +#endif +#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE +# define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L) +#endif +#ifndef SEC_E_CRYPTO_SYSTEM_INVALID +# define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) +#endif +#ifndef SEC_E_MAX_REFERRALS_EXCEEDED +# define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L) +#endif +#ifndef SEC_E_MUST_BE_KDC +# define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L) +#endif +#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED +# define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL) +#endif +#ifndef SEC_E_TOO_MANY_PRINCIPALS +# define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL) +#endif +#ifndef SEC_E_NO_PA_DATA +# define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL) +#endif +#ifndef SEC_E_PKINIT_NAME_MISMATCH +# define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL) +#endif +#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED +# define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL) +#endif +#ifndef SEC_E_SHUTDOWN_IN_PROGRESS +# define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL) +#endif +#ifndef SEC_E_KDC_INVALID_REQUEST +# define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L) +#endif +#ifndef SEC_E_KDC_UNABLE_TO_REFER +# define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L) +#endif +#ifndef SEC_E_KDC_UNKNOWN_ETYPE +# define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L) +#endif +#ifndef SEC_E_UNSUPPORTED_PREAUTH +# define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L) +#endif +#ifndef SEC_E_DELEGATION_REQUIRED +# define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L) +#endif +#ifndef SEC_E_BAD_BINDINGS +# define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L) +#endif +#ifndef SEC_E_MULTIPLE_ACCOUNTS +# define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L) +#endif +#ifndef SEC_E_NO_KERB_KEY +# define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L) +#endif +#ifndef SEC_E_CERT_WRONG_USAGE +# define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L) +#endif +#ifndef SEC_E_DOWNGRADE_DETECTED +# define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_REVOKED +# define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED +# define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_C +# define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L) +#endif +#ifndef SEC_E_PKINIT_CLIENT_FAILURE +# define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L) +#endif +#ifndef SEC_E_SMARTCARD_CERT_EXPIRED +# define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L) +#endif +#ifndef SEC_E_NO_S4U_PROT_SUPPORT +# define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L) +#endif +#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE +# define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L) +#endif +#ifndef SEC_E_REVOCATION_OFFLINE_KDC +# define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L) +#endif +#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC +# define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L) +#endif +#ifndef SEC_E_KDC_CERT_EXPIRED +# define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL) +#endif +#ifndef SEC_E_KDC_CERT_REVOKED +# define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL) +#endif +#ifndef SEC_E_INVALID_PARAMETER +# define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL) +#endif +#ifndef SEC_E_DELEGATION_POLICY +# define SEC_E_DELEGATION_POLICY ((HRESULT)0x8009035EL) +#endif +#ifndef SEC_E_POLICY_NLTM_ONLY +# define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL) +#endif + +#ifndef SEC_I_CONTINUE_NEEDED +# define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L) +#endif +#ifndef SEC_I_COMPLETE_NEEDED +# define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L) +#endif +#ifndef SEC_I_COMPLETE_AND_CONTINUE +# define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L) +#endif +#ifndef SEC_I_LOCAL_LOGON +# define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L) +#endif +#ifndef SEC_I_CONTEXT_EXPIRED +# define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) +#endif +#ifndef SEC_I_INCOMPLETE_CREDENTIALS +# define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L) +#endif +#ifndef SEC_I_RENEGOTIATE +# define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L) +#endif +#ifndef SEC_I_NO_LSA_CONTEXT +# define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L) +#endif +#ifndef SEC_I_SIGNATURE_NEEDED +# define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) +#endif + +#ifndef CRYPT_E_REVOKED +# define CRYPT_E_REVOKED ((HRESULT)0x80092010L) +#endif + +#ifdef UNICODE +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_UNICODE +#else +# define SECFLAG_WINNT_AUTH_IDENTITY \ + (unsigned long)SEC_WINNT_AUTH_IDENTITY_ANSI +#endif + +/* + * Definitions required from ntsecapi.h are directly provided below this point + * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h + */ +#define KERB_WRAP_NO_ENCRYPT 0x80000001 + +#endif /* USE_WINDOWS_SSPI */ + +#endif /* HEADER_CURL_SSPI_H */ diff --git a/external/curl prx/include/curl_threads.h b/external/curl prx/include/curl_threads.h new file mode 100644 index 0000000..2a93644 --- /dev/null +++ b/external/curl prx/include/curl_threads.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_THREADS_H +#define HEADER_CURL_THREADS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(USE_THREADS_POSIX) +# define CURL_STDCALL +# define curl_mutex_t pthread_mutex_t +# define curl_thread_t pthread_t * +# define curl_thread_t_null (pthread_t *)0 +# define Curl_mutex_init(m) pthread_mutex_init(m, NULL) +# define Curl_mutex_acquire(m) pthread_mutex_lock(m) +# define Curl_mutex_release(m) pthread_mutex_unlock(m) +# define Curl_mutex_destroy(m) pthread_mutex_destroy(m) +#elif defined(USE_THREADS_WIN32) +# define CURL_STDCALL __stdcall +# define curl_mutex_t CRITICAL_SECTION +# define curl_thread_t HANDLE +# define curl_thread_t_null (HANDLE)0 +# if !defined(_WIN32_WINNT) || !defined(_WIN32_WINNT_VISTA) || \ + (_WIN32_WINNT < _WIN32_WINNT_VISTA) || \ + (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)) +# define Curl_mutex_init(m) InitializeCriticalSection(m) +# else +# define Curl_mutex_init(m) InitializeCriticalSectionEx(m, 0, 1) +# endif +# define Curl_mutex_acquire(m) EnterCriticalSection(m) +# define Curl_mutex_release(m) LeaveCriticalSection(m) +# define Curl_mutex_destroy(m) DeleteCriticalSection(m) +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +/* !checksrc! disable SPACEBEFOREPAREN 1 */ +curl_thread_t Curl_thread_create(unsigned int (CURL_STDCALL *func) (void *), + void *arg); + +void Curl_thread_destroy(curl_thread_t hnd); + +int Curl_thread_join(curl_thread_t *hnd); + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* HEADER_CURL_THREADS_H */ diff --git a/external/curl prx/include/curlx.h b/external/curl prx/include/curlx.h new file mode 100644 index 0000000..3e9b516 --- /dev/null +++ b/external/curl prx/include/curlx.h @@ -0,0 +1,103 @@ +#ifndef HEADER_CURL_CURLX_H +#define HEADER_CURL_CURLX_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Defines protos and includes all header files that provide the curlx_* + * functions. The curlx_* functions are not part of the libcurl API, but are + * stand-alone functions whose sources can be built and linked by apps if need + * be. + */ + +#include +/* this is still a public header file that provides the curl_mprintf() + functions while they still are offered publicly. They will be made library- + private one day */ + +#include "strcase.h" +/* "strcase.h" provides the strcasecompare protos */ + +#include "strtoofft.h" +/* "strtoofft.h" provides this function: curlx_strtoofft(), returns a + curl_off_t number from a given string. +*/ + +#include "nonblock.h" +/* "nonblock.h" provides curlx_nonblock() */ + +#include "warnless.h" +/* "warnless.h" provides functions: + + curlx_ultous() + curlx_ultouc() + curlx_uztosi() +*/ + +/* Now setup curlx_ * names for the functions that are to become curlx_ and + be removed from a future libcurl official API: + curlx_getenv + curlx_mprintf (and its variations) + curlx_strcasecompare + curlx_strncasecompare + +*/ + +#define curlx_getenv curl_getenv +#define curlx_mvsnprintf curl_mvsnprintf +#define curlx_msnprintf curl_msnprintf +#define curlx_maprintf curl_maprintf +#define curlx_mvaprintf curl_mvaprintf +#define curlx_msprintf curl_msprintf +#define curlx_mprintf curl_mprintf +#define curlx_mfprintf curl_mfprintf +#define curlx_mvsprintf curl_mvsprintf +#define curlx_mvprintf curl_mvprintf +#define curlx_mvfprintf curl_mvfprintf + +#ifdef ENABLE_CURLX_PRINTF +/* If this define is set, we define all "standard" printf() functions to use + the curlx_* version instead. It makes the source code transparent and + easier to understand/patch. Undefine them first. */ +# undef printf +# undef fprintf +# undef sprintf +# undef msnprintf +# undef vprintf +# undef vfprintf +# undef vsprintf +# undef mvsnprintf +# undef aprintf +# undef vaprintf + +# define printf curlx_mprintf +# define fprintf curlx_mfprintf +# define sprintf curlx_msprintf +# define msnprintf curlx_msnprintf +# define vprintf curlx_mvprintf +# define vfprintf curlx_mvfprintf +# define mvsnprintf curlx_mvsnprintf +# define aprintf curlx_maprintf +# define vaprintf curlx_mvaprintf +#endif /* ENABLE_CURLX_PRINTF */ + +#endif /* HEADER_CURL_CURLX_H */ diff --git a/external/curl prx/include/cyassl.h b/external/curl prx/include/cyassl.h new file mode 100644 index 0000000..01e11cc --- /dev/null +++ b/external/curl prx/include/cyassl.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_CYASSL_H +#define HEADER_CURL_CYASSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_CYASSL + +extern const struct Curl_ssl Curl_ssl_cyassl; + +#endif /* USE_CYASSL */ +#endif /* HEADER_CURL_CYASSL_H */ diff --git a/external/curl prx/include/dict.h b/external/curl prx/include/dict.h new file mode 100644 index 0000000..12c0f33 --- /dev/null +++ b/external/curl prx/include/dict.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_DICT_H +#define HEADER_CURL_DICT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_DICT +extern const struct Curl_handler Curl_handler_dict; +#endif + +#endif /* HEADER_CURL_DICT_H */ diff --git a/external/curl prx/include/digest.h b/external/curl prx/include/digest.h new file mode 100644 index 0000000..8686c44 --- /dev/null +++ b/external/curl prx/include/digest.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_DIGEST_H +#define HEADER_CURL_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + +enum { + CURLDIGESTALGO_MD5, + CURLDIGESTALGO_MD5SESS, + CURLDIGESTALGO_SHA256, + CURLDIGESTALGO_SHA256SESS, + CURLDIGESTALGO_SHA512_256, + CURLDIGESTALGO_SHA512_256SESS +}; + +/* This is used to extract the realm from a challenge message */ +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr); + +#endif + +#endif /* HEADER_CURL_DIGEST_H */ diff --git a/external/curl prx/include/doh.h b/external/curl prx/include/doh.h new file mode 100644 index 0000000..83c79bc --- /dev/null +++ b/external/curl prx/include/doh.h @@ -0,0 +1,105 @@ +#ifndef HEADER_CURL_DOH_H +#define HEADER_CURL_DOH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" +#include "curl_addrinfo.h" + +/* + * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name + * and returns a 'Curl_addrinfo *' with the address information. + */ + +Curl_addrinfo *Curl_doh(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + +CURLcode Curl_doh_is_resolved(struct connectdata *conn, + struct Curl_dns_entry **dns); + +int Curl_doh_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +typedef enum { + DOH_OK, + DOH_DNS_BAD_LABEL, /* 1 */ + DOH_DNS_OUT_OF_RANGE, /* 2 */ + DOH_DNS_LABEL_LOOP, /* 3 */ + DOH_TOO_SMALL_BUFFER, /* 4 */ + DOH_OUT_OF_MEM, /* 5 */ + DOH_DNS_RDATA_LEN, /* 6 */ + DOH_DNS_MALFORMAT, /* 7 */ + DOH_DNS_BAD_RCODE, /* 8 - no such name */ + DOH_DNS_UNEXPECTED_TYPE, /* 9 */ + DOH_DNS_UNEXPECTED_CLASS, /* 10 */ + DOH_NO_CONTENT, /* 11 */ + DOH_DNS_BAD_ID /* 12 */ +} DOHcode; + +typedef enum { + DNS_TYPE_A = 1, + DNS_TYPE_NS = 2, + DNS_TYPE_CNAME = 5, + DNS_TYPE_AAAA = 28 +} DNStype; + +#define DOH_MAX_ADDR 24 +#define DOH_MAX_CNAME 4 + +struct cnamestore { + size_t len; /* length of cname */ + char *alloc; /* allocated pointer */ + size_t allocsize; /* allocated size */ +}; + +struct dohaddr { + int type; + union { + unsigned char v4[4]; /* network byte order */ + unsigned char v6[16]; + } ip; +}; + +struct dohentry { + unsigned int ttl; + int numaddr; + struct dohaddr addr[DOH_MAX_ADDR]; + int numcname; + struct cnamestore cname[DOH_MAX_CNAME]; +}; + + +#ifdef DEBUGBUILD +DOHcode doh_encode(const char *host, + DNStype dnstype, + unsigned char *dnsp, /* buffer */ + size_t len, /* buffer size */ + size_t *olen); /* output length */ +DOHcode doh_decode(unsigned char *doh, + size_t dohlen, + DNStype dnstype, + struct dohentry *d); +void de_cleanup(struct dohentry *d); +#endif +#endif /* HEADER_CURL_DOH_H */ diff --git a/external/curl prx/include/dotdot.h b/external/curl prx/include/dotdot.h new file mode 100644 index 0000000..125af43 --- /dev/null +++ b/external/curl prx/include/dotdot.h @@ -0,0 +1,25 @@ +#ifndef HEADER_CURL_DOTDOT_H +#define HEADER_CURL_DOTDOT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +char *Curl_dedotdotify(const char *input); +#endif /* HEADER_CURL_DOTDOT_H */ diff --git a/external/curl prx/include/easyif.h b/external/curl prx/include/easyif.h new file mode 100644 index 0000000..6ba7e54 --- /dev/null +++ b/external/curl prx/include/easyif.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_EASYIF_H +#define HEADER_CURL_EASYIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by easy.c + */ +#ifdef CURLDEBUG +CURL_EXTERN CURLcode curl_easy_perform_ev(struct Curl_easy *easy); +#endif + +#endif /* HEADER_CURL_EASYIF_H */ diff --git a/external/curl prx/include/escape.h b/external/curl prx/include/escape.h new file mode 100644 index 0000000..3aa6c31 --- /dev/null +++ b/external/curl prx/include/escape.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_ESCAPE_H +#define HEADER_CURL_ESCAPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +bool Curl_isunreserved(unsigned char in); +CURLcode Curl_urldecode(CURL *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_crlf); + +#endif /* HEADER_CURL_ESCAPE_H */ diff --git a/external/curl prx/include/file.h b/external/curl prx/include/file.h new file mode 100644 index 0000000..20828ad --- /dev/null +++ b/external/curl prx/include/file.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_FILE_H +#define HEADER_CURL_FILE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/**************************************************************************** + * FILE unique setup + ***************************************************************************/ +struct FILEPROTO { + char *path; /* the path we operate on */ + char *freepath; /* pointer to the allocated block we must free, this might + differ from the 'path' pointer */ + int fd; /* open file descriptor to read from! */ +}; + +#ifndef CURL_DISABLE_FILE +extern const struct Curl_handler Curl_handler_file; +#endif + +#endif /* HEADER_CURL_FILE_H */ diff --git a/external/curl prx/include/fileinfo.h b/external/curl prx/include/fileinfo.h new file mode 100644 index 0000000..f4d8f3b --- /dev/null +++ b/external/curl prx/include/fileinfo.h @@ -0,0 +1,36 @@ +#ifndef HEADER_CURL_FILEINFO_H +#define HEADER_CURL_FILEINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include +#include "llist.h" + +struct fileinfo { + struct curl_fileinfo info; + struct curl_llist_element list; +}; + +struct fileinfo *Curl_fileinfo_alloc(void); +void Curl_fileinfo_cleanup(struct fileinfo *finfo); + +#endif /* HEADER_CURL_FILEINFO_H */ diff --git a/external/curl prx/include/formdata.h b/external/curl prx/include/formdata.h new file mode 100644 index 0000000..1246c2b --- /dev/null +++ b/external/curl prx/include/formdata.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_FORMDATA_H +#define HEADER_CURL_FORMDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* used by FormAdd for temporary storage */ +typedef struct FormInfo { + char *name; + bool name_alloc; + size_t namelength; + char *value; + bool value_alloc; + curl_off_t contentslength; + char *contenttype; + bool contenttype_alloc; + long flags; + char *buffer; /* pointer to existing buffer used for file upload */ + size_t bufferlength; + char *showfilename; /* The file name to show. If not set, the actual + file name will be used */ + bool showfilename_alloc; + char *userp; /* pointer for the read callback */ + struct curl_slist *contentheader; + struct FormInfo *more; +} FormInfo; + +CURLcode Curl_getformdata(struct Curl_easy *data, + curl_mimepart *, + struct curl_httppost *post, + curl_read_callback fread_func); + +#endif /* HEADER_CURL_FORMDATA_H */ diff --git a/external/curl prx/include/ftp.h b/external/curl prx/include/ftp.h new file mode 100644 index 0000000..828d69a --- /dev/null +++ b/external/curl prx/include/ftp.h @@ -0,0 +1,162 @@ +#ifndef HEADER_CURL_FTP_H +#define HEADER_CURL_FTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" + +#ifndef CURL_DISABLE_FTP +extern const struct Curl_handler Curl_handler_ftp; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_ftps; +#endif + +CURLcode Curl_ftpsend(struct connectdata *, const char *cmd); +CURLcode Curl_GetFTPResponse(ssize_t *nread, struct connectdata *conn, + int *ftpcode); +#endif /* CURL_DISABLE_FTP */ + +/**************************************************************************** + * FTP unique setup + ***************************************************************************/ +typedef enum { + FTP_STOP, /* do nothing state, stops the state machine */ + FTP_WAIT220, /* waiting for the initial 220 response immediately after + a connect */ + FTP_AUTH, + FTP_USER, + FTP_PASS, + FTP_ACCT, + FTP_PBSZ, + FTP_PROT, + FTP_CCC, + FTP_PWD, + FTP_SYST, + FTP_NAMEFMT, + FTP_QUOTE, /* waiting for a response to a command sent in a quote list */ + FTP_RETR_PREQUOTE, + FTP_STOR_PREQUOTE, + FTP_POSTQUOTE, + FTP_CWD, /* change dir */ + FTP_MKD, /* if the dir didn't exist */ + FTP_MDTM, /* to figure out the datestamp */ + FTP_TYPE, /* to set type when doing a head-like request */ + FTP_LIST_TYPE, /* set type when about to do a dir list */ + FTP_RETR_TYPE, /* set type when about to RETR a file */ + FTP_STOR_TYPE, /* set type when about to STOR a file */ + FTP_SIZE, /* get the remote file's size for head-like request */ + FTP_RETR_SIZE, /* get the remote file's size for RETR */ + FTP_STOR_SIZE, /* get the size for STOR */ + FTP_REST, /* when used to check if the server supports it in head-like */ + FTP_RETR_REST, /* when asking for "resume" in for RETR */ + FTP_PORT, /* generic state for PORT, LPRT and EPRT, check count1 */ + FTP_PRET, /* generic state for PRET RETR, PRET STOR and PRET LIST/NLST */ + FTP_PASV, /* generic state for PASV and EPSV, check count1 */ + FTP_LIST, /* generic state for LIST, NLST or a custom list command */ + FTP_RETR, + FTP_STOR, /* generic state for STOR and APPE */ + FTP_QUIT, + FTP_LAST /* never used */ +} ftpstate; + +struct ftp_parselist_data; /* defined later in ftplistparser.c */ + +struct ftp_wc { + struct ftp_parselist_data *parser; + + struct { + curl_write_callback write_function; + FILE *file_descriptor; + } backup; +}; + +typedef enum { + FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */ + FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */ + FTPFILE_SINGLECWD = 3 /* make one CWD, then SIZE / RETR / STOR on the + file */ +} curl_ftpfile; + +/* This FTP struct is used in the Curl_easy. All FTP data that is + connection-oriented must be in FTP_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct FTP { + char *user; /* user name string */ + char *passwd; /* password string */ + char *path; /* points to the urlpieces struct field */ + char *pathalloc; /* if non-NULL a pointer to an allocated path */ + + /* transfer a file/body or not, done as a typedefed enum just to make + debuggers display the full symbol and not just the numerical value */ + curl_pp_transfer transfer; + curl_off_t downloadsize; +}; + + +/* ftp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ftp_conn { + struct pingpong pp; + char *entrypath; /* the PWD reply when we logged on */ + char **dirs; /* realloc()ed array for path components */ + int dirdepth; /* number of entries used in the 'dirs' array */ + int diralloc; /* number of entries allocated for the 'dirs' array */ + char *file; /* decoded file */ + bool dont_check; /* Set to TRUE to prevent the final (post-transfer) + file size and 226/250 status check. It should still + read the line, just ignore the result. */ + bool ctl_valid; /* Tells Curl_ftp_quit() whether or not to do anything. If + the connection has timed out or been closed, this + should be FALSE when it gets to Curl_ftp_quit() */ + bool cwddone; /* if it has been determined that the proper CWD combo + already has been done */ + int cwdcount; /* number of CWD commands issued */ + bool cwdfail; /* set TRUE if a CWD command fails, as then we must prevent + caching the current directory */ + bool wait_data_conn; /* this is set TRUE if data connection is waited */ + char *prevpath; /* conn->path from the previous transfer */ + curl_ftpfile prevmethod; /* ftp method in previous transfer */ + char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a + and others (A/I or zero) */ + int count1; /* general purpose counter for the state machine */ + int count2; /* general purpose counter for the state machine */ + int count3; /* general purpose counter for the state machine */ + ftpstate state; /* always use ftp.c:state() to change state! */ + ftpstate state_saved; /* transfer type saved to be reloaded after + data connection is established */ + curl_off_t retr_size_saved; /* Size of retrieved file saved */ + char *server_os; /* The target server operating system. */ + curl_off_t known_filesize; /* file size is different from -1, if wildcard + LIST parsing was done and wc_statemach set + it */ + /* newhost is the (allocated) IP addr or host name to connect the data + connection to */ + char *newhost; /* this is the pair to connect the DATA... */ + unsigned short newport; /* connection to */ + +}; + +#define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ + +#endif /* HEADER_CURL_FTP_H */ diff --git a/external/curl prx/include/ftplistparser.h b/external/curl prx/include/ftplistparser.h new file mode 100644 index 0000000..8128887 --- /dev/null +++ b/external/curl prx/include/ftplistparser.h @@ -0,0 +1,41 @@ +#ifndef HEADER_CURL_FTPLISTPARSER_H +#define HEADER_CURL_FTPLISTPARSER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_FTP + +/* WRITEFUNCTION callback for parsing LIST responses */ +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr); + +struct ftp_parselist_data; /* defined inside ftplibparser.c */ + +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data); + +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void); + +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data); + +#endif /* CURL_DISABLE_FTP */ +#endif /* HEADER_CURL_FTPLISTPARSER_H */ diff --git a/external/curl prx/include/getinfo.h b/external/curl prx/include/getinfo.h new file mode 100644 index 0000000..aecf717 --- /dev/null +++ b/external/curl prx/include/getinfo.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CURL_GETINFO_H +#define HEADER_CURL_GETINFO_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...); +CURLcode Curl_initinfo(struct Curl_easy *data); + +#endif /* HEADER_CURL_GETINFO_H */ diff --git a/external/curl prx/include/gopher.h b/external/curl prx/include/gopher.h new file mode 100644 index 0000000..501c990 --- /dev/null +++ b/external/curl prx/include/gopher.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_GOPHER_H +#define HEADER_CURL_GOPHER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifndef CURL_DISABLE_GOPHER +extern const struct Curl_handler Curl_handler_gopher; +#endif + +#endif /* HEADER_CURL_GOPHER_H */ diff --git a/external/curl prx/include/gskit.h b/external/curl prx/include/gskit.h new file mode 100644 index 0000000..466ee4d --- /dev/null +++ b/external/curl prx/include/gskit.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_GSKIT_H +#define HEADER_CURL_GSKIT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * This header should only be needed to get included by vtls.c and gskit.c + */ + +#include "urldata.h" + +#ifdef USE_GSKIT + +extern const struct Curl_ssl Curl_ssl_gskit; + +#endif /* USE_GSKIT */ + +#endif /* HEADER_CURL_GSKIT_H */ diff --git a/external/curl prx/include/gtls.h b/external/curl prx/include/gtls.h new file mode 100644 index 0000000..780fc10 --- /dev/null +++ b/external/curl prx/include/gtls.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_GTLS_H +#define HEADER_CURL_GTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_gnutls; + +#endif /* USE_GNUTLS */ +#endif /* HEADER_CURL_GTLS_H */ diff --git a/external/curl prx/include/hash.h b/external/curl prx/include/hash.h new file mode 100644 index 0000000..90a25d1 --- /dev/null +++ b/external/curl prx/include/hash.h @@ -0,0 +1,100 @@ +#ifndef HEADER_CURL_HASH_H +#define HEADER_CURL_HASH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#include "llist.h" + +/* Hash function prototype */ +typedef size_t (*hash_function) (void *key, + size_t key_length, + size_t slots_num); + +/* + Comparator function prototype. Compares two keys. +*/ +typedef size_t (*comp_function) (void *key1, + size_t key1_len, + void *key2, + size_t key2_len); + +typedef void (*curl_hash_dtor)(void *); + +struct curl_hash { + struct curl_llist *table; + + /* Hash function to be used for this hash table */ + hash_function hash_func; + + /* Comparator function to compare keys */ + comp_function comp_func; + curl_hash_dtor dtor; + int slots; + size_t size; +}; + +struct curl_hash_element { + struct curl_llist_element list; + void *ptr; + size_t key_len; + char key[1]; /* allocated memory following the struct */ +}; + +struct curl_hash_iterator { + struct curl_hash *hash; + int slot_index; + struct curl_llist_element *current_element; +}; + +int Curl_hash_init(struct curl_hash *h, + int slots, + hash_function hfunc, + comp_function comparator, + curl_hash_dtor dtor); + +void *Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p); +int Curl_hash_delete(struct curl_hash *h, void *key, size_t key_len); +void *Curl_hash_pick(struct curl_hash *, void *key, size_t key_len); +void Curl_hash_apply(struct curl_hash *h, void *user, + void (*cb)(void *user, void *ptr)); +int Curl_hash_count(struct curl_hash *h); +void Curl_hash_destroy(struct curl_hash *h); +void Curl_hash_clean(struct curl_hash *h); +void Curl_hash_clean_with_criterium(struct curl_hash *h, void *user, + int (*comp)(void *, void *)); +size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num); +size_t Curl_str_key_compare(void *k1, size_t key1_len, void *k2, + size_t key2_len); +void Curl_hash_start_iterate(struct curl_hash *hash, + struct curl_hash_iterator *iter); +struct curl_hash_element * +Curl_hash_next_element(struct curl_hash_iterator *iter); + +void Curl_hash_print(struct curl_hash *h, + void (*func)(void *)); + + +#endif /* HEADER_CURL_HASH_H */ diff --git a/external/curl prx/include/hostcheck.h b/external/curl prx/include/hostcheck.h new file mode 100644 index 0000000..f562df9 --- /dev/null +++ b/external/curl prx/include/hostcheck.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_HOSTCHECK_H +#define HEADER_CURL_HOSTCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#define CURL_HOST_NOMATCH 0 +#define CURL_HOST_MATCH 1 +int Curl_cert_hostcheck(const char *match_pattern, const char *hostname); + +#endif /* HEADER_CURL_HOSTCHECK_H */ diff --git a/external/curl prx/include/hostip.h b/external/curl prx/include/hostip.h new file mode 100644 index 0000000..cd43882 --- /dev/null +++ b/external/curl prx/include/hostip.h @@ -0,0 +1,252 @@ +#ifndef HEADER_CURL_HOSTIP_H +#define HEADER_CURL_HOSTIP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "hash.h" +#include "curl_addrinfo.h" +#include "asyn.h" + +#ifdef HAVE_SETJMP_H +#include +#endif + +#ifdef NETWARE +#undef in_addr_t +#define in_addr_t unsigned long +#endif + +/* Allocate enough memory to hold the full name information structs and + * everything. OSF1 is known to require at least 8872 bytes. The buffer + * required for storing all possible aliases and IP numbers is according to + * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! + */ +#define CURL_HOSTENT_SIZE 9000 + +#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this + many seconds for a name resolve */ + +#define CURL_ASYNC_SUCCESS CURLE_OK + +struct addrinfo; +struct hostent; +struct Curl_easy; +struct connectdata; + +/* + * Curl_global_host_cache_init() initializes and sets up a global DNS cache. + * Global DNS cache is general badness. Do not use. This will be removed in + * a future version. Use the share interface instead! + * + * Returns a struct curl_hash pointer on success, NULL on failure. + */ +struct curl_hash *Curl_global_host_cache_init(void); +void Curl_global_host_cache_dtor(void); + +struct Curl_dns_entry { + Curl_addrinfo *addr; + /* timestamp == 0 -- CURLOPT_RESOLVE entry, doesn't timeout */ + time_t timestamp; + /* use-counter, use Curl_resolv_unlock to release reference */ + long inuse; +}; + +/* + * Curl_resolv() returns an entry with the info for the specified host + * and port. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +/* return codes */ +#define CURLRESOLV_TIMEDOUT -2 +#define CURLRESOLV_ERROR -1 +#define CURLRESOLV_RESOLVED 0 +#define CURLRESOLV_PENDING 1 +int Curl_resolv(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry); +int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, + int port, struct Curl_dns_entry **dnsentry, + time_t timeoutms); + +#ifdef CURLRES_IPV6 +/* + * Curl_ipv6works() returns TRUE if IPv6 seems to work. + */ +bool Curl_ipv6works(void); +#else +#define Curl_ipv6works() FALSE +#endif + +/* + * Curl_ipvalid() checks what CURL_IPRESOLVE_* requirements that might've + * been set and returns TRUE if they are OK. + */ +bool Curl_ipvalid(struct connectdata *conn); + + +/* + * Curl_getaddrinfo() is the generic low-level name resolve API within this + * source file. There are several versions of this function - for different + * name resolve layers (selected at build-time). They all take this same set + * of arguments + */ +Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, + const char *hostname, + int port, + int *waitp); + + +/* unlock a previously resolved dns entry */ +void Curl_resolv_unlock(struct Curl_easy *data, + struct Curl_dns_entry *dns); + +/* for debugging purposes only: */ +void Curl_scan_cache_used(void *user, void *ptr); + +/* init a new dns cache and return success */ +int Curl_mk_dnscache(struct curl_hash *hash); + +/* prune old entries from the DNS cache */ +void Curl_hostcache_prune(struct Curl_easy *data); + +/* Return # of addresses in a Curl_addrinfo struct */ +int Curl_num_addresses(const Curl_addrinfo *addr); + +#if defined(CURLDEBUG) && defined(HAVE_GETNAMEINFO) +int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa, + GETNAMEINFO_TYPE_ARG2 salen, + char *host, GETNAMEINFO_TYPE_ARG46 hostlen, + char *serv, GETNAMEINFO_TYPE_ARG46 servlen, + GETNAMEINFO_TYPE_ARG7 flags, + int line, const char *source); +#endif + +/* IPv4 threadsafe resolve function used for synch and asynch builds */ +Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); + +CURLcode Curl_once_resolved(struct connectdata *conn, bool *protocol_connect); + +/* + * Curl_addrinfo_callback() is used when we build with any asynch specialty. + * Handles end of async request processing. Inserts ai into hostcache when + * status is CURL_ASYNC_SUCCESS. Twiddles fields in conn to indicate async + * request completed whether successful or failed. + */ +CURLcode Curl_addrinfo_callback(struct connectdata *conn, + int status, + Curl_addrinfo *ai); + +/* + * Curl_printable_address() returns a printable version of the 1st address + * given in the 'ip' argument. The result will be stored in the buf that is + * bufsize bytes big. + */ +const char *Curl_printable_address(const Curl_addrinfo *ip, + char *buf, size_t bufsize); + +/* + * Curl_fetch_addr() fetches a 'Curl_dns_entry' already in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if not in the cache. + * + * The returned data *MUST* be "unlocked" with Curl_resolv_unlock() after + * use, or we'll leak memory! + */ +struct Curl_dns_entry * +Curl_fetch_addr(struct connectdata *conn, + const char *hostname, + int port); + +/* + * Curl_cache_addr() stores a 'Curl_addrinfo' struct in the DNS cache. + * + * Returns the Curl_dns_entry entry pointer or NULL if the storage failed. + */ +struct Curl_dns_entry * +Curl_cache_addr(struct Curl_easy *data, Curl_addrinfo *addr, + const char *hostname, int port); + +#ifndef INADDR_NONE +#define CURL_INADDR_NONE (in_addr_t) ~0 +#else +#define CURL_INADDR_NONE INADDR_NONE +#endif + +#ifdef HAVE_SIGSETJMP +/* Forward-declaration of variable defined in hostip.c. Beware this + * is a global and unique instance. This is used to store the return + * address that we can jump back to from inside a signal handler. + * This is not thread-safe stuff. + */ +extern sigjmp_buf curl_jmpenv; +#endif + +/* + * Function provided by the resolver backend to set DNS servers to use. + */ +CURLcode Curl_set_dns_servers(struct Curl_easy *data, char *servers); + +/* + * Function provided by the resolver backend to set + * outgoing interface to use for DNS requests + */ +CURLcode Curl_set_dns_interface(struct Curl_easy *data, + const char *interf); + +/* + * Function provided by the resolver backend to set + * local IPv4 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip4(struct Curl_easy *data, + const char *local_ip4); + +/* + * Function provided by the resolver backend to set + * local IPv6 address to use as source address for DNS requests + */ +CURLcode Curl_set_dns_local_ip6(struct Curl_easy *data, + const char *local_ip6); + +/* + * Clean off entries from the cache + */ +void Curl_hostcache_clean(struct Curl_easy *data, struct curl_hash *hash); + +/* + * Destroy the hostcache of this handle. + */ +void Curl_hostcache_destroy(struct Curl_easy *data); + +/* + * Populate the cache with specified entries from CURLOPT_RESOLVE. + */ +CURLcode Curl_loadhostpairs(struct Curl_easy *data); + +CURLcode Curl_resolv_check(struct connectdata *conn, + struct Curl_dns_entry **dns); +int Curl_resolv_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + +#endif /* HEADER_CURL_HOSTIP_H */ diff --git a/external/curl prx/include/http.h b/external/curl prx/include/http.h new file mode 100644 index 0000000..a59fe7a --- /dev/null +++ b/external/curl prx/include/http.h @@ -0,0 +1,260 @@ +#ifndef HEADER_CURL_HTTP_H +#define HEADER_CURL_HTTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef CURL_DISABLE_HTTP + +#ifdef USE_NGHTTP2 +#include +#endif + +extern const struct Curl_handler Curl_handler_http; + +#ifdef USE_SSL +extern const struct Curl_handler Curl_handler_https; +#endif + +/* Header specific functions */ +bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const char *content); /* content string to find */ + +char *Curl_copy_header_value(const char *header); + +char *Curl_checkProxyheaders(const struct connectdata *conn, + const char *thisheader); +/* ------------------------------------------------------------------------- */ +/* + * The add_buffer series of functions are used to build one large memory chunk + * from repeated function invokes. Used so that the entire HTTP request can + * be sent in one go. + */ +struct Curl_send_buffer { + char *buffer; + size_t size_max; + size_t size_used; +}; +typedef struct Curl_send_buffer Curl_send_buffer; + +Curl_send_buffer *Curl_add_buffer_init(void); +void Curl_add_buffer_free(Curl_send_buffer **inp); +CURLcode Curl_add_bufferf(Curl_send_buffer **inp, const char *fmt, ...) + WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer(Curl_send_buffer **inp, const void *inptr, + size_t size) WARN_UNUSED_RESULT; +CURLcode Curl_add_buffer_send(Curl_send_buffer **inp, + struct connectdata *conn, + curl_off_t *bytes_written, + size_t included_body_bytes, + int socketindex); + +CURLcode Curl_add_timecondition(struct Curl_easy *data, + Curl_send_buffer *buf); +CURLcode Curl_add_custom_headers(struct connectdata *conn, + bool is_connect, + Curl_send_buffer *req_buffer); +CURLcode Curl_http_compile_trailers(struct curl_slist *trailers, + Curl_send_buffer *buffer, + struct Curl_easy *handle); + +/* protocol-specific functions set up to be called by the main engine */ +CURLcode Curl_http(struct connectdata *conn, bool *done); +CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); +CURLcode Curl_http_connect(struct connectdata *conn, bool *done); +CURLcode Curl_http_setup_conn(struct connectdata *conn); + +/* The following functions are defined in http_chunks.c */ +void Curl_httpchunk_init(struct connectdata *conn); +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, + ssize_t length, ssize_t *wrote); + +/* These functions are in http.c */ +void Curl_http_auth_stage(struct Curl_easy *data, int stage); +CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, + const char *auth); +CURLcode Curl_http_auth_act(struct connectdata *conn); +CURLcode Curl_http_perhapsrewind(struct connectdata *conn); + +/* If only the PICKNONE bit is set, there has been a round-trip and we + selected to use no auth at all. Ie, we actively select no auth, as opposed + to not having one selected. The other CURLAUTH_* defines are present in the + public curl/curl.h header. */ +#define CURLAUTH_PICKNONE (1<<30) /* don't use auth */ + +/* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST + data get included in the initial data chunk sent to the server. If the + data is larger than this, it will automatically get split up in multiple + system calls. + + This value used to be fairly big (100K), but we must take into account that + if the server rejects the POST due for authentication reasons, this data + will always be unconditionally sent and thus it may not be larger than can + always be afforded to send twice. + + It must not be greater than 64K to work on VMS. +*/ +#ifndef MAX_INITIAL_POST_SIZE +#define MAX_INITIAL_POST_SIZE (64*1024) +#endif + +/* EXPECT_100_THRESHOLD is the request body size limit for when libcurl will + * automatically add an "Expect: 100-continue" header in HTTP requests. When + * the size is unknown, it will always add it. + * + */ +#ifndef EXPECT_100_THRESHOLD +#define EXPECT_100_THRESHOLD 1024 +#endif + +#endif /* CURL_DISABLE_HTTP */ + +/**************************************************************************** + * HTTP unique setup + ***************************************************************************/ +struct HTTP { + curl_mimepart *sendit; + curl_off_t postsize; /* off_t to handle large file sizes */ + const char *postdata; + + const char *p_pragma; /* Pragma: string */ + const char *p_accept; /* Accept: string */ + + /* For FORM posting */ + curl_mimepart form; + + struct back { + curl_read_callback fread_func; /* backup storage for fread pointer */ + void *fread_in; /* backup storage for fread_in pointer */ + const char *postdata; + curl_off_t postsize; + } backup; + + enum { + HTTPSEND_NADA, /* init */ + HTTPSEND_REQUEST, /* sending a request */ + HTTPSEND_BODY, /* sending body */ + HTTPSEND_LAST /* never use this */ + } sending; + +#ifndef CURL_DISABLE_HTTP + Curl_send_buffer *send_buffer; /* used if the request couldn't be sent in + one chunk, points to an allocated + send_buffer struct */ +#endif +#ifdef USE_NGHTTP2 + /*********** for HTTP/2 we store stream-local data here *************/ + int32_t stream_id; /* stream we are interested in */ + + bool bodystarted; + /* We store non-final and final response headers here, per-stream */ + Curl_send_buffer *header_recvbuf; + size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into + upper layer */ + Curl_send_buffer *trailer_recvbuf; + int status_code; /* HTTP status code */ + const uint8_t *pausedata; /* pointer to data received in on_data_chunk */ + size_t pauselen; /* the number of bytes left in data */ + bool closed; /* TRUE on HTTP2 stream close */ + bool close_handled; /* TRUE if stream closure is handled by libcurl */ + char *mem; /* points to a buffer in memory to store received data */ + size_t len; /* size of the buffer 'mem' points to */ + size_t memlen; /* size of data copied to mem */ + + const uint8_t *upload_mem; /* points to a buffer to read from */ + size_t upload_len; /* size of the buffer 'upload_mem' points to */ + curl_off_t upload_left; /* number of bytes left to upload */ + + char **push_headers; /* allocated array */ + size_t push_headers_used; /* number of entries filled in */ + size_t push_headers_alloc; /* number of entries allocated */ +#endif +}; + +#ifdef USE_NGHTTP2 +/* h2 settings for this connection */ +struct h2settings { + uint32_t max_concurrent_streams; + bool enable_push; +}; +#endif + +struct http_conn { +#ifdef USE_NGHTTP2 +#define H2_BINSETTINGS_LEN 80 + nghttp2_session *h2; + uint8_t binsettings[H2_BINSETTINGS_LEN]; + size_t binlen; /* length of the binsettings data */ + Curl_send *send_underlying; /* underlying send Curl_send callback */ + Curl_recv *recv_underlying; /* underlying recv Curl_recv callback */ + char *inbuf; /* buffer to receive data from underlying socket */ + size_t inbuflen; /* number of bytes filled in inbuf */ + size_t nread_inbuf; /* number of bytes read from in inbuf */ + /* We need separate buffer for transmission and reception because we + may call nghttp2_session_send() after the + nghttp2_session_mem_recv() but mem buffer is still not full. In + this case, we wrongly sends the content of mem buffer if we share + them for both cases. */ + int32_t pause_stream_id; /* stream ID which paused + nghttp2_session_mem_recv */ + size_t drain_total; /* sum of all stream's UrlState.drain */ + + /* this is a hash of all individual streams (Curl_easy structs) */ + struct h2settings settings; + + /* list of settings that will be sent */ + nghttp2_settings_entry local_settings[3]; + size_t local_settings_num; + uint32_t error_code; /* HTTP/2 error code */ +#else + int unused; /* prevent a compiler warning */ +#endif +}; + +CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + struct connectdata *conn, + ssize_t *nread, + bool *stop_reading); + +/** + * Curl_http_output_auth() setups the authentication headers for the + * host/proxy and the correct authentication + * method. conn->data->state.authdone is set to TRUE when authentication is + * done. + * + * @param conn all information about the current connection + * @param request pointer to the request keyword + * @param path pointer to the requested path + * @param proxytunnel boolean if this is the request setting up a "proxy + * tunnel" + * + * @returns CURLcode + */ +CURLcode +Curl_http_output_auth(struct connectdata *conn, + const char *request, + const char *path, + bool proxytunnel); /* TRUE if this is the request setting + up the proxy tunnel */ + +#endif /* HEADER_CURL_HTTP_H */ diff --git a/external/curl prx/include/http2.h b/external/curl prx/include/http2.h new file mode 100644 index 0000000..db6217b --- /dev/null +++ b/external/curl prx/include/http2.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_HTTP2_H +#define HEADER_CURL_HTTP2_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NGHTTP2 +#include "http.h" + +/* value for MAX_CONCURRENT_STREAMS we use until we get an updated setting + from the peer */ +#define DEFAULT_MAX_CONCURRENT_STREAMS 13 + +/* + * Store nghttp2 version info in this buffer, Prefix with a space. Return + * total length written. + */ +int Curl_http2_ver(char *p, size_t len); + +const char *Curl_http2_strerror(uint32_t err); + +CURLcode Curl_http2_init(struct connectdata *conn); +void Curl_http2_init_state(struct UrlState *state); +void Curl_http2_init_userset(struct UserDefined *set); +CURLcode Curl_http2_send_request(struct connectdata *conn); +CURLcode Curl_http2_request_upgrade(Curl_send_buffer *req, + struct connectdata *conn); +CURLcode Curl_http2_setup(struct connectdata *conn); +CURLcode Curl_http2_switched(struct connectdata *conn, + const char *data, size_t nread); +/* called from Curl_http_setup_conn */ +void Curl_http2_setup_conn(struct connectdata *conn); +void Curl_http2_setup_req(struct Curl_easy *data); +void Curl_http2_done(struct connectdata *conn, bool premature); +CURLcode Curl_http2_done_sending(struct connectdata *conn); +CURLcode Curl_http2_add_child(struct Curl_easy *parent, + struct Curl_easy *child, + bool exclusive); +void Curl_http2_remove_child(struct Curl_easy *parent, + struct Curl_easy *child); +void Curl_http2_cleanup_dependencies(struct Curl_easy *data); + +/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ +bool Curl_h2_http_1_1_error(struct connectdata *conn); +#else /* USE_NGHTTP2 */ +#define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup(x) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_switched(x,y,z) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_setup_conn(x) Curl_nop_stmt +#define Curl_http2_setup_req(x) +#define Curl_http2_init_state(x) +#define Curl_http2_init_userset(x) +#define Curl_http2_done(x,y) +#define Curl_http2_done_sending(x) +#define Curl_http2_add_child(x, y, z) +#define Curl_http2_remove_child(x, y) +#define Curl_http2_cleanup_dependencies(x) +#define Curl_h2_http_1_1_error(x) 0 +#endif + +#endif /* HEADER_CURL_HTTP2_H */ diff --git a/external/curl prx/include/http_chunks.h b/external/curl prx/include/http_chunks.h new file mode 100644 index 0000000..b969c55 --- /dev/null +++ b/external/curl prx/include/http_chunks.h @@ -0,0 +1,90 @@ +#ifndef HEADER_CURL_HTTP_CHUNKS_H +#define HEADER_CURL_HTTP_CHUNKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +/* + * The longest possible hexadecimal number we support in a chunked transfer. + * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() + * to convert it, we "only" support 2^32 bytes chunk data. + */ +#define MAXNUM_SIZE 16 + +typedef enum { + /* await and buffer all hexadecimal digits until we get one that isn't a + hexadecimal digit. When done, we go CHUNK_LF */ + CHUNK_HEX, + + /* wait for LF, ignore all else */ + CHUNK_LF, + + /* We eat the amount of data specified. When done, we move on to the + POST_CR state. */ + CHUNK_DATA, + + /* POSTLF should get a CR and then a LF and nothing else, then move back to + HEX as the CRLF combination marks the end of a chunk. A missing CR is no + big deal. */ + CHUNK_POSTLF, + + /* Used to mark that we're out of the game. NOTE: that there's a 'dataleft' + field in the struct that will tell how many bytes that were not passed to + the client in the end of the last buffer! */ + CHUNK_STOP, + + /* At this point optional trailer headers can be found, unless the next line + is CRLF */ + CHUNK_TRAILER, + + /* A trailer CR has been found - next state is CHUNK_TRAILER_POSTCR. + Next char must be a LF */ + CHUNK_TRAILER_CR, + + /* A trailer LF must be found now, otherwise CHUNKE_BAD_CHUNK will be + signalled If this is an empty trailer CHUNKE_STOP will be signalled. + Otherwise the trailer will be broadcasted via Curl_client_write() and the + next state will be CHUNK_TRAILER */ + CHUNK_TRAILER_POSTCR +} ChunkyState; + +typedef enum { + CHUNKE_STOP = -1, + CHUNKE_OK = 0, + CHUNKE_TOO_LONG_HEX = 1, + CHUNKE_ILLEGAL_HEX, + CHUNKE_BAD_CHUNK, + CHUNKE_WRITE_ERROR, + CHUNKE_BAD_ENCODING, + CHUNKE_OUT_OF_MEMORY, + CHUNKE_LAST +} CHUNKcode; + +const char *Curl_chunked_strerror(CHUNKcode code); + +struct Curl_chunker { + char hexbuffer[ MAXNUM_SIZE + 1]; + int hexindex; + ChunkyState state; + curl_off_t datasize; + size_t dataleft; /* untouched data amount at the end of the last buffer */ +}; + +#endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/external/curl prx/include/http_digest.h b/external/curl prx/include/http_digest.h new file mode 100644 index 0000000..fd225c7 --- /dev/null +++ b/external/curl prx/include/http_digest.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_HTTP_DIGEST_H +#define HEADER_CURL_HTTP_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* this is for digest header input */ +CURLcode Curl_input_digest(struct connectdata *conn, + bool proxy, const char *header); + +/* this is for creating digest header output */ +CURLcode Curl_output_digest(struct connectdata *conn, + bool proxy, + const unsigned char *request, + const unsigned char *uripath); + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH) +void Curl_digest_cleanup(struct Curl_easy *data); +#else +#define Curl_digest_cleanup(x) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_HTTP_DIGEST_H */ diff --git a/external/curl prx/include/http_negotiate.h b/external/curl prx/include/http_negotiate.h new file mode 100644 index 0000000..d4a7f09 --- /dev/null +++ b/external/curl prx/include/http_negotiate.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_HTTP_NEGOTIATE_H +#define HEADER_CURL_HTTP_NEGOTIATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_SPNEGO + +/* this is for Negotiate header input */ +CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating Negotiate header output */ +CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy); + +void Curl_cleanup_negotiate(struct connectdata *conn); + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_HTTP_NEGOTIATE_H */ diff --git a/external/curl prx/include/http_ntlm.h b/external/curl prx/include/http_ntlm.h new file mode 100644 index 0000000..d186bbe --- /dev/null +++ b/external/curl prx/include/http_ntlm.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CURL_NTLM_H +#define HEADER_CURL_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) + +/* this is for ntlm header input */ +CURLcode Curl_input_ntlm(struct connectdata *conn, bool proxy, + const char *header); + +/* this is for creating ntlm header output */ +CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy); + +void Curl_http_ntlm_cleanup(struct connectdata *conn); + +#endif /* !CURL_DISABLE_HTTP && USE_NTLM */ + +#endif /* HEADER_CURL_NTLM_H */ diff --git a/external/curl prx/include/http_proxy.h b/external/curl prx/include/http_proxy.h new file mode 100644 index 0000000..e19fa85 --- /dev/null +++ b/external/curl prx/include/http_proxy.h @@ -0,0 +1,51 @@ +#ifndef HEADER_CURL_HTTP_PROXY_H +#define HEADER_CURL_HTTP_PROXY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include "urldata.h" + +#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) +/* ftp can use this as well */ +CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, + const char *hostname, int remote_port); + +/* Default proxy timeout in milliseconds */ +#define PROXY_TIMEOUT (3600*1000) + +CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex); + +bool Curl_connect_complete(struct connectdata *conn); +bool Curl_connect_ongoing(struct connectdata *conn); + +#else +#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN +#define Curl_proxy_connect(x,y) CURLE_OK +#define Curl_connect_complete(x) CURLE_OK +#define Curl_connect_ongoing(x) FALSE +#endif + +void Curl_connect_free(struct Curl_easy *data); + +#endif /* HEADER_CURL_HTTP_PROXY_H */ diff --git a/external/curl prx/include/if2ip.h b/external/curl prx/include/if2ip.h new file mode 100644 index 0000000..a11b1c2 --- /dev/null +++ b/external/curl prx/include/if2ip.h @@ -0,0 +1,82 @@ +#ifndef HEADER_CURL_IF2IP_H +#define HEADER_CURL_IF2IP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* IPv6 address scopes. */ +#define IPV6_SCOPE_GLOBAL 0 /* Global scope. */ +#define IPV6_SCOPE_LINKLOCAL 1 /* Link-local scope. */ +#define IPV6_SCOPE_SITELOCAL 2 /* Site-local scope (deprecated). */ +#define IPV6_SCOPE_UNIQUELOCAL 3 /* Unique local */ +#define IPV6_SCOPE_NODELOCAL 4 /* Loopback. */ + +unsigned int Curl_ipv6_scope(const struct sockaddr *sa); + +typedef enum { + IF2IP_NOT_FOUND = 0, /* Interface not found */ + IF2IP_AF_NOT_SUPPORTED = 1, /* Int. exists but has no address for this af */ + IF2IP_FOUND = 2 /* The address has been stored in "buf" */ +} if2ip_result_t; + +if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope, + unsigned int remote_scope_id, const char *interf, + char *buf, int buf_size); + +#ifdef __INTERIX + +/* Nedelcho Stanev's work-around for SFU 3.0 */ +struct ifreq { +#define IFNAMSIZ 16 +#define IFHWADDRLEN 6 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + } ifr_ifru; +}; + +/* This define was added by Daniel to avoid an extra #ifdef INTERIX in the + C code. */ + +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ + +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ + +#endif /* __INTERIX */ + +#endif /* HEADER_CURL_IF2IP_H */ diff --git a/external/curl prx/include/imap.h b/external/curl prx/include/imap.h new file mode 100644 index 0000000..0efcfd2 --- /dev/null +++ b/external/curl prx/include/imap.h @@ -0,0 +1,98 @@ +#ifndef HEADER_CURL_IMAP_H +#define HEADER_CURL_IMAP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * IMAP unique setup + ***************************************************************************/ +typedef enum { + IMAP_STOP, /* do nothing state, stops the state machine */ + IMAP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + IMAP_CAPABILITY, + IMAP_STARTTLS, + IMAP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + IMAP_AUTHENTICATE, + IMAP_LOGIN, + IMAP_LIST, + IMAP_SELECT, + IMAP_FETCH, + IMAP_FETCH_FINAL, + IMAP_APPEND, + IMAP_APPEND_FINAL, + IMAP_SEARCH, + IMAP_LOGOUT, + IMAP_LAST /* never used */ +} imapstate; + +/* This IMAP struct is used in the Curl_easy. All IMAP data that is + connection-oriented must be in imap_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct IMAP { + curl_pp_transfer transfer; + char *mailbox; /* Mailbox to select */ + char *uidvalidity; /* UIDVALIDITY to check in select */ + char *uid; /* Message UID to fetch */ + char *mindex; /* Index in mail box of mail to fetch */ + char *section; /* Message SECTION to fetch */ + char *partial; /* Message PARTIAL to fetch */ + char *query; /* Query to search for */ + char *custom; /* Custom request */ + char *custom_params; /* Parameters for the custom request */ +}; + +/* imap_conn is used for struct connection-oriented data in the connectdata + struct */ +struct imap_conn { + struct pingpong pp; + imapstate state; /* Always use imap.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + bool preauth; /* Is this connection PREAUTH? */ + struct SASL sasl; /* SASL-related parameters */ + unsigned int preftype; /* Preferred authentication type */ + int cmdid; /* Last used command ID */ + char resptag[5]; /* Response tag to wait for */ + bool tls_supported; /* StartTLS capability supported by server */ + bool login_disabled; /* LOGIN command disabled by server */ + bool ir_supported; /* Initial response supported by server */ + char *mailbox; /* The last selected mailbox */ + char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ +}; + +extern const struct Curl_handler Curl_handler_imap; +extern const struct Curl_handler Curl_handler_imaps; + +/* Authentication type flags */ +#define IMAP_TYPE_CLEARTEXT (1 << 0) +#define IMAP_TYPE_SASL (1 << 1) + +/* Authentication type values */ +#define IMAP_TYPE_NONE 0 +#define IMAP_TYPE_ANY ~0U + +#endif /* HEADER_CURL_IMAP_H */ diff --git a/external/curl prx/include/inet_ntop.h b/external/curl prx/include/inet_ntop.h new file mode 100644 index 0000000..d150bb6 --- /dev/null +++ b/external/curl prx/include/inet_ntop.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_INET_NTOP_H +#define HEADER_CURL_INET_NTOP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +char *Curl_inet_ntop(int af, const void *addr, char *buf, size_t size); + +#ifdef HAVE_INET_NTOP +#ifdef HAVE_ARPA_INET_H +#include +#endif +#define Curl_inet_ntop(af,addr,buf,size) \ + inet_ntop(af, addr, buf, (curl_socklen_t)size) +#endif + +#endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/external/curl prx/include/inet_pton.h b/external/curl prx/include/inet_pton.h new file mode 100644 index 0000000..0209b9b --- /dev/null +++ b/external/curl prx/include/inet_pton.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_INET_PTON_H +#define HEADER_CURL_INET_PTON_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +int Curl_inet_pton(int, const char *, void *); + +#ifdef HAVE_INET_PTON +#ifdef HAVE_ARPA_INET_H +#include +#elif defined(HAVE_WS2TCPIP_H) +/* inet_pton() exists in Vista or later */ +#include +#endif +#define Curl_inet_pton(x,y,z) inet_pton(x,y,z) +#endif + +#endif /* HEADER_CURL_INET_PTON_H */ diff --git a/external/curl prx/include/llist.h b/external/curl prx/include/llist.h new file mode 100644 index 0000000..b9d4c89 --- /dev/null +++ b/external/curl prx/include/llist.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_LLIST_H +#define HEADER_CURL_LLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include + +typedef void (*curl_llist_dtor)(void *, void *); + +struct curl_llist_element { + void *ptr; + struct curl_llist_element *prev; + struct curl_llist_element *next; +}; + +struct curl_llist { + struct curl_llist_element *head; + struct curl_llist_element *tail; + curl_llist_dtor dtor; + size_t size; +}; + +void Curl_llist_init(struct curl_llist *, curl_llist_dtor); +void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *, + const void *, struct curl_llist_element *node); +void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *, + void *); +size_t Curl_llist_count(struct curl_llist *); +void Curl_llist_destroy(struct curl_llist *, void *); +void Curl_llist_move(struct curl_llist *, struct curl_llist_element *, + struct curl_llist *, struct curl_llist_element *); + +#endif /* HEADER_CURL_LLIST_H */ diff --git a/external/curl prx/include/mbedtls.h b/external/curl prx/include/mbedtls.h new file mode 100644 index 0000000..4a93860 --- /dev/null +++ b/external/curl prx/include/mbedtls.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MBEDTLS_H +#define HEADER_CURL_MBEDTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +extern const struct Curl_ssl Curl_ssl_mbedtls; + +#endif /* USE_MBEDTLS */ +#endif /* HEADER_CURL_MBEDTLS_H */ diff --git a/external/curl prx/include/memdebug.h b/external/curl prx/include/memdebug.h new file mode 100644 index 0000000..5236f60 --- /dev/null +++ b/external/curl prx/include/memdebug.h @@ -0,0 +1,174 @@ +#ifndef HEADER_CURL_MEMDEBUG_H +#define HEADER_CURL_MEMDEBUG_H +#ifdef CURLDEBUG +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * CAUTION: this header is designed to work when included by the app-side + * as well as the library. Do not mix with library internals! + */ + +#define CURL_MT_LOGFNAME_BUFSIZE 512 + +extern FILE *curl_dbg_logfile; + +/* memory functions */ +CURL_EXTERN void *curl_dbg_malloc(size_t size, int line, const char *source); +CURL_EXTERN void *curl_dbg_calloc(size_t elements, size_t size, int line, + const char *source); +CURL_EXTERN void *curl_dbg_realloc(void *ptr, size_t size, int line, + const char *source); +CURL_EXTERN void curl_dbg_free(void *ptr, int line, const char *source); +CURL_EXTERN char *curl_dbg_strdup(const char *str, int line, const char *src); +#if defined(WIN32) && defined(UNICODE) +CURL_EXTERN wchar_t *curl_dbg_wcsdup(const wchar_t *str, int line, + const char *source); +#endif + +CURL_EXTERN void curl_dbg_memdebug(const char *logname); +CURL_EXTERN void curl_dbg_memlimit(long limit); +CURL_EXTERN void curl_dbg_log(const char *format, ...); + +/* file descriptor manipulators */ +CURL_EXTERN curl_socket_t curl_dbg_socket(int domain, int type, int protocol, + int line, const char *source); +CURL_EXTERN void curl_dbg_mark_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN int curl_dbg_sclose(curl_socket_t sockfd, + int line, const char *source); +CURL_EXTERN curl_socket_t curl_dbg_accept(curl_socket_t s, void *a, void *alen, + int line, const char *source); +#ifdef HAVE_SOCKETPAIR +CURL_EXTERN int curl_dbg_socketpair(int domain, int type, int protocol, + curl_socket_t socket_vector[2], + int line, const char *source); +#endif + +/* send/receive sockets */ +CURL_EXTERN SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, + SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf, + SEND_TYPE_ARG3 len, + SEND_TYPE_ARG4 flags, int line, + const char *source); +CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, + RECV_TYPE_ARG2 buf, + RECV_TYPE_ARG3 len, + RECV_TYPE_ARG4 flags, int line, + const char *source); + +/* FILE functions */ +CURL_EXTERN FILE *curl_dbg_fopen(const char *file, const char *mode, int line, + const char *source); +CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); + +#ifndef MEMDEBUG_NODEFINES + +/* Set this symbol on the command-line, recompile all lib-sources */ +#undef strdup +#define strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define calloc(nbelem,size) curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define realloc(ptr,size) curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) +#define send(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) +#define recv(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) + +#ifdef WIN32 +# ifdef UNICODE +# undef wcsdup +# define wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _wcsdup +# define _wcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +# else +# undef _tcsdup +# define _tcsdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +# endif +#endif + +#undef socket +#define socket(domain,type,protocol)\ + curl_dbg_socket(domain, type, protocol, __LINE__, __FILE__) +#undef accept /* for those with accept as a macro */ +#define accept(sock,addr,len)\ + curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) +#ifdef HAVE_SOCKETPAIR +#define socketpair(domain,type,protocol,socket_vector)\ + curl_dbg_socketpair(domain, type, protocol, socket_vector, __LINE__, __FILE__) +#endif + +#ifdef HAVE_GETADDRINFO +#if defined(getaddrinfo) && defined(__osf__) +/* OSF/1 and Tru64 have getaddrinfo as a define already, so we cannot define + our macro as for other platforms. Instead, we redefine the new name they + define getaddrinfo to become! */ +#define ogetaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#else +#undef getaddrinfo +#define getaddrinfo(host,serv,hint,res) \ + curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) +#endif +#endif /* HAVE_GETADDRINFO */ + +#ifdef HAVE_FREEADDRINFO +#undef freeaddrinfo +#define freeaddrinfo(data) \ + curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) +#endif /* HAVE_FREEADDRINFO */ + +/* sclose is probably already defined, redefine it! */ +#undef sclose +#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) + +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) + +#undef fopen +#define fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) +#undef fdopen +#define fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) +#define fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) + +#endif /* MEMDEBUG_NODEFINES */ + +#endif /* CURLDEBUG */ + +/* +** Following section applies even when CURLDEBUG is not defined. +*/ + +#ifndef fake_sclose +#define fake_sclose(x) Curl_nop_stmt +#endif + +/* + * Curl_safefree defined as a macro to allow MemoryTracking feature + * to log free() calls at same location where Curl_safefree is used. + * This macro also assigns NULL to given pointer when free'd. + */ + +#define Curl_safefree(ptr) \ + do { free((ptr)); (ptr) = NULL;} WHILE_FALSE + +#endif /* HEADER_CURL_MEMDEBUG_H */ diff --git a/external/curl prx/include/mesalink.h b/external/curl prx/include/mesalink.h new file mode 100644 index 0000000..54cb94a --- /dev/null +++ b/external/curl prx/include/mesalink.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MESALINK_H +#define HEADER_CURL_MESALINK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017-2018, Yiming Jing, + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MESALINK + +extern const struct Curl_ssl Curl_ssl_mesalink; + +#endif /* USE_MESALINK */ +#endif /* HEADER_CURL_MESALINK_H */ diff --git a/external/curl prx/include/mime.h b/external/curl prx/include/mime.h new file mode 100644 index 0000000..0721c8c --- /dev/null +++ b/external/curl prx/include/mime.h @@ -0,0 +1,146 @@ +#ifndef HEADER_CURL_MIME_H +#define HEADER_CURL_MIME_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define MIME_RAND_BOUNDARY_CHARS 16 /* Nb. of random boundary chars. */ +#define MAX_ENCODED_LINE_LENGTH 76 /* Maximum encoded line length. */ +#define ENCODING_BUFFER_SIZE 256 /* Encoding temp buffers size. */ + +/* Part flags. */ +#define MIME_USERHEADERS_OWNER (1 << 0) +#define MIME_BODY_ONLY (1 << 1) + +#define FILE_CONTENTTYPE_DEFAULT "application/octet-stream" +#define MULTIPART_CONTENTTYPE_DEFAULT "multipart/mixed" +#define DISPOSITION_DEFAULT "attachment" + +/* Part source kinds. */ +enum mimekind { + MIMEKIND_NONE = 0, /* Part not set. */ + MIMEKIND_DATA, /* Allocated mime data. */ + MIMEKIND_FILE, /* Data from file. */ + MIMEKIND_CALLBACK, /* Data from `read' callback. */ + MIMEKIND_MULTIPART, /* Data is a mime subpart. */ + MIMEKIND_LAST +}; + +/* Readback state tokens. */ +enum mimestate { + MIMESTATE_BEGIN, /* Readback has not yet started. */ + MIMESTATE_CURLHEADERS, /* In curl-generated headers. */ + MIMESTATE_USERHEADERS, /* In caller's supplied headers. */ + MIMESTATE_EOH, /* End of headers. */ + MIMESTATE_BODY, /* Placeholder. */ + MIMESTATE_BOUNDARY1, /* In boundary prefix. */ + MIMESTATE_BOUNDARY2, /* In boundary. */ + MIMESTATE_CONTENT, /* In content. */ + MIMESTATE_END, /* End of part reached. */ + MIMESTATE_LAST +}; + +/* Mime headers strategies. */ +enum mimestrategy { + MIMESTRATEGY_MAIL, /* Mime mail. */ + MIMESTRATEGY_FORM, /* HTTP post form. */ + MIMESTRATEGY_LAST +}; + +/* Content transfer encoder. */ +typedef struct { + const char * name; /* Encoding name. */ + size_t (*encodefunc)(char *buffer, size_t size, bool ateof, + curl_mimepart *part); /* Encoded read. */ + curl_off_t (*sizefunc)(curl_mimepart *part); /* Encoded size. */ +} mime_encoder; + +/* Content transfer encoder state. */ +typedef struct { + size_t pos; /* Position on output line. */ + size_t bufbeg; /* Next data index in input buffer. */ + size_t bufend; /* First unused byte index in input buffer. */ + char buf[ENCODING_BUFFER_SIZE]; /* Input buffer. */ +} mime_encoder_state; + +/* Mime readback state. */ +typedef struct { + enum mimestate state; /* Current state token. */ + void *ptr; /* State-dependent pointer. */ + size_t offset; /* State-dependent offset. */ +} mime_state; + +/* minimum buffer size for the boundary string */ +#define MIME_BOUNDARY_LEN (24 + MIME_RAND_BOUNDARY_CHARS + 1) + +/* A mime multipart. */ +struct curl_mime_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mimepart *parent; /* Parent part. */ + curl_mimepart *firstpart; /* First part. */ + curl_mimepart *lastpart; /* Last part. */ + char boundary[MIME_BOUNDARY_LEN]; /* The part boundary. */ + mime_state state; /* Current readback state. */ +}; + +/* A mime part. */ +struct curl_mimepart_s { + struct Curl_easy *easy; /* The associated easy handle. */ + curl_mime *parent; /* Parent mime structure. */ + curl_mimepart *nextpart; /* Forward linked list. */ + enum mimekind kind; /* The part kind. */ + char *data; /* Memory data or file name. */ + curl_read_callback readfunc; /* Read function. */ + curl_seek_callback seekfunc; /* Seek function. */ + curl_free_callback freefunc; /* Argument free function. */ + void *arg; /* Argument to callback functions. */ + FILE *fp; /* File pointer. */ + struct curl_slist *curlheaders; /* Part headers. */ + struct curl_slist *userheaders; /* Part headers. */ + char *mimetype; /* Part mime type. */ + char *filename; /* Remote file name. */ + char *name; /* Data name. */ + curl_off_t datasize; /* Expected data size. */ + unsigned int flags; /* Flags. */ + mime_state state; /* Current readback state. */ + const mime_encoder *encoder; /* Content data encoder. */ + mime_encoder_state encstate; /* Data encoder state. */ +}; + + +/* Prototypes. */ +void Curl_mime_initpart(curl_mimepart *part, struct Curl_easy *easy); +void Curl_mime_cleanpart(curl_mimepart *part); +CURLcode Curl_mime_duppart(curl_mimepart *dst, const curl_mimepart *src); +CURLcode Curl_mime_set_subparts(curl_mimepart *part, + curl_mime *subparts, int take_ownership); +CURLcode Curl_mime_prepare_headers(curl_mimepart *part, + const char *contenttype, + const char *disposition, + enum mimestrategy strategy); +curl_off_t Curl_mime_size(curl_mimepart *part); +size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, + void *instream); +CURLcode Curl_mime_rewind(curl_mimepart *part); +CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...); +const char *Curl_mime_contenttype(const char *filename); + +#endif /* HEADER_CURL_MIME_H */ diff --git a/external/curl prx/include/multihandle.h b/external/curl prx/include/multihandle.h new file mode 100644 index 0000000..ea2bf35 --- /dev/null +++ b/external/curl prx/include/multihandle.h @@ -0,0 +1,158 @@ +#ifndef HEADER_CURL_MULTIHANDLE_H +#define HEADER_CURL_MULTIHANDLE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "conncache.h" +#include "psl.h" + +struct Curl_message { + struct curl_llist_element list; + /* the 'CURLMsg' is the part that is visible to the external user */ + struct CURLMsg extmsg; +}; + +/* NOTE: if you add a state here, add the name to the statename[] array as + well! +*/ +typedef enum { + CURLM_STATE_INIT, /* 0 - start in this state */ + CURLM_STATE_CONNECT_PEND, /* 1 - no connections, waiting for one */ + CURLM_STATE_CONNECT, /* 2 - resolve/connect has been sent off */ + CURLM_STATE_WAITRESOLVE, /* 3 - awaiting the resolve to finalize */ + CURLM_STATE_WAITCONNECT, /* 4 - awaiting the TCP connect to finalize */ + CURLM_STATE_WAITPROXYCONNECT, /* 5 - awaiting HTTPS proxy SSL initialization + to complete and/or proxy CONNECT to + finalize */ + CURLM_STATE_SENDPROTOCONNECT, /* 6 - initiate protocol connect procedure */ + CURLM_STATE_PROTOCONNECT, /* 7 - completing the protocol-specific connect + phase */ + CURLM_STATE_WAITDO, /* 8 - wait for our turn to send the request */ + CURLM_STATE_DO, /* 9 - start send off the request (part 1) */ + CURLM_STATE_DOING, /* 10 - sending off the request (part 1) */ + CURLM_STATE_DO_MORE, /* 11 - send off the request (part 2) */ + CURLM_STATE_DO_DONE, /* 12 - done sending off request */ + CURLM_STATE_WAITPERFORM, /* 13 - wait for our turn to read the response */ + CURLM_STATE_PERFORM, /* 14 - transfer data */ + CURLM_STATE_TOOFAST, /* 15 - wait because limit-rate exceeded */ + CURLM_STATE_DONE, /* 16 - post data transfer operation */ + CURLM_STATE_COMPLETED, /* 17 - operation complete */ + CURLM_STATE_MSGSENT, /* 18 - the operation complete message is sent */ + CURLM_STATE_LAST /* 19 - not a true state, never use this */ +} CURLMstate; + +/* we support N sockets per easy handle. Set the corresponding bit to what + action we should wait for */ +#define MAX_SOCKSPEREASYHANDLE 5 +#define GETSOCK_READABLE (0x00ff) +#define GETSOCK_WRITABLE (0xff00) + +#define CURLPIPE_ANY (CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX) + +/* This is the struct known as CURLM on the outside */ +struct Curl_multi { + /* First a simple identifier to easier detect if a user mix up + this multi handle with an easy handle. Set this to CURL_MULTI_HANDLE. */ + long type; + + /* We have a doubly-linked circular list with easy handles */ + struct Curl_easy *easyp; + struct Curl_easy *easylp; /* last node */ + + int num_easy; /* amount of entries in the linked list above. */ + int num_alive; /* amount of easy handles that are added but have not yet + reached COMPLETE state */ + + struct curl_llist msglist; /* a list of messages from completed transfers */ + + struct curl_llist pending; /* Curl_easys that are in the + CURLM_STATE_CONNECT_PEND state */ + + /* callback function and user data pointer for the *socket() API */ + curl_socket_callback socket_cb; + void *socket_userp; + + /* callback function and user data pointer for server push */ + curl_push_callback push_cb; + void *push_userp; + + /* Hostname cache */ + struct curl_hash hostcache; + +#ifdef USE_LIBPSL + /* PSL cache. */ + struct PslCache psl; +#endif + + /* timetree points to the splay-tree of time nodes to figure out expire + times of all currently set timers */ + struct Curl_tree *timetree; + + /* 'sockhash' is the lookup hash for socket descriptor => easy handles (note + the pluralis form, there can be more than one easy handle waiting on the + same actual socket) */ + struct curl_hash sockhash; + + /* pipelining wanted bits (CURLPIPE*) */ + long pipelining; + + bool recheckstate; /* see Curl_multi_connchanged */ + + /* Shared connection cache (bundles)*/ + struct conncache conn_cache; + + long maxconnects; /* if >0, a fixed limit of the maximum number of entries + we're allowed to grow the connection cache to */ + + long max_host_connections; /* if >0, a fixed limit of the maximum number + of connections per host */ + + long max_total_connections; /* if >0, a fixed limit of the maximum number + of connections in total */ + + long max_pipeline_length; /* if >0, maximum number of requests in a + pipeline */ + + long content_length_penalty_size; /* a connection with a + content-length bigger than + this is not considered + for pipelining */ + + long chunk_length_penalty_size; /* a connection with a chunk length + bigger than this is not + considered for pipelining */ + + struct curl_llist pipelining_site_bl; /* List of sites that are blacklisted + from pipelining */ + + struct curl_llist pipelining_server_bl; /* List of server types that are + blacklisted from pipelining */ + + /* timer callback and user data pointer for the *socket() API */ + curl_multi_timer_callback timer_cb; + void *timer_userp; + struct curltime timer_lastcall; /* the fixed time for the timeout for the + previous callback */ + bool in_callback; /* true while executing a callback */ +}; + +#endif /* HEADER_CURL_MULTIHANDLE_H */ diff --git a/external/curl prx/include/multiif.h b/external/curl prx/include/multiif.h new file mode 100644 index 0000000..ed35ef4 --- /dev/null +++ b/external/curl prx/include/multiif.h @@ -0,0 +1,110 @@ +#ifndef HEADER_CURL_MULTIIF_H +#define HEADER_CURL_MULTIIF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Prototypes for library-wide functions provided by multi.c + */ + +void Curl_updatesocket(struct Curl_easy *data); +void Curl_expire(struct Curl_easy *data, time_t milli, expire_id); +void Curl_expire_clear(struct Curl_easy *data); +void Curl_expire_done(struct Curl_easy *data, expire_id id); +bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits); +void Curl_detach_connnection(struct Curl_easy *data); +void Curl_attach_connnection(struct Curl_easy *data, + struct connectdata *conn); +void Curl_set_in_callback(struct Curl_easy *data, bool value); +bool Curl_is_in_callback(struct Curl_easy *easy); + +/* Internal version of curl_multi_init() accepts size parameters for the + socket and connection hashes */ +struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize); + +/* the write bits start at bit 16 for the *getsock() bitmap */ +#define GETSOCK_WRITEBITSTART 16 + +#define GETSOCK_BLANK 0 /* no bits set */ + +/* set the bit for the given sock number to make the bitmap for writable */ +#define GETSOCK_WRITESOCK(x) (1 << (GETSOCK_WRITEBITSTART + (x))) + +/* set the bit for the given sock number to make the bitmap for readable */ +#define GETSOCK_READSOCK(x) (1 << (x)) + +#ifdef DEBUGBUILD + /* + * Curl_multi_dump is not a stable public function, this is only meant to + * allow easier tracking of the internal handle's state and what sockets + * they use. Only for research and development DEBUGBUILD enabled builds. + */ +void Curl_multi_dump(struct Curl_multi *multi); +#endif + +/* Return the value of the CURLMOPT_MAX_HOST_CONNECTIONS option */ +size_t Curl_multi_max_host_connections(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE option */ +curl_off_t Curl_multi_content_length_penalty_size(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE option */ +curl_off_t Curl_multi_chunk_length_penalty_size(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_PIPELINING_SITE_BL option */ +struct curl_llist *Curl_multi_pipelining_site_bl(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_PIPELINING_SERVER_BL option */ +struct curl_llist *Curl_multi_pipelining_server_bl(struct Curl_multi *multi); + +/* Return the value of the CURLMOPT_MAX_TOTAL_CONNECTIONS option */ +size_t Curl_multi_max_total_connections(struct Curl_multi *multi); + +void Curl_multi_connchanged(struct Curl_multi *multi); + +/* + * Curl_multi_closed() + * + * Used by the connect code to tell the multi_socket code that one of the + * sockets we were using is about to be closed. This function will then + * remove it from the sockethash for this handle to make the multi_socket API + * behave properly, especially for the case when libcurl will create another + * socket again and it gets the same file descriptor number. + */ + +void Curl_multi_closed(struct Curl_easy *data, curl_socket_t s); + +/* + * Add a handle and move it into PERFORM state at once. For pushed streams. + */ +CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, + struct Curl_easy *data, + struct connectdata *conn); + +CURLMcode Curl_multi_wait(struct Curl_multi *multi, + struct curl_waitfd extra_fds[], + unsigned int extra_nfds, + int timeout_ms, + int *ret, + bool *gotsocket); /* if any socket was checked */ + +#endif /* HEADER_CURL_MULTIIF_H */ diff --git a/external/curl prx/include/netrc.h b/external/curl prx/include/netrc.h new file mode 100644 index 0000000..fe3dc35 --- /dev/null +++ b/external/curl prx/include/netrc.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_NETRC_H +#define HEADER_CURL_NETRC_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ +int Curl_parsenetrc(const char *host, + char **loginp, + char **passwordp, + bool *login_changed, + bool *password_changed, + char *filename); + /* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine + * section in the netrc. + * If (*loginp)[0] != 0, search for password within machine and login. + */ + +#endif /* HEADER_CURL_NETRC_H */ diff --git a/external/curl prx/include/non-ascii.h b/external/curl prx/include/non-ascii.h new file mode 100644 index 0000000..5fb5771 --- /dev/null +++ b/external/curl prx/include/non-ascii.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_NON_ASCII_H +#define HEADER_CURL_NON_ASCII_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef CURL_DOES_CONVERSIONS + +#include "urldata.h" + +/* + * Curl_convert_clone() returns a malloced copy of the source string (if + * returning CURLE_OK), with the data converted to network format. + * + * If no conversion was needed *outbuf may be NULL. + */ +CURLcode Curl_convert_clone(struct Curl_easy *data, + const char *indata, + size_t insize, + char **outbuf); + +void Curl_convert_init(struct Curl_easy *data); +void Curl_convert_setup(struct Curl_easy *data); +void Curl_convert_close(struct Curl_easy *data); + +CURLcode Curl_convert_to_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_network(struct Curl_easy *data, + char *buffer, size_t length); +CURLcode Curl_convert_from_utf8(struct Curl_easy *data, + char *buffer, size_t length); +#else +#define Curl_convert_clone(a,b,c,d) ((void)a, CURLE_OK) +#define Curl_convert_init(x) Curl_nop_stmt +#define Curl_convert_setup(x) Curl_nop_stmt +#define Curl_convert_close(x) Curl_nop_stmt +#define Curl_convert_to_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_network(a,b,c) ((void)a, CURLE_OK) +#define Curl_convert_from_utf8(a,b,c) ((void)a, CURLE_OK) +#endif + +#endif /* HEADER_CURL_NON_ASCII_H */ diff --git a/external/curl prx/include/nonblock.h b/external/curl prx/include/nonblock.h new file mode 100644 index 0000000..eb18ea1 --- /dev/null +++ b/external/curl prx/include/nonblock.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_NONBLOCK_H +#define HEADER_CURL_NONBLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include /* for curl_socket_t */ + +int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ + int nonblock /* TRUE or FALSE */); + +#endif /* HEADER_CURL_NONBLOCK_H */ diff --git a/external/curl prx/include/nssg.h b/external/curl prx/include/nssg.h new file mode 100644 index 0000000..41e51b0 --- /dev/null +++ b/external/curl prx/include/nssg.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_NSSG_H +#define HEADER_CURL_NSSG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_NSS +/* + * This header should only be needed to get included by vtls.c and nss.c + */ + +#include "urldata.h" + +/* initialize NSS library if not already */ +CURLcode Curl_nss_force_init(struct Curl_easy *data); + +extern const struct Curl_ssl Curl_ssl_nss; + +#endif /* USE_NSS */ +#endif /* HEADER_CURL_NSSG_H */ diff --git a/external/curl prx/include/ntlm.h b/external/curl prx/include/ntlm.h new file mode 100644 index 0000000..1136b0f --- /dev/null +++ b/external/curl prx/include/ntlm.h @@ -0,0 +1,143 @@ +#ifndef HEADER_VAUTH_NTLM_H +#define HEADER_VAUTH_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NTLM + +/* NTLM buffer fixed size, large enough for long user + host + domain */ +#define NTLM_BUFSIZE 1024 + +/* Stuff only required for curl_ntlm_msgs.c */ +#ifdef BUILDING_CURL_NTLM_MSGS_C + +/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */ + +#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) +/* Indicates that Unicode strings are supported for use in security buffer + data. */ + +#define NTLMFLAG_NEGOTIATE_OEM (1<<1) +/* Indicates that OEM strings are supported for use in security buffer data. */ + +#define NTLMFLAG_REQUEST_TARGET (1<<2) +/* Requests that the server's authentication realm be included in the Type 2 + message. */ + +/* unknown (1<<3) */ +#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ + +#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ + +#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) +/* Indicates that datagram authentication is being used. */ + +#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ + +#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) +/* Indicates that NTLM authentication is being used. */ + +/* unknown (1<<10) */ + +#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ + +#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ + +#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ + +#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ + +#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ + +#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ + +#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ + +#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ + +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ + +#define NTLMFLAG_NEGOTIATE_128 (1<<29) +/* Indicates that 128-bit encryption is supported. */ + +#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ + +#define NTLMFLAG_NEGOTIATE_56 (1<<31) +/* Indicates that 56-bit encryption is supported. */ + +#endif /* BUILDING_CURL_NTLM_MSGS_C */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_VAUTH_NTLM_H */ diff --git a/external/curl prx/include/openssl.h b/external/curl prx/include/openssl.h new file mode 100644 index 0000000..114dc4b --- /dev/null +++ b/external/curl prx/include/openssl.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_SSLUSE_H +#define HEADER_CURL_SSLUSE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL +/* + * This header should only be needed to get included by vtls.c and openssl.c + */ + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_openssl; + +#endif /* USE_OPENSSL */ +#endif /* HEADER_CURL_SSLUSE_H */ diff --git a/external/curl prx/include/parsedate.h b/external/curl prx/include/parsedate.h new file mode 100644 index 0000000..8dc3b90 --- /dev/null +++ b/external/curl prx/include/parsedate.h @@ -0,0 +1,30 @@ +#ifndef HEADER_CURL_PARSEDATE_H +#define HEADER_CURL_PARSEDATE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +extern const char * const Curl_wkday[7]; +extern const char * const Curl_month[12]; + +CURLcode Curl_gmtime(time_t intime, struct tm *store); + +#endif /* HEADER_CURL_PARSEDATE_H */ diff --git a/external/curl prx/include/pingpong.h b/external/curl prx/include/pingpong.h new file mode 100644 index 0000000..dbe1f8d --- /dev/null +++ b/external/curl prx/include/pingpong.h @@ -0,0 +1,151 @@ +#ifndef HEADER_CURL_PINGPONG_H +#define HEADER_CURL_PINGPONG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_FTP) || \ + !defined(CURL_DISABLE_POP3) || !defined(CURL_DISABLE_SMTP) +#define USE_PINGPONG +#endif + +/* forward-declaration, this is defined in urldata.h */ +struct connectdata; + +typedef enum { + FTPTRANSFER_BODY, /* yes do transfer a body */ + FTPTRANSFER_INFO, /* do still go through to get info/headers */ + FTPTRANSFER_NONE, /* don't get anything and don't get info */ + FTPTRANSFER_LAST /* end of list marker, never used */ +} curl_pp_transfer; + +/* + * 'pingpong' is the generic struct used for protocols doing server<->client + * conversations in a back-and-forth style such as FTP, IMAP, POP3, SMTP etc. + * + * It holds response cache and non-blocking sending data. + */ +struct pingpong { + char *cache; /* data cache between getresponse()-calls */ + size_t cache_size; /* size of cache in bytes */ + size_t nread_resp; /* number of bytes currently read of a server response */ + char *linestart_resp; /* line start pointer for the server response + reader function */ + bool pending_resp; /* set TRUE when a server response is pending or in + progress, and is cleared once the last response is + read */ + char *sendthis; /* allocated pointer to a buffer that is to be sent to the + server */ + size_t sendleft; /* number of bytes left to send from the sendthis buffer */ + size_t sendsize; /* total size of the sendthis buffer */ + struct curltime response; /* set to Curl_now() when a command has been sent + off, used to time-out response reading */ + long response_time; /* When no timeout is given, this is the amount of + milliseconds we await for a server response. */ + + struct connectdata *conn; /* points to the connectdata struct that this + belongs to */ + + /* Function pointers the protocols MUST implement and provide for the + pingpong layer to function */ + + CURLcode (*statemach_act)(struct connectdata *conn); + + bool (*endofresp)(struct connectdata *conn, char *ptr, size_t len, + int *code); +}; + +/* + * Curl_pp_statemach() + * + * called repeatedly until done. Set 'wait' to make it wait a while on the + * socket if there's no traffic. + */ +CURLcode Curl_pp_statemach(struct pingpong *pp, bool block, + bool disconnecting); + +/* initialize stuff to prepare for reading a fresh new response */ +void Curl_pp_init(struct pingpong *pp); + +/* Returns timeout in ms. 0 or negative number means the timeout has already + triggered */ +time_t Curl_pp_state_timeout(struct pingpong *pp, bool disconnecting); + + +/*********************************************************************** + * + * Curl_pp_sendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_sendf(struct pingpong *pp, + const char *fmt, ...); + +/*********************************************************************** + * + * Curl_pp_vsendf() + * + * Send the formatted string as a command to a pingpong server. Note that + * the string should not have any CRLF appended, as this function will + * append the necessary things itself. + * + * made to never block + */ +CURLcode Curl_pp_vsendf(struct pingpong *pp, + const char *fmt, + va_list args); + +/* + * Curl_pp_readresp() + * + * Reads a piece of a server response. + */ +CURLcode Curl_pp_readresp(curl_socket_t sockfd, + struct pingpong *pp, + int *code, /* return the server code if done */ + size_t *size); /* size of the response */ + + +CURLcode Curl_pp_flushsend(struct pingpong *pp); + +/* call this when a pingpong connection is disconnected */ +CURLcode Curl_pp_disconnect(struct pingpong *pp); + +int Curl_pp_getsock(struct pingpong *pp, curl_socket_t *socks, + int numsocks); + + +/*********************************************************************** + * + * Curl_pp_moredata() + * + * Returns whether there are still more data in the cache and so a call + * to Curl_pp_readresp() will not block. + */ +bool Curl_pp_moredata(struct pingpong *pp); + +#endif /* HEADER_CURL_PINGPONG_H */ diff --git a/external/curl prx/include/pipeline.h b/external/curl prx/include/pipeline.h new file mode 100644 index 0000000..413ba31 --- /dev/null +++ b/external/curl prx/include/pipeline.h @@ -0,0 +1,56 @@ +#ifndef HEADER_CURL_PIPELINE_H +#define HEADER_CURL_PIPELINE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2015 - 2017, Daniel Stenberg, , et al. + * Copyright (C) 2013 - 2014, Linus Nielsen Feltzing, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle, + struct connectdata *conn); +void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle, + struct connectdata *conn); +bool Curl_pipeline_penalized(struct Curl_easy *data, + struct connectdata *conn); + +bool Curl_pipeline_site_blacklisted(struct Curl_easy *handle, + struct connectdata *conn); + +CURLMcode Curl_pipeline_set_site_blacklist(char **sites, + struct curl_llist *list_ptr); + +bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle, + char *server_name); + +CURLMcode Curl_pipeline_set_server_blacklist(char **servers, + struct curl_llist *list_ptr); + +bool Curl_pipeline_checkget_write(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_pipeline_checkget_read(struct Curl_easy *data, + struct connectdata *conn); +void Curl_pipeline_leave_write(struct connectdata *conn); +void Curl_pipeline_leave_read(struct connectdata *conn); +bool Curl_recvpipe_head(struct Curl_easy *data, + struct connectdata *conn); +bool Curl_sendpipe_head(struct Curl_easy *data, + struct connectdata *conn); + +#endif /* HEADER_CURL_PIPELINE_H */ diff --git a/external/curl prx/include/polarssl.h b/external/curl prx/include/polarssl.h new file mode 100644 index 0000000..23c3636 --- /dev/null +++ b/external/curl prx/include/polarssl.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_POLARSSL_H +#define HEADER_CURL_POLARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_POLARSSL + +extern const struct Curl_ssl Curl_ssl_polarssl; + +#endif /* USE_POLARSSL */ +#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/external/curl prx/include/polarssl_threadlock.h b/external/curl prx/include/polarssl_threadlock.h new file mode 100644 index 0000000..dda5359 --- /dev/null +++ b/external/curl prx/include/polarssl_threadlock.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H +#define HEADER_CURL_POLARSSL_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2015, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined USE_POLARSSL) || (defined USE_MBEDTLS) + +#if defined(USE_THREADS_POSIX) +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) +# define POLARSSL_MUTEX_T HANDLE +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +int Curl_polarsslthreadlock_thread_setup(void); +int Curl_polarsslthreadlock_thread_cleanup(void); +int Curl_polarsslthreadlock_lock_function(int n); +int Curl_polarsslthreadlock_unlock_function(int n); + +#else + +#define Curl_polarsslthreadlock_thread_setup() 1 +#define Curl_polarsslthreadlock_thread_cleanup() 1 +#define Curl_polarsslthreadlock_lock_function(x) 1 +#define Curl_polarsslthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_POLARSSL */ + +#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */ diff --git a/external/curl prx/include/pop3.h b/external/curl prx/include/pop3.h new file mode 100644 index 0000000..a8e697c --- /dev/null +++ b/external/curl prx/include/pop3.h @@ -0,0 +1,95 @@ +#ifndef HEADER_CURL_POP3_H +#define HEADER_CURL_POP3_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2015, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * POP3 unique setup + ***************************************************************************/ +typedef enum { + POP3_STOP, /* do nothing state, stops the state machine */ + POP3_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + POP3_CAPA, + POP3_STARTTLS, + POP3_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + POP3_AUTH, + POP3_APOP, + POP3_USER, + POP3_PASS, + POP3_COMMAND, + POP3_QUIT, + POP3_LAST /* never used */ +} pop3state; + +/* This POP3 struct is used in the Curl_easy. All POP3 data that is + connection-oriented must be in pop3_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct POP3 { + curl_pp_transfer transfer; + char *id; /* Message ID */ + char *custom; /* Custom Request */ +}; + +/* pop3_conn is used for struct connection-oriented data in the connectdata + struct */ +struct pop3_conn { + struct pingpong pp; + pop3state state; /* Always use pop3.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + size_t strip; /* Number of bytes from the start to ignore as + non-body */ + struct SASL sasl; /* SASL-related storage */ + unsigned int authtypes; /* Accepted authentication types */ + unsigned int preftype; /* Preferred authentication type */ + char *apoptimestamp; /* APOP timestamp from the server greeting */ + bool tls_supported; /* StartTLS capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_pop3; +extern const struct Curl_handler Curl_handler_pop3s; + +/* Authentication type flags */ +#define POP3_TYPE_CLEARTEXT (1 << 0) +#define POP3_TYPE_APOP (1 << 1) +#define POP3_TYPE_SASL (1 << 2) + +/* Authentication type values */ +#define POP3_TYPE_NONE 0 +#define POP3_TYPE_ANY ~0U + +/* This is the 5-bytes End-Of-Body marker for POP3 */ +#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" +#define POP3_EOB_LEN 5 + +/* This function scans the body after the end-of-body and writes everything + * until the end is found */ +CURLcode Curl_pop3_write(struct connectdata *conn, char *str, size_t nread); + +#endif /* HEADER_CURL_POP3_H */ diff --git a/external/curl prx/include/progress.h b/external/curl prx/include/progress.h new file mode 100644 index 0000000..3515ac6 --- /dev/null +++ b/external/curl prx/include/progress.h @@ -0,0 +1,64 @@ +#ifndef HEADER_CURL_PROGRESS_H +#define HEADER_CURL_PROGRESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "timeval.h" + + +typedef enum { + TIMER_NONE, + TIMER_STARTOP, + TIMER_STARTSINGLE, + TIMER_NAMELOOKUP, + TIMER_CONNECT, + TIMER_APPCONNECT, + TIMER_PRETRANSFER, + TIMER_STARTTRANSFER, + TIMER_POSTRANSFER, + TIMER_STARTACCEPT, + TIMER_REDIRECT, + TIMER_LAST /* must be last */ +} timerid; + +int Curl_pgrsDone(struct connectdata *); +void Curl_pgrsStartNow(struct Curl_easy *data); +void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size); +void Curl_ratelimit(struct Curl_easy *data, struct curltime now); +int Curl_pgrsUpdate(struct connectdata *); +void Curl_pgrsResetTransferSizes(struct Curl_easy *data); +void Curl_pgrsTime(struct Curl_easy *data, timerid timer); +timediff_t Curl_pgrsLimitWaitTime(curl_off_t cursize, + curl_off_t startsize, + curl_off_t limit, + struct curltime start, + struct curltime now); + +#define PGRS_HIDE (1<<4) +#define PGRS_UL_SIZE_KNOWN (1<<5) +#define PGRS_DL_SIZE_KNOWN (1<<6) +#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ + +#endif /* HEADER_CURL_PROGRESS_H */ diff --git a/external/curl prx/include/psl.h b/external/curl prx/include/psl.h new file mode 100644 index 0000000..e9f99d0 --- /dev/null +++ b/external/curl prx/include/psl.h @@ -0,0 +1,47 @@ +#ifndef HEADER_PSL_H +#define HEADER_PSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_LIBPSL +#include + +#define PSL_TTL (72 * 3600) /* PSL time to live before a refresh. */ + +struct PslCache { + const psl_ctx_t *psl; /* The PSL. */ + time_t expires; /* Time this PSL life expires. */ + bool dynamic; /* PSL should be released when no longer needed. */ +}; + +const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy); +void Curl_psl_release(struct Curl_easy *easy); +void Curl_psl_destroy(struct PslCache *pslcache); + +#else + +#define Curl_psl_use(easy) NULL +#define Curl_psl_release(easy) +#define Curl_psl_destroy(pslcache) + +#endif /* USE_LIBPSL */ +#endif /* HEADER_PSL_H */ diff --git a/external/curl prx/include/rand.h b/external/curl prx/include/rand.h new file mode 100644 index 0000000..5deb041 --- /dev/null +++ b/external/curl prx/include/rand.h @@ -0,0 +1,50 @@ +#ifndef HEADER_CURL_RAND_H +#define HEADER_CURL_RAND_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_rand() stores 'num' number of random unsigned characters in the buffer + * 'rnd' points to. + * + * If libcurl is built without TLS support or with a TLS backend that lacks a + * proper random API (Gskit, PolarSSL or mbedTLS), this function will use + * "weak" random. + * + * When built *with* TLS support and a backend that offers strong random, it + * will return error if it cannot provide strong random values. + * + * NOTE: 'data' may be passed in as NULL when coming from external API without + * easy handle! + * + */ +CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num); + +/* + * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random + * hexadecimal digits PLUS a zero terminating byte. It must be an odd number + * size. + */ +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, + size_t num); + +#endif /* HEADER_CURL_RAND_H */ diff --git a/external/curl prx/include/rtsp.h b/external/curl prx/include/rtsp.h new file mode 100644 index 0000000..2f9cc32 --- /dev/null +++ b/external/curl prx/include/rtsp.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_RTSP_H +#define HEADER_CURL_RTSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_RTSP + +extern const struct Curl_handler Curl_handler_rtsp; + +CURLcode Curl_rtsp_parseheader(struct connectdata *conn, char *header); + +#else +/* disabled */ +#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN + +#endif /* CURL_DISABLE_RTSP */ + +/* + * RTSP Connection data + * + * Currently, only used for tracking incomplete RTP data reads + */ +struct rtsp_conn { + char *rtp_buf; + ssize_t rtp_bufsize; + int rtp_channel; +}; + +/**************************************************************************** + * RTSP unique setup + ***************************************************************************/ +struct RTSP { + /* + * http_wrapper MUST be the first element of this structure for the wrap + * logic to work. In this way, we get a cheap polymorphism because + * &(data->state.proto.rtsp) == &(data->state.proto.http) per the C spec + * + * HTTP functions can safely treat this as an HTTP struct, but RTSP aware + * functions can also index into the later elements. + */ + struct HTTP http_wrapper; /*wrap HTTP to do the heavy lifting */ + + long CSeq_sent; /* CSeq of this request */ + long CSeq_recv; /* CSeq received */ +}; + + +#endif /* HEADER_CURL_RTSP_H */ diff --git a/external/curl prx/include/schannel.h b/external/curl prx/include/schannel.h new file mode 100644 index 0000000..ee8d7d4 --- /dev/null +++ b/external/curl prx/include/schannel.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_SCHANNEL_H +#define HEADER_CURL_SCHANNEL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Marc Hoersken, , et al. + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#include +#include +#include "curl_sspi.h" + +#include "urldata.h" + +/* has been included via the above . + * Or in case of ldap.c, it was included via . + * And since has this: + * #define X509_NAME ((LPCSTR) 7) + * + * And in BoringSSL's there is: + * typedef struct X509_name_st X509_NAME; + * etc. + * + * this will cause all kinds of C-preprocessing paste errors in + * BoringSSL's : So just undefine those defines here + * (and only here). + */ +#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL) +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +#endif + +extern const struct Curl_ssl Curl_ssl_schannel; + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); + +/* structs to expose only in schannel.c and schannel_verify.c */ +#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifdef __MINGW32__ +#include <_mingw.h> +#ifdef __MINGW64_VERSION_MAJOR +#define HAS_MANUAL_VERIFY_API +#endif +#else +#include +#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN +#define HAS_MANUAL_VERIFY_API +#endif +#endif + +struct curl_schannel_cred { + CredHandle cred_handle; + TimeStamp time_stamp; + int refcount; +}; + +struct curl_schannel_ctxt { + CtxtHandle ctxt_handle; + TimeStamp time_stamp; +}; + +struct ssl_backend_data { + struct curl_schannel_cred *cred; + struct curl_schannel_ctxt *ctxt; + SecPkgContext_StreamSizes stream_sizes; + size_t encdata_length, decdata_length; + size_t encdata_offset, decdata_offset; + unsigned char *encdata_buffer, *decdata_buffer; + /* encdata_is_incomplete: if encdata contains only a partial record that + can't be decrypted without another Curl_read_plain (that is, status is + SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes + more bytes into encdata then set this back to false. */ + bool encdata_is_incomplete; + unsigned long req_flags, ret_flags; + CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ + bool recv_sspi_close_notify; /* true if connection closed by close_notify */ + bool recv_connection_closed; /* true if connection closed, regardless how */ + bool use_alpn; /* true if ALPN is used for this connection */ +#ifdef HAS_MANUAL_VERIFY_API + bool use_manual_cred_validation; /* true if manual cred validation is used */ +#endif +}; +#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ + +#endif /* USE_SCHANNEL */ +#endif /* HEADER_CURL_SCHANNEL_H */ diff --git a/external/curl prx/include/sectransp.h b/external/curl prx/include/sectransp.h new file mode 100644 index 0000000..5cec797 --- /dev/null +++ b/external/curl prx/include/sectransp.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SECTRANSP + +extern const struct Curl_ssl Curl_ssl_sectransp; + +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/external/curl prx/include/select.h b/external/curl prx/include/select.h new file mode 100644 index 0000000..9a1ba45 --- /dev/null +++ b/external/curl prx/include/select.h @@ -0,0 +1,115 @@ +#ifndef HEADER_CURL_SELECT_H +#define HEADER_CURL_SELECT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_POLL_H +#include +#elif defined(HAVE_SYS_POLL_H) +#include +#endif + +/* + * Definition of pollfd struct and constants for platforms lacking them. + */ + +#if !defined(HAVE_STRUCT_POLLFD) && \ + !defined(HAVE_SYS_POLL_H) && \ + !defined(HAVE_POLL_H) && \ + !defined(POLLIN) + +#define POLLIN 0x01 +#define POLLPRI 0x02 +#define POLLOUT 0x04 +#define POLLERR 0x08 +#define POLLHUP 0x10 +#define POLLNVAL 0x20 + +struct pollfd +{ + curl_socket_t fd; + short events; + short revents; +}; + +#endif + +#ifndef POLLRDNORM +#define POLLRDNORM POLLIN +#endif + +#ifndef POLLWRNORM +#define POLLWRNORM POLLOUT +#endif + +#ifndef POLLRDBAND +#define POLLRDBAND POLLPRI +#endif + +/* there are three CSELECT defines that are defined in the public header that + are exposed to users, but this *IN2 bit is only ever used internally and + therefore defined here */ +#define CURL_CSELECT_IN2 (CURL_CSELECT_ERR << 1) + +int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + curl_socket_t writefd, + time_t timeout_ms); + +#define SOCKET_READABLE(x,z) \ + Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) +#define SOCKET_WRITABLE(x,z) \ + Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z) + +int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); + +/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, + * EINTR condition is honored and function might exit early without + * awaiting full timeout. Otherwise EINTR will be ignored and full + * timeout will elapse. */ +extern int Curl_ack_eintr; + +int Curl_wait_ms(int timeout_ms); + +#ifdef TPF +int tpf_select_libcurl(int maxfds, fd_set* reads, fd_set* writes, + fd_set* excepts, struct timeval* tv); +#endif + +/* Winsock and TPF sockets are not in range [0..FD_SETSIZE-1], which + unfortunately makes it impossible for us to easily check if they're valid +*/ +#if defined(USE_WINSOCK) || defined(TPF) +#define VALID_SOCK(x) 1 +#define VERIFY_SOCK(x) Curl_nop_stmt +#else +#define VALID_SOCK(s) (((s) >= 0) && ((s) < FD_SETSIZE)) +#define VERIFY_SOCK(x) do { \ + if(!VALID_SOCK(x)) { \ + SET_SOCKERRNO(EINVAL); \ + return -1; \ + } \ +} WHILE_FALSE +#endif + +#endif /* HEADER_CURL_SELECT_H */ diff --git a/external/curl prx/include/sendf.h b/external/curl prx/include/sendf.h new file mode 100644 index 0000000..c68b017 --- /dev/null +++ b/external/curl prx/include/sendf.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SENDF_H +#define HEADER_CURL_SENDF_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *, + const char *fmt, ...); +void Curl_infof(struct Curl_easy *, const char *fmt, ...); +void Curl_failf(struct Curl_easy *, const char *fmt, ...); + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + +#if defined(HAVE_VARIADIC_MACROS_C99) +#define infof(...) Curl_nop_stmt +#elif defined(HAVE_VARIADIC_MACROS_GCC) +#define infof(x...) Curl_nop_stmt +#else +#error "missing VARIADIC macro define, fix and rebuild!" +#endif + +#else /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define infof Curl_infof + +#endif /* CURL_DISABLE_VERBOSE_STRINGS */ + +#define failf Curl_failf + +#define CLIENTWRITE_BODY (1<<0) +#define CLIENTWRITE_HEADER (1<<1) +#define CLIENTWRITE_BOTH (CLIENTWRITE_BODY|CLIENTWRITE_HEADER) + +CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr, + size_t len) WARN_UNUSED_RESULT; + +bool Curl_recv_has_postponed_data(struct connectdata *conn, int sockindex); + +/* internal read-function, does plain socket only */ +CURLcode Curl_read_plain(curl_socket_t sockfd, + char *buf, + size_t bytesfromsocket, + ssize_t *n); + +ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf, + size_t len, CURLcode *code); +ssize_t Curl_send_plain(struct connectdata *conn, int num, + const void *mem, size_t len, CURLcode *code); + +/* internal read-function, does plain socket, SSL and krb4 */ +CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd, + char *buf, size_t buffersize, + ssize_t *n); +/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */ +CURLcode Curl_write(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* internal write-function, does plain sockets ONLY */ +CURLcode Curl_write_plain(struct connectdata *conn, + curl_socket_t sockfd, + const void *mem, size_t len, + ssize_t *written); + +/* the function used to output verbose information */ +int Curl_debug(struct Curl_easy *data, curl_infotype type, + char *ptr, size_t size); + + +#endif /* HEADER_CURL_SENDF_H */ diff --git a/external/curl prx/include/setopt.h b/external/curl prx/include/setopt.h new file mode 100644 index 0000000..c658e04 --- /dev/null +++ b/external/curl prx/include/setopt.h @@ -0,0 +1,29 @@ +#ifndef HEADER_CURL_SETOPT_H +#define HEADER_CURL_SETOPT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +CURLcode Curl_setstropt(char **charp, const char *s); +CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, + va_list arg); + +#endif /* HEADER_CURL_SETOPT_H */ diff --git a/external/curl prx/include/setup-os400.h b/external/curl prx/include/setup-os400.h new file mode 100644 index 0000000..a3c2a7b --- /dev/null +++ b/external/curl prx/include/setup-os400.h @@ -0,0 +1,223 @@ +#ifndef HEADER_CURL_SETUP_OS400_H +#define HEADER_CURL_SETUP_OS400_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + + +/* OS/400 netdb.h does not define NI_MAXHOST. */ +#define NI_MAXHOST 1025 + +/* OS/400 netdb.h does not define NI_MAXSERV. */ +#define NI_MAXSERV 32 + +/* No OS/400 header file defines u_int32_t. */ +typedef unsigned long u_int32_t; + + +/* System API wrapper prototypes & definitions to support ASCII parameters. */ + +#include +#include +#include +#include +#include + +extern int Curl_getaddrinfo_a(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +#define getaddrinfo Curl_getaddrinfo_a + + +extern int Curl_getnameinfo_a(const struct sockaddr *sa, + curl_socklen_t salen, + char *nodename, curl_socklen_t nodenamelen, + char *servname, curl_socklen_t servnamelen, + int flags); +#define getnameinfo Curl_getnameinfo_a + + +/* GSKit wrappers. */ + +extern int Curl_gsk_environment_open(gsk_handle * my_env_handle); +#define gsk_environment_open Curl_gsk_environment_open + +extern int Curl_gsk_secure_soc_open(gsk_handle my_env_handle, + gsk_handle * my_session_handle); +#define gsk_secure_soc_open Curl_gsk_secure_soc_open + +extern int Curl_gsk_environment_close(gsk_handle * my_env_handle); +#define gsk_environment_close Curl_gsk_environment_close + +extern int Curl_gsk_secure_soc_close(gsk_handle * my_session_handle); +#define gsk_secure_soc_close Curl_gsk_secure_soc_close + +extern int Curl_gsk_environment_init(gsk_handle my_env_handle); +#define gsk_environment_init Curl_gsk_environment_init + +extern int Curl_gsk_secure_soc_init(gsk_handle my_session_handle); +#define gsk_secure_soc_init Curl_gsk_secure_soc_init + +extern int Curl_gsk_attribute_set_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char *buffer, + int bufSize); +#define gsk_attribute_set_buffer Curl_gsk_attribute_set_buffer_a + +extern int Curl_gsk_attribute_set_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE enumValue); +#define gsk_attribute_set_enum Curl_gsk_attribute_set_enum + +extern int Curl_gsk_attribute_set_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int numValue); +#define gsk_attribute_set_numeric_value Curl_gsk_attribute_set_numeric_value + +extern int Curl_gsk_attribute_set_callback(gsk_handle my_gsk_handle, + GSK_CALLBACK_ID callBackID, + void *callBackAreaPtr); +#define gsk_attribute_set_callback Curl_gsk_attribute_set_callback + +extern int Curl_gsk_attribute_get_buffer_a(gsk_handle my_gsk_handle, + GSK_BUF_ID bufID, + const char **buffer, + int *bufSize); +#define gsk_attribute_get_buffer Curl_gsk_attribute_get_buffer_a + +extern int Curl_gsk_attribute_get_enum(gsk_handle my_gsk_handle, + GSK_ENUM_ID enumID, + GSK_ENUM_VALUE *enumValue); +#define gsk_attribute_get_enum Curl_gsk_attribute_get_enum + +extern int Curl_gsk_attribute_get_numeric_value(gsk_handle my_gsk_handle, + GSK_NUM_ID numID, + int *numValue); +#define gsk_attribute_get_numeric_value Curl_gsk_attribute_get_numeric_value + +extern int Curl_gsk_attribute_get_cert_info(gsk_handle my_gsk_handle, + GSK_CERT_ID certID, + const gsk_cert_data_elem **certDataElem, + int *certDataElementCount); +#define gsk_attribute_get_cert_info Curl_gsk_attribute_get_cert_info + +extern int Curl_gsk_secure_soc_misc(gsk_handle my_session_handle, + GSK_MISC_ID miscID); +#define gsk_secure_soc_misc Curl_gsk_secure_soc_misc + +extern int Curl_gsk_secure_soc_read(gsk_handle my_session_handle, + char *readBuffer, + int readBufSize, int *amtRead); +#define gsk_secure_soc_read Curl_gsk_secure_soc_read + +extern int Curl_gsk_secure_soc_write(gsk_handle my_session_handle, + char *writeBuffer, + int writeBufSize, int *amtWritten); +#define gsk_secure_soc_write Curl_gsk_secure_soc_write + +extern const char * Curl_gsk_strerror_a(int gsk_return_value); +#define gsk_strerror Curl_gsk_strerror_a + +extern int Curl_gsk_secure_soc_startInit(gsk_handle my_session_handle, + int IOCompletionPort, + Qso_OverlappedIO_t * communicationsArea); +#define gsk_secure_soc_startInit Curl_gsk_secure_soc_startInit + + +/* GSSAPI wrappers. */ + +extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, + gss_buffer_t in_name, + gss_OID in_name_type, + gss_name_t * out_name); +#define gss_import_name Curl_gss_import_name_a + + +extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, gss_OID mech_type, + gss_msg_ctx_t * message_context, + gss_buffer_t status_string); +#define gss_display_status Curl_gss_display_status_a + + +extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, + gss_cred_id_t cred_handle, + gss_ctx_id_t * context_handle, + gss_name_t target_name, + gss_OID mech_type, + gss_flags_t req_flags, + OM_uint32 time_req, + gss_channel_bindings_t + input_chan_bindings, + gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + gss_flags_t * ret_flags, + OM_uint32 * time_rec); +#define gss_init_sec_context Curl_gss_init_sec_context_a + + +extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token); +#define gss_delete_sec_context Curl_gss_delete_sec_context_a + + +/* LDAP wrappers. */ + +#define BerValue struct berval + +#define ldap_url_parse ldap_url_parse_utf8 +#define ldap_init Curl_ldap_init_a +#define ldap_simple_bind_s Curl_ldap_simple_bind_s_a +#define ldap_search_s Curl_ldap_search_s_a +#define ldap_get_values_len Curl_ldap_get_values_len_a +#define ldap_err2string Curl_ldap_err2string_a +#define ldap_get_dn Curl_ldap_get_dn_a +#define ldap_first_attribute Curl_ldap_first_attribute_a +#define ldap_next_attribute Curl_ldap_next_attribute_a + +/* Some socket functions must be wrapped to process textual addresses + like AF_UNIX. */ + +extern int Curl_os400_connect(int sd, struct sockaddr * destaddr, int addrlen); +extern int Curl_os400_bind(int sd, struct sockaddr * localaddr, int addrlen); +extern int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + struct sockaddr * dstaddr, int addrlen); +extern int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen); + +#define connect Curl_os400_connect +#define bind Curl_os400_bind +#define sendto Curl_os400_sendto +#define recvfrom Curl_os400_recvfrom + +#ifdef HAVE_LIBZ +#define zlibVersion Curl_os400_zlibVersion +#define inflateInit_ Curl_os400_inflateInit_ +#define inflateInit2_ Curl_os400_inflateInit2_ +#define inflate Curl_os400_inflate +#define inflateEnd Curl_os400_inflateEnd +#endif + +#endif /* HEADER_CURL_SETUP_OS400_H */ diff --git a/external/curl prx/include/setup-vms.h b/external/curl prx/include/setup-vms.h new file mode 100644 index 0000000..6c454ae --- /dev/null +++ b/external/curl prx/include/setup-vms.h @@ -0,0 +1,443 @@ +#ifndef HEADER_CURL_SETUP_VMS_H +#define HEADER_CURL_SETUP_VMS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* */ +/* JEM, 12/30/12, VMS now generates config.h, so only define wrappers for */ +/* getenv(), getpwuid() and provide is_vms_shell() */ +/* Also need upper case symbols for system services, and */ +/* OpenSSL, and some Kerberos image */ + +#ifdef __DECC +#pragma message save +#pragma message disable dollarid +#endif + +/* Hide the stuff we are overriding */ +#define getenv decc_getenv +#ifdef __DECC +# if __INITIAL_POINTER_SIZE != 64 +# define getpwuid decc_getpwuid +# endif +#endif +#include +char *decc$getenv(const char *__name); +#include + +#include +#include + +#undef getenv +#undef getpwuid +#define getenv vms_getenv +#define getpwuid vms_getpwuid + +/* VAX needs these in upper case when compiling exact case */ +#define sys$assign SYS$ASSIGN +#define sys$dassgn SYS$DASSGN +#define sys$qiow SYS$QIOW + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __save +# endif +#endif + +#if __USE_LONG_GID_T +# define decc_getpwuid DECC$__LONG_GID_GETPWUID +#else +# if __INITIAL_POINTER_SIZE +# define decc_getpwuid decc$__32_getpwuid +# else +# define decc_getpwuid decc$getpwuid +# endif +#endif + + struct passwd * decc_getpwuid(uid_t uid); + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE == 32 +/* Translate the path, but only if the path is a VMS file specification */ +/* The translation is usually only needed for older versions of VMS */ +static char *vms_translate_path(const char *path) +{ + char *unix_path; + char *test_str; + + /* See if the result is in VMS format, if not, we are done */ + /* Assume that this is a PATH, not just some data */ + test_str = strpbrk(path, ":[<^"); + if(test_str == NULL) { + return (char *)path; + } + + unix_path = decc$translate_vms(path); + + if((int)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return (char *)path; + } +} +# else + /* VMS translate path is actually not needed on the current 64 bit */ + /* VMS platforms, so instead of figuring out the pointer settings */ + /* Change it to a noop */ +# define vms_translate_path(__path) __path +# endif +#endif + +#ifdef __DECC +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __restore +# endif +#endif + +static char *vms_getenv(const char *envvar) +{ + char *result; + char *vms_path; + + /* first use the DECC getenv() function */ + result = decc$getenv(envvar); + if(result == NULL) { + return result; + } + + vms_path = result; + result = vms_translate_path(vms_path); + + /* note that if you backport this to use VAX C RTL, that the VAX C RTL */ + /* may do a malloc(2048) for each call to getenv(), so you will need */ + /* to add a free(vms_path) */ + /* Do not do a free() for DEC C RTL builds, which should be used for */ + /* VMS 5.5-2 and later, even if using GCC */ + + return result; +} + + +static struct passwd vms_passwd_cache; + +static struct passwd * vms_getpwuid(uid_t uid) +{ + struct passwd * my_passwd; + +/* Hack needed to support 64 bit builds, decc_getpwnam is 32 bit only */ +#ifdef __DECC +# if __INITIAL_POINTER_SIZE + __char_ptr32 unix_path; +# else + char *unix_path; +# endif +#else + char *unix_path; +#endif + + my_passwd = decc_getpwuid(uid); + if(my_passwd == NULL) { + return my_passwd; + } + + unix_path = vms_translate_path(my_passwd->pw_dir); + + if((long)unix_path <= 0) { + /* We can not translate it, so return the original string */ + return my_passwd; + } + + /* If no changes needed just return it */ + if(unix_path == my_passwd->pw_dir) { + return my_passwd; + } + + /* Need to copy the structure returned */ + /* Since curl is only using pw_dir, no need to fix up */ + /* the pw_shell when running under Bash */ + vms_passwd_cache.pw_name = my_passwd->pw_name; + vms_passwd_cache.pw_uid = my_passwd->pw_uid; + vms_passwd_cache.pw_gid = my_passwd->pw_uid; + vms_passwd_cache.pw_dir = unix_path; + vms_passwd_cache.pw_shell = my_passwd->pw_shell; + + return &vms_passwd_cache; +} + +#ifdef __DECC +#pragma message restore +#endif + +/* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */ +/* VMS libraries should have universal symbols in exact and uppercase */ + +#define ASN1_INTEGER_get ASN1_INTEGER_GET +#define ASN1_STRING_data ASN1_STRING_DATA +#define ASN1_STRING_length ASN1_STRING_LENGTH +#define ASN1_STRING_print ASN1_STRING_PRINT +#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 +#define ASN1_STRING_type ASN1_STRING_TYPE +#define BIO_ctrl BIO_CTRL +#define BIO_free BIO_FREE +#define BIO_new BIO_NEW +#define BIO_s_mem BIO_S_MEM +#define BN_bn2bin BN_BN2BIN +#define BN_num_bits BN_NUM_BITS +#define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA +#define CRYPTO_free CRYPTO_FREE +#define CRYPTO_malloc CRYPTO_MALLOC +#define CONF_modules_load_file CONF_MODULES_LOAD_FILE +#ifdef __VAX +# ifdef VMS_OLD_SSL + /* Ancient OpenSSL on VAX/VMS missing this constant */ +# define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 +# undef CONF_modules_load_file + static int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags) { + return 1; + } +# endif +#endif +#define DES_ecb_encrypt DES_ECB_ENCRYPT +#define DES_set_key DES_SET_KEY +#define DES_set_odd_parity DES_SET_ODD_PARITY +#define ENGINE_ctrl ENGINE_CTRL +#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD +#define ENGINE_finish ENGINE_FINISH +#define ENGINE_free ENGINE_FREE +#define ENGINE_get_first ENGINE_GET_FIRST +#define ENGINE_get_id ENGINE_GET_ID +#define ENGINE_get_next ENGINE_GET_NEXT +#define ENGINE_init ENGINE_INIT +#define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES +#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY +#define ENGINE_set_default ENGINE_SET_DEFAULT +#define ERR_clear_error ERR_CLEAR_ERROR +#define ERR_error_string ERR_ERROR_STRING +#define ERR_error_string_n ERR_ERROR_STRING_N +#define ERR_free_strings ERR_FREE_STRINGS +#define ERR_get_error ERR_GET_ERROR +#define ERR_peek_error ERR_PEEK_ERROR +#define ERR_remove_state ERR_REMOVE_STATE +#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS +#define EVP_PKEY_free EVP_PKEY_FREE +#define EVP_cleanup EVP_CLEANUP +#define GENERAL_NAMES_free GENERAL_NAMES_FREE +#define i2d_X509_PUBKEY I2D_X509_PUBKEY +#define MD4_Final MD4_FINAL +#define MD4_Init MD4_INIT +#define MD4_Update MD4_UPDATE +#define MD5_Final MD5_FINAL +#define MD5_Init MD5_INIT +#define MD5_Update MD5_UPDATE +#define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF +#ifndef __VAX +#define OPENSSL_load_builtin_modules OPENSSL_LOAD_BUILTIN_MODULES +#endif +#define PEM_read_X509 PEM_READ_X509 +#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 +#define PKCS12_PBE_add PKCS12_PBE_ADD +#define PKCS12_free PKCS12_FREE +#define PKCS12_parse PKCS12_PARSE +#define RAND_add RAND_ADD +#define RAND_bytes RAND_BYTES +#define RAND_egd RAND_EGD +#define RAND_file_name RAND_FILE_NAME +#define RAND_load_file RAND_LOAD_FILE +#define RAND_status RAND_STATUS +#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME +#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA +#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL +#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY +#define SSL_CTX_ctrl SSL_CTX_CTRL +#define SSL_CTX_free SSL_CTX_FREE +#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE +#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS +#define SSL_CTX_new SSL_CTX_NEW +#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST +#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD +#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB +#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK +#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY +#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY +#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE +#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE +#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE +#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE +#define SSL_SESSION_free SSL_SESSION_FREE +#define SSL_connect SSL_CONNECT +#define SSL_free SSL_FREE +#define SSL_get1_session SSL_GET1_SESSION +#define SSL_get_certificate SSL_GET_CERTIFICATE +#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER +#define SSL_get_error SSL_GET_ERROR +#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN +#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE +#define SSL_get_privatekey SSL_GET_PRIVATEKEY +#define SSL_get_session SSL_GET_SESSION +#define SSL_get_shutdown SSL_GET_SHUTDOWN +#define SSL_get_verify_result SSL_GET_VERIFY_RESULT +#define SSL_library_init SSL_LIBRARY_INIT +#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS +#define SSL_new SSL_NEW +#define SSL_peek SSL_PEEK +#define SSL_pending SSL_PENDING +#define SSL_read SSL_READ +#define SSL_set_connect_state SSL_SET_CONNECT_STATE +#define SSL_set_fd SSL_SET_FD +#define SSL_set_session SSL_SET_SESSION +#define SSL_shutdown SSL_SHUTDOWN +#define SSL_version SSL_VERSION +#define SSL_write SSL_WRITE +#define SSLeay SSLEAY +#define SSLv23_client_method SSLV23_CLIENT_METHOD +#define SSLv3_client_method SSLV3_CLIENT_METHOD +#define TLSv1_client_method TLSV1_CLIENT_METHOD +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_get0_user_data UI_GET0_USER_DATA +#define UI_get_input_flags UI_GET_INPUT_FLAGS +#define UI_get_string_type UI_GET_STRING_TYPE +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_method_get_closer UI_METHOD_GET_CLOSER +#define UI_method_get_opener UI_METHOD_GET_OPENER +#define UI_method_get_reader UI_METHOD_GET_READER +#define UI_method_get_writer UI_METHOD_GET_WRITER +#define UI_method_set_closer UI_METHOD_SET_CLOSER +#define UI_method_set_opener UI_METHOD_SET_OPENER +#define UI_method_set_reader UI_METHOD_SET_READER +#define UI_method_set_writer UI_METHOD_SET_WRITER +#define UI_OpenSSL UI_OPENSSL +#define UI_set_result UI_SET_RESULT +#define X509V3_EXT_print X509V3_EXT_PRINT +#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL +#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA +#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT +#define X509_LOOKUP_file X509_LOOKUP_FILE +#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA +#define X509_NAME_get_entry X509_NAME_GET_ENTRY +#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID +#define X509_NAME_print_ex X509_NAME_PRINT_EX +#define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT +#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP +#define X509_STORE_set_flags X509_STORE_SET_FLAGS +#define X509_check_issued X509_CHECK_ISSUED +#define X509_free X509_FREE +#define X509_get_ext_d2i X509_GET_EXT_D2I +#define X509_get_issuer_name X509_GET_ISSUER_NAME +#define X509_get_pubkey X509_GET_PUBKEY +#define X509_get_serialNumber X509_GET_SERIALNUMBER +#define X509_get_subject_name X509_GET_SUBJECT_NAME +#define X509_load_crl_file X509_LOAD_CRL_FILE +#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING +#define d2i_PKCS12_fp D2I_PKCS12_FP +#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT +#define sk_num SK_NUM +#define sk_pop SK_POP +#define sk_pop_free SK_POP_FREE +#define sk_value SK_VALUE +#ifdef __VAX +#define OPENSSL_NO_SHA256 +#endif +#define SHA256_Final SHA256_FINAL +#define SHA256_Init SHA256_INIT +#define SHA256_Update SHA256_UPDATE + +#define USE_UPPERCASE_GSSAPI 1 +#define gss_seal GSS_SEAL +#define gss_unseal GSS_UNSEAL + +#define USE_UPPERCASE_KRBAPI 1 + +/* AI_NUMERICHOST needed for IP V6 support in Curl */ +#ifdef HAVE_NETDB_H +#include +#ifndef AI_NUMERICHOST +#ifdef ENABLE_IPV6 +#undef ENABLE_IPV6 +#endif +#endif +#endif + +/* VAX symbols are always in uppercase */ +#ifdef __VAX +#define inflate INFLATE +#define inflateEnd INFLATEEND +#define inflateInit2_ INFLATEINIT2_ +#define inflateInit_ INFLATEINIT_ +#define zlibVersion ZLIBVERSION +#endif + +/* Older VAX OpenSSL port defines these as Macros */ +/* Need to include the headers first and then redefine */ +/* that way a newer port will also work if some one has one */ +#ifdef __VAX + +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) +# define des_set_odd_parity DES_SET_ODD_PARITY +# define des_set_key DES_SET_KEY +# define des_ecb_encrypt DES_ECB_ENCRYPT + +# endif +# include +# ifndef OpenSSL_add_all_algorithms +# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS + void OPENSSL_ADD_ALL_ALGORITHMS(void); +# endif + + /* Curl defines these to lower case and VAX needs them in upper case */ + /* So we need static routines */ +# if (OPENSSL_VERSION_NUMBER < 0x00907001L) + +# undef des_set_odd_parity +# undef DES_set_odd_parity +# undef des_set_key +# undef DES_set_key +# undef des_ecb_encrypt +# undef DES_ecb_encrypt + + static void des_set_odd_parity(des_cblock *key) { + DES_SET_ODD_PARITY(key); + } + + static int des_set_key(const_des_cblock *key, + des_key_schedule schedule) { + return DES_SET_KEY(key, schedule); + } + + static void des_ecb_encrypt(const_des_cblock *input, + des_cblock *output, + des_key_schedule ks, int enc) { + DES_ECB_ENCRYPT(input, output, ks, enc); + } +#endif +/* Need this to stop a macro redefinition error */ +#if OPENSSL_VERSION_NUMBER < 0x00907000L +# ifdef X509_STORE_set_flags +# undef X509_STORE_set_flags +# define X509_STORE_set_flags(x,y) Curl_nop_stmt +# endif +#endif +#endif + +#endif /* HEADER_CURL_SETUP_VMS_H */ diff --git a/external/curl prx/include/share.h b/external/curl prx/include/share.h new file mode 100644 index 0000000..a7dea41 --- /dev/null +++ b/external/curl prx/include/share.h @@ -0,0 +1,66 @@ +#ifndef HEADER_CURL_SHARE_H +#define HEADER_CURL_SHARE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +#include "cookie.h" +#include "psl.h" +#include "urldata.h" +#include "conncache.h" + +/* SalfordC says "A structure member may not be volatile". Hence: + */ +#ifdef __SALFORDC__ +#define CURL_VOLATILE +#else +#define CURL_VOLATILE volatile +#endif + +/* this struct is libcurl-private, don't export details */ +struct Curl_share { + unsigned int specifier; + CURL_VOLATILE unsigned int dirty; + + curl_lock_function lockfunc; + curl_unlock_function unlockfunc; + void *clientdata; + struct conncache conn_cache; + struct curl_hash hostcache; +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + struct CookieInfo *cookies; +#endif +#ifdef USE_LIBPSL + struct PslCache psl; +#endif + + struct curl_ssl_session *sslsession; + size_t max_ssl_sessions; + long sessionage; +}; + +CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, + curl_lock_access); +CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); + +#endif /* HEADER_CURL_SHARE_H */ diff --git a/external/curl prx/include/sigpipe.h b/external/curl prx/include/sigpipe.h new file mode 100644 index 0000000..3960a13 --- /dev/null +++ b/external/curl prx/include/sigpipe.h @@ -0,0 +1,79 @@ +#ifndef HEADER_CURL_SIGPIPE_H +#define HEADER_CURL_SIGPIPE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if defined(HAVE_SIGNAL_H) && defined(HAVE_SIGACTION) && \ + (defined(USE_OPENSSL) || defined(USE_MBEDTLS)) +#include + +struct sigpipe_ignore { + struct sigaction old_pipe_act; + bool no_signal; +}; + +#define SIGPIPE_VARIABLE(x) struct sigpipe_ignore x + +/* + * sigpipe_ignore() makes sure we ignore SIGPIPE while running libcurl + * internals, and then sigpipe_restore() will restore the situation when we + * return from libcurl again. + */ +static void sigpipe_ignore(struct Curl_easy *data, + struct sigpipe_ignore *ig) +{ + /* get a local copy of no_signal because the Curl_easy might not be + around when we restore */ + ig->no_signal = data->set.no_signal; + if(!data->set.no_signal) { + struct sigaction action; + /* first, extract the existing situation */ + memset(&ig->old_pipe_act, 0, sizeof(struct sigaction)); + sigaction(SIGPIPE, NULL, &ig->old_pipe_act); + action = ig->old_pipe_act; + /* ignore this signal */ + action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &action, NULL); + } +} + +/* + * sigpipe_restore() puts back the outside world's opinion of signal handler + * and SIGPIPE handling. It MUST only be called after a corresponding + * sigpipe_ignore() was used. + */ +static void sigpipe_restore(struct sigpipe_ignore *ig) +{ + if(!ig->no_signal) + /* restore the outside state */ + sigaction(SIGPIPE, &ig->old_pipe_act, NULL); +} + +#else +/* for systems without sigaction */ +#define sigpipe_ignore(x,y) Curl_nop_stmt +#define sigpipe_restore(x) Curl_nop_stmt +#define SIGPIPE_VARIABLE(x) +#endif + +#endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/external/curl prx/include/slist.h b/external/curl prx/include/slist.h new file mode 100644 index 0000000..d73dbf6 --- /dev/null +++ b/external/curl prx/include/slist.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_SLIST_H +#define HEADER_CURL_SLIST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2013, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* + * Curl_slist_duplicate() duplicates a linked list. It always returns the + * address of the first record of the cloned list or NULL in case of an + * error (or if the input list was NULL). + */ +struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); + +/* + * Curl_slist_append_nodup() takes ownership of the given string and appends + * it to the list. + */ +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, + char *data); + +#endif /* HEADER_CURL_SLIST_H */ diff --git a/external/curl prx/include/smb.h b/external/curl prx/include/smb.h new file mode 100644 index 0000000..9ce6b56 --- /dev/null +++ b/external/curl prx/include/smb.h @@ -0,0 +1,259 @@ +#ifndef HEADER_CURL_SMB_H +#define HEADER_CURL_SMB_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014, Bill Nagel , Exacq Technologies + * Copyright (C) 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +enum smb_conn_state { + SMB_NOT_CONNECTED = 0, + SMB_CONNECTING, + SMB_NEGOTIATE, + SMB_SETUP, + SMB_CONNECTED +}; + +struct smb_conn { + enum smb_conn_state state; + char *user; + char *domain; + char *share; + unsigned char challenge[8]; + unsigned int session_key; + unsigned short uid; + char *recv_buf; + size_t upload_size; + size_t send_size; + size_t sent; + size_t got; +}; + +/* + * Definitions for SMB protocol data structures + */ +#ifdef BUILDING_CURL_SMB_C + +#if defined(_MSC_VER) || defined(__ILEC400__) +# define PACK +# pragma pack(push) +# pragma pack(1) +#elif defined(__GNUC__) +# define PACK __attribute__((packed)) +#else +# define PACK +#endif + +#define SMB_COM_CLOSE 0x04 +#define SMB_COM_READ_ANDX 0x2e +#define SMB_COM_WRITE_ANDX 0x2f +#define SMB_COM_TREE_DISCONNECT 0x71 +#define SMB_COM_NEGOTIATE 0x72 +#define SMB_COM_SETUP_ANDX 0x73 +#define SMB_COM_TREE_CONNECT_ANDX 0x75 +#define SMB_COM_NT_CREATE_ANDX 0xa2 +#define SMB_COM_NO_ANDX_COMMAND 0xff + +#define SMB_WC_CLOSE 0x03 +#define SMB_WC_READ_ANDX 0x0c +#define SMB_WC_WRITE_ANDX 0x0e +#define SMB_WC_SETUP_ANDX 0x0d +#define SMB_WC_TREE_CONNECT_ANDX 0x04 +#define SMB_WC_NT_CREATE_ANDX 0x18 + +#define SMB_FLAGS_CANONICAL_PATHNAMES 0x10 +#define SMB_FLAGS_CASELESS_PATHNAMES 0x08 +#define SMB_FLAGS2_UNICODE_STRINGS 0x8000 +#define SMB_FLAGS2_IS_LONG_NAME 0x0040 +#define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001 + +#define SMB_CAP_LARGE_FILES 0x08 +#define SMB_GENERIC_WRITE 0x40000000 +#define SMB_GENERIC_READ 0x80000000 +#define SMB_FILE_SHARE_ALL 0x07 +#define SMB_FILE_OPEN 0x01 +#define SMB_FILE_OVERWRITE_IF 0x05 + +#define SMB_ERR_NOACCESS 0x00050001 + +struct smb_header { + unsigned char nbt_type; + unsigned char nbt_flags; + unsigned short nbt_length; + unsigned char magic[4]; + unsigned char command; + unsigned int status; + unsigned char flags; + unsigned short flags2; + unsigned short pid_high; + unsigned char signature[8]; + unsigned short pad; + unsigned short tid; + unsigned short pid; + unsigned short uid; + unsigned short mid; +} PACK; + +struct smb_negotiate_response { + struct smb_header h; + unsigned char word_count; + unsigned short dialect_index; + unsigned char security_mode; + unsigned short max_mpx_count; + unsigned short max_number_vcs; + unsigned int max_buffer_size; + unsigned int max_raw_size; + unsigned int session_key; + unsigned int capabilities; + unsigned int system_time_low; + unsigned int system_time_high; + unsigned short server_time_zone; + unsigned char encryption_key_length; + unsigned short byte_count; + char bytes[1]; +} PACK; + +struct andx { + unsigned char command; + unsigned char pad; + unsigned short offset; +} PACK; + +struct smb_setup { + unsigned char word_count; + struct andx andx; + unsigned short max_buffer_size; + unsigned short max_mpx_count; + unsigned short vc_number; + unsigned int session_key; + unsigned short lengths[2]; + unsigned int pad; + unsigned int capabilities; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_tree_connect { + unsigned char word_count; + struct andx andx; + unsigned short flags; + unsigned short pw_len; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create { + unsigned char word_count; + struct andx andx; + unsigned char pad; + unsigned short name_length; + unsigned int flags; + unsigned int root_fid; + unsigned int access; + curl_off_t allocation_size; + unsigned int ext_file_attributes; + unsigned int share_access; + unsigned int create_disposition; + unsigned int create_options; + unsigned int impersonation_level; + unsigned char security_flags; + unsigned short byte_count; + char bytes[1024]; +} PACK; + +struct smb_nt_create_response { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned char op_lock_level; + unsigned short fid; + unsigned int create_disposition; + + curl_off_t create_time; + curl_off_t last_access_time; + curl_off_t last_write_time; + curl_off_t last_change_time; + unsigned int ext_file_attributes; + curl_off_t allocation_size; + curl_off_t end_of_file; + +} PACK; + +struct smb_read { + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned short max_bytes; + unsigned short min_bytes; + unsigned int timeout; + unsigned short remaining; + unsigned int offset_high; + unsigned short byte_count; +} PACK; + +struct smb_write { + struct smb_header h; + unsigned char word_count; + struct andx andx; + unsigned short fid; + unsigned int offset; + unsigned int timeout; + unsigned short write_mode; + unsigned short remaining; + unsigned short pad; + unsigned short data_length; + unsigned short data_offset; + unsigned int offset_high; + unsigned short byte_count; + unsigned char pad2; +} PACK; + +struct smb_close { + unsigned char word_count; + unsigned short fid; + unsigned int last_mtime; + unsigned short byte_count; +} PACK; + +struct smb_tree_disconnect { + unsigned char word_count; + unsigned short byte_count; +} PACK; + +#if defined(_MSC_VER) || defined(__ILEC400__) +# pragma pack(pop) +#endif + +#endif /* BUILDING_CURL_SMB_C */ + +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) + +#if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO) + +extern const struct Curl_handler Curl_handler_smb; +extern const struct Curl_handler Curl_handler_smbs; + +#endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */ + +#endif /* CURL_DISABLE_SMB && USE_NTLM && CURL_SIZEOF_CURL_OFF_T > 4 */ + +#endif /* HEADER_CURL_SMB_H */ diff --git a/external/curl prx/include/smtp.h b/external/curl prx/include/smtp.h new file mode 100644 index 0000000..b67340a --- /dev/null +++ b/external/curl prx/include/smtp.h @@ -0,0 +1,91 @@ +#ifndef HEADER_CURL_SMTP_H +#define HEADER_CURL_SMTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2009 - 2014, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "pingpong.h" +#include "curl_sasl.h" + +/**************************************************************************** + * SMTP unique setup + ***************************************************************************/ +typedef enum { + SMTP_STOP, /* do nothing state, stops the state machine */ + SMTP_SERVERGREET, /* waiting for the initial greeting immediately after + a connect */ + SMTP_EHLO, + SMTP_HELO, + SMTP_STARTTLS, + SMTP_UPGRADETLS, /* asynchronously upgrade the connection to SSL/TLS + (multi mode only) */ + SMTP_AUTH, + SMTP_COMMAND, /* VRFY, EXPN, NOOP, RSET and HELP */ + SMTP_MAIL, /* MAIL FROM */ + SMTP_RCPT, /* RCPT TO */ + SMTP_DATA, + SMTP_POSTDATA, + SMTP_QUIT, + SMTP_LAST /* never used */ +} smtpstate; + +/* This SMTP struct is used in the Curl_easy. All SMTP data that is + connection-oriented must be in smtp_conn to properly deal with the fact that + perhaps the Curl_easy is changed between the times the connection is + used. */ +struct SMTP { + curl_pp_transfer transfer; + char *custom; /* Custom Request */ + struct curl_slist *rcpt; /* Recipient list */ + size_t eob; /* Number of bytes of the EOB (End Of Body) that + have been received so far */ + bool trailing_crlf; /* Specifies if the tailing CRLF is present */ +}; + +/* smtp_conn is used for struct connection-oriented data in the connectdata + struct */ +struct smtp_conn { + struct pingpong pp; + smtpstate state; /* Always use smtp.c:state() to change state! */ + bool ssldone; /* Is connect() over SSL done? */ + char *domain; /* Client address/name to send in the EHLO */ + struct SASL sasl; /* SASL-related storage */ + bool tls_supported; /* StartTLS capability supported by server */ + bool size_supported; /* If server supports SIZE extension according to + RFC 1870 */ + bool auth_supported; /* AUTH capability supported by server */ +}; + +extern const struct Curl_handler Curl_handler_smtp; +extern const struct Curl_handler Curl_handler_smtps; + +/* this is the 5-bytes End-Of-Body marker for SMTP */ +#define SMTP_EOB "\x0d\x0a\x2e\x0d\x0a" +#define SMTP_EOB_LEN 5 +#define SMTP_EOB_FIND_LEN 3 + +/* if found in data, replace it with this string instead */ +#define SMTP_EOB_REPL "\x0d\x0a\x2e\x2e" +#define SMTP_EOB_REPL_LEN 4 + +CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread); + +#endif /* HEADER_CURL_SMTP_H */ diff --git a/external/curl prx/include/sockaddr.h b/external/curl prx/include/sockaddr.h new file mode 100644 index 0000000..6379f5f --- /dev/null +++ b/external/curl prx/include/sockaddr.h @@ -0,0 +1,42 @@ +#ifndef HEADER_CURL_SOCKADDR_H +#define HEADER_CURL_SOCKADDR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2009, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" +#include +struct Curl_sockaddr_storage { + union { + struct sockaddr sa; + struct sockaddr_in sa_in; +#ifdef ENABLE_IPV6 + struct sockaddr_in6 sa_in6; +#endif +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + struct sockaddr_storage sa_stor; +#else + char cbuf[256]; /* this should be big enough to fit a lot */ +#endif + } buffer; +}; + +#endif /* HEADER_CURL_SOCKADDR_H */ diff --git a/external/curl prx/include/socks.h b/external/curl prx/include/socks.h new file mode 100644 index 0000000..daa07c1 --- /dev/null +++ b/external/curl prx/include/socks.h @@ -0,0 +1,75 @@ +#ifndef HEADER_CURL_SOCKS_H +#define HEADER_CURL_SOCKS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef CURL_DISABLE_PROXY +#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN +#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN +#else +/* + * Helper read-from-socket functions. Does the same as Curl_read() but it + * blocks until all bytes amount of buffersize will be read. No more, no less. + * + * This is STUPID BLOCKING behaviour which we frown upon, but right now this + * is what we have... + */ +int Curl_blockread_all(struct connectdata *conn, + curl_socket_t sockfd, + char *buf, + ssize_t buffersize, + ssize_t *n); + +/* + * This function logs in to a SOCKS4(a) proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS4(const char *proxy_name, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +/* + * This function logs in to a SOCKS5 proxy and sends the specifics to the + * final destination server. + */ +CURLcode Curl_SOCKS5(const char *proxy_name, + const char *proxy_password, + const char *hostname, + int remote_port, + int sockindex, + struct connectdata *conn); + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) +/* + * This function handles the SOCKS5 GSS-API negotiation and initialisation + */ +CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex, + struct connectdata *conn); +#endif + +#endif /* CURL_DISABLE_PROXY */ + +#endif /* HEADER_CURL_SOCKS_H */ diff --git a/external/curl prx/include/speedcheck.h b/external/curl prx/include/speedcheck.h new file mode 100644 index 0000000..5c2dc9a --- /dev/null +++ b/external/curl prx/include/speedcheck.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURL_SPEEDCHECK_H +#define HEADER_CURL_SPEEDCHECK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include "timeval.h" + +void Curl_speedinit(struct Curl_easy *data); +CURLcode Curl_speedcheck(struct Curl_easy *data, + struct curltime now); + +#endif /* HEADER_CURL_SPEEDCHECK_H */ diff --git a/external/curl prx/include/splay.h b/external/curl prx/include/splay.h new file mode 100644 index 0000000..4612ec2 --- /dev/null +++ b/external/curl prx/include/splay.h @@ -0,0 +1,68 @@ +#ifndef HEADER_CURL_SPLAY_H +#define HEADER_CURL_SPLAY_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1997 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include "timeval.h" + +struct Curl_tree { + struct Curl_tree *smaller; /* smaller node */ + struct Curl_tree *larger; /* larger node */ + struct Curl_tree *samen; /* points to the next node with identical key */ + struct Curl_tree *samep; /* points to the prev node with identical key */ + struct curltime key; /* this node's "sort" key */ + void *payload; /* data the splay code doesn't care about */ +}; + +struct Curl_tree *Curl_splay(struct curltime i, + struct Curl_tree *t); + +struct Curl_tree *Curl_splayinsert(struct curltime key, + struct Curl_tree *t, + struct Curl_tree *newnode); + +#if 0 +struct Curl_tree *Curl_splayremove(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); +#endif + +struct Curl_tree *Curl_splaygetbest(struct curltime key, + struct Curl_tree *t, + struct Curl_tree **removed); + +int Curl_splayremovebyaddr(struct Curl_tree *t, + struct Curl_tree *removenode, + struct Curl_tree **newroot); + +#define Curl_splaycomparekeys(i,j) ( ((i.tv_sec) < (j.tv_sec)) ? -1 : \ + ( ((i.tv_sec) > (j.tv_sec)) ? 1 : \ + ( ((i.tv_usec) < (j.tv_usec)) ? -1 : \ + ( ((i.tv_usec) > (j.tv_usec)) ? 1 : 0)))) + +#ifdef DEBUGBUILD +void Curl_splayprint(struct Curl_tree * t, int d, char output); +#else +#define Curl_splayprint(x,y,z) Curl_nop_stmt +#endif + +#endif /* HEADER_CURL_SPLAY_H */ diff --git a/external/curl prx/include/ssh.h b/external/curl prx/include/ssh.h new file mode 100644 index 0000000..0620aac --- /dev/null +++ b/external/curl prx/include/ssh.h @@ -0,0 +1,245 @@ +#ifndef HEADER_CURL_SSH_H +#define HEADER_CURL_SSH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(HAVE_LIBSSH2_H) +#include +#include +#elif defined(HAVE_LIBSSH_LIBSSH_H) +#include +#include +#endif /* HAVE_LIBSSH2_H */ + +/**************************************************************************** + * SSH unique setup + ***************************************************************************/ +typedef enum { + SSH_NO_STATE = -1, /* Used for "nextState" so say there is none */ + SSH_STOP = 0, /* do nothing state, stops the state machine */ + + SSH_INIT, /* First state in SSH-CONNECT */ + SSH_S_STARTUP, /* Session startup */ + SSH_HOSTKEY, /* verify hostkey */ + SSH_AUTHLIST, + SSH_AUTH_PKEY_INIT, + SSH_AUTH_PKEY, + SSH_AUTH_PASS_INIT, + SSH_AUTH_PASS, + SSH_AUTH_AGENT_INIT, /* initialize then wait for connection to agent */ + SSH_AUTH_AGENT_LIST, /* ask for list then wait for entire list to come */ + SSH_AUTH_AGENT, /* attempt one key at a time */ + SSH_AUTH_HOST_INIT, + SSH_AUTH_HOST, + SSH_AUTH_KEY_INIT, + SSH_AUTH_KEY, + SSH_AUTH_GSSAPI, + SSH_AUTH_DONE, + SSH_SFTP_INIT, + SSH_SFTP_REALPATH, /* Last state in SSH-CONNECT */ + + SSH_SFTP_QUOTE_INIT, /* First state in SFTP-DO */ + SSH_SFTP_POSTQUOTE_INIT, /* (Possibly) First state in SFTP-DONE */ + SSH_SFTP_QUOTE, + SSH_SFTP_NEXT_QUOTE, + SSH_SFTP_QUOTE_STAT, + SSH_SFTP_QUOTE_SETSTAT, + SSH_SFTP_QUOTE_SYMLINK, + SSH_SFTP_QUOTE_MKDIR, + SSH_SFTP_QUOTE_RENAME, + SSH_SFTP_QUOTE_RMDIR, + SSH_SFTP_QUOTE_UNLINK, + SSH_SFTP_QUOTE_STATVFS, + SSH_SFTP_GETINFO, + SSH_SFTP_FILETIME, + SSH_SFTP_TRANS_INIT, + SSH_SFTP_UPLOAD_INIT, + SSH_SFTP_CREATE_DIRS_INIT, + SSH_SFTP_CREATE_DIRS, + SSH_SFTP_CREATE_DIRS_MKDIR, + SSH_SFTP_READDIR_INIT, + SSH_SFTP_READDIR, + SSH_SFTP_READDIR_LINK, + SSH_SFTP_READDIR_BOTTOM, + SSH_SFTP_READDIR_DONE, + SSH_SFTP_DOWNLOAD_INIT, + SSH_SFTP_DOWNLOAD_STAT, /* Last state in SFTP-DO */ + SSH_SFTP_CLOSE, /* Last state in SFTP-DONE */ + SSH_SFTP_SHUTDOWN, /* First state in SFTP-DISCONNECT */ + SSH_SCP_TRANS_INIT, /* First state in SCP-DO */ + SSH_SCP_UPLOAD_INIT, + SSH_SCP_DOWNLOAD_INIT, + SSH_SCP_DOWNLOAD, + SSH_SCP_DONE, + SSH_SCP_SEND_EOF, + SSH_SCP_WAIT_EOF, + SSH_SCP_WAIT_CLOSE, + SSH_SCP_CHANNEL_FREE, /* Last state in SCP-DONE */ + SSH_SESSION_DISCONNECT, /* First state in SCP-DISCONNECT */ + SSH_SESSION_FREE, /* Last state in SCP/SFTP-DISCONNECT */ + SSH_QUIT, + SSH_LAST /* never used */ +} sshstate; + +/* this struct is used in the HandleData struct which is part of the + Curl_easy, which means this is used on a per-easy handle basis. + Everything that is strictly related to a connection is banned from this + struct. */ +struct SSHPROTO { + char *path; /* the path we operate on */ +}; + +/* ssh_conn is used for struct connection-oriented data in the connectdata + struct */ +struct ssh_conn { + const char *authlist; /* List of auth. methods, managed by libssh2 */ + + /* common */ + const char *passphrase; /* pass-phrase to use */ + char *rsa_pub; /* path name */ + char *rsa; /* path name */ + bool authed; /* the connection has been authenticated fine */ + sshstate state; /* always use ssh.c:state() to change state! */ + sshstate nextstate; /* the state to goto after stopping */ + CURLcode actualcode; /* the actual error code */ + struct curl_slist *quote_item; /* for the quote option */ + char *quote_path1; /* two generic pointers for the QUOTE stuff */ + char *quote_path2; + + bool acceptfail; /* used by the SFTP_QUOTE (continue if + quote command fails) */ + char *homedir; /* when doing SFTP we figure out home dir in the + connect phase */ + size_t readdir_len, readdir_totalLen, readdir_currLen; + char *readdir_line; + char *readdir_linkPath; + /* end of READDIR stuff */ + + int secondCreateDirs; /* counter use by the code to see if the + second attempt has been made to change + to/create a directory */ + char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ + + int orig_waitfor; /* default READ/WRITE bits wait for */ + +#if defined(USE_LIBSSH) +/* our variables */ + unsigned kbd_state; /* 0 or 1 */ + ssh_key privkey; + ssh_key pubkey; + int auth_methods; + ssh_session ssh_session; + ssh_scp scp_session; + sftp_session sftp_session; + sftp_file sftp_file; + sftp_dir sftp_dir; + + unsigned sftp_recv_state; /* 0 or 1 */ + int sftp_file_index; /* for async read */ + sftp_attributes readdir_attrs; /* used by the SFTP readdir actions */ + sftp_attributes readdir_link_attrs; /* used by the SFTP readdir actions */ + sftp_attributes quote_attrs; /* used by the SFTP_QUOTE state */ + + const char *readdir_filename; /* points within readdir_attrs */ + const char *readdir_longentry; + char *readdir_tmp; +#elif defined(USE_LIBSSH2) + char *readdir_filename; + char *readdir_longentry; + + LIBSSH2_SFTP_ATTRIBUTES quote_attrs; /* used by the SFTP_QUOTE state */ + + /* Here's a set of struct members used by the SFTP_READDIR state */ + LIBSSH2_SFTP_ATTRIBUTES readdir_attrs; + LIBSSH2_SESSION *ssh_session; /* Secure Shell session */ + LIBSSH2_CHANNEL *ssh_channel; /* Secure Shell channel handle */ + LIBSSH2_SFTP *sftp_session; /* SFTP handle */ + LIBSSH2_SFTP_HANDLE *sftp_handle; + +#ifdef HAVE_LIBSSH2_AGENT_API + LIBSSH2_AGENT *ssh_agent; /* proxy to ssh-agent/pageant */ + struct libssh2_agent_publickey *sshagent_identity, + *sshagent_prev_identity; +#endif + + /* note that HAVE_LIBSSH2_KNOWNHOST_API is a define set in the libssh2.h + header */ +#ifdef HAVE_LIBSSH2_KNOWNHOST_API + LIBSSH2_KNOWNHOSTS *kh; +#endif +#endif /* USE_LIBSSH */ +}; + +#if defined(USE_LIBSSH) + +#define CURL_LIBSSH_VERSION ssh_version(0) + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#elif defined(USE_LIBSSH2) + +/* Feature detection based on version numbers to better work with + non-configure platforms */ + +#if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x001000) +# error "SCP/SFTP protocols require libssh2 0.16 or later" +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010000 +#define HAVE_LIBSSH2_SFTP_SEEK64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010100 +#define HAVE_LIBSSH2_VERSION 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010205 +#define HAVE_LIBSSH2_INIT 1 +#define HAVE_LIBSSH2_EXIT 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010206 +#define HAVE_LIBSSH2_KNOWNHOST_CHECKP 1 +#define HAVE_LIBSSH2_SCP_SEND64 1 +#endif + +#if LIBSSH2_VERSION_NUM >= 0x010208 +#define HAVE_LIBSSH2_SESSION_HANDSHAKE 1 +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +extern const struct Curl_handler Curl_handler_scp; +extern const struct Curl_handler Curl_handler_sftp; + +#endif /* USE_LIBSSH2 */ + +#endif /* HEADER_CURL_SSH_H */ diff --git a/external/curl prx/include/strcase.h b/external/curl prx/include/strcase.h new file mode 100644 index 0000000..6fee384 --- /dev/null +++ b/external/curl prx/include/strcase.h @@ -0,0 +1,50 @@ +#ifndef HEADER_CURL_STRCASE_H +#define HEADER_CURL_STRCASE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +/* + * Only "raw" case insensitive strings. This is meant to be locale independent + * and only compare strings we know are safe for this. + * + * The function is capable of comparing a-z case insensitively even for + * non-ascii. + */ + +#define strcasecompare(a,b) Curl_strcasecompare(a,b) +#define strncasecompare(a,b,c) Curl_strncasecompare(a,b,c) + +int Curl_strcasecompare(const char *first, const char *second); +int Curl_safe_strcasecompare(const char *first, const char *second); +int Curl_strncasecompare(const char *first, const char *second, size_t max); + +char Curl_raw_toupper(char in); + +/* checkprefix() is a shorter version of the above, used when the first + argument is zero-byte terminated */ +#define checkprefix(a,b) curl_strnequal(a,b,strlen(a)) + +void Curl_strntoupper(char *dest, const char *src, size_t n); + +#endif /* HEADER_CURL_STRCASE_H */ diff --git a/external/curl prx/include/strdup.h b/external/curl prx/include/strdup.h new file mode 100644 index 0000000..ae3d5d0 --- /dev/null +++ b/external/curl prx/include/strdup.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_STRDUP_H +#define HEADER_CURL_STRDUP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifndef HAVE_STRDUP +extern char *curlx_strdup(const char *str); +#endif +void *Curl_memdup(const void *src, size_t buffer_length); +void *Curl_saferealloc(void *ptr, size_t size); + +#endif /* HEADER_CURL_STRDUP_H */ diff --git a/external/curl prx/include/strerror.h b/external/curl prx/include/strerror.h new file mode 100644 index 0000000..683b5b4 --- /dev/null +++ b/external/curl prx/include/strerror.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRERROR_H +#define HEADER_CURL_STRERROR_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "urldata.h" + +#define STRERROR_LEN 128 /* a suitable length */ + +const char *Curl_strerror(int err, char *buf, size_t buflen); +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); +#endif + +#endif /* HEADER_CURL_STRERROR_H */ diff --git a/external/curl prx/include/strtok.h b/external/curl prx/include/strtok.h new file mode 100644 index 0000000..90b831e --- /dev/null +++ b/external/curl prx/include/strtok.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_STRTOK_H +#define HEADER_CURL_STRTOK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +#include + +#ifndef HAVE_STRTOK_R +char *Curl_strtok_r(char *s, const char *delim, char **last); +#define strtok_r Curl_strtok_r +#else +#include +#endif + +#endif /* HEADER_CURL_STRTOK_H */ diff --git a/external/curl prx/include/strtoofft.h b/external/curl prx/include/strtoofft.h new file mode 100644 index 0000000..be19cd7 --- /dev/null +++ b/external/curl prx/include/strtoofft.h @@ -0,0 +1,52 @@ +#ifndef HEADER_CURL_STRTOOFFT_H +#define HEADER_CURL_STRTOOFFT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * Determine which string to integral data type conversion function we use + * to implement string conversion to our curl_off_t integral data type. + * + * Notice that curl_off_t might be 64 or 32 bit wide, and that it might use + * an underlying data type which might be 'long', 'int64_t', 'long long' or + * '__int64' and more remotely other data types. + * + * On systems where the size of curl_off_t is greater than the size of 'long' + * the conversion function to use is strtoll() if it is available, otherwise, + * we emulate its functionality with our own clone. + * + * On systems where the size of curl_off_t is smaller or equal than the size + * of 'long' the conversion function to use is strtol(). + */ + +typedef enum { + CURL_OFFT_OK, /* parsed fine */ + CURL_OFFT_FLOW, /* over or underflow */ + CURL_OFFT_INVAL /* nothing was parsed */ +} CURLofft; + +CURLofft curlx_strtoofft(const char *str, char **endp, int base, + curl_off_t *num); + +#endif /* HEADER_CURL_STRTOOFFT_H */ diff --git a/external/curl prx/include/system_win32.h b/external/curl prx/include/system_win32.h new file mode 100644 index 0000000..926328a --- /dev/null +++ b/external/curl prx/include/system_win32.h @@ -0,0 +1,67 @@ +#ifndef HEADER_CURL_SYSTEM_WIN32_H +#define HEADER_CURL_SYSTEM_WIN32_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2016, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(WIN32) + +extern LARGE_INTEGER Curl_freq; +extern bool Curl_isVistaOrGreater; + +CURLcode Curl_win32_init(long flags); +void Curl_win32_cleanup(long init_flags); + +/* Version condition */ +typedef enum { + VERSION_LESS_THAN, + VERSION_LESS_THAN_EQUAL, + VERSION_EQUAL, + VERSION_GREATER_THAN_EQUAL, + VERSION_GREATER_THAN +} VersionCondition; + +/* Platform identifier */ +typedef enum { + PLATFORM_DONT_CARE, + PLATFORM_WINDOWS, + PLATFORM_WINNT +} PlatformIdentifier; + +/* This is used to verify if we are running on a specific windows version */ +bool Curl_verify_windows_version(const unsigned int majorVersion, + const unsigned int minorVersion, + const PlatformIdentifier platform, + const VersionCondition condition); + +#if defined(USE_WINDOWS_SSPI) || (!defined(CURL_DISABLE_TELNET) && \ + defined(USE_WINSOCK)) + +/* This is used to dynamically load DLLs */ +HMODULE Curl_load_library(LPCTSTR filename); + +#endif /* USE_WINDOWS_SSPI || (!CURL_DISABLE_TELNET && USE_WINSOCK) */ + +#endif /* WIN32 */ + +#endif /* HEADER_CURL_SYSTEM_WIN32_H */ diff --git a/external/curl prx/include/telnet.h b/external/curl prx/include/telnet.h new file mode 100644 index 0000000..668a78a --- /dev/null +++ b/external/curl prx/include/telnet.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TELNET_H +#define HEADER_CURL_TELNET_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TELNET +extern const struct Curl_handler Curl_handler_telnet; +#endif + +#endif /* HEADER_CURL_TELNET_H */ diff --git a/external/curl prx/include/tftp.h b/external/curl prx/include/tftp.h new file mode 100644 index 0000000..1335f64 --- /dev/null +++ b/external/curl prx/include/tftp.h @@ -0,0 +1,28 @@ +#ifndef HEADER_CURL_TFTP_H +#define HEADER_CURL_TFTP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2007, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#ifndef CURL_DISABLE_TFTP +extern const struct Curl_handler Curl_handler_tftp; +#endif + +#endif /* HEADER_CURL_TFTP_H */ diff --git a/external/curl prx/include/timeval.h b/external/curl prx/include/timeval.h new file mode 100644 index 0000000..96867d7 --- /dev/null +++ b/external/curl prx/include/timeval.h @@ -0,0 +1,58 @@ +#ifndef HEADER_CURL_TIMEVAL_H +#define HEADER_CURL_TIMEVAL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if SIZEOF_TIME_T < 8 +typedef int timediff_t; +#define CURL_FORMAT_TIMEDIFF_T "d" +#else +typedef curl_off_t timediff_t; +#define CURL_FORMAT_TIMEDIFF_T CURL_FORMAT_CURL_OFF_T +#endif + +struct curltime { + time_t tv_sec; /* seconds */ + int tv_usec; /* microseconds */ +}; + +struct curltime Curl_now(void); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +timediff_t Curl_timediff(struct curltime t1, struct curltime t2); + +/* + * Make sure that the first argument (t1) is the more recent time and t2 is + * the older time, as otherwise you get a weird negative time-diff back... + * + * Returns: the time difference in number of microseconds. + */ +timediff_t Curl_timediff_us(struct curltime newer, struct curltime older); + +#endif /* HEADER_CURL_TIMEVAL_H */ diff --git a/external/curl prx/include/transfer.h b/external/curl prx/include/transfer.h new file mode 100644 index 0000000..a9bff63 --- /dev/null +++ b/external/curl prx/include/transfer.h @@ -0,0 +1,71 @@ +#ifndef HEADER_CURL_TRANSFER_H +#define HEADER_CURL_TRANSFER_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#define Curl_headersep(x) ((((x)==':') || ((x)==';'))) +char *Curl_checkheaders(const struct connectdata *conn, + const char *thisheader); + +void Curl_init_CONNECT(struct Curl_easy *data); + +CURLcode Curl_pretransfer(struct Curl_easy *data); +CURLcode Curl_second_connect(struct connectdata *conn); +CURLcode Curl_posttransfer(struct Curl_easy *data); + +typedef enum { + FOLLOW_NONE, /* not used within the function, just a placeholder to + allow initing to this */ + FOLLOW_FAKE, /* only records stuff, not actually following */ + FOLLOW_RETRY, /* set if this is a request retry as opposed to a real + redirect following */ + FOLLOW_REDIR, /* a full true redirect */ + FOLLOW_LAST /* never used */ +} followtype; + +CURLcode Curl_follow(struct Curl_easy *data, char *newurl, + followtype type); +CURLcode Curl_readwrite(struct connectdata *conn, + struct Curl_easy *data, bool *done, + bool *comeback); +int Curl_single_getsock(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_readrewind(struct connectdata *conn); +CURLcode Curl_fillreadbuffer(struct connectdata *conn, size_t bytes, + size_t *nreadp); +CURLcode Curl_retry_request(struct connectdata *conn, char **url); +bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); +CURLcode Curl_get_upload_buffer(struct Curl_easy *data); + +/* This sets up a forthcoming transfer */ +void +Curl_setup_transfer (struct Curl_easy *data, + int sockindex, /* socket index to read from or -1 */ + curl_off_t size, /* -1 if unknown at this point */ + bool getheader, /* TRUE if header parsing is wanted */ + int writesockindex /* socket index to write to. May be + the same we read from. -1 + disables */ + ); + +#endif /* HEADER_CURL_TRANSFER_H */ diff --git a/external/curl prx/include/url.h b/external/curl prx/include/url.h new file mode 100644 index 0000000..fbd8ef9 --- /dev/null +++ b/external/curl prx/include/url.h @@ -0,0 +1,110 @@ +#ifndef HEADER_CURL_URL_H +#define HEADER_CURL_URL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE +#define READBUFFER_MAX CURL_MAX_READ_SIZE +#define READBUFFER_MIN 1024 + +/* The default upload buffer size, should not be smaller than + CURL_MAX_WRITE_SIZE, as it needs to hold a full buffer as could be sent in + a write callback. + + The size was 16KB for many years but was bumped to 64KB because it makes + libcurl able to do significantly faster uploads in some circumstances. Even + larger buffers can help further, but this is deemed a fair memory/speed + compromise. */ +#define UPLOADBUFFER_DEFAULT 65536 +#define UPLOADBUFFER_MAX (2*1024*1024) +#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE + +/* + * Prototypes for library-wide functions provided by url.c + */ + +CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn); +CURLcode Curl_open(struct Curl_easy **curl); +CURLcode Curl_init_userdefined(struct Curl_easy *data); + +void Curl_freeset(struct Curl_easy * data); +/* free the URL pieces */ +void Curl_up_free(struct Curl_easy *data); +CURLcode Curl_uc_to_curlcode(CURLUcode uc); +CURLcode Curl_close(struct Curl_easy *data); /* opposite of curl_open() */ +CURLcode Curl_connect(struct Curl_easy *, bool *async, bool *protocol_connect); +CURLcode Curl_disconnect(struct Curl_easy *data, + struct connectdata *, bool dead_connection); +CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_connecting(struct connectdata *conn, bool *done); +CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done); +CURLcode Curl_setup_conn(struct connectdata *conn, + bool *protocol_done); +void Curl_free_request_state(struct Curl_easy *data); + +int Curl_protocol_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +int Curl_doing_getsock(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); +CURLcode Curl_parse_login_details(const char *login, const size_t len, + char **userptr, char **passwdptr, + char **optionsptr); + +int Curl_removeHandleFromPipeline(struct Curl_easy *handle, + struct curl_llist *pipeline); +/* remove the specified connection from all (possible) pipelines and related + queues */ +void Curl_getoff_all_pipelines(struct Curl_easy *data, + struct connectdata *conn); + +CURLcode Curl_upkeep(struct conncache *conn_cache, void *data); + +const struct Curl_handler *Curl_builtin_scheme(const char *scheme); + +#define CURL_DEFAULT_PROXY_PORT 1080 /* default proxy port unless specified */ +#define CURL_DEFAULT_HTTPS_PROXY_PORT 443 /* default https proxy port unless + specified */ + +CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); + +#ifdef CURL_DISABLE_VERBOSE_STRINGS +#define Curl_verboseconnect(x) Curl_nop_stmt +#else +void Curl_verboseconnect(struct connectdata *conn); +#endif + +#define CONNECT_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[sockindex]) + +#define CONNECT_FIRSTSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[FIRSTSOCKET]) + +#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\ + (conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\ + !conn->bits.proxy_ssl_connected[SECONDARYSOCKET]) + +#endif /* HEADER_CURL_URL_H */ diff --git a/external/curl prx/include/urlapi-int.h b/external/curl prx/include/urlapi-int.h new file mode 100644 index 0000000..75a3605 --- /dev/null +++ b/external/curl prx/include/urlapi-int.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_URLAPI_INT_H +#define HEADER_CURL_URLAPI_INT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" +/* scheme is not URL encoded, the longest libcurl supported ones are 6 + letters */ +#define MAX_SCHEME_LEN 8 + +bool Curl_is_absolute_url(const char *url, char *scheme, size_t buflen); +char *Curl_concat_url(const char *base, const char *relurl); +size_t Curl_strlen_url(const char *url, bool relative); +void Curl_strcpy_url(char *output, const char *url, bool relative); + +#ifdef DEBUGBUILD +CURLUcode Curl_parse_port(struct Curl_URL *u, char *hostname); +#endif + +#endif /* HEADER_CURL_URLAPI_INT_H */ diff --git a/external/curl prx/include/urldata.h b/external/curl prx/include/urldata.h new file mode 100644 index 0000000..24187a4 --- /dev/null +++ b/external/curl prx/include/urldata.h @@ -0,0 +1,1826 @@ +#ifndef HEADER_CURL_URLDATA_H +#define HEADER_CURL_URLDATA_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* This file is for lib internal stuff */ + +#include "curl_setup.h" + +#define PORT_FTP 21 +#define PORT_FTPS 990 +#define PORT_TELNET 23 +#define PORT_HTTP 80 +#define PORT_HTTPS 443 +#define PORT_DICT 2628 +#define PORT_LDAP 389 +#define PORT_LDAPS 636 +#define PORT_TFTP 69 +#define PORT_SSH 22 +#define PORT_IMAP 143 +#define PORT_IMAPS 993 +#define PORT_POP3 110 +#define PORT_POP3S 995 +#define PORT_SMB 445 +#define PORT_SMBS 445 +#define PORT_SMTP 25 +#define PORT_SMTPS 465 /* sometimes called SSMTP */ +#define PORT_RTSP 554 +#define PORT_RTMP 1935 +#define PORT_RTMPT PORT_HTTP +#define PORT_RTMPS PORT_HTTPS +#define PORT_GOPHER 70 + +#define DICT_MATCH "/MATCH:" +#define DICT_MATCH2 "/M:" +#define DICT_MATCH3 "/FIND:" +#define DICT_DEFINE "/DEFINE:" +#define DICT_DEFINE2 "/D:" +#define DICT_DEFINE3 "/LOOKUP:" + +#define CURL_DEFAULT_USER "anonymous" +#define CURL_DEFAULT_PASSWORD "ftp@example.com" + +/* Convenience defines for checking protocols or their SSL based version. Each + protocol handler should only ever have a single CURLPROTO_ in its protocol + field. */ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) +#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) + +#define DEFAULT_CONNCACHE_SIZE 5 + +/* length of longest IPv6 address string including the trailing null */ +#define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + +/* Default FTP/IMAP etc response timeout in milliseconds. + Symbian OS panics when given a timeout much greater than 1/2 hour. +*/ +#define RESP_TIMEOUT (120*1000) + +#include "cookie.h" +#include "psl.h" +#include "formdata.h" + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif + +#include "timeval.h" + +#include + +#include "http_chunks.h" /* for the structs and enum stuff */ +#include "hostip.h" +#include "hash.h" +#include "splay.h" + +/* return the count of bytes sent, or -1 on error */ +typedef ssize_t (Curl_send)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *buf, /* data to write */ + size_t len, /* max amount to write */ + CURLcode *err); /* error to return */ + +/* return the count of bytes read, or -1 on error */ +typedef ssize_t (Curl_recv)(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + char *buf, /* store data here */ + size_t len, /* max amount to read */ + CURLcode *err); /* error to return */ + +#include "mime.h" +#include "imap.h" +#include "pop3.h" +#include "smtp.h" +#include "ftp.h" +#include "file.h" +#include "ssh.h" +#include "http.h" +#include "rtsp.h" +#include "smb.h" +#include "wildcard.h" +#include "multihandle.h" + +#ifdef HAVE_GSSAPI +# ifdef HAVE_GSSGNU +# include +# elif defined HAVE_GSSAPI_GSSAPI_H +# include +# else +# include +# endif +# ifdef HAVE_GSSAPI_GSSAPI_GENERIC_H +# include +# endif +#endif + +#ifdef HAVE_LIBSSH2_H +#include +#include +#endif /* HAVE_LIBSSH2_H */ + + +/* The "master buffer" is for HTTP pipelining */ +#define MASTERBUF_SIZE 16384 + +/* Initial size of the buffer to store headers in, it'll be enlarged in case + of need. */ +#define HEADERSIZE 256 + +#define CURLEASY_MAGIC_NUMBER 0xc0dedbadU +#define GOOD_EASY_HANDLE(x) \ + ((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) + +/* the type we use for storing a single boolean bit */ +typedef unsigned int bit; + +#ifdef HAVE_GSSAPI +/* Types needed for krb5-ftp connections */ +struct krb5buffer { + void *data; + size_t size; + size_t index; + bit eof_flag:1; +}; + +enum protection_level { + PROT_NONE, /* first in list */ + PROT_CLEAR, + PROT_SAFE, + PROT_CONFIDENTIAL, + PROT_PRIVATE, + PROT_CMD, + PROT_LAST /* last in list */ +}; +#endif + +/* enum for the nonblocking SSL connection state machine */ +typedef enum { + ssl_connect_1, + ssl_connect_2, + ssl_connect_2_reading, + ssl_connect_2_writing, + ssl_connect_3, + ssl_connect_done +} ssl_connect_state; + +typedef enum { + ssl_connection_none, + ssl_connection_negotiating, + ssl_connection_complete +} ssl_connection_state; + +/* SSL backend-specific data; declared differently by each SSL backend */ +struct ssl_backend_data; + +/* struct for data related to each SSL connection */ +struct ssl_connect_data { + /* Use ssl encrypted communications TRUE/FALSE, not necessarily using it atm + but at least asked to or meaning to use it. See 'state' for the exact + current state of the connection. */ + ssl_connection_state state; + ssl_connect_state connecting_state; +#if defined(USE_SSL) + struct ssl_backend_data *backend; +#endif + bit use:1; +}; + +struct ssl_primary_config { + long version; /* what version the client wants to use */ + long version_max; /* max supported version the client wants to use*/ + char *CApath; /* certificate dir (doesn't work on windows) */ + char *CAfile; /* certificate to verify peer against */ + char *clientcert; + char *random_file; /* path to file containing "random" data */ + char *egdsocket; /* path to file containing the EGD daemon socket */ + char *cipher_list; /* list of ciphers to use */ + char *cipher_list13; /* list of TLS 1.3 cipher suites to use */ + bit verifypeer:1; /* set TRUE if this is desired */ + bit verifyhost:1; /* set TRUE if CN/SAN must match hostname */ + bit verifystatus:1; /* set TRUE if certificate status must be checked */ + bit sessionid:1; /* cache session IDs or not */ +}; + +struct ssl_config_data { + struct ssl_primary_config primary; + long certverifyresult; /* result from the certificate verification */ + char *CRLfile; /* CRL to check certificate revocation */ + char *issuercert;/* optional issuer certificate filename */ + curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ + void *fsslctxp; /* parameter for call back */ + char *cert; /* client certificate file name */ + char *cert_type; /* format for certificate (default: PEM)*/ + char *key; /* private key file name */ + char *key_type; /* format for private key (default: PEM) */ + char *key_passwd; /* plain text private key password */ +#ifdef USE_TLS_SRP + char *username; /* TLS username (for, e.g., SRP) */ + char *password; /* TLS password (for, e.g., SRP) */ + enum CURL_TLSAUTH authtype; /* TLS authentication type (default SRP) */ +#endif + bit certinfo:1; /* gather lots of certificate info */ + bit falsestart:1; + bit enable_beast:1; /* allow this flaw for interoperability's sake*/ + bit no_revoke:1; /* disable SSL certificate revocation checks */ +}; + +struct ssl_general_config { + size_t max_ssl_sessions; /* SSL session id cache size */ +}; + +/* information stored about one single SSL session */ +struct curl_ssl_session { + char *name; /* host name for which this ID was used */ + char *conn_to_host; /* host name for the connection (may be NULL) */ + const char *scheme; /* protocol scheme used */ + void *sessionid; /* as returned from the SSL layer */ + size_t idsize; /* if known, otherwise 0 */ + long age; /* just a number, the higher the more recent */ + int remote_port; /* remote port */ + int conn_to_port; /* remote port for the connection (may be -1) */ + struct ssl_primary_config ssl_config; /* setup for this session */ +}; + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +/* Struct used for Digest challenge-response authentication */ +struct digestdata { +#if defined(USE_WINDOWS_SSPI) + BYTE *input_token; + size_t input_token_len; + CtxtHandle *http_context; + /* copy of user/passwd used to make the identity for http_context. + either may be NULL. */ + char *user; + char *passwd; +#else + char *nonce; + char *cnonce; + char *realm; + int algo; + char *opaque; + char *qop; + char *algorithm; + int nc; /* nounce count */ + bit stale:1; /* set true for re-negotiation */ + bit userhash:1; +#endif +}; + +typedef enum { + NTLMSTATE_NONE, + NTLMSTATE_TYPE1, + NTLMSTATE_TYPE2, + NTLMSTATE_TYPE3, + NTLMSTATE_LAST +} curlntlm; + +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) +#include +#endif + +/* Struct used for GSSAPI (Kerberos V5) authentication */ +#if defined(USE_KERBEROS5) +struct kerberos5data { +#if defined(USE_WINDOWS_SSPI) + CredHandle *credentials; + CtxtHandle *context; + TCHAR *spn; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; +#else + gss_ctx_id_t context; + gss_name_t spn; +#endif +}; +#endif + +/* Struct used for NTLM challenge-response authentication */ +#if defined(USE_NTLM) +struct ntlmdata { + curlntlm state; +#ifdef USE_WINDOWS_SSPI +/* The sslContext is used for the Schannel bindings. The + * api is available on the Windows 7 SDK and later. + */ +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + size_t token_max; + BYTE *output_token; + BYTE *input_token; + size_t input_token_len; + TCHAR *spn; +#else + unsigned int flags; + unsigned char nonce[8]; + void *target_info; /* TargetInfo received in the ntlm type-2 message */ + unsigned int target_info_len; +#endif +}; +#endif + +#ifdef USE_SPNEGO +struct negotiatedata { + /* When doing Negotiate (SPNEGO) auth, we first need to send a token + and then validate the received one. */ + enum { + GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT, GSS_AUTHDONE, GSS_AUTHSUCC + } state; +#ifdef HAVE_GSSAPI + OM_uint32 status; + gss_ctx_id_t context; + gss_name_t spn; + gss_buffer_desc output_token; +#else +#ifdef USE_WINDOWS_SSPI +#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS + CtxtHandle *sslContext; +#endif + DWORD status; + CredHandle *credentials; + CtxtHandle *context; + SEC_WINNT_AUTH_IDENTITY identity; + SEC_WINNT_AUTH_IDENTITY *p_identity; + TCHAR *spn; + size_t token_max; + BYTE *output_token; + size_t output_token_length; +#endif +#endif + bool noauthpersist; + bool havenoauthpersist; + bool havenegdata; + bool havemultiplerequests; +}; +#endif + + +/* + * Boolean values that concerns this connection. + */ +struct ConnectBits { + /* always modify bits.close with the connclose() and connkeep() macros! */ + bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy + is complete */ + bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set + the first time on the first connect function call */ + bit close:1; /* if set, we close the connection after this request */ + bit reuse:1; /* if set, this is a re-used connection */ + bit conn_to_host:1; /* if set, this connection has a "connect to host" + that overrides the host in the URL */ + bit conn_to_port:1; /* if set, this connection has a "connect to port" + that overrides the port in the URL (remote port) */ + bit proxy:1; /* if set, this transfer is done through a proxy - any type */ + bit httpproxy:1; /* if set, this transfer is done through a http proxy */ + bit socksproxy:1; /* if set, this transfer is done through a socks proxy */ + bit user_passwd:1; /* do we use user+password for this connection? */ + bit proxy_user_passwd:1; /* user+password for the proxy? */ + bit ipv6_ip:1; /* we communicate with a remote site specified with pure IPv6 + IP address */ + bit ipv6:1; /* we communicate with a site using an IPv6 address */ + bit do_more:1; /* this is set TRUE if the ->curl_do_more() function is + supposed to be called, after ->curl_do() */ + bit protoconnstart:1;/* the protocol layer has STARTED its operation after + the TCP layer connect */ + bit retry:1; /* this connection is about to get closed and then + re-attempted at another connection. */ + bit tunnel_proxy:1; /* if CONNECT is used to "tunnel" through the proxy. + This is implicit when SSL-protocols are used through + proxies, but can also be enabled explicitly by + apps */ + bit authneg:1; /* TRUE when the auth phase has started, which means + that we are creating a request with an auth header, + but it is not the final request in the auth + negotiation. */ + bit rewindaftersend:1;/* TRUE when the sending couldn't be stopped even + though it will be discarded. When the whole send + operation is done, we must call the data rewind + callback. */ + bit ftp_use_epsv:1; /* As set with CURLOPT_FTP_USE_EPSV, but if we find out + EPSV doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_eprt:1; /* As set with CURLOPT_FTP_USE_EPRT, but if we find out + EPRT doesn't work we disable it for the forthcoming + requests */ + bit ftp_use_data_ssl:1; /* Enabled SSL for the data connection */ + bit netrc:1; /* name+password provided by netrc */ + bit userpwd_in_url:1; /* name+password found in url */ + bit stream_was_rewound:1; /* The stream was rewound after a request read + past the end of its response byte boundary */ + bit proxy_connect_closed:1; /* TRUE if a proxy disconnected the connection + in a CONNECT request with auth, so that + libcurl should reconnect and continue. */ + bit bound:1; /* set true if bind() has already been done on this socket/ + connection */ + bit type_set:1; /* type= was used in the URL */ + bit multiplex:1; /* connection is multiplexed */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit tls_enable_npn:1; /* TLS NPN extension? */ + bit tls_enable_alpn:1; /* TLS ALPN extension? */ + bit socksproxy_connecting:1; /* connecting through a socks proxy */ + bit connect_only:1; +}; + +struct hostname { + char *rawalloc; /* allocated "raw" version of the name */ + char *encalloc; /* allocated IDN-encoded version of the name */ + char *name; /* name to use internally, might be encoded, might be raw */ + const char *dispname; /* name to display, as 'name' might be encoded */ +}; + +/* + * Flags on the keepon member of the Curl_transfer_keeper + */ + +#define KEEP_NONE 0 +#define KEEP_RECV (1<<0) /* there is or may be data to read */ +#define KEEP_SEND (1<<1) /* there is or may be data to write */ +#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there + might still be data to read */ +#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there + might still be data to write */ +#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ +#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ + +#define KEEP_RECVBITS (KEEP_RECV | KEEP_RECV_HOLD | KEEP_RECV_PAUSE) +#define KEEP_SENDBITS (KEEP_SEND | KEEP_SEND_HOLD | KEEP_SEND_PAUSE) + +struct Curl_async { + char *hostname; + int port; + struct Curl_dns_entry *dns; + int status; /* if done is TRUE, this is the status from the callback */ + void *os_specific; /* 'struct thread_data' for Windows */ + bit done:1; /* set TRUE when the lookup is complete */ +}; + +#define FIRSTSOCKET 0 +#define SECONDARYSOCKET 1 + +/* These function pointer types are here only to allow easier typecasting + within the source when we need to cast between data pointers (such as NULL) + and function pointers. */ +typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); +typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); + +enum expect100 { + EXP100_SEND_DATA, /* enough waiting, just send the body now */ + EXP100_AWAITING_CONTINUE, /* waiting for the 100 Continue header */ + EXP100_SENDING_REQUEST, /* still sending the request but will wait for + the 100 header once done with the request */ + EXP100_FAILED /* used on 417 Expectation Failed */ +}; + +enum upgrade101 { + UPGR101_INIT, /* default state */ + UPGR101_REQUESTED, /* upgrade requested */ + UPGR101_RECEIVED, /* response received */ + UPGR101_WORKING /* talking upgraded protocol */ +}; + +struct dohresponse { + unsigned char *memory; + size_t size; +}; + +/* one of these for each DoH request */ +struct dnsprobe { + CURL *easy; + int dnstype; + unsigned char dohbuffer[512]; + size_t dohlen; + struct dohresponse serverdoh; +}; + +struct dohdata { + struct curl_slist *headers; + struct dnsprobe probe[2]; + unsigned int pending; /* still outstanding requests */ + const char *host; + int port; +}; + +/* + * Request specific data in the easy handle (Curl_easy). Previously, + * these members were on the connectdata struct but since a conn struct may + * now be shared between different Curl_easys, we store connection-specific + * data here. This struct only keeps stuff that's interesting for *this* + * request, as it will be cleared between multiple ones + */ +struct SingleRequest { + curl_off_t size; /* -1 if unknown at this point */ + curl_off_t maxdownload; /* in bytes, the maximum amount of data to fetch, + -1 means unlimited */ + curl_off_t bytecount; /* total number of bytes read */ + curl_off_t writebytecount; /* number of bytes written */ + + curl_off_t headerbytecount; /* only count received headers */ + curl_off_t deductheadercount; /* this amount of bytes doesn't count when we + check if anything has been transferred at + the end of a connection. We use this + counter to make only a 100 reply (without a + following second response code) result in a + CURLE_GOT_NOTHING error code */ + + struct curltime start; /* transfer started at this time */ + struct curltime now; /* current time */ + enum { + HEADER_NORMAL, /* no bad header at all */ + HEADER_PARTHEADER, /* part of the chunk is a bad header, the rest + is normal data */ + HEADER_ALLBAD /* all was believed to be header */ + } badheader; /* the header was deemed bad and will be + written as body */ + int headerline; /* counts header lines to better track the + first one */ + char *hbufp; /* points at *end* of header line */ + size_t hbuflen; + char *str; /* within buf */ + char *str_start; /* within buf */ + char *end_ptr; /* within buf */ + char *p; /* within headerbuff */ + curl_off_t offset; /* possible resume offset read from the + Content-Range: header */ + int httpcode; /* error code from the 'HTTP/1.? XXX' or + 'RTSP/1.? XXX' line */ + struct curltime start100; /* time stamp to wait for the 100 code from */ + enum expect100 exp100; /* expect 100 continue state */ + enum upgrade101 upgr101; /* 101 upgrade state */ + + struct contenc_writer_s *writer_stack; /* Content unencoding stack. */ + /* See sec 3.5, RFC2616. */ + time_t timeofdoc; + long bodywrites; + char *buf; + int keepon; + char *location; /* This points to an allocated version of the Location: + header data */ + char *newurl; /* Set to the new URL to use when a redirect or a retry is + wanted */ + + /* 'upload_present' is used to keep a byte counter of how much data there is + still left in the buffer, aimed for upload. */ + ssize_t upload_present; + + /* 'upload_fromhere' is used as a read-pointer when we uploaded parts of a + buffer, so the next read should read from where this pointer points to, + and the 'upload_present' contains the number of bytes available at this + position */ + char *upload_fromhere; + void *protop; /* Allocated protocol-specific data. Each protocol + handler makes sure this points to data it needs. */ + struct dohdata doh; /* DoH specific data for this request */ + bit header:1; /* incoming data has HTTP header */ + bit content_range:1; /* set TRUE if Content-Range: was found */ + bit upload_done:1; /* set to TRUE when doing chunked transfer-encoding + upload and we're uploading the last chunk */ + bit ignorebody:1; /* we read a response-body but we ignore it! */ + bit ignorecl:1; /* This HTTP response has no body so we ignore the + Content-Length: header */ + bit chunk:1; /* if set, this is a chunked transfer-encoding */ + bit upload_chunky:1; /* set TRUE if we are doing chunked transfer-encoding + on upload */ + bit getheader:1; /* TRUE if header parsing is wanted */ + bit forbidchunk:1; /* used only to explicitly forbid chunk-upload for + specific upload buffers. See readmoredata() in http.c + for details. */ +}; + +/* + * Specific protocol handler. + */ + +struct Curl_handler { + const char *scheme; /* URL scheme name. */ + + /* Complement to setup_connection_internals(). */ + CURLcode (*setup_connection)(struct connectdata *); + + /* These two functions MUST be set to be protocol dependent */ + CURLcode (*do_it)(struct connectdata *, bool *done); + Curl_done_func done; + + /* If the curl_do() function is better made in two halves, this + * curl_do_more() function will be called afterwards, if set. For example + * for doing the FTP stuff after the PASV/PORT command. + */ + Curl_do_more_func do_more; + + /* This function *MAY* be set to a protocol-dependent function that is run + * after the connect() and everything is done, as a step in the connection. + * The 'done' pointer points to a bool that should be set to TRUE if the + * function completes before return. If it doesn't complete, the caller + * should call the curl_connecting() function until it is. + */ + CURLcode (*connect_it)(struct connectdata *, bool *done); + + /* See above. */ + CURLcode (*connecting)(struct connectdata *, bool *done); + CURLcode (*doing)(struct connectdata *, bool *done); + + /* Called from the multi interface during the PROTOCONNECT phase, and it + should then return a proper fd set */ + int (*proto_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DOING phase, and it should + then return a proper fd set */ + int (*doing_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_MORE phase, and it should + then return a proper fd set */ + int (*domore_getsock)(struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* Called from the multi interface during the DO_DONE, PERFORM and + WAITPERFORM phases, and it should then return a proper fd set. Not setting + this will make libcurl use the generic default one. */ + int (*perform_getsock)(const struct connectdata *conn, + curl_socket_t *socks, + int numsocks); + + /* This function *MAY* be set to a protocol-dependent function that is run + * by the curl_disconnect(), as a step in the disconnection. If the handler + * is called because the connection has been considered dead, dead_connection + * is set to TRUE. + */ + CURLcode (*disconnect)(struct connectdata *, bool dead_connection); + + /* If used, this function gets called from transfer.c:readwrite_data() to + allow the protocol to do extra reads/writes */ + CURLcode (*readwrite)(struct Curl_easy *data, struct connectdata *conn, + ssize_t *nread, bool *readmore); + + /* This function can perform various checks on the connection. See + CONNCHECK_* for more information about the checks that can be performed, + and CONNRESULT_* for the results that can be returned. */ + unsigned int (*connection_check)(struct connectdata *conn, + unsigned int checks_to_perform); + + long defport; /* Default port. */ + unsigned int protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ +}; + +#define PROTOPT_NONE 0 /* nothing extra */ +#define PROTOPT_SSL (1<<0) /* uses SSL */ +#define PROTOPT_DUAL (1<<1) /* this protocol uses two connections */ +#define PROTOPT_CLOSEACTION (1<<2) /* need action before socket close */ +/* some protocols will have to call the underlying functions without regard to + what exact state the socket signals. IE even if the socket says "readable", + the send function might need to be called while uploading, or vice versa. +*/ +#define PROTOPT_DIRLOCK (1<<3) +#define PROTOPT_NONETWORK (1<<4) /* protocol doesn't use the network! */ +#define PROTOPT_NEEDSPWD (1<<5) /* needs a password, and if none is set it + gets a default */ +#define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle + url query strings (?foo=bar) ! */ +#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login credentials per + request instead of per connection */ +#define PROTOPT_ALPN_NPN (1<<8) /* set ALPN and/or NPN for this */ +#define PROTOPT_STREAM (1<<9) /* a protocol with individual logical streams */ +#define PROTOPT_URLOPTIONS (1<<10) /* allow options part in the userinfo field + of the URL */ +#define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a + HTTP proxy as HTTP proxies may know + this protocol and act as a gateway */ +#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ + +#define CONNCHECK_NONE 0 /* No checks */ +#define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */ +#define CONNCHECK_KEEPALIVE (1<<1) /* Perform any keepalive function. */ + +#define CONNRESULT_NONE 0 /* No extra information. */ +#define CONNRESULT_DEAD (1<<0) /* The connection is dead. */ + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND +struct postponed_data { + char *buffer; /* Temporal store for received data during + sending, must be freed */ + size_t allocated_size; /* Size of temporal store */ + size_t recv_size; /* Size of received data during sending */ + size_t recv_processed; /* Size of processed part of postponed data */ +#ifdef DEBUGBUILD + curl_socket_t bindsock;/* Structure must be bound to specific socket, + used only for DEBUGASSERT */ +#endif /* DEBUGBUILD */ +}; +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + +struct proxy_info { + struct hostname host; + long port; + curl_proxytype proxytype; /* what kind of proxy that is in use */ + char *user; /* proxy user name string, allocated */ + char *passwd; /* proxy password string, allocated */ +}; + +#define CONNECT_BUFFER_SIZE 16384 + +/* struct for HTTP CONNECT state data */ +struct http_connect_state { + char connect_buffer[CONNECT_BUFFER_SIZE]; + int perline; /* count bytes per line */ + int keepon; + char *line_start; + char *ptr; /* where to store more data */ + curl_off_t cl; /* size of content to read and ignore */ + enum { + TUNNEL_INIT, /* init/default/no tunnel state */ + TUNNEL_CONNECT, /* CONNECT has been sent off */ + TUNNEL_COMPLETE /* CONNECT response received completely */ + } tunnel_state; + bit chunked_encoding:1; + bit close_connection:1; +}; + +/* + * The connectdata struct contains all fields and variables that should be + * unique for an entire connection. + */ +struct connectdata { + /* 'data' is the CURRENT Curl_easy using this connection -- take great + caution that this might very well vary between different times this + connection is used! */ + struct Curl_easy *data; + + struct curl_llist_element bundle_node; /* conncache */ + + /* chunk is for HTTP chunked encoding, but is in the general connectdata + struct only because we can do just about any protocol through a HTTP proxy + and a HTTP proxy may in fact respond using chunked encoding */ + struct Curl_chunker chunk; + + curl_closesocket_callback fclosesocket; /* function closing the socket(s) */ + void *closesocket_client; + + /* This is used by the connection cache logic. If this returns TRUE, this + handle is being used by one or more easy handles and can only used by any + other easy handle without careful consideration (== only for + pipelining/multiplexing) and it cannot be used by another multi + handle! */ +#define CONN_INUSE(c) ((c)->send_pipe.size + (c)->recv_pipe.size) + + /**** Fields set when inited and not modified again */ + long connection_id; /* Contains a unique number to make it easier to + track the connections in the log output */ + + /* 'dns_entry' is the particular host we use. This points to an entry in the + DNS cache and it will not get pruned while locked. It gets unlocked in + Curl_done(). This entry will be NULL if the connection is re-used as then + there is no name resolve done. */ + struct Curl_dns_entry *dns_entry; + + /* 'ip_addr' is the particular IP we connected to. It points to a struct + within the DNS cache, so this pointer is only valid as long as the DNS + cache entry remains locked. It gets unlocked in Curl_done() */ + Curl_addrinfo *ip_addr; + Curl_addrinfo *tempaddr[2]; /* for happy eyeballs */ + + /* 'ip_addr_str' is the ip_addr data as a human readable string. + It remains available as long as the connection does, which is longer than + the ip_addr itself. */ + char ip_addr_str[MAX_IPADR_LEN]; + + unsigned int scope_id; /* Scope id for IPv6 */ + + int socktype; /* SOCK_STREAM or SOCK_DGRAM */ + + struct hostname host; + char *hostname_resolve; /* host name to resolve to address, allocated */ + char *secondaryhostname; /* secondary socket host name (ftp) */ + struct hostname conn_to_host; /* the host to connect to. valid only if + bits.conn_to_host is set */ + + struct proxy_info socks_proxy; + struct proxy_info http_proxy; + + long port; /* which port to use locally */ + int remote_port; /* the remote port, not the proxy port! */ + int conn_to_port; /* the remote port to connect to. valid only if + bits.conn_to_port is set */ + unsigned short secondary_port; /* secondary socket remote port to connect to + (ftp) */ + + /* 'primary_ip' and 'primary_port' get filled with peer's numerical + ip address and port number whenever an outgoing connection is + *attempted* from the primary socket to a remote address. When more + than one address is tried for a connection these will hold data + for the last attempt. When the connection is actually established + these are updated with data which comes directly from the socket. */ + + char primary_ip[MAX_IPADR_LEN]; + long primary_port; + + /* 'local_ip' and 'local_port' get filled with local's numerical + ip address and port number whenever an outgoing connection is + **established** from the primary socket to a remote address. */ + + char local_ip[MAX_IPADR_LEN]; + long local_port; + + char *user; /* user name string, allocated */ + char *passwd; /* password string, allocated */ + char *options; /* options string, allocated */ + + char *oauth_bearer; /* bearer token for OAuth 2.0, allocated */ + + int httpversion; /* the HTTP version*10 reported by the server */ + int rtspversion; /* the RTSP version*10 reported by the server */ + + struct curltime now; /* "current" time */ + struct curltime created; /* creation time */ + curl_socket_t sock[2]; /* two sockets, the second is used for the data + transfer when doing FTP */ + curl_socket_t tempsock[2]; /* temporary sockets for happy eyeballs */ + bool sock_accepted[2]; /* TRUE if the socket on this index was created with + accept() */ + Curl_recv *recv[2]; + Curl_send *send[2]; + +#ifdef USE_RECV_BEFORE_SEND_WORKAROUND + struct postponed_data postponed[2]; /* two buffers for two sockets */ +#endif /* USE_RECV_BEFORE_SEND_WORKAROUND */ + struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */ + struct ssl_connect_data proxy_ssl[2]; /* this is for proxy ssl-stuff */ +#ifdef USE_SSL + void *ssl_extra; /* separately allocated backend-specific data */ +#endif + struct ssl_primary_config ssl_config; + struct ssl_primary_config proxy_ssl_config; + struct ConnectBits bits; /* various state-flags for this connection */ + + /* connecttime: when connect() is called on the current IP address. Used to + be able to track when to move on to try next IP - but only when the multi + interface is used. */ + struct curltime connecttime; + /* The two fields below get set in Curl_connecthost */ + int num_addr; /* number of addresses to try to connect to */ + time_t timeoutms_per_addr; /* how long time in milliseconds to spend on + trying to connect to each IP address */ + + const struct Curl_handler *handler; /* Connection's protocol handler */ + const struct Curl_handler *given; /* The protocol first given */ + + long ip_version; /* copied from the Curl_easy at creation time */ + + /* Protocols can use a custom keepalive mechanism to keep connections alive. + This allows those protocols to track the last time the keepalive mechanism + was used on this connection. */ + struct curltime keepalive; + + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + + /**** curl_get() phase fields */ + + curl_socket_t sockfd; /* socket to read from or CURL_SOCKET_BAD */ + curl_socket_t writesockfd; /* socket to write to, it may very + well be the same we read from. + CURL_SOCKET_BAD disables */ + + /** Dynamically allocated strings, MUST be freed before this **/ + /** struct is killed. **/ + struct dynamically_allocated_data { + char *proxyuserpwd; + char *uagent; + char *accept_encoding; + char *userpwd; + char *rangeline; + char *ref; + char *host; + char *cookiehost; + char *rtsp_transport; + char *te; /* TE: request header */ + } allocptr; + +#ifdef HAVE_GSSAPI + bit sec_complete:1; /* if Kerberos is enabled for this connection */ + enum protection_level command_prot; + enum protection_level data_prot; + enum protection_level request_data_prot; + size_t buffer_size; + struct krb5buffer in_buffer; + void *app_data; + const struct Curl_sec_client_mech *mech; + struct sockaddr_in local_addr; +#endif + +#if defined(USE_KERBEROS5) /* Consider moving some of the above GSS-API */ + struct kerberos5data krb5; /* variables into the structure definition, */ +#endif /* however, some of them are ftp specific. */ + + struct curl_llist send_pipe; /* List of handles waiting to send on this + pipeline */ + struct curl_llist recv_pipe; /* List of handles waiting to read their + responses on this pipeline */ + char *master_buffer; /* The master buffer allocated on-demand; + used for pipelining. */ + size_t read_pos; /* Current read position in the master buffer */ + size_t buf_len; /* Length of the buffer?? */ + + + curl_seek_callback seek_func; /* function that seeks the input */ + void *seek_client; /* pointer to pass to the seek() above */ + + /*************** Request - specific items ************/ +#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS) + CtxtHandle *sslContext; +#endif + +#if defined(USE_NTLM) + struct ntlmdata ntlm; /* NTLM differs from other authentication schemes + because it authenticates connections, not + single requests! */ + struct ntlmdata proxyntlm; /* NTLM data for proxy */ + +#if defined(NTLM_WB_ENABLED) + /* used for communication with Samba's winbind daemon helper ntlm_auth */ + curl_socket_t ntlm_auth_hlpr_socket; + pid_t ntlm_auth_hlpr_pid; + char *challenge_header; + char *response_header; +#endif +#endif + +#ifdef USE_SPNEGO + struct negotiatedata negotiate; /* state data for host Negotiate auth */ + struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */ +#endif + + /* data used for the asynch name resolve callback */ + struct Curl_async async; + + /* These three are used for chunked-encoding trailer support */ + char *trailer; /* allocated buffer to store trailer in */ + int trlMax; /* allocated buffer size */ + int trlPos; /* index of where to store data */ + + union { + struct ftp_conn ftpc; + struct http_conn httpc; + struct ssh_conn sshc; + struct tftp_state_data *tftpc; + struct imap_conn imapc; + struct pop3_conn pop3c; + struct smtp_conn smtpc; + struct rtsp_conn rtspc; + struct smb_conn smbc; + void *generic; /* RTMP and LDAP use this */ + } proto; + + int cselect_bits; /* bitmask of socket events */ + int waitfor; /* current READ/WRITE bits to wait for */ + +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + int socks5_gssapi_enctype; +#endif + + /* When this connection is created, store the conditions for the local end + bind. This is stored before the actual bind and before any connection is + made and will serve the purpose of being used for comparison reasons so + that subsequent bound-requested connections aren't accidentally re-using + wrong connections. */ + char *localdev; + unsigned short localport; + int localportrange; + struct http_connect_state *connect_state; /* for HTTP CONNECT */ + struct connectbundle *bundle; /* The bundle we are member of */ + int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */ + +#ifdef USE_UNIX_SOCKETS + char *unix_domain_socket; + bit abstract_unix_socket:1; +#endif + bit tls_upgraded:1; + /* the two following *_inuse fields are only flags, not counters in any way. + If TRUE it means the channel is in use, and if FALSE it means the channel + is up for grabs by one. */ + bit readchannel_inuse:1; /* whether the read channel is in use by an easy + handle */ + bit writechannel_inuse:1; /* whether the write channel is in use by an easy + handle */ +}; + +/* The end of connectdata. */ + +/* + * Struct to keep statistical and informational data. + * All variables in this struct must be initialized/reset in Curl_initinfo(). + */ +struct PureInfo { + int httpcode; /* Recent HTTP, FTP, RTSP or SMTP response code */ + int httpproxycode; /* response code from proxy when received separate */ + int httpversion; /* the http version number X.Y = X*10+Y */ + time_t filetime; /* If requested, this is might get set. Set to -1 if the + time was unretrievable. */ + curl_off_t header_size; /* size of read header(s) in bytes */ + curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + unsigned long proxyauthavail; /* what proxy auth types were announced */ + unsigned long httpauthavail; /* what host auth types were announced */ + long numconnects; /* how many new connection did libcurl created */ + char *contenttype; /* the content type of the object */ + char *wouldredirect; /* URL this would've been redirected to if asked to */ + + /* PureInfo members 'conn_primary_ip', 'conn_primary_port', 'conn_local_ip' + and, 'conn_local_port' are copied over from the connectdata struct in + order to allow curl_easy_getinfo() to return this information even when + the session handle is no longer associated with a connection, and also + allow curl_easy_reset() to clear this information from the session handle + without disturbing information which is still alive, and that might be + reused, in the connection cache. */ + + char conn_primary_ip[MAX_IPADR_LEN]; + long conn_primary_port; + char conn_local_ip[MAX_IPADR_LEN]; + long conn_local_port; + const char *conn_scheme; + unsigned int conn_protocol; + struct curl_certinfo certs; /* info about the certs, only populated in + OpenSSL builds. Asked for with + CURLOPT_CERTINFO / CURLINFO_CERTINFO */ + + bit timecond:1; /* set to TRUE if the time condition didn't match, which + thus made the document NOT get fetched */ +}; + + +struct Progress { + time_t lastshow; /* time() of the last displayed progress meter or NULL to + force redraw at next call */ + curl_off_t size_dl; /* total expected size */ + curl_off_t size_ul; /* total expected size */ + curl_off_t downloaded; /* transferred so far */ + curl_off_t uploaded; /* transferred so far */ + + curl_off_t current_speed; /* uses the currently fastest transfer */ + + int width; /* screen width at download start */ + int flags; /* see progress.h */ + + time_t timespent; + + curl_off_t dlspeed; + curl_off_t ulspeed; + + time_t t_nslookup; + time_t t_connect; + time_t t_appconnect; + time_t t_pretransfer; + time_t t_starttransfer; + time_t t_redirect; + + struct curltime start; + struct curltime t_startsingle; + struct curltime t_startop; + struct curltime t_acceptdata; + + + /* upload speed limit */ + struct curltime ul_limit_start; + curl_off_t ul_limit_size; + /* download speed limit */ + struct curltime dl_limit_start; + curl_off_t dl_limit_size; + +#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */ + + curl_off_t speeder[ CURR_TIME ]; + struct curltime speeder_time[ CURR_TIME ]; + int speeder_c; + bit callback:1; /* set when progress callback is used */ + bit is_t_startransfer_set:1; +}; + +typedef enum { + HTTPREQ_NONE, /* first in list */ + HTTPREQ_GET, + HTTPREQ_POST, + HTTPREQ_POST_FORM, /* we make a difference internally */ + HTTPREQ_POST_MIME, /* we make a difference internally */ + HTTPREQ_PUT, + HTTPREQ_HEAD, + HTTPREQ_OPTIONS, + HTTPREQ_LAST /* last in list */ +} Curl_HttpReq; + +typedef enum { + RTSPREQ_NONE, /* first in list */ + RTSPREQ_OPTIONS, + RTSPREQ_DESCRIBE, + RTSPREQ_ANNOUNCE, + RTSPREQ_SETUP, + RTSPREQ_PLAY, + RTSPREQ_PAUSE, + RTSPREQ_TEARDOWN, + RTSPREQ_GET_PARAMETER, + RTSPREQ_SET_PARAMETER, + RTSPREQ_RECORD, + RTSPREQ_RECEIVE, + RTSPREQ_LAST /* last in list */ +} Curl_RtspReq; + +/* + * Values that are generated, temporary or calculated internally for a + * "session handle" must be defined within the 'struct UrlState'. This struct + * will be used within the Curl_easy struct. When the 'Curl_easy' + * struct is cloned, this data MUST NOT be copied. + * + * Remember that any "state" information goes globally for the curl handle. + * Session-data MUST be put in the connectdata struct and here. */ +#define MAX_CURL_USER_LENGTH 256 +#define MAX_CURL_PASSWORD_LENGTH 256 + +struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by + app (with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH). */ + unsigned long picked; + unsigned long avail; /* Bitmask for what the server reports to support for + this resource */ + bit done:1; /* TRUE when the auth phase is done and ready to do the + *actual* request */ + bit multipass:1; /* TRUE if this is not yet authenticated but within the + auth multipass negotiation */ + bit iestyle:1; /* TRUE if digest should be done IE-style or FALSE if it + should be RFC compliant */ +}; + +struct Curl_http2_dep { + struct Curl_http2_dep *next; + struct Curl_easy *data; +}; + +/* + * This struct is for holding data that was attempted to get sent to the user's + * callback but is held due to pausing. One instance per type (BOTH, HEADER, + * BODY). + */ +struct tempbuf { + char *buf; /* allocated buffer to keep data in when a write callback + returns to make the connection paused */ + size_t len; /* size of the 'tempwrite' allocated buffer */ + int type; /* type of the 'tempwrite' buffer as a bitmask that is used with + Curl_client_write() */ +}; + +/* Timers */ +typedef enum { + EXPIRE_100_TIMEOUT, + EXPIRE_ASYNC_NAME, + EXPIRE_CONNECTTIMEOUT, + EXPIRE_DNS_PER_NAME, + EXPIRE_HAPPY_EYEBALLS, + EXPIRE_MULTI_PENDING, + EXPIRE_RUN_NOW, + EXPIRE_SPEEDCHECK, + EXPIRE_TIMEOUT, + EXPIRE_TOOFAST, + EXPIRE_LAST /* not an actual timer, used as a marker only */ +} expire_id; + + +typedef enum { + TRAILERS_NONE, + TRAILERS_INITIALIZED, + TRAILERS_SENDING, + TRAILERS_DONE +} trailers_state; + + +/* + * One instance for each timeout an easy handle can set. + */ +struct time_node { + struct curl_llist_element list; + struct curltime time; + expire_id eid; +}; + +/* individual pieces of the URL */ +struct urlpieces { + char *scheme; + char *hostname; + char *port; + char *user; + char *password; + char *options; + char *path; + char *query; +}; + +struct UrlState { + + /* Points to the connection cache */ + struct conncache *conn_cache; + + /* buffers to store authentication data in, as parsed from input options */ + struct curltime keeps_speed; /* for the progress meter really */ + + struct connectdata *lastconnect; /* The last connection, NULL if undefined */ + + char *headerbuff; /* allocated buffer to store headers in */ + size_t headersize; /* size of the allocation */ + + char *buffer; /* download buffer */ + char *ulbuf; /* allocated upload buffer or NULL */ + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ + char *first_host; /* host name of the first (not followed) request. + if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: + following not keep sending user+password... This is + strdup() data. + */ + int first_remote_port; /* remote port of the first (not followed) request */ + struct curl_ssl_session *session; /* array of 'max_ssl_sessions' size */ + long sessionage; /* number of the most recent session */ + unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */ + struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */ + char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */ + int os_errno; /* filled in with errno whenever an error occurs */ +#ifdef HAVE_SIGNAL + /* storage for the previous bag^H^H^HSIGPIPE signal handler :-) */ + void (*prev_signal)(int sig); +#endif + struct digestdata digest; /* state data for host Digest auth */ + struct digestdata proxydigest; /* state data for proxy Digest auth */ + + struct auth authhost; /* auth details for host */ + struct auth authproxy; /* auth details for proxy */ + + void *resolver; /* resolver state, if it is used in the URL state - + ares_channel f.e. */ + +#if defined(USE_OPENSSL) + /* void instead of ENGINE to avoid bleeding OpenSSL into this header */ + void *engine; +#endif /* USE_OPENSSL */ + struct curltime expiretime; /* set this with Curl_expire() only */ + struct Curl_tree timenode; /* for the splay stuff */ + struct curl_llist timeoutlist; /* list of pending timeouts */ + struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */ + + /* a place to store the most recently set FTP entrypath */ + char *most_recent_ftp_entrypath; + + int httpversion; /* the lowest HTTP version*10 reported by any server + involved in this request */ + +#if !defined(WIN32) && !defined(MSDOS) && !defined(__EMX__) && \ + !defined(__SYMBIAN32__) +/* do FTP line-end conversions on most platforms */ +#define CURL_DO_LINEEND_CONV + /* for FTP downloads: track CRLF sequences that span blocks */ + bit prev_block_had_trailing_cr:1; + /* for FTP downloads: how many CRLFs did we converted to LFs? */ + curl_off_t crlf_conversions; +#endif + char *range; /* range, if used. See README for detailed specification on + this syntax. */ + curl_off_t resume_from; /* continue [ftp] transfer from here */ + + /* This RTSP state information survives requests and connections */ + long rtsp_next_client_CSeq; /* the session's next client CSeq */ + long rtsp_next_server_CSeq; /* the session's next server CSeq */ + long rtsp_CSeq_recv; /* most recent CSeq received */ + + curl_off_t infilesize; /* size of file to upload, -1 means unknown. + Copied from set.filesize at start of operation */ + + size_t drain; /* Increased when this stream has data to read, even if its + socket is not necessarily is readable. Decreased when + checked. */ + + curl_read_callback fread_func; /* read callback/function */ + void *in; /* CURLOPT_READDATA */ + + struct Curl_easy *stream_depends_on; + int stream_weight; + CURLU *uh; /* URL handle for the current parsed URL */ + struct urlpieces up; +#ifndef CURL_DISABLE_HTTP + size_t trailers_bytes_sent; + Curl_send_buffer *trailers_buf; /* a buffer containing the compiled trailing + headers */ +#endif + trailers_state trailers_state; /* whether we are sending trailers + and what stage are we at */ +#ifdef CURLDEBUG + bit conncache_lock:1; +#endif + /* when curl_easy_perform() is called, the multi handle is "owned" by + the easy handle so curl_easy_cleanup() on such an easy handle will + also close the multi handle! */ + bit multi_owned_by_easy:1; + + bit this_is_a_follow:1; /* this is a followed Location: request */ + bit refused_stream:1; /* this was refused, try again */ + bit errorbuf:1; /* Set to TRUE if the error buffer is already filled in. + This must be set to FALSE every time _easy_perform() is + called. */ + bit allow_port:1; /* Is set.use_port allowed to take effect or not. This + is always set TRUE when curl_easy_perform() is called. */ + bit authproblem:1; /* TRUE if there's some problem authenticating */ + /* set after initial USER failure, to prevent an authentication loop */ + bit ftp_trying_alternative:1; + bit wildcardmatch:1; /* enable wildcard matching */ + bit expect100header:1; /* TRUE if we added Expect: 100-continue */ + bit use_range:1; + bit rangestringalloc:1; /* the range string is malloc()'ed */ + bit done:1; /* set to FALSE when Curl_init_do() is called and set to TRUE + when multi_done() is called, to prevent multi_done() to get + invoked twice when the multi interface is used. */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ +}; + + +/* + * This 'DynamicStatic' struct defines dynamic states that actually change + * values in the 'UserDefined' area, which MUST be taken into consideration + * if the UserDefined struct is cloned or similar. You can probably just + * copy these, but each one indicate a special action on other data. + */ + +struct DynamicStatic { + char *url; /* work URL, copied from UserDefined */ + char *referer; /* referer string */ + struct curl_slist *cookielist; /* list of cookie files set by + curl_easy_setopt(COOKIEFILE) calls */ + struct curl_slist *resolve; /* set to point to the set.resolve list when + this should be dealt with in pretransfer */ + bit url_alloc:1; /* URL string is malloc()'ed */ + bit referer_alloc:1; /* referer string is malloc()ed */ + bit wildcard_resolve:1; /* Set to true if any resolve change is a + wildcard */ +}; + +/* + * This 'UserDefined' struct must only contain data that is set once to go + * for many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" MUST be defined within the + * 'struct UrlState' instead. The only exceptions MUST note the changes in + * the 'DynamicStatic' struct. + * Character pointer fields point to dynamic storage, unless otherwise stated. + */ + +struct Curl_multi; /* declared and used only in multi.c */ + +enum dupstring { + STRING_CERT_ORIG, /* client certificate file name */ + STRING_CERT_PROXY, /* client certificate file name */ + STRING_CERT_TYPE_ORIG, /* format for certificate (default: PEM)*/ + STRING_CERT_TYPE_PROXY, /* format for certificate (default: PEM)*/ + STRING_COOKIE, /* HTTP cookie string to send */ + STRING_COOKIEJAR, /* dump all cookies to this file */ + STRING_CUSTOMREQUEST, /* HTTP/FTP/RTSP request/method to use */ + STRING_DEFAULT_PROTOCOL, /* Protocol to use when the URL doesn't specify */ + STRING_DEVICE, /* local network interface/address to use */ + STRING_ENCODING, /* Accept-Encoding string */ + STRING_FTP_ACCOUNT, /* ftp account data */ + STRING_FTP_ALTERNATIVE_TO_USER, /* command to send if USER/PASS fails */ + STRING_FTPPORT, /* port to send with the FTP PORT command */ + STRING_KEY_ORIG, /* private key file name */ + STRING_KEY_PROXY, /* private key file name */ + STRING_KEY_PASSWD_ORIG, /* plain text private key password */ + STRING_KEY_PASSWD_PROXY, /* plain text private key password */ + STRING_KEY_TYPE_ORIG, /* format for private key (default: PEM) */ + STRING_KEY_TYPE_PROXY, /* format for private key (default: PEM) */ + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ + STRING_PROXY, /* proxy to use */ + STRING_PRE_PROXY, /* pre socks proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ + STRING_SET_URL, /* what original URL to work on */ + STRING_SSL_CAPATH_ORIG, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAPATH_PROXY, /* CA directory name (doesn't work on windows) */ + STRING_SSL_CAFILE_ORIG, /* certificate file to verify peer against */ + STRING_SSL_CAFILE_PROXY, /* certificate file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_ORIG, /* public key file to verify peer against */ + STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ + STRING_SSL_CIPHER_LIST_ORIG, /* list of ciphers to use */ + STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ + STRING_SSL_CIPHER13_LIST_ORIG, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */ + STRING_SSL_EGDSOCKET, /* path to file containing the EGD daemon socket */ + STRING_SSL_RANDOM_FILE, /* path to file containing "random" data */ + STRING_USERAGENT, /* User-Agent string */ + STRING_SSL_CRLFILE_ORIG, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_ISSUERCERT_ORIG, /* issuer cert file to check certificate */ + STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ + STRING_SSL_ENGINE, /* name of ssl engine */ + STRING_USERNAME, /* , if used */ + STRING_PASSWORD, /* , if used */ + STRING_OPTIONS, /* , if used */ + STRING_PROXYUSERNAME, /* Proxy , if used */ + STRING_PROXYPASSWORD, /* Proxy , if used */ + STRING_NOPROXY, /* List of hosts which should not use the proxy, if + used */ + STRING_RTSP_SESSION_ID, /* Session ID to use */ + STRING_RTSP_STREAM_URI, /* Stream URI for this request */ + STRING_RTSP_TRANSPORT, /* Transport for this session */ +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) + STRING_SSH_PRIVATE_KEY, /* path to the private key file for auth */ + STRING_SSH_PUBLIC_KEY, /* path to the public key file for auth */ + STRING_SSH_HOST_PUBLIC_KEY_MD5, /* md5 of host public key in ascii hex */ + STRING_SSH_KNOWNHOSTS, /* file name of knownhosts file */ +#endif + STRING_PROXY_SERVICE_NAME, /* Proxy service name */ + STRING_SERVICE_NAME, /* Service name */ + STRING_MAIL_FROM, + STRING_MAIL_AUTH, + +#ifdef USE_TLS_SRP + STRING_TLSAUTH_USERNAME_ORIG, /* TLS auth */ + STRING_TLSAUTH_USERNAME_PROXY, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_ORIG, /* TLS auth */ + STRING_TLSAUTH_PASSWORD_PROXY, /* TLS auth */ +#endif + STRING_BEARER, /* , if used */ +#ifdef USE_UNIX_SOCKETS + STRING_UNIX_SOCKET_PATH, /* path to Unix socket, if used */ +#endif + STRING_TARGET, /* CURLOPT_REQUEST_TARGET */ + STRING_DOH, /* CURLOPT_DOH_URL */ +#ifdef USE_ALTSVC + STRING_ALTSVC, /* CURLOPT_ALTSVC */ +#endif + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, + + /* -- below this are pointers to binary data that cannot be strdup'ed. --- */ + + STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + + STRING_LAST /* not used, just an end-of-list marker */ +}; + +/* callback that gets called when this easy handle is completed within a multi + handle. Only used for internally created transfers, like for example + DoH. */ +typedef int (*multidone_func)(struct Curl_easy *easy, CURLcode result); + +struct UserDefined { + FILE *err; /* the stderr user data goes here */ + void *debugdata; /* the data that will be passed to fdebug */ + char *errorbuffer; /* (Static) store failure messages in here */ + long proxyport; /* If non-zero, use this port number by default. If the + proxy string features a ":[port]" that one will override + this. */ + void *out; /* CURLOPT_WRITEDATA */ + void *in_set; /* CURLOPT_READDATA */ + void *writeheader; /* write the header to this if non-NULL */ + void *rtp_out; /* write RTP to this if non-NULL */ + long use_port; /* which port to use (when not using default) */ + unsigned long httpauth; /* kind of HTTP authentication to use (bitmask) */ + unsigned long proxyauth; /* kind of proxy authentication to use (bitmask) */ + unsigned long socks5auth;/* kind of SOCKS5 authentication to use (bitmask) */ + long followlocation; /* as in HTTP Location: */ + long maxredirs; /* maximum no. of http(s) redirects to follow, set to -1 + for infinity */ + + int keep_post; /* keep POSTs as POSTs after a 30x request; each + bit represents a request, from 301 to 303 */ + void *postfields; /* if POST, set the fields' values here */ + curl_seek_callback seek_func; /* function that seeks the input */ + curl_off_t postfieldsize; /* if POST, this might have a size to use instead + of strlen(), and then the data *may* be binary + (contain zero bytes) */ + unsigned short localport; /* local port number to bind to */ + int localportrange; /* number of additional port numbers to test in case the + 'localport' one can't be bind()ed */ + curl_write_callback fwrite_func; /* function that stores the output */ + curl_write_callback fwrite_header; /* function that stores headers */ + curl_write_callback fwrite_rtp; /* function that stores interleaved RTP */ + curl_read_callback fread_func_set; /* function that reads the input */ + curl_progress_callback fprogress; /* OLD and deprecated progress callback */ + curl_xferinfo_callback fxferinfo; /* progress callback */ + curl_debug_callback fdebug; /* function that write informational data */ + curl_ioctl_callback ioctl_func; /* function for I/O control */ + curl_sockopt_callback fsockopt; /* function for setting socket options */ + void *sockopt_client; /* pointer to pass to the socket options callback */ + curl_opensocket_callback fopensocket; /* function for checking/translating + the address and opening the + socket */ + void *opensocket_client; + curl_closesocket_callback fclosesocket; /* function for closing the + socket */ + void *closesocket_client; + + void *seek_client; /* pointer to pass to the seek callback */ + /* the 3 curl_conv_callback functions below are used on non-ASCII hosts */ + /* function to convert from the network encoding: */ + curl_conv_callback convfromnetwork; + /* function to convert to the network encoding: */ + curl_conv_callback convtonetwork; + /* function to convert from UTF-8 encoding: */ + curl_conv_callback convfromutf8; + + void *progress_client; /* pointer to pass to the progress callback */ + void *ioctl_client; /* pointer to pass to the ioctl callback */ + long timeout; /* in milliseconds, 0 means no timeout */ + long connecttimeout; /* in milliseconds, 0 means no timeout */ + long accepttimeout; /* in milliseconds, 0 means no timeout */ + long happy_eyeballs_timeout; /* in milliseconds, 0 is a valid value */ + long server_response_timeout; /* in milliseconds, 0 means no timeout */ + long tftp_blksize; /* in bytes, 0 means use default */ + curl_off_t filesize; /* size of file to upload, -1 means unknown */ + long low_speed_limit; /* bytes/second */ + long low_speed_time; /* number of seconds */ + curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ + curl_off_t max_recv_speed; /* high speed limit in bytes/second for + download */ + curl_off_t set_resume_from; /* continue [ftp] transfer from here */ + struct curl_slist *headers; /* linked list of extra headers */ + struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ + struct curl_httppost *httppost; /* linked list of old POST data */ + curl_mimepart mimepost; /* MIME/POST data. */ + struct curl_slist *quote; /* after connection is established */ + struct curl_slist *postquote; /* after the transfer */ + struct curl_slist *prequote; /* before the transfer, after type */ + struct curl_slist *source_quote; /* 3rd party quote */ + struct curl_slist *source_prequote; /* in 3rd party transfer mode - before + the transfer on source host */ + struct curl_slist *source_postquote; /* in 3rd party transfer mode - after + the transfer on source host */ + struct curl_slist *telnet_options; /* linked list of telnet options */ + struct curl_slist *resolve; /* list of names to add/remove from + DNS cache */ + struct curl_slist *connect_to; /* list of host:port mappings to override + the hostname and port to connect to */ + curl_TimeCond timecondition; /* kind of time/date comparison */ + time_t timevalue; /* what time to compare with */ + Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */ + long httpversion; /* when non-zero, a specific HTTP version requested to + be used in the library's request(s) */ + struct ssl_config_data ssl; /* user defined SSL stuff */ + struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ + struct ssl_general_config general_ssl; /* general user defined SSL stuff */ + curl_proxytype proxytype; /* what kind of proxy that is in use */ + long dns_cache_timeout; /* DNS cache timeout */ + long buffer_size; /* size of receive buffer to use */ + size_t upload_buffer_size; /* size of upload buffer to use, + keep it >= CURL_MAX_WRITE_SIZE */ + void *private_data; /* application-private data */ + struct curl_slist *http200aliases; /* linked list of aliases for http200 */ + long ipver; /* the CURL_IPRESOLVE_* defines in the public header file + 0 - whatever, 1 - v2, 2 - v6 */ + curl_off_t max_filesize; /* Maximum file size to download */ + curl_ftpfile ftp_filemethod; /* how to get to a file when FTP is used */ + int ftp_create_missing_dirs; /* 1 - create directories that don't exist + 2 - the same but also allow MKD to fail once + */ + curl_sshkeycallback ssh_keyfunc; /* key matching callback */ + void *ssh_keyfunc_userp; /* custom pointer to callback */ + enum CURL_NETRC_OPTION + use_netrc; /* defined in include/curl.h */ + curl_usessl use_ssl; /* if AUTH TLS is to be attempted etc, for FTP or + IMAP or POP3 or others! */ + curl_ftpauth ftpsslauth; /* what AUTH XXX to be attempted */ + curl_ftpccc ftp_ccc; /* FTP CCC options */ + long new_file_perms; /* Permissions to use when creating remote files */ + long new_directory_perms; /* Permissions to use when creating remote dirs */ + long ssh_auth_types; /* allowed SSH auth types */ + char *str[STRING_LAST]; /* array of strings, pointing to allocated memory */ + unsigned int scope_id; /* Scope id for IPv6 */ + long allowed_protocols; + long redir_protocols; + struct curl_slist *mail_rcpt; /* linked list of mail recipients */ + /* Common RTSP header options */ + Curl_RtspReq rtspreq; /* RTSP request type */ + long rtspversion; /* like httpversion, for RTSP */ + curl_chunk_bgn_callback chunk_bgn; /* called before part of transfer + starts */ + curl_chunk_end_callback chunk_end; /* called after part transferring + stopped */ + curl_fnmatch_callback fnmatch; /* callback to decide which file corresponds + to pattern (e.g. if WILDCARDMATCH is on) */ + void *fnmatch_data; + + long gssapi_delegation; /* GSS-API credential delegation, see the + documentation of CURLOPT_GSSAPI_DELEGATION */ + + long tcp_keepidle; /* seconds in idle before sending keepalive probe */ + long tcp_keepintvl; /* seconds between TCP keepalive probes */ + + size_t maxconnects; /* Max idle connections in the connection cache */ + + long expect_100_timeout; /* in milliseconds */ + struct Curl_easy *stream_depends_on; + int stream_weight; + struct Curl_http2_dep *stream_dependents; + + curl_resolver_start_callback resolver_start; /* optional callback called + before resolver start */ + void *resolver_start_client; /* pointer to pass to resolver start callback */ + long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + multidone_func fmultidone; + struct Curl_easy *dohfor; /* this is a DoH request for that transfer */ + CURLU *uh; /* URL handle for the current parsed URL */ + void *trailer_data; /* pointer to pass to trailer data callback */ + curl_trailer_callback trailer_callback; /* trailing data callback */ + bit is_fread_set:1; /* has read callback been set to non-NULL? */ + bit is_fwrite_set:1; /* has write callback been set to non-NULL? */ + bit free_referer:1; /* set TRUE if 'referer' points to a string we + allocated */ + bit tftp_no_options:1; /* do not send TFTP options requests */ + bit sep_headers:1; /* handle host and proxy headers separately */ + bit cookiesession:1; /* new cookie session? */ + bit crlf:1; /* convert crlf on ftp upload(?) */ + bit strip_path_slash:1; /* strip off initial slash from path */ + bit ssh_compression:1; /* enable SSH compression */ + +/* Here follows boolean settings that define how to behave during + this session. They are STATIC, set by libcurl users or at least initially + and they don't change during operations. */ + bit get_filetime:1; /* get the time and get of the remote file */ + bit tunnel_thru_httpproxy:1; /* use CONNECT through a HTTP proxy */ + bit prefer_ascii:1; /* ASCII rather than binary */ + bit ftp_append:1; /* append, not overwrite, on upload */ + bit ftp_list_only:1; /* switch FTP command for listing directories */ + bit ftp_use_port:1; /* use the FTP PORT command */ + bit hide_progress:1; /* don't use the progress meter */ + bit http_fail_on_error:1; /* fail on HTTP error codes >= 400 */ + bit http_keep_sending_on_error:1; /* for HTTP status codes >= 300 */ + bit http_follow_location:1; /* follow HTTP redirects */ + bit http_transfer_encoding:1; /* request compressed HTTP + transfer-encoding */ + bit allow_auth_to_other_hosts:1; + bit include_header:1; /* include received protocol headers in data output */ + bit http_set_referer:1; /* is a custom referer used */ + bit http_auto_referer:1; /* set "correct" referer when following + location: */ + bit opt_no_body:1; /* as set with CURLOPT_NOBODY */ + bit upload:1; /* upload request */ + bit verbose:1; /* output verbosity */ + bit krb:1; /* Kerberos connection requested */ + bit reuse_forbid:1; /* forbidden to be reused, close after use */ + bit reuse_fresh:1; /* do not re-use an existing connection */ + bit ftp_use_epsv:1; /* if EPSV is to be attempted or not */ + bit ftp_use_eprt:1; /* if EPRT is to be attempted or not */ + bit ftp_use_pret:1; /* if PRET is to be used before PASV or not */ + + bit no_signal:1; /* do not use any signal/alarm handler */ + bit global_dns_cache:1; /* subject for future removal */ + bit tcp_nodelay:1; /* whether to enable TCP_NODELAY or not */ + bit ignorecl:1; /* ignore content length */ + bit ftp_skip_ip:1; /* skip the IP address the FTP server passes on to + us */ + bit connect_only:1; /* make connection, let application use the socket */ + bit http_te_skip:1; /* pass the raw body data to the user, even when + transfer-encoded (chunked, compressed) */ + bit http_ce_skip:1; /* pass the raw body data to the user, even when + content-encoded (chunked, compressed) */ + bit proxy_transfer_mode:1; /* set transfer mode (;type=) when doing + FTP via an HTTP proxy */ +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + bit socks5_gssapi_nec:1; /* Flag to support NEC SOCKS5 server */ +#endif + bit sasl_ir:1; /* Enable/disable SASL initial response */ + bit wildcard_enabled:1; /* enable wildcard matching */ + bit tcp_keepalive:1; /* use TCP keepalives */ + bit tcp_fastopen:1; /* use TCP Fast Open */ + bit ssl_enable_npn:1; /* TLS NPN extension? */ + bit ssl_enable_alpn:1;/* TLS ALPN extension? */ + bit path_as_is:1; /* allow dotdots? */ + bit pipewait:1; /* wait for pipe/multiplex status before starting a + new connection */ + bit suppress_connect_headers:1; /* suppress proxy CONNECT response headers + from user callbacks */ + bit dns_shuffle_addresses:1; /* whether to shuffle addresses before use */ + bit stream_depends_e:1; /* set or don't set the Exclusive bit */ + bit haproxyprotocol:1; /* whether to send HAProxy PROXY protocol v1 + header */ + bit abstract_unix_socket:1; + bit disallow_username_in_url:1; /* disallow username in url */ + bit doh:1; /* DNS-over-HTTPS enabled */ + bit doh_get:1; /* use GET for DoH requests, instead of POST */ + bit http09_allowed:1; /* allow HTTP/0.9 responses */ +}; + +struct Names { + struct curl_hash *hostcache; + enum { + HCACHE_NONE, /* not pointing to anything */ + HCACHE_GLOBAL, /* points to the (shrug) global one */ + HCACHE_MULTI, /* points to a shared one in the multi handle */ + HCACHE_SHARED /* points to a shared one in a shared object */ + } hostcachetype; +}; + +/* + * The 'connectdata' struct MUST have all the connection oriented stuff as we + * may have several simultaneous connections and connection structs in memory. + * + * The 'struct UserDefined' must only contain data that is set once to go for + * many (perhaps) independent connections. Values that are generated or + * calculated internally for the "session handle" must be defined within the + * 'struct UrlState' instead. + */ + +struct Curl_easy { + /* first, two fields for the linked list of these */ + struct Curl_easy *next; + struct Curl_easy *prev; + + struct connectdata *conn; + struct curl_llist_element connect_queue; + struct curl_llist_element pipeline_queue; + struct curl_llist_element sh_queue; /* list per Curl_sh_entry */ + + CURLMstate mstate; /* the handle's state */ + CURLcode result; /* previous result */ + + struct Curl_message msg; /* A single posted message. */ + + /* Array with the plain socket numbers this handle takes care of, in no + particular order. Note that all sockets are added to the sockhash, where + the state etc are also kept. This array is mostly used to detect when a + socket is to be removed from the hash. See singlesocket(). */ + curl_socket_t sockets[MAX_SOCKSPEREASYHANDLE]; + int actions[MAX_SOCKSPEREASYHANDLE]; /* action for each socket in + sockets[] */ + int numsocks; + + struct Names dns; + struct Curl_multi *multi; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used by + the multi interface */ + struct Curl_multi *multi_easy; /* if non-NULL, points to the multi handle + struct to which this "belongs" when used + by the easy interface */ + struct Curl_share *share; /* Share, handles global variable mutexing */ +#ifdef USE_LIBPSL + struct PslCache *psl; /* The associated PSL cache. */ +#endif + struct SingleRequest req; /* Request-specific data */ + struct UserDefined set; /* values set by the libcurl user */ + struct DynamicStatic change; /* possibly modified userdefined data */ + struct CookieInfo *cookies; /* the cookies, read from files and servers. + NOTE that the 'cookie' field in the + UserDefined struct defines if the "engine" + is to be used or not. */ +#ifdef USE_ALTSVC + struct altsvcinfo *asi; /* the alt-svc cache */ +#endif + struct Progress progress; /* for all the progress meter data */ + struct UrlState state; /* struct for fields used for state info and + other dynamic purposes */ + struct WildcardData wildcard; /* wildcard download state info */ + struct PureInfo info; /* stats, reports and info data */ + struct curl_tlssessioninfo tsi; /* Information about the TLS session, only + valid after a client has asked for it */ +#if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV) + iconv_t outbound_cd; /* for translating to the network encoding */ + iconv_t inbound_cd; /* for translating from the network encoding */ + iconv_t utf8_cd; /* for translating to UTF8 */ +#endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */ + unsigned int magic; /* set to a CURLEASY_MAGIC_NUMBER */ +}; + +#define LIBCURL_NAME "libcurl" + +#endif /* HEADER_CURL_URLDATA_H */ diff --git a/external/curl prx/include/vauth.h b/external/curl prx/include/vauth.h new file mode 100644 index 0000000..f430642 --- /dev/null +++ b/external/curl prx/include/vauth.h @@ -0,0 +1,207 @@ +#ifndef HEADER_CURL_VAUTH_H +#define HEADER_CURL_VAUTH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2017, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +struct digestdata; +#endif + +#if defined(USE_NTLM) +struct ntlmdata; +#endif + +#if defined(USE_KERBEROS5) +struct kerberos5data; +#endif + +#if (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) && defined(USE_SPNEGO) +struct negotiatedata; +#endif + +#if defined(USE_WINDOWS_SSPI) +#define GSS_ERROR(status) (status & 0x80000000) +#endif + +/* This is used to build a SPN string */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#endif + +/* This is used to test if the user contains a Windows domain name */ +bool Curl_auth_user_contains_domain(const char *user); + +/* This is used to generate a base64 encoded PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen); + +/* This is used to generate a base64 encoded EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen); + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +/* This is used to decode a CRAM-MD5 challenge message */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen); + +/* This is used to generate a CRAM-MD5 response message */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to evaluate if DIGEST is supported */ +bool Curl_auth_is_digest_supported(void); + +/* This is used to generate a base64 encoded DIGEST-MD5 response message */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen); + +/* This is used to decode a HTTP DIGEST challenge message */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest); + +/* This is used to generate a HTTP DIGEST response message */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uri, + struct digestdata *digest, + char **outptr, size_t *outlen); + +/* This is used to clean up the digest specific data */ +void Curl_auth_digest_cleanup(struct digestdata *digest); +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ + +#if defined(USE_NTLM) +/* This is used to evaluate if NTLM is supported */ +bool Curl_auth_is_ntlm_supported(void); + +/* This is used to generate a base64 encoded NTLM type-1 message */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, + size_t *outlen); + +/* This is used to decode a base64 encoded NTLM type-2 message */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm); + +/* This is used to generate a base64 encoded NTLM type-3 message */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen); + +/* This is used to clean up the NTLM specific data */ +void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm); +#endif /* USE_NTLM */ + +/* This is used to generate a base64 encoded OAuth 2.0 message */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen); +#if defined(USE_KERBEROS5) +/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ +bool Curl_auth_is_gssapi_supported(void); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token + message */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security + token message */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *input, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen); + +/* This is used to clean up the GSSAPI specific data */ +void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5); +#endif /* USE_KERBEROS5 */ + +#if defined(USE_SPNEGO) +/* This is used to evaluate if SPNEGO (Negotiate) is supported */ +bool Curl_auth_is_spnego_supported(void); + +/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge + message */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *passwood, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego); + +/* This is used to generate a base64 encoded SPNEGO (Negotiate) response + message */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen); + +/* This is used to clean up the SPNEGO specifiec data */ +void Curl_auth_spnego_cleanup(struct negotiatedata *nego); + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_VAUTH_H */ diff --git a/external/curl prx/include/vauth/digest.h b/external/curl prx/include/vauth/digest.h new file mode 100644 index 0000000..8686c44 --- /dev/null +++ b/external/curl prx/include/vauth/digest.h @@ -0,0 +1,47 @@ +#ifndef HEADER_CURL_DIGEST_H +#define HEADER_CURL_DIGEST_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) + +#define DIGEST_MAX_VALUE_LENGTH 256 +#define DIGEST_MAX_CONTENT_LENGTH 1024 + +enum { + CURLDIGESTALGO_MD5, + CURLDIGESTALGO_MD5SESS, + CURLDIGESTALGO_SHA256, + CURLDIGESTALGO_SHA256SESS, + CURLDIGESTALGO_SHA512_256, + CURLDIGESTALGO_SHA512_256SESS +}; + +/* This is used to extract the realm from a challenge message */ +bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, + const char **endptr); + +#endif + +#endif /* HEADER_CURL_DIGEST_H */ diff --git a/external/curl prx/include/vauth/ntlm.h b/external/curl prx/include/vauth/ntlm.h new file mode 100644 index 0000000..1136b0f --- /dev/null +++ b/external/curl prx/include/vauth/ntlm.h @@ -0,0 +1,143 @@ +#ifndef HEADER_VAUTH_NTLM_H +#define HEADER_VAUTH_NTLM_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_NTLM + +/* NTLM buffer fixed size, large enough for long user + host + domain */ +#define NTLM_BUFSIZE 1024 + +/* Stuff only required for curl_ntlm_msgs.c */ +#ifdef BUILDING_CURL_NTLM_MSGS_C + +/* Flag bits definitions based on https://davenport.sourceforge.io/ntlm.html */ + +#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) +/* Indicates that Unicode strings are supported for use in security buffer + data. */ + +#define NTLMFLAG_NEGOTIATE_OEM (1<<1) +/* Indicates that OEM strings are supported for use in security buffer data. */ + +#define NTLMFLAG_REQUEST_TARGET (1<<2) +/* Requests that the server's authentication realm be included in the Type 2 + message. */ + +/* unknown (1<<3) */ +#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ + +#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ + +#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) +/* Indicates that datagram authentication is being used. */ + +#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ + +#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) +/* Indicates that NTLM authentication is being used. */ + +/* unknown (1<<10) */ + +#define NTLMFLAG_NEGOTIATE_ANONYMOUS (1<<11) +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ + +#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ + +#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ + +#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ + +#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ + +#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ + +#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ + +#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ + +#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) +/* unknown purpose */ + +#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) +/* unknown purpose */ + +#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ + +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ + +#define NTLMFLAG_NEGOTIATE_128 (1<<29) +/* Indicates that 128-bit encryption is supported. */ + +#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ + +#define NTLMFLAG_NEGOTIATE_56 (1<<31) +/* Indicates that 56-bit encryption is supported. */ + +#endif /* BUILDING_CURL_NTLM_MSGS_C */ + +#endif /* USE_NTLM */ + +#endif /* HEADER_VAUTH_NTLM_H */ diff --git a/external/curl prx/include/vauth/vauth.h b/external/curl prx/include/vauth/vauth.h new file mode 100644 index 0000000..f430642 --- /dev/null +++ b/external/curl prx/include/vauth/vauth.h @@ -0,0 +1,207 @@ +#ifndef HEADER_CURL_VAUTH_H +#define HEADER_CURL_VAUTH_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2014 - 2017, Steve Holme, . + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +struct Curl_easy; + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +struct digestdata; +#endif + +#if defined(USE_NTLM) +struct ntlmdata; +#endif + +#if defined(USE_KERBEROS5) +struct kerberos5data; +#endif + +#if (defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)) && defined(USE_SPNEGO) +struct negotiatedata; +#endif + +#if defined(USE_WINDOWS_SSPI) +#define GSS_ERROR(status) (status & 0x80000000) +#endif + +/* This is used to build a SPN string */ +#if !defined(USE_WINDOWS_SSPI) +char *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#else +TCHAR *Curl_auth_build_spn(const char *service, const char *host, + const char *realm); +#endif + +/* This is used to test if the user contains a Windows domain name */ +bool Curl_auth_user_contains_domain(const char *user); + +/* This is used to generate a base64 encoded PLAIN cleartext message */ +CURLcode Curl_auth_create_plain_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded LOGIN cleartext message */ +CURLcode Curl_auth_create_login_message(struct Curl_easy *data, + const char *valuep, char **outptr, + size_t *outlen); + +/* This is used to generate a base64 encoded EXTERNAL cleartext message */ +CURLcode Curl_auth_create_external_message(struct Curl_easy *data, + const char *user, char **outptr, + size_t *outlen); + +#if !defined(CURL_DISABLE_CRYPTO_AUTH) +/* This is used to decode a CRAM-MD5 challenge message */ +CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, + size_t *outlen); + +/* This is used to generate a CRAM-MD5 response message */ +CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, + const char *chlg, + const char *userp, + const char *passwdp, + char **outptr, size_t *outlen); + +/* This is used to evaluate if DIGEST is supported */ +bool Curl_auth_is_digest_supported(void); + +/* This is used to generate a base64 encoded DIGEST-MD5 response message */ +CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, + const char *chlg64, + const char *userp, + const char *passwdp, + const char *service, + char **outptr, size_t *outlen); + +/* This is used to decode a HTTP DIGEST challenge message */ +CURLcode Curl_auth_decode_digest_http_message(const char *chlg, + struct digestdata *digest); + +/* This is used to generate a HTTP DIGEST response message */ +CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const unsigned char *request, + const unsigned char *uri, + struct digestdata *digest, + char **outptr, size_t *outlen); + +/* This is used to clean up the digest specific data */ +void Curl_auth_digest_cleanup(struct digestdata *digest); +#endif /* !CURL_DISABLE_CRYPTO_AUTH */ + +#if defined(USE_NTLM) +/* This is used to evaluate if NTLM is supported */ +bool Curl_auth_is_ntlm_supported(void); + +/* This is used to generate a base64 encoded NTLM type-1 message */ +CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + struct ntlmdata *ntlm, + char **outptr, + size_t *outlen); + +/* This is used to decode a base64 encoded NTLM type-2 message */ +CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, + const char *type2msg, + struct ntlmdata *ntlm); + +/* This is used to generate a base64 encoded NTLM type-3 message */ +CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + struct ntlmdata *ntlm, + char **outptr, size_t *outlen); + +/* This is used to clean up the NTLM specific data */ +void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm); +#endif /* USE_NTLM */ + +/* This is used to generate a base64 encoded OAuth 2.0 message */ +CURLcode Curl_auth_create_oauth_bearer_message(struct Curl_easy *data, + const char *user, + const char *host, + const long port, + const char *bearer, + char **outptr, size_t *outlen); +#if defined(USE_KERBEROS5) +/* This is used to evaluate if GSSAPI (Kerberos V5) is supported */ +bool Curl_auth_is_gssapi_supported(void); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) user token + message */ +CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, + const char *userp, + const char *passwdp, + const char *service, + const char *host, + const bool mutual, + const char *chlg64, + struct kerberos5data *krb5, + char **outptr, size_t *outlen); + +/* This is used to generate a base64 encoded GSSAPI (Kerberos V5) security + token message */ +CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, + const char *input, + struct kerberos5data *krb5, + char **outptr, + size_t *outlen); + +/* This is used to clean up the GSSAPI specific data */ +void Curl_auth_gssapi_cleanup(struct kerberos5data *krb5); +#endif /* USE_KERBEROS5 */ + +#if defined(USE_SPNEGO) +/* This is used to evaluate if SPNEGO (Negotiate) is supported */ +bool Curl_auth_is_spnego_supported(void); + +/* This is used to decode a base64 encoded SPNEGO (Negotiate) challenge + message */ +CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, + const char *user, + const char *passwood, + const char *service, + const char *host, + const char *chlg64, + struct negotiatedata *nego); + +/* This is used to generate a base64 encoded SPNEGO (Negotiate) response + message */ +CURLcode Curl_auth_create_spnego_message(struct Curl_easy *data, + struct negotiatedata *nego, + char **outptr, size_t *outlen); + +/* This is used to clean up the SPNEGO specifiec data */ +void Curl_auth_spnego_cleanup(struct negotiatedata *nego); + +#endif /* USE_SPNEGO */ + +#endif /* HEADER_CURL_VAUTH_H */ diff --git a/external/curl prx/include/vtls.h b/external/curl prx/include/vtls.h new file mode 100644 index 0000000..2a87ca1 --- /dev/null +++ b/external/curl prx/include/vtls.h @@ -0,0 +1,278 @@ +#ifndef HEADER_CURL_VTLS_H +#define HEADER_CURL_VTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +struct connectdata; +struct ssl_connect_data; + +#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */ +#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */ +#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */ +#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ +#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ +#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ + +struct Curl_ssl { + /* + * This *must* be the first entry to allow returning the list of available + * backends in curl_global_sslset(). + */ + curl_ssl_backend info; + unsigned int supports; /* bitfield, see above */ + size_t sizeof_ssl_backend_data; + + int (*init)(void); + void (*cleanup)(void); + + size_t (*version)(char *buffer, size_t size); + int (*check_cxn)(struct connectdata *cxn); + int (*shut_down)(struct connectdata *conn, int sockindex); + bool (*data_pending)(const struct connectdata *conn, + int connindex); + + /* return 0 if a find random is filled in */ + CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy, + size_t length); + bool (*cert_status_request)(void); + + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); + CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, + bool *done); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); + void (*close_one)(struct connectdata *conn, int sockindex); + void (*close_all)(struct Curl_easy *data); + void (*session_free)(void *ptr); + + CURLcode (*set_engine)(struct Curl_easy *data, const char *engine); + CURLcode (*set_engine_default)(struct Curl_easy *data); + struct curl_slist *(*engines_list)(struct Curl_easy *data); + + bool (*false_start)(void); + + CURLcode (*md5sum)(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5sumlen); + CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, + unsigned char *sha256sum, size_t sha256sumlen); +}; + +#ifdef USE_SSL +extern const struct Curl_ssl *Curl_ssl; +#endif + +int Curl_none_init(void); +void Curl_none_cleanup(void); +int Curl_none_shutdown(struct connectdata *conn, int sockindex); +int Curl_none_check_cxn(struct connectdata *conn); +CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); +void Curl_none_close_all(struct Curl_easy *data); +void Curl_none_session_free(void *ptr); +bool Curl_none_data_pending(const struct connectdata *conn, int connindex); +bool Curl_none_cert_status_request(void); +CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); +CURLcode Curl_none_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); +bool Curl_none_false_start(void); +bool Curl_ssl_tls13_ciphersuites(void); +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len); + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "cyassl.h" /* CyaSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ +#include "mbedtls.h" /* mbedTLS versions */ +#include "mesalink.h" /* MesaLink versions */ + +#ifndef MAX_PINNED_PUBKEY_SIZE +#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ +#endif + +#ifndef MD5_DIGEST_LENGTH +#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */ +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif +#endif + +#ifndef CURL_SHA256_DIGEST_LENGTH +#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ +#endif + +/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +#define ALPN_HTTP_1_1_LENGTH 8 +#define ALPN_HTTP_1_1 "http/1.1" + +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state) +#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \ + data->set.ssl.var) +#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +int Curl_ssl_backend(void); + +#ifdef USE_SSL +int Curl_ssl_init(void); +void Curl_ssl_cleanup(void); +CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +void Curl_ssl_close_all(struct Curl_easy *data); +void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data); + +/* init the SSL session ID cache */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t); +size_t Curl_ssl_version(char *buffer, size_t size); +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +void Curl_ssl_free_certinfo(struct Curl_easy *data); +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, + size_t valuelen); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); + +/* Functions to be used by SSL library adaptation functions */ + +/* Lock session cache mutex. + * Call this before calling other Curl_ssl_*session* functions + * Caller should unlock this mutex as soon as possible, as it may block + * other SSL connection from making progress. + * The purpose of explicitly locking SSL session cache data is to allow + * individual SSL engines to manage session lifetime in their specific way. + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn); + +/* Unlock session cache mutex */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn); + +/* extract a session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must make sure that the ownership of returned sessionid object + * is properly taken (e.g. its refcount is incremented + * under sessionid mutex). + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex); +/* add a new session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must ensure that it has properly shared ownership of this sessionid + * object with cache (e.g. incrementing refcount on success) + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex); +/* Kill a single session ID entry in the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer */ +CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, + size_t length); +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +/* Check pinned public key. */ +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen); + +bool Curl_ssl_cert_status_request(void); + +bool Curl_ssl_false_start(void); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#else /* if not USE_SSL */ + +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE +#define Curl_ssl_tls13_ciphersuites() FALSE +#endif + +#endif /* HEADER_CURL_VTLS_H */ diff --git a/external/curl prx/include/vtls/cyassl.h b/external/curl prx/include/vtls/cyassl.h new file mode 100644 index 0000000..01e11cc --- /dev/null +++ b/external/curl prx/include/vtls/cyassl.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CURL_CYASSL_H +#define HEADER_CURL_CYASSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_CYASSL + +extern const struct Curl_ssl Curl_ssl_cyassl; + +#endif /* USE_CYASSL */ +#endif /* HEADER_CURL_CYASSL_H */ diff --git a/external/curl prx/include/vtls/gskit.h b/external/curl prx/include/vtls/gskit.h new file mode 100644 index 0000000..466ee4d --- /dev/null +++ b/external/curl prx/include/vtls/gskit.h @@ -0,0 +1,38 @@ +#ifndef HEADER_CURL_GSKIT_H +#define HEADER_CURL_GSKIT_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +/* + * This header should only be needed to get included by vtls.c and gskit.c + */ + +#include "urldata.h" + +#ifdef USE_GSKIT + +extern const struct Curl_ssl Curl_ssl_gskit; + +#endif /* USE_GSKIT */ + +#endif /* HEADER_CURL_GSKIT_H */ diff --git a/external/curl prx/include/vtls/gtls.h b/external/curl prx/include/vtls/gtls.h new file mode 100644 index 0000000..780fc10 --- /dev/null +++ b/external/curl prx/include/vtls/gtls.h @@ -0,0 +1,34 @@ +#ifndef HEADER_CURL_GTLS_H +#define HEADER_CURL_GTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_GNUTLS + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_gnutls; + +#endif /* USE_GNUTLS */ +#endif /* HEADER_CURL_GTLS_H */ diff --git a/external/curl prx/include/vtls/mbedtls.h b/external/curl prx/include/vtls/mbedtls.h new file mode 100644 index 0000000..4a93860 --- /dev/null +++ b/external/curl prx/include/vtls/mbedtls.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MBEDTLS_H +#define HEADER_CURL_MBEDTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MBEDTLS + +extern const struct Curl_ssl Curl_ssl_mbedtls; + +#endif /* USE_MBEDTLS */ +#endif /* HEADER_CURL_MBEDTLS_H */ diff --git a/external/curl prx/include/vtls/mesalink.h b/external/curl prx/include/vtls/mesalink.h new file mode 100644 index 0000000..54cb94a --- /dev/null +++ b/external/curl prx/include/vtls/mesalink.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_MESALINK_H +#define HEADER_CURL_MESALINK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2017-2018, Yiming Jing, + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_MESALINK + +extern const struct Curl_ssl Curl_ssl_mesalink; + +#endif /* USE_MESALINK */ +#endif /* HEADER_CURL_MESALINK_H */ diff --git a/external/curl prx/include/vtls/nssg.h b/external/curl prx/include/vtls/nssg.h new file mode 100644 index 0000000..41e51b0 --- /dev/null +++ b/external/curl prx/include/vtls/nssg.h @@ -0,0 +1,39 @@ +#ifndef HEADER_CURL_NSSG_H +#define HEADER_CURL_NSSG_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_NSS +/* + * This header should only be needed to get included by vtls.c and nss.c + */ + +#include "urldata.h" + +/* initialize NSS library if not already */ +CURLcode Curl_nss_force_init(struct Curl_easy *data); + +extern const struct Curl_ssl Curl_ssl_nss; + +#endif /* USE_NSS */ +#endif /* HEADER_CURL_NSSG_H */ diff --git a/external/curl prx/include/vtls/openssl.h b/external/curl prx/include/vtls/openssl.h new file mode 100644 index 0000000..114dc4b --- /dev/null +++ b/external/curl prx/include/vtls/openssl.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CURL_SSLUSE_H +#define HEADER_CURL_SSLUSE_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef USE_OPENSSL +/* + * This header should only be needed to get included by vtls.c and openssl.c + */ + +#include "urldata.h" + +extern const struct Curl_ssl Curl_ssl_openssl; + +#endif /* USE_OPENSSL */ +#endif /* HEADER_CURL_SSLUSE_H */ diff --git a/external/curl prx/include/vtls/polarssl.h b/external/curl prx/include/vtls/polarssl.h new file mode 100644 index 0000000..23c3636 --- /dev/null +++ b/external/curl prx/include/vtls/polarssl.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_POLARSSL_H +#define HEADER_CURL_POLARSSL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2016, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_POLARSSL + +extern const struct Curl_ssl Curl_ssl_polarssl; + +#endif /* USE_POLARSSL */ +#endif /* HEADER_CURL_POLARSSL_H */ diff --git a/external/curl prx/include/vtls/polarssl_threadlock.h b/external/curl prx/include/vtls/polarssl_threadlock.h new file mode 100644 index 0000000..dda5359 --- /dev/null +++ b/external/curl prx/include/vtls/polarssl_threadlock.h @@ -0,0 +1,53 @@ +#ifndef HEADER_CURL_POLARSSL_THREADLOCK_H +#define HEADER_CURL_POLARSSL_THREADLOCK_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2013-2015, Daniel Stenberg, , et al. + * Copyright (C) 2010, Hoi-Ho Chan, + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#if (defined USE_POLARSSL) || (defined USE_MBEDTLS) + +#if defined(USE_THREADS_POSIX) +# define POLARSSL_MUTEX_T pthread_mutex_t +#elif defined(USE_THREADS_WIN32) +# define POLARSSL_MUTEX_T HANDLE +#endif + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + +int Curl_polarsslthreadlock_thread_setup(void); +int Curl_polarsslthreadlock_thread_cleanup(void); +int Curl_polarsslthreadlock_lock_function(int n); +int Curl_polarsslthreadlock_unlock_function(int n); + +#else + +#define Curl_polarsslthreadlock_thread_setup() 1 +#define Curl_polarsslthreadlock_thread_cleanup() 1 +#define Curl_polarsslthreadlock_lock_function(x) 1 +#define Curl_polarsslthreadlock_unlock_function(x) 1 + +#endif /* USE_THREADS_POSIX || USE_THREADS_WIN32 */ + +#endif /* USE_POLARSSL */ + +#endif /* HEADER_CURL_POLARSSL_THREADLOCK_H */ diff --git a/external/curl prx/include/vtls/schannel.h b/external/curl prx/include/vtls/schannel.h new file mode 100644 index 0000000..ee8d7d4 --- /dev/null +++ b/external/curl prx/include/vtls/schannel.h @@ -0,0 +1,108 @@ +#ifndef HEADER_CURL_SCHANNEL_H +#define HEADER_CURL_SCHANNEL_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012, Marc Hoersken, , et al. + * Copyright (C) 2012 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SCHANNEL + +#include +#include +#include "curl_sspi.h" + +#include "urldata.h" + +/* has been included via the above . + * Or in case of ldap.c, it was included via . + * And since has this: + * #define X509_NAME ((LPCSTR) 7) + * + * And in BoringSSL's there is: + * typedef struct X509_name_st X509_NAME; + * etc. + * + * this will cause all kinds of C-preprocessing paste errors in + * BoringSSL's : So just undefine those defines here + * (and only here). + */ +#if defined(HAVE_BORINGSSL) || defined(OPENSSL_IS_BORINGSSL) +# undef X509_NAME +# undef X509_CERT_PAIR +# undef X509_EXTENSIONS +#endif + +extern const struct Curl_ssl Curl_ssl_schannel; + +CURLcode Curl_verify_certificate(struct connectdata *conn, int sockindex); + +/* structs to expose only in schannel.c and schannel_verify.c */ +#ifdef EXPOSE_SCHANNEL_INTERNAL_STRUCTS + +#ifdef __MINGW32__ +#include <_mingw.h> +#ifdef __MINGW64_VERSION_MAJOR +#define HAS_MANUAL_VERIFY_API +#endif +#else +#include +#ifdef CERT_CHAIN_REVOCATION_CHECK_CHAIN +#define HAS_MANUAL_VERIFY_API +#endif +#endif + +struct curl_schannel_cred { + CredHandle cred_handle; + TimeStamp time_stamp; + int refcount; +}; + +struct curl_schannel_ctxt { + CtxtHandle ctxt_handle; + TimeStamp time_stamp; +}; + +struct ssl_backend_data { + struct curl_schannel_cred *cred; + struct curl_schannel_ctxt *ctxt; + SecPkgContext_StreamSizes stream_sizes; + size_t encdata_length, decdata_length; + size_t encdata_offset, decdata_offset; + unsigned char *encdata_buffer, *decdata_buffer; + /* encdata_is_incomplete: if encdata contains only a partial record that + can't be decrypted without another Curl_read_plain (that is, status is + SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes + more bytes into encdata then set this back to false. */ + bool encdata_is_incomplete; + unsigned long req_flags, ret_flags; + CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */ + bool recv_sspi_close_notify; /* true if connection closed by close_notify */ + bool recv_connection_closed; /* true if connection closed, regardless how */ + bool use_alpn; /* true if ALPN is used for this connection */ +#ifdef HAS_MANUAL_VERIFY_API + bool use_manual_cred_validation; /* true if manual cred validation is used */ +#endif +}; +#endif /* EXPOSE_SCHANNEL_INTERNAL_STRUCTS */ + +#endif /* USE_SCHANNEL */ +#endif /* HEADER_CURL_SCHANNEL_H */ diff --git a/external/curl prx/include/vtls/sectransp.h b/external/curl prx/include/vtls/sectransp.h new file mode 100644 index 0000000..5cec797 --- /dev/null +++ b/external/curl prx/include/vtls/sectransp.h @@ -0,0 +1,32 @@ +#ifndef HEADER_CURL_SECTRANSP_H +#define HEADER_CURL_SECTRANSP_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2012 - 2014, Nick Zitzmann, . + * Copyright (C) 2012 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +#ifdef USE_SECTRANSP + +extern const struct Curl_ssl Curl_ssl_sectransp; + +#endif /* USE_SECTRANSP */ +#endif /* HEADER_CURL_SECTRANSP_H */ diff --git a/external/curl prx/include/vtls/vtls.h b/external/curl prx/include/vtls/vtls.h new file mode 100644 index 0000000..2a87ca1 --- /dev/null +++ b/external/curl prx/include/vtls/vtls.h @@ -0,0 +1,278 @@ +#ifndef HEADER_CURL_VTLS_H +#define HEADER_CURL_VTLS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "curl_setup.h" + +struct connectdata; +struct ssl_connect_data; + +#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */ +#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */ +#define SSLSUPP_PINNEDPUBKEY (1<<2) /* supports CURLOPT_PINNEDPUBLICKEY */ +#define SSLSUPP_SSL_CTX (1<<3) /* supports CURLOPT_SSL_CTX */ +#define SSLSUPP_HTTPS_PROXY (1<<4) /* supports access via HTTPS proxies */ +#define SSLSUPP_TLS13_CIPHERSUITES (1<<5) /* supports TLS 1.3 ciphersuites */ + +struct Curl_ssl { + /* + * This *must* be the first entry to allow returning the list of available + * backends in curl_global_sslset(). + */ + curl_ssl_backend info; + unsigned int supports; /* bitfield, see above */ + size_t sizeof_ssl_backend_data; + + int (*init)(void); + void (*cleanup)(void); + + size_t (*version)(char *buffer, size_t size); + int (*check_cxn)(struct connectdata *cxn); + int (*shut_down)(struct connectdata *conn, int sockindex); + bool (*data_pending)(const struct connectdata *conn, + int connindex); + + /* return 0 if a find random is filled in */ + CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy, + size_t length); + bool (*cert_status_request)(void); + + CURLcode (*connect_blocking)(struct connectdata *conn, int sockindex); + CURLcode (*connect_nonblocking)(struct connectdata *conn, int sockindex, + bool *done); + void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info); + void (*close_one)(struct connectdata *conn, int sockindex); + void (*close_all)(struct Curl_easy *data); + void (*session_free)(void *ptr); + + CURLcode (*set_engine)(struct Curl_easy *data, const char *engine); + CURLcode (*set_engine_default)(struct Curl_easy *data); + struct curl_slist *(*engines_list)(struct Curl_easy *data); + + bool (*false_start)(void); + + CURLcode (*md5sum)(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5sumlen); + CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, + unsigned char *sha256sum, size_t sha256sumlen); +}; + +#ifdef USE_SSL +extern const struct Curl_ssl *Curl_ssl; +#endif + +int Curl_none_init(void); +void Curl_none_cleanup(void); +int Curl_none_shutdown(struct connectdata *conn, int sockindex); +int Curl_none_check_cxn(struct connectdata *conn); +CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy, + size_t length); +void Curl_none_close_all(struct Curl_easy *data); +void Curl_none_session_free(void *ptr); +bool Curl_none_data_pending(const struct connectdata *conn, int connindex); +bool Curl_none_cert_status_request(void); +CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine); +CURLcode Curl_none_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_none_engines_list(struct Curl_easy *data); +bool Curl_none_false_start(void); +bool Curl_ssl_tls13_ciphersuites(void); +CURLcode Curl_none_md5sum(unsigned char *input, size_t inputlen, + unsigned char *md5sum, size_t md5len); + +#include "openssl.h" /* OpenSSL versions */ +#include "gtls.h" /* GnuTLS versions */ +#include "nssg.h" /* NSS versions */ +#include "gskit.h" /* Global Secure ToolKit versions */ +#include "polarssl.h" /* PolarSSL versions */ +#include "cyassl.h" /* CyaSSL versions */ +#include "schannel.h" /* Schannel SSPI version */ +#include "sectransp.h" /* SecureTransport (Darwin) version */ +#include "mbedtls.h" /* mbedTLS versions */ +#include "mesalink.h" /* MesaLink versions */ + +#ifndef MAX_PINNED_PUBKEY_SIZE +#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ +#endif + +#ifndef MD5_DIGEST_LENGTH +#ifndef LIBWOLFSSL_VERSION_HEX /* because WolfSSL borks this */ +#define MD5_DIGEST_LENGTH 16 /* fixed size */ +#endif +#endif + +#ifndef CURL_SHA256_DIGEST_LENGTH +#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ +#endif + +/* see https://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg-04 */ +#define ALPN_HTTP_1_1_LENGTH 8 +#define ALPN_HTTP_1_1 "http/1.1" + +/* set of helper macros for the backends to access the correct fields. For the + proxy or for the remote host - to properly support HTTPS proxy */ + +#define SSL_IS_PROXY() (CURLPROXY_HTTPS == conn->http_proxy.proxytype && \ + ssl_connection_complete != conn->proxy_ssl[conn->sock[SECONDARYSOCKET] == \ + CURL_SOCKET_BAD ? FIRSTSOCKET : SECONDARYSOCKET].state) +#define SSL_SET_OPTION(var) (SSL_IS_PROXY() ? data->set.proxy_ssl.var : \ + data->set.ssl.var) +#define SSL_CONN_CONFIG(var) (SSL_IS_PROXY() ? \ + conn->proxy_ssl_config.var : conn->ssl_config.var) + +bool Curl_ssl_config_matches(struct ssl_primary_config* data, + struct ssl_primary_config* needle); +bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source, + struct ssl_primary_config *dest); +void Curl_free_primary_ssl_config(struct ssl_primary_config* sslc); +int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); + +int Curl_ssl_backend(void); + +#ifdef USE_SSL +int Curl_ssl_init(void); +void Curl_ssl_cleanup(void); +CURLcode Curl_ssl_connect(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_connect_nonblocking(struct connectdata *conn, + int sockindex, + bool *done); +/* tell the SSL stuff to close down all open information regarding + connections (and thus session ID caching etc) */ +void Curl_ssl_close_all(struct Curl_easy *data); +void Curl_ssl_close(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_shutdown(struct connectdata *conn, int sockindex); +CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine); +/* Sets engine as default for all SSL operations */ +CURLcode Curl_ssl_set_engine_default(struct Curl_easy *data); +struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data); + +/* init the SSL session ID cache */ +CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t); +size_t Curl_ssl_version(char *buffer, size_t size); +bool Curl_ssl_data_pending(const struct connectdata *conn, + int connindex); +int Curl_ssl_check_cxn(struct connectdata *conn); + +/* Certificate information list handling. */ + +void Curl_ssl_free_certinfo(struct Curl_easy *data); +CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); +CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, int certnum, + const char *label, const char *value, + size_t valuelen); +CURLcode Curl_ssl_push_certinfo(struct Curl_easy *data, int certnum, + const char *label, const char *value); + +/* Functions to be used by SSL library adaptation functions */ + +/* Lock session cache mutex. + * Call this before calling other Curl_ssl_*session* functions + * Caller should unlock this mutex as soon as possible, as it may block + * other SSL connection from making progress. + * The purpose of explicitly locking SSL session cache data is to allow + * individual SSL engines to manage session lifetime in their specific way. + */ +void Curl_ssl_sessionid_lock(struct connectdata *conn); + +/* Unlock session cache mutex */ +void Curl_ssl_sessionid_unlock(struct connectdata *conn); + +/* extract a session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must make sure that the ownership of returned sessionid object + * is properly taken (e.g. its refcount is incremented + * under sessionid mutex). + */ +bool Curl_ssl_getsessionid(struct connectdata *conn, + void **ssl_sessionid, + size_t *idsize, /* set 0 if unknown */ + int sockindex); +/* add a new session ID + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * Caller must ensure that it has properly shared ownership of this sessionid + * object with cache (e.g. incrementing refcount on success) + */ +CURLcode Curl_ssl_addsessionid(struct connectdata *conn, + void *ssl_sessionid, + size_t idsize, + int sockindex); +/* Kill a single session ID entry in the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_kill_session(struct curl_ssl_session *session); +/* delete a session from the cache + * Sessionid mutex must be locked (see Curl_ssl_sessionid_lock). + * This will call engine-specific curlssl_session_free function, which must + * take sessionid object ownership from sessionid cache + * (e.g. decrement refcount). + */ +void Curl_ssl_delsessionid(struct connectdata *conn, void *ssl_sessionid); + +/* get N random bytes into the buffer */ +CURLcode Curl_ssl_random(struct Curl_easy *data, unsigned char *buffer, + size_t length); +CURLcode Curl_ssl_md5sum(unsigned char *tmp, /* input */ + size_t tmplen, + unsigned char *md5sum, /* output */ + size_t md5len); +/* Check pinned public key. */ +CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, + const char *pinnedpubkey, + const unsigned char *pubkey, size_t pubkeylen); + +bool Curl_ssl_cert_status_request(void); + +bool Curl_ssl_false_start(void); + +#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */ + +#else /* if not USE_SSL */ + +/* When SSL support is not present, just define away these function calls */ +#define Curl_ssl_init() 1 +#define Curl_ssl_cleanup() Curl_nop_stmt +#define Curl_ssl_connect(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_close_all(x) Curl_nop_stmt +#define Curl_ssl_close(x,y) Curl_nop_stmt +#define Curl_ssl_shutdown(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN +#define Curl_ssl_engines_list(x) NULL +#define Curl_ssl_send(a,b,c,d,e) -1 +#define Curl_ssl_recv(a,b,c,d,e) -1 +#define Curl_ssl_initsessions(x,y) CURLE_OK +#define Curl_ssl_version(x,y) 0 +#define Curl_ssl_data_pending(x,y) 0 +#define Curl_ssl_check_cxn(x) 0 +#define Curl_ssl_free_certinfo(x) Curl_nop_stmt +#define Curl_ssl_connect_nonblocking(x,y,z) CURLE_NOT_BUILT_IN +#define Curl_ssl_kill_session(x) Curl_nop_stmt +#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_cert_status_request() FALSE +#define Curl_ssl_false_start() FALSE +#define Curl_ssl_tls13_ciphersuites() FALSE +#endif + +#endif /* HEADER_CURL_VTLS_H */ diff --git a/external/curl prx/include/warnless.h b/external/curl prx/include/warnless.h new file mode 100644 index 0000000..ea4c439 --- /dev/null +++ b/external/curl prx/include/warnless.h @@ -0,0 +1,112 @@ +#ifndef HEADER_CURL_WARNLESS_H +#define HEADER_CURL_WARNLESS_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#ifdef USE_WINSOCK +#include /* for curl_socket_t */ +#endif + +#define CURLX_FUNCTION_CAST(target_type, func) \ + (target_type)(void (*) (void))(func) + +unsigned short curlx_ultous(unsigned long ulnum); + +unsigned char curlx_ultouc(unsigned long ulnum); + +int curlx_ultosi(unsigned long ulnum); + +int curlx_uztosi(size_t uznum); + +curl_off_t curlx_uztoso(size_t uznum); + +unsigned long curlx_uztoul(size_t uznum); + +unsigned int curlx_uztoui(size_t uznum); + +int curlx_sltosi(long slnum); + +unsigned int curlx_sltoui(long slnum); + +unsigned short curlx_sltous(long slnum); + +ssize_t curlx_uztosz(size_t uznum); + +size_t curlx_sotouz(curl_off_t sonum); + +int curlx_sztosi(ssize_t sznum); + +unsigned short curlx_uitous(unsigned int uinum); + +size_t curlx_sitouz(int sinum); + +#ifdef USE_WINSOCK + +int curlx_sktosi(curl_socket_t s); + +curl_socket_t curlx_sitosk(int i); + +#endif /* USE_WINSOCK */ + +#if defined(WIN32) || defined(_WIN32) + +ssize_t curlx_read(int fd, void *buf, size_t count); + +ssize_t curlx_write(int fd, const void *buf, size_t count); + +#ifndef BUILDING_WARNLESS_C +# undef read +# define read(fd, buf, count) curlx_read(fd, buf, count) +# undef write +# define write(fd, buf, count) curlx_write(fd, buf, count) +#endif + +#endif /* WIN32 || _WIN32 */ + +#if defined(__INTEL_COMPILER) && defined(__unix__) + +int curlx_FD_ISSET(int fd, fd_set *fdset); + +void curlx_FD_SET(int fd, fd_set *fdset); + +void curlx_FD_ZERO(fd_set *fdset); + +unsigned short curlx_htons(unsigned short usnum); + +unsigned short curlx_ntohs(unsigned short usnum); + +#ifndef BUILDING_WARNLESS_C +# undef FD_ISSET +# define FD_ISSET(a,b) curlx_FD_ISSET((a),(b)) +# undef FD_SET +# define FD_SET(a,b) curlx_FD_SET((a),(b)) +# undef FD_ZERO +# define FD_ZERO(a) curlx_FD_ZERO((a)) +# undef htons +# define htons(a) curlx_htons((a)) +# undef ntohs +# define ntohs(a) curlx_ntohs((a)) +#endif + +#endif /* __INTEL_COMPILER && __unix__ */ + +#endif /* HEADER_CURL_WARNLESS_H */ diff --git a/external/curl prx/include/wildcard.h b/external/curl prx/include/wildcard.h new file mode 100644 index 0000000..b782612 --- /dev/null +++ b/external/curl prx/include/wildcard.h @@ -0,0 +1,61 @@ +#ifndef HEADER_CURL_WILDCARD_H +#define HEADER_CURL_WILDCARD_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2010 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include + +#include "llist.h" + +/* list of wildcard process states */ +typedef enum { + CURLWC_CLEAR = 0, + CURLWC_INIT = 1, + CURLWC_MATCHING, /* library is trying to get list of addresses for + downloading */ + CURLWC_DOWNLOADING, + CURLWC_CLEAN, /* deallocate resources and reset settings */ + CURLWC_SKIP, /* skip over concrete file */ + CURLWC_ERROR, /* error cases */ + CURLWC_DONE /* if is wildcard->state == CURLWC_DONE wildcard loop + will end */ +} curl_wildcard_states; + +typedef void (*curl_wildcard_dtor)(void *ptr); + +/* struct keeping information about wildcard download process */ +struct WildcardData { + curl_wildcard_states state; + char *path; /* path to the directory, where we trying wildcard-match */ + char *pattern; /* wildcard pattern */ + struct curl_llist filelist; /* llist with struct Curl_fileinfo */ + void *protdata; /* pointer to protocol specific temporary data */ + curl_wildcard_dtor dtor; + void *customptr; /* for CURLOPT_CHUNK_DATA pointer */ +}; + +CURLcode Curl_wildcard_init(struct WildcardData *wc); +void Curl_wildcard_dtor(struct WildcardData *wc); + +struct Curl_easy; + +#endif /* HEADER_CURL_WILDCARD_H */ diff --git a/external/curl prx/include/x509asn1.h b/external/curl prx/include/x509asn1.h new file mode 100644 index 0000000..ce40297 --- /dev/null +++ b/external/curl prx/include/x509asn1.h @@ -0,0 +1,134 @@ +#ifndef HEADER_CURL_X509ASN1_H +#define HEADER_CURL_X509ASN1_H + +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2016, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#if defined(USE_GSKIT) || defined(USE_NSS) || defined(USE_GNUTLS) || \ + defined(USE_CYASSL) || defined(USE_SCHANNEL) + +#include "urldata.h" + +/* + * Constants. + */ + +/* Largest supported ASN.1 structure. */ +#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ + +/* ASN.1 classes. */ +#define CURL_ASN1_UNIVERSAL 0 +#define CURL_ASN1_APPLICATION 1 +#define CURL_ASN1_CONTEXT_SPECIFIC 2 +#define CURL_ASN1_PRIVATE 3 + +/* ASN.1 types. */ +#define CURL_ASN1_BOOLEAN 1 +#define CURL_ASN1_INTEGER 2 +#define CURL_ASN1_BIT_STRING 3 +#define CURL_ASN1_OCTET_STRING 4 +#define CURL_ASN1_NULL 5 +#define CURL_ASN1_OBJECT_IDENTIFIER 6 +#define CURL_ASN1_OBJECT_DESCRIPTOR 7 +#define CURL_ASN1_INSTANCE_OF 8 +#define CURL_ASN1_REAL 9 +#define CURL_ASN1_ENUMERATED 10 +#define CURL_ASN1_EMBEDDED 11 +#define CURL_ASN1_UTF8_STRING 12 +#define CURL_ASN1_RELATIVE_OID 13 +#define CURL_ASN1_SEQUENCE 16 +#define CURL_ASN1_SET 17 +#define CURL_ASN1_NUMERIC_STRING 18 +#define CURL_ASN1_PRINTABLE_STRING 19 +#define CURL_ASN1_TELETEX_STRING 20 +#define CURL_ASN1_VIDEOTEX_STRING 21 +#define CURL_ASN1_IA5_STRING 22 +#define CURL_ASN1_UTC_TIME 23 +#define CURL_ASN1_GENERALIZED_TIME 24 +#define CURL_ASN1_GRAPHIC_STRING 25 +#define CURL_ASN1_VISIBLE_STRING 26 +#define CURL_ASN1_GENERAL_STRING 27 +#define CURL_ASN1_UNIVERSAL_STRING 28 +#define CURL_ASN1_CHARACTER_STRING 29 +#define CURL_ASN1_BMP_STRING 30 + + +/* + * Types. + */ + +/* ASN.1 parsed element. */ +typedef struct { + const char * header; /* Pointer to header byte. */ + const char * beg; /* Pointer to element data. */ + const char * end; /* Pointer to 1st byte after element. */ + unsigned char class; /* ASN.1 element class. */ + unsigned char tag; /* ASN.1 element tag. */ + bool constructed; /* Element is constructed. */ +} curl_asn1Element; + + +/* ASN.1 OID table entry. */ +typedef struct { + const char * numoid; /* Dotted-numeric OID. */ + const char * textoid; /* OID name. */ +} curl_OID; + + +/* X509 certificate: RFC 5280. */ +typedef struct { + curl_asn1Element certificate; + curl_asn1Element version; + curl_asn1Element serialNumber; + curl_asn1Element signatureAlgorithm; + curl_asn1Element signature; + curl_asn1Element issuer; + curl_asn1Element notBefore; + curl_asn1Element notAfter; + curl_asn1Element subject; + curl_asn1Element subjectPublicKeyInfo; + curl_asn1Element subjectPublicKeyAlgorithm; + curl_asn1Element subjectPublicKey; + curl_asn1Element issuerUniqueID; + curl_asn1Element subjectUniqueID; + curl_asn1Element extensions; +} curl_X509certificate; + + +/* + * Prototypes. + */ + +const char *Curl_getASN1Element(curl_asn1Element *elem, + const char *beg, const char *end); +const char *Curl_ASN1tostr(curl_asn1Element *elem, int type); +const char *Curl_DNtostr(curl_asn1Element *dn); +int Curl_parseX509(curl_X509certificate *cert, + const char *beg, const char *end); +CURLcode Curl_extract_certinfo(struct connectdata *conn, int certnum, + const char *beg, const char *end); +CURLcode Curl_verifyhost(struct connectdata *conn, + const char *beg, const char *end); +#endif /* USE_GSKIT or USE_NSS or USE_GNUTLS or USE_CYASSL or USE_SCHANNEL */ +#endif /* HEADER_CURL_X509ASN1_H */ diff --git a/external/curl prx/src/curl.c b/external/curl prx/src/curl.c new file mode 100644 index 0000000..ed4f46d --- /dev/null +++ b/external/curl prx/src/curl.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int curlDownloadFile(const char * url, + const char * file, + const char * ua, + int( * update_cb)(void * p, int64_t dltotal, int64_t dlnow, int64_t ultotal, int64_t ulnow)) { + CURL * curl = NULL; + FILE * imageFD = fopen(file, "wb"); + if (!imageFD) { + return -1336; + } + + CURLcode res; + if (!curl) curl = curl_easy_init(); + if (curl) { + curl_easy_setopt(curl, CURLOPT_URL, url); + // Set user agent string + curl_easy_setopt(curl, CURLOPT_USERAGENT, ua); + // not sure how to use this when enabled + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + // not sure how to use this when enabled + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + // Set SSL VERSION to TLS 1.2 + curl_easy_setopt(curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + // Set timeout for the connection to build + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); + // Follow redirects (?) + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + // The function that will be used to write the data + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite); + // The data filedescriptor which will be written to + curl_easy_setopt(curl, CURLOPT_WRITEDATA, imageFD); + // maximum number of redirects allowed + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 20); + // Fail the request if the HTTP code returned is equal to or larger than 400 + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + // request using SSL for the FTP transfer if available + curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY); + + /* pass the struct pointer into the xferinfo function */ + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, update_cb); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, NULL); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + + // Perform the request + res = curl_easy_perform(curl); + if (res != CURLE_OK) { + printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + return -res; + + } else { + int httpresponsecode = 0; + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, & httpresponsecode); + // close filedescriptor + fclose(imageFD); + // cleanup + curl_easy_cleanup(curl); + return httpresponsecode; + } + + } else { + printf("NO CURL curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + } + + // close filedescriptor + fclose(imageFD); + + // cleanup + curl_easy_cleanup(curl); + + return -1337; + +} \ No newline at end of file diff --git a/external/curl prx/src/easy.c b/external/curl prx/src/easy.c new file mode 100644 index 0000000..c48d983 --- /dev/null +++ b/external/curl prx/src/easy.c @@ -0,0 +1,1138 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +/* + * See comment in curl_memory.h for the explanation of this sanity check. + */ + +#ifdef CURLX_NO_MEMORY_CALLBACKS +#error "libcurl shall not ever be built with CURLX_NO_MEMORY_CALLBACKS defined" +#endif + + +#include +#include +#include +#include +#include "urldata.h" +#include +#include "transfer.h" +#include "vtls/vtls.h" +#include "url.h" +#include "getinfo.h" +#include "hostip.h" +#include "share.h" +#include "strdup.h" +#include "progress.h" +#include "easyif.h" +#include "multiif.h" +#include "select.h" +#include "sendf.h" /* for failf function prototype */ +#include "connect.h" /* for Curl_getconnectinfo */ +#include "slist.h" +#include "mime.h" +#include "amigaos.h" +#include "non-ascii.h" +#include "warnless.h" +#include "multiif.h" +#include "sigpipe.h" +#include "ssh.h" +#include "setopt.h" +#include "http_digest.h" +#include "system_win32.h" +#define HAVE_STRDUP 1 + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +void Curl_version_init(void); + +/* true globals -- for curl_global_init() and curl_global_cleanup() */ +static unsigned int initialized; +static long init_flags; + +/* + * strdup (and other memory functions) is redefined in complicated + * ways, but at this point it must be defined as the system-supplied strdup + * so the callback pointer is initialized correctly. + */ +#if defined(_WIN32_WCE) +#define system_strdup _strdup +#elif !defined(HAVE_STRDUP) +#define system_strdup curlx_strdup +#else +#define system_strdup strdup +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#endif + +#ifndef __SYMBIAN32__ +/* + * If a memory-using function (like curl_getenv) is used before + * curl_global_init() is called, we need to have these pointers set already. + */ +curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc; +curl_free_callback Curl_cfree = (curl_free_callback)free; +curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc; +curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup; +curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) +curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif +#else +/* + * Symbian OS doesn't support initialization to code in writable static data. + * Initialization will occur in the curl_global_init() call. + */ +curl_malloc_callback Curl_cmalloc; +curl_free_callback Curl_cfree; +curl_realloc_callback Curl_crealloc; +curl_strdup_callback Curl_cstrdup; +curl_calloc_callback Curl_ccalloc; +#endif + +#if defined(_MSC_VER) && defined(_DLL) && !defined(__POCC__) +# pragma warning(default:4232) /* MSVC extension, dllimport identity */ +#endif + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +static CURLcode global_init(long flags, bool memoryfuncs) +{ + if(initialized++) + return CURLE_OK; + + if(memoryfuncs) { + /* Setup the default memory functions here (again) */ + Curl_cmalloc = (curl_malloc_callback)malloc; + Curl_cfree = (curl_free_callback)free; + Curl_crealloc = (curl_realloc_callback)realloc; + Curl_cstrdup = (curl_strdup_callback)system_strdup; + Curl_ccalloc = (curl_calloc_callback)calloc; +#if defined(WIN32) && defined(UNICODE) + Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup; +#endif + } + + if(!Curl_ssl_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n")); + return CURLE_FAILED_INIT; + } + +#ifdef WIN32 + if(Curl_win32_init(flags)) { + DEBUGF(fprintf(stderr, "Error: win32_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef __AMIGA__ + if(!Curl_amiga_init()) { + DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#ifdef NETWARE + if(netware_init()) { + DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n")); + } +#endif + + if(Curl_resolver_global_init()) { + DEBUGF(fprintf(stderr, "Error: resolver_global_init failed\n")); + return CURLE_FAILED_INIT; + } + + (void)Curl_ipv6works(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT) + if(libssh2_init(0)) { + DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + +#if defined(USE_LIBSSH) + if(ssh_init()) { + DEBUGF(fprintf(stderr, "Error: libssh_init failed\n")); + return CURLE_FAILED_INIT; + } +#endif + + if(flags & CURL_GLOBAL_ACK_EINTR) + Curl_ack_eintr = 1; + + init_flags = flags; + + Curl_version_init(); + + return CURLE_OK; +} + + +/** + * curl_global_init() globally initializes curl given a bitwise set of the + * different features of what to initialize. + */ +CURLcode curl_global_init(long flags) +{ + return global_init(flags, TRUE); +} + +/* + * curl_global_init_mem() globally initializes curl and also registers the + * user provided callback routines. + */ +CURLcode curl_global_init_mem(long flags, curl_malloc_callback m, + curl_free_callback f, curl_realloc_callback r, + curl_strdup_callback s, curl_calloc_callback c) +{ + /* Invalid input, return immediately */ + if(!m || !f || !r || !s || !c) + return CURLE_FAILED_INIT; + + if(initialized) { + /* Already initialized, don't do it again, but bump the variable anyway to + work like curl_global_init() and require the same amount of cleanup + calls. */ + initialized++; + return CURLE_OK; + } + + /* set memory functions before global_init() in case it wants memory + functions */ + Curl_cmalloc = m; + Curl_cfree = f; + Curl_cstrdup = s; + Curl_crealloc = r; + Curl_ccalloc = c; + + /* Call the actual init function, but without setting */ + return global_init(flags, FALSE); +} + +/** + * curl_global_cleanup() globally cleanups curl, uses the value of + * "init_flags" to determine what needs to be cleaned up and what doesn't. + */ +void curl_global_cleanup(void) +{ + if(!initialized) + return; + + if(--initialized) + return; + + Curl_global_host_cache_dtor(); + Curl_ssl_cleanup(); + Curl_resolver_global_cleanup(); + +#ifdef WIN32 + Curl_win32_cleanup(init_flags); +#endif + + Curl_amiga_cleanup(); + +#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT) + (void)libssh2_exit(); +#endif + +#if defined(USE_LIBSSH) + (void)ssh_finalize(); +#endif + + init_flags = 0; +} + +/* + * curl_easy_init() is the external interface to alloc, setup and init an + * easy handle that is returned. If anything goes wrong, NULL is returned. + */ +struct Curl_easy *curl_easy_init(void) +{ + CURLcode result; + struct Curl_easy *data; + + /* Make sure we inited the global SSL stuff */ + if(!initialized) { + result = curl_global_init(CURL_GLOBAL_DEFAULT); + if(result) { + /* something in the global init failed, return nothing */ + DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n")); + return NULL; + } + } + + /* We use curl_open() with undefined URL so far */ + result = Curl_open(&data); + if(result) { + DEBUGF(fprintf(stderr, "Error: Curl_open failed\n")); + return NULL; + } + + return data; +} + +#ifdef CURLDEBUG + +struct socketmonitor { + struct socketmonitor *next; /* the next node in the list or NULL */ + struct pollfd socket; /* socket info of what to monitor */ +}; + +struct events { + long ms; /* timeout, run the timeout function when reached */ + bool msbump; /* set TRUE when timeout is set by callback */ + int num_sockets; /* number of nodes in the monitor list */ + struct socketmonitor *list; /* list of sockets to monitor */ + int running_handles; /* store the returned number */ +}; + +/* events_timer + * + * Callback that gets called with a new value when the timeout should be + * updated. + */ + +static int events_timer(struct Curl_multi *multi, /* multi handle */ + long timeout_ms, /* see above */ + void *userp) /* private callback pointer */ +{ + struct events *ev = userp; + (void)multi; + if(timeout_ms == -1) + /* timeout removed */ + timeout_ms = 0; + else if(timeout_ms == 0) + /* timeout is already reached! */ + timeout_ms = 1; /* trigger asap */ + + ev->ms = timeout_ms; + ev->msbump = TRUE; + return 0; +} + + +/* poll2cselect + * + * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones + */ +static int poll2cselect(int pollmask) +{ + int omask = 0; + if(pollmask & POLLIN) + omask |= CURL_CSELECT_IN; + if(pollmask & POLLOUT) + omask |= CURL_CSELECT_OUT; + if(pollmask & POLLERR) + omask |= CURL_CSELECT_ERR; + return omask; +} + + +/* socketcb2poll + * + * convert from libcurl' CURL_POLL_* bit definitions to poll()'s + */ +static short socketcb2poll(int pollmask) +{ + short omask = 0; + if(pollmask & CURL_POLL_IN) + omask |= POLLIN; + if(pollmask & CURL_POLL_OUT) + omask |= POLLOUT; + return omask; +} + +/* events_socket + * + * Callback that gets called with information about socket activity to + * monitor. + */ +static int events_socket(struct Curl_easy *easy, /* easy handle */ + curl_socket_t s, /* socket */ + int what, /* see above */ + void *userp, /* private callback + pointer */ + void *socketp) /* private socket + pointer */ +{ + struct events *ev = userp; + struct socketmonitor *m; + struct socketmonitor *prev = NULL; + +#if defined(CURL_DISABLE_VERBOSE_STRINGS) + (void) easy; +#endif + (void)socketp; + + m = ev->list; + while(m) { + if(m->socket.fd == s) { + + if(what == CURL_POLL_REMOVE) { + struct socketmonitor *nxt = m->next; + /* remove this node from the list of monitored sockets */ + if(prev) + prev->next = nxt; + else + ev->list = nxt; + free(m); + m = nxt; + infof(easy, "socket cb: socket %d REMOVED\n", s); + } + else { + /* The socket 's' is already being monitored, update the activity + mask. Convert from libcurl bitmask to the poll one. */ + m->socket.events = socketcb2poll(what); + infof(easy, "socket cb: socket %d UPDATED as %s%s\n", s, + what&CURL_POLL_IN?"IN":"", + what&CURL_POLL_OUT?"OUT":""); + } + break; + } + prev = m; + m = m->next; /* move to next node */ + } + if(!m) { + if(what == CURL_POLL_REMOVE) { + /* this happens a bit too often, libcurl fix perhaps? */ + /* fprintf(stderr, + "%s: socket %d asked to be REMOVED but not present!\n", + __func__, s); */ + } + else { + m = malloc(sizeof(struct socketmonitor)); + if(m) { + m->next = ev->list; + m->socket.fd = s; + m->socket.events = socketcb2poll(what); + m->socket.revents = 0; + ev->list = m; + infof(easy, "socket cb: socket %d ADDED as %s%s\n", s, + what&CURL_POLL_IN?"IN":"", + what&CURL_POLL_OUT?"OUT":""); + } + else + return CURLE_OUT_OF_MEMORY; + } + } + + return 0; +} + + +/* + * events_setup() + * + * Do the multi handle setups that only event-based transfers need. + */ +static void events_setup(struct Curl_multi *multi, struct events *ev) +{ + /* timer callback */ + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, events_timer); + curl_multi_setopt(multi, CURLMOPT_TIMERDATA, ev); + + /* socket callback */ + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, events_socket); + curl_multi_setopt(multi, CURLMOPT_SOCKETDATA, ev); +} + + +/* wait_or_timeout() + * + * waits for activity on any of the given sockets, or the timeout to trigger. + */ + +static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done) { + CURLMsg *msg; + struct socketmonitor *m; + struct pollfd *f; + struct pollfd fds[4]; + int numfds = 0; + int pollrc; + int i; + struct curltime before; + struct curltime after; + + /* populate the fds[] array */ + for(m = ev->list, f = &fds[0]; m; m = m->next) { + f->fd = m->socket.fd; + f->events = m->socket.events; + f->revents = 0; + /* fprintf(stderr, "poll() %d check socket %d\n", numfds, f->fd); */ + f++; + numfds++; + } + + /* get the time stamp to use to figure out how long poll takes */ + before = Curl_now(); + + /* wait for activity or timeout */ + pollrc = Curl_poll(fds, numfds, (int)ev->ms); + + after = Curl_now(); + + ev->msbump = FALSE; /* reset here */ + + if(0 == pollrc) { + /* timeout! */ + ev->ms = 0; + /* fprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ + mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); + } + else if(pollrc > 0) { + /* loop over the monitored sockets to see which ones had activity */ + for(i = 0; i< numfds; i++) { + if(fds[i].revents) { + /* socket activity, tell libcurl */ + int act = poll2cselect(fds[i].revents); /* convert */ + infof(multi->easyp, "call curl_multi_socket_action(socket %d)\n", + fds[i].fd); + mcode = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); + } + } + + if(!ev->msbump) { + /* If nothing updated the timeout, we decrease it by the spent time. + * If it was updated, it has the new timeout time stored already. + */ + timediff_t timediff = Curl_timediff(after, before); + if(timediff > 0) { + if(timediff > ev->ms) + ev->ms = 0; + else + ev->ms -= (long)timediff; + } + } + } + else + return CURLE_RECV_ERROR; + + if(mcode) + return CURLE_URL_MALFORMAT; /* TODO: return a proper error! */ + + /* we don't really care about the "msgs_in_queue" value returned in the + second argument */ + msg = curl_multi_info_read(multi, &pollrc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + + return result; +} + + +/* easy_events() + * + * Runs a transfer in a blocking manner using the events-based API + */ +static CURLcode easy_events(struct Curl_multi *multi) +{ + /* this struct is made static to allow it to be used after this function + returns and curl_multi_remove_handle() is called */ + static struct events evs = {2, FALSE, 0, NULL, 0}; + + /* if running event-based, do some further multi inits */ + events_setup(multi, &evs); + + return wait_or_timeout(multi, &evs); +} +#else /* CURLDEBUG */ +/* when not built with debug, this function doesn't exist */ +#define easy_events(x) CURLE_NOT_BUILT_IN +#endif + +static CURLcode easy_transfer(struct Curl_multi *multi) +{ + bool done = FALSE; + CURLMcode mcode = CURLM_OK; + CURLcode result = CURLE_OK; + + while(!done && !mcode) { + int still_running = 0; + bool gotsocket = FALSE; + + mcode = Curl_multi_wait(multi, NULL, 0, 1000, NULL, &gotsocket); + + if(!mcode) { + if(!gotsocket) { + long sleep_ms; + + /* If it returns without any filedescriptor instantly, we need to + avoid busy-looping during periods where it has nothing particular + to wait for */ + curl_multi_timeout(multi, &sleep_ms); + if(sleep_ms) { + if(sleep_ms > 1000) + sleep_ms = 1000; + Curl_wait_ms((int)sleep_ms); + } + } + + mcode = curl_multi_perform(multi, &still_running); + } + + /* only read 'still_running' if curl_multi_perform() return OK */ + if(!mcode && !still_running) { + int rc; + CURLMsg *msg = curl_multi_info_read(multi, &rc); + if(msg) { + result = msg->data.result; + done = TRUE; + } + } + } + + /* Make sure to return some kind of error if there was a multi problem */ + if(mcode) { + result = (mcode == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : + /* The other multi errors should never happen, so return + something suitably generic */ + CURLE_BAD_FUNCTION_ARGUMENT; + } + + return result; +} + + +/* + * easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + * + * CONCEPT: This function creates a multi handle, adds the easy handle to it, + * runs curl_multi_perform() until the transfer is done, then detaches the + * easy handle, destroys the multi handle and returns the easy handle's return + * code. + * + * REALITY: it can't just create and destroy the multi handle that easily. It + * needs to keep it around since if this easy handle is used again by this + * function, the same multi handle must be re-used so that the same pools and + * caches can be used. + * + * DEBUG: if 'events' is set TRUE, this function will use a replacement engine + * instead of curl_multi_perform() and use curl_multi_socket_action(). + */ +static CURLcode easy_perform(struct Curl_easy *data, bool events) +{ + struct Curl_multi *multi; + CURLMcode mcode; + CURLcode result = CURLE_OK; + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.errorbuffer) + /* clear this as early as possible */ + data->set.errorbuffer[0] = 0; + + if(data->multi) { + printf("easy handle already used in multi handle\n"); + return CURLE_FAILED_INIT; + } + + if(data->multi_easy) + multi = data->multi_easy; + else { + /* this multi handle will only ever have a single easy handled attached + to it, so make it use minimal hashes */ + multi = Curl_multi_handle(1, 3); + if(!multi) + return CURLE_OUT_OF_MEMORY; + data->multi_easy = multi; + } + + if(multi->in_callback) + return CURLE_RECURSIVE_API_CALL; + + /* Copy the MAXCONNECTS option to the multi handle */ + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects); + mcode = curl_multi_add_handle(multi, data); + if(mcode) { + curl_multi_cleanup(multi); + if(mcode == CURLM_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; + return CURLE_FAILED_INIT; + } + + sigpipe_ignore(data, &pipe_st); + + /* assign this after curl_multi_add_handle() since that function checks for + it and rejects this handle otherwise */ + data->multi = multi; + + /* run the transfer */ + result = events ? easy_events(multi) : easy_transfer(multi); + + /* ignoring the return code isn't nice, but atm we can't really handle + a failure here, room for future improvement! */ + (void)curl_multi_remove_handle(multi, data); + sigpipe_restore(&pipe_st); + /* The multi handle is kept alive, owned by the easy handle */ + return result; +} + + +/* + * curl_easy_perform() is the external interface that performs a blocking + * transfer as previously setup. + */ +CURLcode curl_easy_perform(struct Curl_easy *data) +{ + return easy_perform(data, FALSE); +} + +#ifdef CURLDEBUG +/* + * curl_easy_perform_ev() is the external interface that performs a blocking + * transfer using the event-based API internally. + */ +CURLcode curl_easy_perform_ev(struct Curl_easy *data) +{ + return easy_perform(data, TRUE); +} + +#endif + +/* + * curl_easy_cleanup() is the external interface to cleaning/freeing the given + * easy handle. + */ +void curl_easy_cleanup(struct Curl_easy *data) +{ + SIGPIPE_VARIABLE(pipe_st); + + if(!data) + return; + + sigpipe_ignore(data, &pipe_st); + Curl_close(data); + sigpipe_restore(&pipe_st); +} + +/* + * curl_easy_getinfo() is an external interface that allows an app to retrieve + * information from a performed transfer and similar. + */ +#undef curl_easy_getinfo +CURLcode curl_easy_getinfo(struct Curl_easy *data, CURLINFO info, ...) +{ + va_list arg; + void *paramp; + CURLcode result; + + va_start(arg, info); + paramp = va_arg(arg, void *); + + result = Curl_getinfo(data, info, paramp); + + va_end(arg); + return result; +} + +static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) +{ + CURLcode result = CURLE_OK; + enum dupstring i; + + /* Copy src->set into dst->set first, then deal with the strings + afterwards */ + dst->set = src->set; + Curl_mime_initpart(&dst->set.mimepost, dst); + + /* clear all string pointers first */ + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ + for(i = (enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + result = Curl_setstropt(&dst->set.str[i], src->set.str[i]); + if(result) + return result; + } + + /* duplicate memory areas pointed to */ + i = STRING_COPYPOSTFIELDS; + if(src->set.postfieldsize && src->set.str[i]) { + /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ + dst->set.str[i] = Curl_memdup(src->set.str[i], + curlx_sotouz(src->set.postfieldsize)); + if(!dst->set.str[i]) + return CURLE_OUT_OF_MEMORY; + /* point to the new copy */ + dst->set.postfields = dst->set.str[i]; + } + + /* Duplicate mime data. */ + result = Curl_mime_duppart(&dst->set.mimepost, &src->set.mimepost); + + if(src->set.resolve) + dst->change.resolve = dst->set.resolve; + + return result; +} + +/* + * curl_easy_duphandle() is an external interface to allow duplication of a + * given input easy handle. The returned handle will be a new working handle + * with all options set exactly as the input source handle. + */ +struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) +{ + struct Curl_easy *outcurl = calloc(1, sizeof(struct Curl_easy)); + if(NULL == outcurl) + goto fail; + + /* + * We setup a few buffers we need. We should probably make them + * get setup on-demand in the code, as that would probably decrease + * the likeliness of us forgetting to init a buffer here in the future. + */ + outcurl->set.buffer_size = data->set.buffer_size; + outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1); + if(!outcurl->state.buffer) + goto fail; + + outcurl->state.headerbuff = malloc(HEADERSIZE); + if(!outcurl->state.headerbuff) + goto fail; + outcurl->state.headersize = HEADERSIZE; + + /* copy all userdefined values */ + if(dupset(outcurl, data)) + goto fail; + + /* the connection cache is setup on demand */ + outcurl->state.conn_cache = NULL; + + outcurl->state.lastconnect = NULL; + + outcurl->progress.flags = data->progress.flags; + outcurl->progress.callback = data->progress.callback; + + if(data->cookies) { + /* If cookies are enabled in the parent handle, we enable them + in the clone as well! */ + outcurl->cookies = Curl_cookie_init(data, + data->cookies->filename, + outcurl->cookies, + data->set.cookiesession); + if(!outcurl->cookies) + goto fail; + } + + /* duplicate all values in 'change' */ + if(data->change.cookielist) { + outcurl->change.cookielist = + Curl_slist_duplicate(data->change.cookielist); + if(!outcurl->change.cookielist) + goto fail; + } + + if(data->change.url) { + outcurl->change.url = strdup(data->change.url); + if(!outcurl->change.url) + goto fail; + outcurl->change.url_alloc = TRUE; + } + + if(data->change.referer) { + outcurl->change.referer = strdup(data->change.referer); + if(!outcurl->change.referer) + goto fail; + outcurl->change.referer_alloc = TRUE; + } + + /* Reinitialize an SSL engine for the new handle + * note: the engine name has already been copied by dupset */ + if(outcurl->set.str[STRING_SSL_ENGINE]) { + if(Curl_ssl_set_engine(outcurl, outcurl->set.str[STRING_SSL_ENGINE])) + goto fail; + } + + /* Clone the resolver handle, if present, for the new handle */ + if(Curl_resolver_duphandle(outcurl, + &outcurl->state.resolver, + data->state.resolver)) + goto fail; + + Curl_convert_setup(outcurl); + + Curl_initinfo(outcurl); + + outcurl->magic = CURLEASY_MAGIC_NUMBER; + + /* we reach this point and thus we are OK */ + + return outcurl; + + fail: + + if(outcurl) { + curl_slist_free_all(outcurl->change.cookielist); + outcurl->change.cookielist = NULL; + Curl_safefree(outcurl->state.buffer); + Curl_safefree(outcurl->state.headerbuff); + Curl_safefree(outcurl->change.url); + Curl_safefree(outcurl->change.referer); + Curl_freeset(outcurl); + free(outcurl); + } + + return NULL; +} + +/* + * curl_easy_reset() is an external interface that allows an app to re- + * initialize a session handle to the default values. + */ +void curl_easy_reset(struct Curl_easy *data) +{ + Curl_free_request_state(data); + + /* zero out UserDefined data: */ + Curl_freeset(data); + memset(&data->set, 0, sizeof(struct UserDefined)); + (void)Curl_init_userdefined(data); + + /* zero out Progress data: */ + memset(&data->progress, 0, sizeof(struct Progress)); + + /* zero out PureInfo data: */ + Curl_initinfo(data); + + data->progress.flags |= PGRS_HIDE; + data->state.current_speed = -1; /* init to negative == impossible */ + + /* zero out authentication data: */ + memset(&data->state.authhost, 0, sizeof(struct auth)); + memset(&data->state.authproxy, 0, sizeof(struct auth)); + Curl_digest_cleanup(data); +} + +/* + * curl_easy_pause() allows an application to pause or unpause a specific + * transfer and direction. This function sets the full new state for the + * current connection this easy handle operates on. + * + * NOTE: if you have the receiving paused and you call this function to remove + * the pausing, you may get your write callback called at this point. + * + * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ +CURLcode curl_easy_pause(struct Curl_easy *data, int action) +{ + struct SingleRequest *k = &data->req; + CURLcode result = CURLE_OK; + + /* first switch off both pause bits */ + int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE); + + /* set the new desired pause bits */ + newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) | + ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0); + + /* put it back in the keepon */ + k->keepon = newstate; + + if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempcount) { + /* there are buffers for sending that can be delivered as the receive + pausing is lifted! */ + unsigned int i; + unsigned int count = data->state.tempcount; + struct tempbuf writebuf[3]; /* there can only be three */ + struct connectdata *conn = data->conn; + struct Curl_easy *saved_data = NULL; + + /* copy the structs to allow for immediate re-pausing */ + for(i = 0; i < data->state.tempcount; i++) { + writebuf[i] = data->state.tempwrite[i]; + data->state.tempwrite[i].buf = NULL; + } + data->state.tempcount = 0; + + /* set the connection's current owner */ + if(conn->data != data) { + saved_data = conn->data; + conn->data = data; + } + + for(i = 0; i < count; i++) { + /* even if one function returns error, this loops through and frees all + buffers */ + if(!result) + result = Curl_client_write(conn, writebuf[i].type, writebuf[i].buf, + writebuf[i].len); + free(writebuf[i].buf); + } + + /* recover previous owner of the connection */ + if(saved_data) + conn->data = saved_data; + + if(result) + return result; + } + + /* if there's no error and we're not pausing both directions, we want + to have this handle checked soon */ + if(!result && + ((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) != + (KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) ) + Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */ + + /* This transfer may have been moved in or out of the bundle, update + the corresponding socket callback, if used */ + Curl_updatesocket(data); + + return result; +} + + +static CURLcode easy_connection(struct Curl_easy *data, + curl_socket_t *sfd, + struct connectdata **connp) +{ + if(data == NULL) + return CURLE_BAD_FUNCTION_ARGUMENT; + + /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */ + if(!data->set.connect_only) { + failf(data, "CONNECT_ONLY is required!"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + *sfd = Curl_getconnectinfo(data, connp); + + if(*sfd == CURL_SOCKET_BAD) { + failf(data, "Failed to get recent socket"); + return CURLE_UNSUPPORTED_PROTOCOL; + } + + return CURLE_OK; +} + +/* + * Receives data from the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + * Returns CURLE_OK on success, error code on error. + */ +CURLcode curl_easy_recv(struct Curl_easy *data, void *buffer, size_t buflen, + size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_read(c, sfd, buffer, buflen, &n1); + + if(result) + return result; + + *n = (size_t)n1; + + return CURLE_OK; +} + +/* + * Sends data over the connected socket. Use after successful + * curl_easy_perform() with CURLOPT_CONNECT_ONLY option. + */ +CURLcode curl_easy_send(struct Curl_easy *data, const void *buffer, + size_t buflen, size_t *n) +{ + curl_socket_t sfd; + CURLcode result; + ssize_t n1; + struct connectdata *c = NULL; + + if(Curl_is_in_callback(data)) + return CURLE_RECURSIVE_API_CALL; + + result = easy_connection(data, &sfd, &c); + if(result) + return result; + + *n = 0; + result = Curl_write(c, sfd, buffer, buflen, &n1); + + if(n1 == -1) + return CURLE_SEND_ERROR; + + /* detect EAGAIN */ + if(!result && !n1) + return CURLE_AGAIN; + + *n = (size_t)n1; + + return result; +} + +/* + * Performs connection upkeep for the given session handle. + */ +CURLcode curl_easy_upkeep(struct Curl_easy *data) +{ + /* Verify that we got an easy handle we can work with. */ + if(!GOOD_EASY_HANDLE(data)) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->multi_easy) { + /* Use the common function to keep connections alive. */ + return Curl_upkeep(&data->multi_easy->conn_cache, data); + } + else { + /* No connections, so just return success */ + return CURLE_OK; + } +} diff --git a/external/curl prx/src/escape.c b/external/curl prx/src/escape.c new file mode 100644 index 0000000..7121db3 --- /dev/null +++ b/external/curl prx/src/escape.c @@ -0,0 +1,244 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/* Escape and unescape URL encoding in strings. The functions return a new + * allocated string or NULL if an error occurred. */ + +#include "curl_setup.h" + +#include + +#include "urldata.h" +#include "warnless.h" +#include "non-ascii.h" +#include "escape.h" +#include "strdup.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +/* Portable character check (remember EBCDIC). Do not use isalnum() because + its behavior is altered by the current locale. + See https://tools.ietf.org/html/rfc3986#section-2.3 +*/ +bool Curl_isunreserved(unsigned char in) +{ + switch(in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': case '~': + return TRUE; + default: + break; + } + return FALSE; +} + +/* for ABI-compatibility with previous versions */ +char *curl_escape(const char *string, int inlength) +{ + return curl_easy_escape(NULL, string, inlength); +} + +/* for ABI-compatibility with previous versions */ +char *curl_unescape(const char *string, int length) +{ + return curl_easy_unescape(NULL, string, length, NULL); +} + +char *curl_easy_escape(struct Curl_easy *data, const char *string, + int inlength) +{ + size_t alloc; + char *ns; + char *testing_ptr = NULL; + size_t newlen; + size_t strindex = 0; + size_t length; + CURLcode result; + + if(inlength < 0) + return NULL; + + alloc = (inlength?(size_t)inlength:strlen(string)) + 1; + newlen = alloc; + + ns = malloc(alloc); + if(!ns) + return NULL; + + length = alloc-1; + while(length--) { + unsigned char in = *string; /* we need to treat the characters unsigned */ + + if(Curl_isunreserved(in)) + /* just copy this */ + ns[strindex++] = in; + else { + /* encode it */ + newlen += 2; /* the size grows with two, since this'll become a %XX */ + if(newlen > alloc) { + alloc *= 2; + testing_ptr = Curl_saferealloc(ns, alloc); + if(!testing_ptr) + return NULL; + ns = testing_ptr; + } + + result = Curl_convert_to_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_to_network calls failf if unsuccessful */ + free(ns); + return NULL; + } + + msnprintf(&ns[strindex], 4, "%%%02X", in); + + strindex += 3; + } + string++; + } + ns[strindex] = 0; /* terminate it */ + return ns; +} + +/* + * Curl_urldecode() URL decodes the given string. + * + * Optionally detects control characters (byte codes lower than 32) in the + * data and rejects such data. + * + * Returns a pointer to a malloced string in *ostring with length given in + * *olen. If length == 0, the length is assumed to be strlen(string). + * + * 'data' can be set to NULL but then this function can't convert network + * data to host for non-ascii. + */ +CURLcode Curl_urldecode(struct Curl_easy *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_ctrl) +{ + size_t alloc = (length?length:strlen(string)) + 1; + char *ns = malloc(alloc); + size_t strindex = 0; + unsigned long hex; + CURLcode result = CURLE_OK; + + if(!ns) + return CURLE_OUT_OF_MEMORY; + + while(--alloc > 0) { + unsigned char in = *string; + if(('%' == in) && (alloc > 2) && + ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; + hexstr[0] = string[1]; + hexstr[1] = string[2]; + hexstr[2] = 0; + + hex = strtoul(hexstr, &ptr, 16); + + in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ + + if(data) { + result = Curl_convert_from_network(data, (char *)&in, 1); + if(result) { + /* Curl_convert_from_network calls failf if unsuccessful */ + free(ns); + return result; + } + } + + string += 2; + alloc -= 2; + } + + if(reject_ctrl && (in < 0x20)) { + free(ns); + return CURLE_URL_MALFORMAT; + } + + ns[strindex++] = in; + string++; + } + ns[strindex] = 0; /* terminate it */ + + if(olen) + /* store output size */ + *olen = strindex; + + /* store output string */ + *ostring = ns; + + return CURLE_OK; +} + +/* + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +char *curl_easy_unescape(struct Curl_easy *data, const char *string, + int length, int *olen) +{ + char *str = NULL; + if(length >= 0) { + size_t inputlen = length; + size_t outputlen; + CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen, + FALSE); + if(res) + return NULL; + + if(olen) { + if(outputlen <= (size_t) INT_MAX) + *olen = curlx_uztosi(outputlen); + else + /* too large to return in an int, fail! */ + Curl_safefree(str); + } + } + return str; +} + +/* For operating systems/environments that use different malloc/free + systems for the app and for this library, we provide a free that uses + the library's memory system */ +void curl_free(void *p) +{ + free(p); +} diff --git a/external/curl prx/src/setopt.c b/external/curl prx/src/setopt.c new file mode 100644 index 0000000..b5f74a9 --- /dev/null +++ b/external/curl prx/src/setopt.c @@ -0,0 +1,2716 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#ifdef HAVE_LINUX_TCP_H +#include +#endif + +#include "urldata.h" +#include "url.h" +#include "progress.h" +#include "content_encoding.h" +#include "strcase.h" +#include "share.h" +#include "vtls/vtls.h" +#include "warnless.h" +#include "sendf.h" +#include "http2.h" +#include "setopt.h" +#include "multiif.h" +#include "altsvc.h" + +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +CURLcode Curl_setstropt(char **charp, const char *s) +{ + /* Release the previous storage at `charp' and replace by a dynamic storage + copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ + + Curl_safefree(*charp); + + if(s) { + char *str = strdup(s); + + if(!str) + return CURLE_OUT_OF_MEMORY; + + *charp = str; + } + + return CURLE_OK; +} + +static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) +{ + CURLcode result = CURLE_OK; + char *user = NULL; + char *passwd = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ + if(option) { + result = Curl_parse_login_details(option, strlen(option), + (userp ? &user : NULL), + (passwdp ? &passwd : NULL), + NULL); + } + + if(!result) { + /* Store the username part of option if required */ + if(userp) { + if(!user && option && option[0] == ':') { + /* Allocate an empty string instead of returning NULL as user name */ + user = strdup(""); + if(!user) + result = CURLE_OUT_OF_MEMORY; + } + + Curl_safefree(*userp); + *userp = user; + } + + /* Store the password part of option if required */ + if(passwdp) { + Curl_safefree(*passwdp); + *passwdp = passwd; + } + } + + return result; +} + +#define C_SSLVERSION_VALUE(x) (x & 0xffff) +#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) + +static CURLcode vsetopt(struct Curl_easy *data, CURLoption option, + va_list param) +{ + char *argptr; + CURLcode result = CURLE_OK; + long arg; + curl_off_t bigsize; + + switch(option) { + case CURLOPT_DNS_CACHE_TIMEOUT: + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.dns_cache_timeout = arg; + break; + case CURLOPT_DNS_USE_GLOBAL_CACHE: +#if 0 /* deprecated */ + /* remember we want this enabled */ + arg = va_arg(param, long); + data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE; +#endif + break; + case CURLOPT_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSL_CIPHER_LIST: + /* set a list of cipher we want to use in the SSL connection for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_ORIG], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PROXY_TLS13_CIPHERS: + if(Curl_ssl_tls13_ciphersuites()) { + /* set preferred list of TLS 1.3 cipher suites for proxy */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY], + va_arg(param, char *)); + } + else + return CURLE_NOT_BUILT_IN; + break; + + case CURLOPT_RANDOM_FILE: + /* + * This is the path name to a file that contains random data to seed + * the random SSL stuff with. The file is only used for reading. + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_RANDOM_FILE], + va_arg(param, char *)); + break; + case CURLOPT_EGDSOCKET: + /* + * The Entropy Gathering Daemon socket pathname + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_EGDSOCKET], + va_arg(param, char *)); + break; + case CURLOPT_MAXCONNECTS: + /* + * Set the absolute number of maximum simultaneous alive connection that + * libcurl is allowed to have. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxconnects = arg; + break; + case CURLOPT_FORBID_REUSE: + /* + * When this transfer is done, it must not be left to be reused by a + * subsequent transfer but shall be closed immediately. + */ + data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FRESH_CONNECT: + /* + * This transfer shall not use a previously cached connection but + * should be made with a fresh new connect! + */ + data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_VERBOSE: + /* + * Verbose means infof() calls that give a lot of information about + * the connection and transfer procedures as well as internal choices. + */ + data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_HEADER: + /* + * Set to include the header in the general data output stream. + */ + data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_NOPROGRESS: + /* + * Shut off the internal supported progress meter + */ + data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.hide_progress) + data->progress.flags |= PGRS_HIDE; + else + data->progress.flags &= ~PGRS_HIDE; + break; + case CURLOPT_NOBODY: + /* + * Do not include the body part in the output data stream. + */ + data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FAILONERROR: + /* + * Don't output the >=400 error code HTML-page, but instead only + * return error. + */ + data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_KEEP_SENDING_ON_ERROR: + data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + case CURLOPT_UPLOAD: + case CURLOPT_PUT: + /* + * We want to sent data to the remote host. If this is HTTP, that equals + * using the PUT request. + */ + data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE; + if(data->set.upload) { + /* If this is HTTP, PUT is what's needed to "upload" */ + data->set.httpreq = HTTPREQ_PUT; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + /* In HTTP, the opposite of upload is GET (unless NOBODY is true as + then this can be changed to HEAD later on) */ + data->set.httpreq = HTTPREQ_GET; + break; + case CURLOPT_REQUEST_TARGET: + result = Curl_setstropt(&data->set.str[STRING_TARGET], + va_arg(param, char *)); + break; + case CURLOPT_FILETIME: + /* + * Try to get the file time of the remote document. The time will + * later (possibly) become available using curl_easy_getinfo(). + */ + data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FTP_CREATE_MISSING_DIRS: + /* + * An FTP option that modifies an upload to create missing directories on + * the server. + */ + switch(va_arg(param, long)) { + case 0: + data->set.ftp_create_missing_dirs = 0; + break; + case 1: + data->set.ftp_create_missing_dirs = 1; + break; + case 2: + data->set.ftp_create_missing_dirs = 2; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; + case CURLOPT_SERVER_RESPONSE_TIMEOUT: + /* + * Option that specifies how quickly an server response must be obtained + * before it is considered failure. For pingpong protocols. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.server_response_timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + case CURLOPT_TFTP_NO_OPTIONS: + /* + * Option that prevents libcurl from sending TFTP option requests to the + * server. + */ + data->set.tftp_no_options = va_arg(param, long) != 0; + break; + case CURLOPT_TFTP_BLKSIZE: + /* + * TFTP option that specifies the block size to use for data transmission. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tftp_blksize = arg; + break; + case CURLOPT_DIRLISTONLY: + /* + * An option that changes the command to one that asks for a list + * only, no file info details. + */ + data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_APPEND: + /* + * We want to upload and append to an existing file. + */ + data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_FTP_FILEMETHOD: + /* + * How do access files over FTP. + */ + arg = va_arg(param, long); + if((arg < CURLFTPMETHOD_DEFAULT) || (arg > CURLFTPMETHOD_SINGLECWD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_filemethod = (curl_ftpfile)arg; + break; + case CURLOPT_NETRC: + /* + * Parse the $HOME/.netrc file + */ + arg = va_arg(param, long); + if((arg < CURL_NETRC_IGNORED) || (arg > CURL_NETRC_REQUIRED)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_netrc = (enum CURL_NETRC_OPTION)arg; + break; + case CURLOPT_NETRC_FILE: + /* + * Use this file instead of the $HOME/.netrc file + */ + result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE], + va_arg(param, char *)); + break; + case CURLOPT_TRANSFERTEXT: + /* + * This option was previously named 'FTPASCII'. Renamed to work with + * more protocols than merely FTP. + * + * Transfer using ASCII (instead of BINARY). + */ + data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TIMECONDITION: + /* + * Set HTTP time condition. This must be one of the defines in the + * curl/curl.h header file. + */ + arg = va_arg(param, long); + if((arg < CURL_TIMECOND_NONE) || (arg > CURL_TIMECOND_LASTMOD)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timecondition = (curl_TimeCond)arg; + break; + case CURLOPT_TIMEVALUE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, long); + break; + + case CURLOPT_TIMEVALUE_LARGE: + /* + * This is the value to compare with the remote document with the + * method set with CURLOPT_TIMECONDITION + */ + data->set.timevalue = (time_t)va_arg(param, curl_off_t); + break; + + case CURLOPT_SSLVERSION: + case CURLOPT_PROXY_SSLVERSION: + /* + * Set explicit SSL version to try to connect with, as some SSL + * implementations are lame. + */ +#ifdef USE_SSL + { + long version, version_max; + struct ssl_primary_config *primary = (option == CURLOPT_SSLVERSION ? + &data->set.ssl.primary : + &data->set.proxy_ssl.primary); + + arg = va_arg(param, long); + + version = C_SSLVERSION_VALUE(arg); + version_max = C_SSLVERSION_MAX_VALUE(arg); + + if(version < CURL_SSLVERSION_DEFAULT || + version >= CURL_SSLVERSION_LAST || + version_max < CURL_SSLVERSION_MAX_NONE || + version_max >= CURL_SSLVERSION_MAX_LAST) + return CURLE_BAD_FUNCTION_ARGUMENT; + + primary->version = version; + primary->version_max = version_max; + } +#else + result = CURLE_UNKNOWN_OPTION; +#endif + break; + +#ifndef CURL_DISABLE_HTTP + case CURLOPT_AUTOREFERER: + /* + * Switch on automatic referer that gets set if curl follows locations. + */ + data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_ACCEPT_ENCODING: + /* + * String to use at the value of Accept-Encoding header. + * + * If the encoding is set to "" we use an Accept-Encoding header that + * encompasses all the encodings we support. + * If the encoding is set to NULL we don't send an Accept-Encoding header + * and ignore an received Content-Encoding header. + * + */ + argptr = va_arg(param, char *); + if(argptr && !*argptr) { + argptr = Curl_all_content_encodings(); + if(!argptr) + result = CURLE_OUT_OF_MEMORY; + else { + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + free(argptr); + } + } + else + result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); + break; + + case CURLOPT_TRANSFER_ENCODING: + data->set.http_transfer_encoding = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_FOLLOWLOCATION: + /* + * Follow Location: header hints on a HTTP-server. + */ + data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_UNRESTRICTED_AUTH: + /* + * Send authentication (user+password) when following locations, even when + * hostname changed. + */ + data->set.allow_auth_to_other_hosts = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_MAXREDIRS: + /* + * The maximum amount of hops you allow curl to follow Location: + * headers. This should mostly be used to detect never-ending loops. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.maxredirs = arg; + break; + + case CURLOPT_POSTREDIR: + /* + * Set the behaviour of POST when redirecting + * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 + * CURL_REDIR_POST_301 - POST is kept as POST after 301 + * CURL_REDIR_POST_302 - POST is kept as POST after 302 + * CURL_REDIR_POST_303 - POST is kept as POST after 303 + * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 + * other - POST is kept as POST after 301 and 302 + */ + arg = va_arg(param, long); + if(arg < CURL_REDIR_GET_ALL) + /* no return error on too high numbers since the bitmask could be + extended in a future */ + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.keep_post = arg & CURL_REDIR_POST_ALL; + break; + + case CURLOPT_POST: + /* Does this option serve a purpose anymore? Yes it does, when + CURLOPT_POSTFIELDS isn't used and the POST data is read off the + callback! */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_POST; + data->set.opt_no_body = FALSE; /* this is implied */ + } + else + data->set.httpreq = HTTPREQ_GET; + break; + + case CURLOPT_COPYPOSTFIELDS: + /* + * A string with POST data. Makes curl HTTP POST. Even if it is NULL. + * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to + * CURLOPT_COPYPOSTFIELDS and not altered later. + */ + argptr = va_arg(param, char *); + + if(!argptr || data->set.postfieldsize == -1) + result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); + else { + /* + * Check that requested length does not overflow the size_t type. + */ + + if((data->set.postfieldsize < 0) || + ((sizeof(curl_off_t) != sizeof(size_t)) && + (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) + result = CURLE_OUT_OF_MEMORY; + else { + char *p; + + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + + /* Allocate even when size == 0. This satisfies the need of possible + later address compare to detect the COPYPOSTFIELDS mode, and + to mark that postfields is used rather than read function or + form data. + */ + p = malloc((size_t)(data->set.postfieldsize? + data->set.postfieldsize:1)); + + if(!p) + result = CURLE_OUT_OF_MEMORY; + else { + if(data->set.postfieldsize) + memcpy(p, argptr, (size_t)data->set.postfieldsize); + + data->set.str[STRING_COPYPOSTFIELDS] = p; + } + } + } + + data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDS: + /* + * Like above, but use static data instead of copying it. + */ + data->set.postfields = va_arg(param, void *); + /* Release old copied data. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.httpreq = HTTPREQ_POST; + break; + + case CURLOPT_POSTFIELDSIZE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, long); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_POSTFIELDSIZE_LARGE: + /* + * The size of the POSTFIELD data to prevent libcurl to do strlen() to + * figure it out. Enables binary posts. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + + if(data->set.postfieldsize < bigsize && + data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { + /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ + (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); + data->set.postfields = NULL; + } + + data->set.postfieldsize = bigsize; + break; + + case CURLOPT_HTTPPOST: + /* + * Set to make us do HTTP POST + */ + data->set.httppost = va_arg(param, struct curl_httppost *); + data->set.httpreq = HTTPREQ_POST_FORM; + data->set.opt_no_body = FALSE; /* this is implied */ + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_MIMEPOST: + /* + * Set to make us do MIME/form POST + */ + result = Curl_mime_set_subparts(&data->set.mimepost, + va_arg(param, curl_mime *), FALSE); + if(!result) { + data->set.httpreq = HTTPREQ_POST_MIME; + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_REFERER: + /* + * String to set in the HTTP Referer: field. + */ + if(data->change.referer_alloc) { + Curl_safefree(data->change.referer); + data->change.referer_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], + va_arg(param, char *)); + data->change.referer = data->set.str[STRING_SET_REFERER]; + break; + + case CURLOPT_USERAGENT: + /* + * String to use in the HTTP User-Agent field + */ + result = Curl_setstropt(&data->set.str[STRING_USERAGENT], + va_arg(param, char *)); + break; + + case CURLOPT_HTTPHEADER: + /* + * Set a list with HTTP headers to use (or replace internals with) + */ + data->set.headers = va_arg(param, struct curl_slist *); + break; + +#ifndef CURL_DISABLE_HTTP + case CURLOPT_PROXYHEADER: + /* + * Set a list with proxy headers to use (or replace internals with) + * + * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a + * long time we remain doing it this way until CURLOPT_PROXYHEADER is + * used. As soon as this option has been used, if set to anything but + * NULL, custom headers for proxies are only picked from this list. + * + * Set this option to NULL to restore the previous behavior. + */ + data->set.proxyheaders = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_HEADEROPT: + /* + * Set header option. + */ + arg = va_arg(param, long); + data->set.sep_headers = (bool)((arg & CURLHEADER_SEPARATE)? TRUE: FALSE); + break; + + case CURLOPT_HTTP200ALIASES: + /* + * Set a list of aliases for HTTP 200 in response header + */ + data->set.http200aliases = va_arg(param, struct curl_slist *); + break; + +#if !defined(CURL_DISABLE_COOKIES) + case CURLOPT_COOKIE: + /* + * Cookie string to send to the remote server in the request. + */ + result = Curl_setstropt(&data->set.str[STRING_COOKIE], + va_arg(param, char *)); + break; + + case CURLOPT_COOKIEFILE: + /* + * Set cookie file to read and parse. Can be used multiple times. + */ + argptr = (char *)va_arg(param, void *); + if(argptr) { + struct curl_slist *cl; + /* append the cookie file name to the list of file names, and deal with + them later */ + cl = curl_slist_append(data->change.cookielist, argptr); + if(!cl) { + curl_slist_free_all(data->change.cookielist); + data->change.cookielist = NULL; + return CURLE_OUT_OF_MEMORY; + } + data->change.cookielist = cl; /* store the list for later use */ + } + break; + + case CURLOPT_COOKIEJAR: + /* + * Set cookie file name to dump all cookies to when we're done. + */ + { + struct CookieInfo *newcookies; + result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], + va_arg(param, char *)); + + /* + * Activate the cookie parser. This may or may not already + * have been made. + */ + newcookies = Curl_cookie_init(data, NULL, data->cookies, + data->set.cookiesession); + if(!newcookies) + result = CURLE_OUT_OF_MEMORY; + data->cookies = newcookies; + } + break; + + case CURLOPT_COOKIESESSION: + /* + * Set this option to TRUE to start a new "cookie session". It will + * prevent the forthcoming read-cookies-from-file actions to accept + * cookies that are marked as being session cookies, as they belong to a + * previous session. + * + * In the original Netscape cookie spec, "session cookies" are cookies + * with no expire date set. RFC2109 describes the same action if no + * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds + * a 'Discard' action that can enforce the discard even for cookies that + * have a Max-Age. + * + * We run mostly with the original cookie spec, as hardly anyone implements + * anything else. + */ + data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_COOKIELIST: + argptr = va_arg(param, char *); + + if(argptr == NULL) + break; + + if(strcasecompare(argptr, "ALL")) { + /* clear all cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearall(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "SESS")) { + /* clear session cookies */ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + Curl_cookie_clearsess(data->cookies); + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + else if(strcasecompare(argptr, "FLUSH")) { + /* flush cookies to file, takes care of the locking */ + Curl_flush_cookies(data, 0); + } + else if(strcasecompare(argptr, "RELOAD")) { + /* reload cookies from file */ + Curl_cookie_loadfiles(data); + break; + } + else { + if(!data->cookies) + /* if cookie engine was not running, activate it */ + data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); + + argptr = strdup(argptr); + if(!argptr || !data->cookies) { + result = CURLE_OUT_OF_MEMORY; + free(argptr); + } + else { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + + if(checkprefix("Set-Cookie:", argptr)) + /* HTTP Header format line */ + Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL, + NULL, TRUE); + + else + /* Netscape format line */ + Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL, + NULL, TRUE); + + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + free(argptr); + } + } + + break; +#endif /* !CURL_DISABLE_COOKIES */ + + case CURLOPT_HTTPGET: + /* + * Set to force us do HTTP GET + */ + if(va_arg(param, long)) { + data->set.httpreq = HTTPREQ_GET; + data->set.upload = FALSE; /* switch off upload */ + data->set.opt_no_body = FALSE; /* this is implied */ + } + break; + + case CURLOPT_HTTP_VERSION: + /* + * This sets a requested HTTP version to be used. The value is one of + * the listed enums in curl/curl.h. + */ + arg = va_arg(param, long); + if(arg < CURL_HTTP_VERSION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; +#ifndef USE_NGHTTP2 + if(arg >= CURL_HTTP_VERSION_2) + return CURLE_UNSUPPORTED_PROTOCOL; +#else + if(arg > CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) + return CURLE_UNSUPPORTED_PROTOCOL; + if(arg == CURL_HTTP_VERSION_NONE) + arg = CURL_HTTP_VERSION_2TLS; +#endif + data->set.httpversion = arg; + break; + + case CURLOPT_EXPECT_100_TIMEOUT_MS: + /* + * Time to wait for a response to a HTTP request containing an + * Expect: 100-continue header before sending the data anyway. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.expect_100_timeout = arg; + break; + + case CURLOPT_HTTP09_ALLOWED: + arg = va_arg(param, unsigned long); + if(arg > 1L) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.http09_allowed = arg ? TRUE : FALSE; + break; +#endif /* CURL_DISABLE_HTTP */ + + case CURLOPT_HTTPAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.httpauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authhost.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.httpauth = auth; + } + break; + + case CURLOPT_CUSTOMREQUEST: + /* + * Set a custom string to use as request + */ + result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], + va_arg(param, char *)); + + /* we don't set + data->set.httpreq = HTTPREQ_CUSTOM; + here, we continue as if we were using the already set type + and this just changes the actual request keyword */ + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_HTTPPROXYTUNNEL: + /* + * Tunnel operations through the proxy instead of normal proxy use + */ + data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ? + TRUE : FALSE; + break; + + case CURLOPT_PROXYPORT: + /* + * Explicitly set HTTP proxy port number. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxyport = arg; + break; + + case CURLOPT_PROXYAUTH: + /* + * Set HTTP Authentication type BITMASK. + */ + { + int bitcheck; + bool authbits; + unsigned long auth = va_arg(param, unsigned long); + + if(auth == CURLAUTH_NONE) { + data->set.proxyauth = auth; + break; + } + + /* the DIGEST_IE bit is only used to set a special marker, for all the + rest we need to handle it as normal DIGEST */ + data->state.authproxy.iestyle = + (bool)((auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE); + + if(auth & CURLAUTH_DIGEST_IE) { + auth |= CURLAUTH_DIGEST; /* set standard digest bit */ + auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ + } + /* switch off bits we can't support */ +#ifndef USE_NTLM + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#elif !defined(NTLM_WB_ENABLED) + auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ +#endif +#ifndef USE_SPNEGO + auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without + GSS-API or SSPI */ +#endif + + /* check if any auth bit lower than CURLAUTH_ONLY is still set */ + bitcheck = 0; + authbits = FALSE; + while(bitcheck < 31) { + if(auth & (1UL << bitcheck++)) { + authbits = TRUE; + break; + } + } + if(!authbits) + return CURLE_NOT_BUILT_IN; /* no supported types left! */ + + data->set.proxyauth = auth; + } + break; + + case CURLOPT_PROXY: + /* + * Set proxy server:port to use as proxy. + * + * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) + * we explicitly say that we don't want to use a proxy + * (even though there might be environment variables saying so). + * + * Setting it to NULL, means no proxy but allows the environment variables + * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PRE_PROXY: + /* + * Set proxy server:port to use as SOCKS proxy. + * + * If the proxy is set to "" or NULL we explicitly say that we don't want + * to use the socks proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY], + va_arg(param, char *)); + break; + + case CURLOPT_PROXYTYPE: + /* + * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME + */ + arg = va_arg(param, long); + if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.proxytype = (curl_proxytype)arg; + break; + + case CURLOPT_PROXY_TRANSFER_MODE: + /* + * set transfer mode (;type=) when doing FTP via an HTTP proxy + */ + switch(va_arg(param, long)) { + case 0: + data->set.proxy_transfer_mode = FALSE; + break; + case 1: + data->set.proxy_transfer_mode = TRUE; + break; + default: + /* reserve other values for future use */ + result = CURLE_UNKNOWN_OPTION; + break; + } + break; +#endif /* CURL_DISABLE_PROXY */ + + case CURLOPT_SOCKS5_AUTH: + data->set.socks5auth = va_arg(param, unsigned long); + if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) + result = CURLE_NOT_BUILT_IN; + break; +#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) + case CURLOPT_SOCKS5_GSSAPI_NEC: + /* + * Set flag for NEC SOCK5 support + */ + data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; +#endif + + case CURLOPT_SOCKS5_GSSAPI_SERVICE: + case CURLOPT_PROXY_SERVICE_NAME: + /* + * Set proxy authentication service name for Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], + va_arg(param, char *)); + break; + + case CURLOPT_SERVICE_NAME: + /* + * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO + */ + result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], + va_arg(param, char *)); + break; + + case CURLOPT_HEADERDATA: + /* + * Custom pointer to pass the header write callback function + */ + data->set.writeheader = (void *)va_arg(param, void *); + break; + case CURLOPT_ERRORBUFFER: + /* + * Error buffer provided by the caller to get the human readable + * error string in. + */ + data->set.errorbuffer = va_arg(param, char *); + break; + case CURLOPT_WRITEDATA: + /* + * FILE pointer to write to. Or possibly + * used as argument to the write callback. + */ + data->set.out = va_arg(param, void *); + break; + case CURLOPT_FTPPORT: + /* + * Use FTP PORT, this also specifies which IP address to use + */ + result = Curl_setstropt(&data->set.str[STRING_FTPPORT], + va_arg(param, char *)); + data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPRT: + data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_EPSV: + data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_USE_PRET: + data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_SSL_CCC: + arg = va_arg(param, long); + if((arg < CURLFTPSSL_CCC_NONE) || (arg > CURLFTPSSL_CCC_ACTIVE)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftp_ccc = (curl_ftpccc)arg; + break; + + case CURLOPT_FTP_SKIP_PASV_IP: + /* + * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the + * bypass of the IP address in PASV responses. + */ + data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_READDATA: + /* + * FILE pointer to read the file to be uploaded from. Or possibly + * used as argument to the read callback. + */ + data->set.in_set = va_arg(param, void *); + break; + case CURLOPT_INFILESIZE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = arg; + break; + case CURLOPT_INFILESIZE_LARGE: + /* + * If known, this should inform curl about the file size of the + * to-be-uploaded file. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.filesize = bigsize; + break; + case CURLOPT_LOW_SPEED_LIMIT: + /* + * The low speed limit that if transfers are below this for + * CURLOPT_LOW_SPEED_TIME, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_limit = arg; + break; + case CURLOPT_MAX_SEND_SPEED_LARGE: + /* + * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE + * bytes per second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_send_speed = bigsize; + break; + case CURLOPT_MAX_RECV_SPEED_LARGE: + /* + * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per + * second the transfer is throttled.. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_recv_speed = bigsize; + break; + case CURLOPT_LOW_SPEED_TIME: + /* + * The low speed time that if transfers are below the set + * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.low_speed_time = arg; + break; + case CURLOPT_CURLU: + /* + * pass CURLU to set URL + */ + data->set.uh = va_arg(param, CURLU *); + break; + case CURLOPT_URL: + /* + * The URL to fetch. + */ + if(data->change.url_alloc) { + /* the already set URL is allocated, free it first! */ + Curl_safefree(data->change.url); + data->change.url_alloc = FALSE; + } + result = Curl_setstropt(&data->set.str[STRING_SET_URL], + va_arg(param, char *)); + data->change.url = data->set.str[STRING_SET_URL]; + break; + case CURLOPT_PORT: + /* + * The port number to use when getting the URL + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_port = arg; + break; + case CURLOPT_TIMEOUT: + /* + * The maximum time you allow curl to use for a single transfer + * operation. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.timeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.timeout = arg; + break; + + case CURLOPT_CONNECTTIMEOUT: + /* + * The maximum time you allow curl to use to connect. + */ + arg = va_arg(param, long); + if((arg >= 0) && (arg <= (INT_MAX/1000))) + data->set.connecttimeout = arg * 1000; + else + return CURLE_BAD_FUNCTION_ARGUMENT; + break; + + case CURLOPT_CONNECTTIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.connecttimeout = arg; + break; + + case CURLOPT_ACCEPTTIMEOUT_MS: + /* + * The maximum time you allow curl to wait for server connect + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.accepttimeout = arg; + break; + + case CURLOPT_USERPWD: + /* + * user:password to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], + &data->set.str[STRING_PASSWORD]); + break; + + case CURLOPT_USERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_USERNAME], + va_arg(param, char *)); + break; + + case CURLOPT_PASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PASSWORD], + va_arg(param, char *)); + break; + + case CURLOPT_LOGIN_OPTIONS: + /* + * authentication options to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_OPTIONS], + va_arg(param, char *)); + break; + + case CURLOPT_XOAUTH2_BEARER: + /* + * OAuth 2.0 bearer token to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_BEARER], + va_arg(param, char *)); + break; + + case CURLOPT_POSTQUOTE: + /* + * List of RAW FTP commands to use after a transfer + */ + data->set.postquote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_PREQUOTE: + /* + * List of RAW FTP commands to use prior to RETR (Wesley Laxton) + */ + data->set.prequote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_QUOTE: + /* + * List of RAW FTP commands to use before a transfer + */ + data->set.quote = va_arg(param, struct curl_slist *); + break; + case CURLOPT_RESOLVE: + /* + * List of NAME:[address] names to populate the DNS cache with + * Prefix the NAME with dash (-) to _remove_ the name from the cache. + * + * Names added with this API will remain in the cache until explicitly + * removed or the handle is cleaned up. + * + * This API can remove any name from the DNS cache, but only entries + * that aren't actually in use right now will be pruned immediately. + */ + data->set.resolve = va_arg(param, struct curl_slist *); + data->change.resolve = data->set.resolve; + break; + case CURLOPT_PROGRESSFUNCTION: + /* + * Progress callback function + */ + data->set.fprogress = va_arg(param, curl_progress_callback); + if(data->set.fprogress) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + break; + + case CURLOPT_XFERINFOFUNCTION: + /* + * Transfer info callback function + */ + data->set.fxferinfo = va_arg(param, curl_xferinfo_callback); + if(data->set.fxferinfo) + data->progress.callback = TRUE; /* no longer internal */ + else + data->progress.callback = FALSE; /* NULL enforces internal */ + + break; + + case CURLOPT_PROGRESSDATA: + /* + * Custom client data to pass to the progress callback + */ + data->set.progress_client = va_arg(param, void *); + break; + +#ifndef CURL_DISABLE_PROXY + case CURLOPT_PROXYUSERPWD: + /* + * user:password needed to use the proxy + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], + &data->set.str[STRING_PROXYPASSWORD]); + break; + case CURLOPT_PROXYUSERNAME: + /* + * authentication user name to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], + va_arg(param, char *)); + break; + case CURLOPT_PROXYPASSWORD: + /* + * authentication password to use in the operation + */ + result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], + va_arg(param, char *)); + break; + case CURLOPT_NOPROXY: + /* + * proxy exception list + */ + result = Curl_setstropt(&data->set.str[STRING_NOPROXY], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_RANGE: + /* + * What range of the file you want to transfer + */ + result = Curl_setstropt(&data->set.str[STRING_SET_RANGE], + va_arg(param, char *)); + break; + case CURLOPT_RESUME_FROM: + /* + * Resume transfer at the given file position + */ + arg = va_arg(param, long); + if(arg < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = arg; + break; + case CURLOPT_RESUME_FROM_LARGE: + /* + * Resume transfer at the given file position + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < -1) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.set_resume_from = bigsize; + break; + case CURLOPT_DEBUGFUNCTION: + /* + * stderr write callback. + */ + data->set.fdebug = va_arg(param, curl_debug_callback); + /* + * if the callback provided is NULL, it'll use the default callback + */ + break; + case CURLOPT_DEBUGDATA: + /* + * Set to a void * that should receive all error writes. This + * defaults to CURLOPT_STDERR for normal operations. + */ + data->set.debugdata = va_arg(param, void *); + break; + case CURLOPT_STDERR: + /* + * Set to a FILE * that should receive all error writes. This + * defaults to stderr for normal operations. + */ + data->set.err = va_arg(param, FILE *); + if(!data->set.err) + data->set.err = stderr; + break; + case CURLOPT_HEADERFUNCTION: + /* + * Set header write callback + */ + data->set.fwrite_header = va_arg(param, curl_write_callback); + break; + case CURLOPT_WRITEFUNCTION: + /* + * Set data write callback + */ + data->set.fwrite_func = va_arg(param, curl_write_callback); + if(!data->set.fwrite_func) { + data->set.is_fwrite_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fwrite_func = (curl_write_callback)fwrite; + } + else + data->set.is_fwrite_set = 1; + break; + case CURLOPT_READFUNCTION: + /* + * Read data callback + */ + data->set.fread_func_set = va_arg(param, curl_read_callback); + if(!data->set.fread_func_set) { + data->set.is_fread_set = 0; + /* When set to NULL, reset to our internal default function */ + data->set.fread_func_set = (curl_read_callback)fread; + } + else + data->set.is_fread_set = 1; + break; + case CURLOPT_SEEKFUNCTION: + /* + * Seek callback. Might be NULL. + */ + data->set.seek_func = va_arg(param, curl_seek_callback); + break; + case CURLOPT_SEEKDATA: + /* + * Seek control callback. Might be NULL. + */ + data->set.seek_client = va_arg(param, void *); + break; + case CURLOPT_CONV_FROM_NETWORK_FUNCTION: + /* + * "Convert from network encoding" callback + */ + data->set.convfromnetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_TO_NETWORK_FUNCTION: + /* + * "Convert to network encoding" callback + */ + data->set.convtonetwork = va_arg(param, curl_conv_callback); + break; + case CURLOPT_CONV_FROM_UTF8_FUNCTION: + /* + * "Convert from UTF-8 encoding" callback + */ + data->set.convfromutf8 = va_arg(param, curl_conv_callback); + break; + case CURLOPT_IOCTLFUNCTION: + /* + * I/O control callback. Might be NULL. + */ + data->set.ioctl_func = va_arg(param, curl_ioctl_callback); + break; + case CURLOPT_IOCTLDATA: + /* + * I/O control data pointer. Might be NULL. + */ + data->set.ioctl_client = va_arg(param, void *); + break; + case CURLOPT_SSLCERT: + /* + * String that holds file name of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERT: + /* + * String that holds file name of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLCERTTYPE: + /* + * String that holds file type of the SSL certificate to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_SSLKEY: + /* + * String that holds file name of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEY: + /* + * String that holds file name of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_SSLKEYTYPE: + /* + * String that holds file type of the SSL key to use for proxy + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_KEYPASSWD: + /* + * String that holds the SSL or SSH private key password. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_KEYPASSWD: + /* + * String that holds the SSL private key password for proxy. + */ + result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_SSLENGINE: + /* + * String that holds the SSL crypto engine. + */ + argptr = va_arg(param, char *); + if(argptr && argptr[0]) { + result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr); + if(!result) { + result = Curl_ssl_set_engine(data, argptr); + } + } + break; + + case CURLOPT_SSLENGINE_DEFAULT: + /* + * flag to set engine as default. + */ + Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL); + result = Curl_ssl_set_engine_default(data); + break; + case CURLOPT_CRLF: + /* + * Kludgy option to enable CRLF conversions. Subject for removal. + */ + data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_HAPROXYPROTOCOL: + /* + * Set to send the HAProxy Proxy Protocol header + */ + data->set.haproxyprotocol = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_INTERFACE: + /* + * Set what interface or address/hostname to bind the socket to when + * performing an operation and thus what from-IP your connection will use. + */ + result = Curl_setstropt(&data->set.str[STRING_DEVICE], + va_arg(param, char *)); + break; + case CURLOPT_LOCALPORT: + /* + * Set what local port to bind the socket to when performing an operation. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localport = curlx_sltous(arg); + break; + case CURLOPT_LOCALPORTRANGE: + /* + * Set number of local ports to try, starting with CURLOPT_LOCALPORT. + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 65535)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.localportrange = curlx_sltosi(arg); + break; + case CURLOPT_KRBLEVEL: + /* + * A string that defines the kerberos security level. + */ + result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], + va_arg(param, char *)); + data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE; + break; + case CURLOPT_GSSAPI_DELEGATION: + /* + * GSS-API credential delegation bitmask + */ + arg = va_arg(param, long); + if(arg < CURLGSSAPI_DELEGATION_NONE) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.gssapi_delegation = arg; + break; + case CURLOPT_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying. + */ + data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifypeer = + data->set.ssl.primary.verifypeer; + } + break; + case CURLOPT_PROXY_SSL_VERIFYPEER: + /* + * Enable peer SSL verifying for proxy. + */ + data->set.proxy_ssl.primary.verifypeer = + (0 != va_arg(param, long))?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifypeer = + data->set.proxy_ssl.primary.verifypeer; + } + break; + case CURLOPT_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifyhost = + data->set.ssl.primary.verifyhost; + } + break; + case CURLOPT_PROXY_SSL_VERIFYHOST: + /* + * Enable verification of the host name in the peer certificate for proxy + */ + arg = va_arg(param, long); + + /* Obviously people are not reading documentation and too many thought + this argument took a boolean when it wasn't and misused it. We thus ban + 1 as a sensible input and we warn about its use. Then we only have the + 2 action internally stored as TRUE. */ + + if(1 == arg) { + failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!"); + return CURLE_BAD_FUNCTION_ARGUMENT; + } + + data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE; + + /* Update the current connection proxy_ssl_config. */ + if(data->conn) { + data->conn->proxy_ssl_config.verifyhost = + data->set.proxy_ssl.primary.verifyhost; + } + break; + case CURLOPT_SSL_VERIFYSTATUS: + /* + * Enable certificate status verifying. + */ + if(!Curl_ssl_cert_status_request()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ? + TRUE : FALSE; + + /* Update the current connection ssl_config. */ + if(data->conn) { + data->conn->ssl_config.verifystatus = + data->set.ssl.primary.verifystatus; + } + break; + case CURLOPT_SSL_CTX_FUNCTION: + /* + * Set a SSL_CTX callback + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_CTX_DATA: + /* + * Set a SSL_CTX callback parameter pointer + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_SSL_CTX) + data->set.ssl.fsslctxp = va_arg(param, void *); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_SSL_FALSESTART: + /* + * Enable TLS false start. + */ + if(!Curl_ssl_false_start()) { + result = CURLE_NOT_BUILT_IN; + break; + } + + data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CERTINFO: +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CERTINFO) + data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE; + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PROXY_PINNEDPUBLICKEY: + /* + * Set pinned public key for SSL connection. + * Specify file name of the public key in DER format. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY) + result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_CAINFO: + /* + * Set CA info for SSL connection. Specify file name of the CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CAINFO: + /* + * Set CA info SSL connection for proxy. Specify file name of the + * CA certificate + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_CAPATH: + /* + * Set CA path info for SSL connection. Specify directory name of the CA + * certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_PROXY_CAPATH: + /* + * Set CA path info for SSL connection proxy. Specify directory name of the + * CA certificates which have been prepared using openssl c_rehash utility. + */ +#ifdef USE_SSL + if(Curl_ssl->supports & SSLSUPP_CA_PATH) + /* This does not work on windows. */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], + va_arg(param, char *)); + else +#endif + result = CURLE_NOT_BUILT_IN; + break; + case CURLOPT_CRLFILE: + /* + * Set CRL file info for SSL connection. Specify file name of the CRL + * to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_PROXY_CRLFILE: + /* + * Set CRL file info for SSL connection for proxy. Specify file name of the + * CRL to check certificates revocation + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], + va_arg(param, char *)); + break; + case CURLOPT_ISSUERCERT: + /* + * Set Issuer certificate file + * to check certificates issuer + */ + result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG], + va_arg(param, char *)); + break; + case CURLOPT_TELNETOPTIONS: + /* + * Set a linked list of telnet options + */ + data->set.telnet_options = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_BUFFERSIZE: + /* + * The application kindly asks for a differently sized receive buffer. + * If it seems reasonable, we'll use it. + */ + arg = va_arg(param, long); + + if(arg > READBUFFER_MAX) + arg = READBUFFER_MAX; + else if(arg < 1) + arg = READBUFFER_SIZE; + else if(arg < READBUFFER_MIN) + arg = READBUFFER_MIN; + + /* Resize if new size */ + if(arg != data->set.buffer_size) { + char *newbuff = realloc(data->state.buffer, arg + 1); + if(!newbuff) { + DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n")); + result = CURLE_OUT_OF_MEMORY; + } + else + data->state.buffer = newbuff; + } + data->set.buffer_size = arg; + + break; + + case CURLOPT_UPLOAD_BUFFERSIZE: + /* + * The application kindly asks for a differently sized upload buffer. + * Cap it to sensible. + */ + arg = va_arg(param, long); + + if(arg > UPLOADBUFFER_MAX) + arg = UPLOADBUFFER_MAX; + else if(arg < UPLOADBUFFER_MIN) + arg = UPLOADBUFFER_MIN; + + data->set.upload_buffer_size = arg; + Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ + break; + + case CURLOPT_NOSIGNAL: + /* + * The application asks not to set any signal() or alarm() handlers, + * even when using a timeout. + */ + data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_SHARE: + { + struct Curl_share *set; + set = va_arg(param, struct Curl_share *); + + /* disconnect from old share, if any */ + if(data->share) { + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + if(data->dns.hostcachetype == HCACHE_SHARED) { + data->dns.hostcache = NULL; + data->dns.hostcachetype = HCACHE_NONE; + } + +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies == data->cookies) + data->cookies = NULL; +#endif + + if(data->share->sslsession == data->state.session) + data->state.session = NULL; + +#ifdef USE_LIBPSL + if(data->psl == &data->share->psl) + data->psl = data->multi? &data->multi->psl: NULL; +#endif + + data->share->dirty--; + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + data->share = NULL; + } + + /* use new share if it set */ + data->share = set; + if(data->share) { + + Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); + + data->share->dirty++; + + if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) { + /* use shared host cache */ + data->dns.hostcache = &data->share->hostcache; + data->dns.hostcachetype = HCACHE_SHARED; + } +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) + if(data->share->cookies) { + /* use shared cookie list, first free own one if any */ + Curl_cookie_cleanup(data->cookies); + /* enable cookies since we now use a share that uses cookies! */ + data->cookies = data->share->cookies; + } +#endif /* CURL_DISABLE_HTTP */ + if(data->share->sslsession) { + data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; + data->state.session = data->share->sslsession; + } +#ifdef USE_LIBPSL + if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) + data->psl = &data->share->psl; +#endif + + Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); + } + /* check for host cache not needed, + * it will be done by curl_easy_perform */ + } + break; + + case CURLOPT_PRIVATE: + /* + * Set private data pointer. + */ + data->set.private_data = va_arg(param, void *); + break; + + case CURLOPT_MAXFILESIZE: + /* + * Set the maximum size of a file to download. + */ + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = arg; + break; + +#ifdef USE_SSL + case CURLOPT_USE_SSL: + /* + * Make transfers attempt to use SSL/TLS. + */ + arg = va_arg(param, long); + if((arg < CURLUSESSL_NONE) || (arg > CURLUSESSL_ALL)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.use_ssl = (curl_usessl)arg; + break; + + case CURLOPT_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + + case CURLOPT_PROXY_SSL_OPTIONS: + arg = va_arg(param, long); + data->set.proxy_ssl.enable_beast = + (bool)((arg&CURLSSLOPT_ALLOW_BEAST) ? TRUE : FALSE); + data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); + break; + +#endif + case CURLOPT_FTPSSLAUTH: + /* + * Set a specific auth for FTP-SSL transfers. + */ + arg = va_arg(param, long); + if((arg < CURLFTPAUTH_DEFAULT) || (arg > CURLFTPAUTH_TLS)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ftpsslauth = (curl_ftpauth)arg; + break; + + case CURLOPT_IPRESOLVE: + arg = va_arg(param, long); + if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.ipver = arg; + break; + + case CURLOPT_MAXFILESIZE_LARGE: + /* + * Set the maximum size of a file to download. + */ + bigsize = va_arg(param, curl_off_t); + if(bigsize < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.max_filesize = bigsize; + break; + + case CURLOPT_TCP_NODELAY: + /* + * Enable or disable TCP_NODELAY, which will disable/enable the Nagle + * algorithm + */ + data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_ACCOUNT: + result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], + va_arg(param, char *)); + break; + + case CURLOPT_IGNORE_CONTENT_LENGTH: + data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_CONNECT_ONLY: + /* + * No data transfer, set up connection and let application use the socket + */ + data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_FTP_ALTERNATIVE_TO_USER: + result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], + va_arg(param, char *)); + break; + + case CURLOPT_SOCKOPTFUNCTION: + /* + * socket callback function: called after socket() but before connect() + */ + data->set.fsockopt = va_arg(param, curl_sockopt_callback); + break; + + case CURLOPT_SOCKOPTDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.sockopt_client = va_arg(param, void *); + break; + + case CURLOPT_OPENSOCKETFUNCTION: + /* + * open/create socket callback function: called instead of socket(), + * before connect() + */ + data->set.fopensocket = va_arg(param, curl_opensocket_callback); + break; + + case CURLOPT_OPENSOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.opensocket_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETFUNCTION: + /* + * close socket callback function: called instead of close() + * when shutting down a connection + */ + data->set.fclosesocket = va_arg(param, curl_closesocket_callback); + break; + + case CURLOPT_RESOLVER_START_FUNCTION: + /* + * resolver start callback function: called before a new resolver request + * is started + */ + data->set.resolver_start = va_arg(param, curl_resolver_start_callback); + break; + + case CURLOPT_RESOLVER_START_DATA: + /* + * resolver start callback data pointer. Might be NULL. + */ + data->set.resolver_start_client = va_arg(param, void *); + break; + + case CURLOPT_CLOSESOCKETDATA: + /* + * socket callback data pointer. Might be NULL. + */ + data->set.closesocket_client = va_arg(param, void *); + break; + + case CURLOPT_SSL_SESSIONID_CACHE: + data->set.ssl.primary.sessionid = (0 != va_arg(param, long)) ? + TRUE : FALSE; + data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; + break; + +#if defined(USE_LIBSSH2) || defined(USE_LIBSSH) + /* we only include SSH options if explicitly built to support SSH */ + case CURLOPT_SSH_AUTH_TYPES: + data->set.ssh_auth_types = va_arg(param, long); + break; + + case CURLOPT_SSH_PUBLIC_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa.pub file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_PRIVATE_KEYFILE: + /* + * Use this file instead of the $HOME/.ssh/id_dsa file + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], + va_arg(param, char *)); + break; + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + /* + * Option to allow for the MD5 of the host public key to be checked + * for validation purposes. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KNOWNHOSTS: + /* + * Store the file name to read known hosts from. + */ + result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], + va_arg(param, char *)); + break; + + case CURLOPT_SSH_KEYFUNCTION: + /* setting to NULL is fine since the ssh.c functions themselves will + then rever to use the internal default */ + data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); + break; + + case CURLOPT_SSH_KEYDATA: + /* + * Custom client data to pass to the SSH keyfunc callback + */ + data->set.ssh_keyfunc_userp = va_arg(param, void *); + break; +#endif /* USE_LIBSSH2 */ + + case CURLOPT_HTTP_TRANSFER_DECODING: + /* + * disable libcurl transfer encoding is used + */ + data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_HTTP_CONTENT_DECODING: + /* + * raw data passed to the application when content encoding is used + */ + data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_NEW_FILE_PERMS: + /* + * Uses these permissions instead of 0644 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_file_perms = arg; + break; + + case CURLOPT_NEW_DIRECTORY_PERMS: + /* + * Uses these permissions instead of 0755 + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0777)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.new_directory_perms = arg; + break; + + case CURLOPT_ADDRESS_SCOPE: + /* + * We always get longs when passed plain numericals, but for this value we + * know that an unsigned int will always hold the value so we blindly + * typecast to this type + */ + arg = va_arg(param, long); + if((arg < 0) || (arg > 0xf)) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.scope_id = curlx_sltoui(arg); + break; + + case CURLOPT_PROTOCOLS: + /* set the bitmask for the protocols that are allowed to be used for the + transfer, which thus helps the app which takes URLs from users or other + external inputs and want to restrict what protocol(s) to deal + with. Defaults to CURLPROTO_ALL. */ + data->set.allowed_protocols = va_arg(param, long); + break; + + case CURLOPT_REDIR_PROTOCOLS: + /* set the bitmask for the protocols that libcurl is allowed to follow to, + as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs + to be set in both bitmasks to be allowed to get redirected to. Defaults + to all protocols except FILE and SCP. */ + data->set.redir_protocols = va_arg(param, long); + break; + + case CURLOPT_DEFAULT_PROTOCOL: + /* Set the protocol to use when the URL doesn't include any protocol */ + result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_FROM: + /* Set the SMTP mail originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_AUTH: + /* Set the SMTP auth originator */ + result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], + va_arg(param, char *)); + break; + + case CURLOPT_MAIL_RCPT: + /* Set the list of mail recipients */ + data->set.mail_rcpt = va_arg(param, struct curl_slist *); + break; + + case CURLOPT_SASL_IR: + /* Enable/disable SASL initial response */ + data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + + case CURLOPT_RTSP_REQUEST: + { + /* + * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) + * Would this be better if the RTSPREQ_* were just moved into here? + */ + long curl_rtspreq = va_arg(param, long); + Curl_RtspReq rtspreq = RTSPREQ_NONE; + switch(curl_rtspreq) { + case CURL_RTSPREQ_OPTIONS: + rtspreq = RTSPREQ_OPTIONS; + break; + + case CURL_RTSPREQ_DESCRIBE: + rtspreq = RTSPREQ_DESCRIBE; + break; + + case CURL_RTSPREQ_ANNOUNCE: + rtspreq = RTSPREQ_ANNOUNCE; + break; + + case CURL_RTSPREQ_SETUP: + rtspreq = RTSPREQ_SETUP; + break; + + case CURL_RTSPREQ_PLAY: + rtspreq = RTSPREQ_PLAY; + break; + + case CURL_RTSPREQ_PAUSE: + rtspreq = RTSPREQ_PAUSE; + break; + + case CURL_RTSPREQ_TEARDOWN: + rtspreq = RTSPREQ_TEARDOWN; + break; + + case CURL_RTSPREQ_GET_PARAMETER: + rtspreq = RTSPREQ_GET_PARAMETER; + break; + + case CURL_RTSPREQ_SET_PARAMETER: + rtspreq = RTSPREQ_SET_PARAMETER; + break; + + case CURL_RTSPREQ_RECORD: + rtspreq = RTSPREQ_RECORD; + break; + + case CURL_RTSPREQ_RECEIVE: + rtspreq = RTSPREQ_RECEIVE; + break; + default: + rtspreq = RTSPREQ_NONE; + } + + data->set.rtspreq = rtspreq; + break; + } + + + case CURLOPT_RTSP_SESSION_ID: + /* + * Set the RTSP Session ID manually. Useful if the application is + * resuming a previously established RTSP session + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_STREAM_URI: + /* + * Set the Stream URI for the RTSP request. Unless the request is + * for generic server options, the application will need to set this. + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_TRANSPORT: + /* + * The content of the Transport: header for the RTSP request + */ + result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], + va_arg(param, char *)); + break; + + case CURLOPT_RTSP_CLIENT_CSEQ: + /* + * Set the CSEQ number to issue for the next RTSP request. Useful if the + * application is resuming a previously broken connection. The CSEQ + * will increment from this new number henceforth. + */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_RTSP_SERVER_CSEQ: + /* Same as the above, but for server-initiated requests */ + data->state.rtsp_next_client_CSeq = va_arg(param, long); + break; + + case CURLOPT_INTERLEAVEDATA: + data->set.rtp_out = va_arg(param, void *); + break; + case CURLOPT_INTERLEAVEFUNCTION: + /* Set the user defined RTP write function */ + data->set.fwrite_rtp = va_arg(param, curl_write_callback); + break; + + case CURLOPT_WILDCARDMATCH: + data->set.wildcard_enabled = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_CHUNK_BGN_FUNCTION: + data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); + break; + case CURLOPT_CHUNK_END_FUNCTION: + data->set.chunk_end = va_arg(param, curl_chunk_end_callback); + break; + case CURLOPT_FNMATCH_FUNCTION: + data->set.fnmatch = va_arg(param, curl_fnmatch_callback); + break; + case CURLOPT_CHUNK_DATA: + data->wildcard.customptr = va_arg(param, void *); + break; + case CURLOPT_FNMATCH_DATA: + data->set.fnmatch_data = va_arg(param, void *); + break; +#ifdef USE_TLS_SRP + case CURLOPT_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_USERNAME: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], + va_arg(param, char *)); + if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] && + !data->set.proxy_ssl.authtype) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */ + break; + case CURLOPT_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.ssl.authtype = CURL_TLSAUTH_NONE; + break; + case CURLOPT_PROXY_TLSAUTH_TYPE: + argptr = va_arg(param, char *); + if(!argptr || + strncasecompare(argptr, "SRP", strlen("SRP"))) + data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; + else + data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE; + break; +#endif + case CURLOPT_DNS_SERVERS: + result = Curl_set_dns_servers(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_INTERFACE: + result = Curl_set_dns_interface(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP4: + result = Curl_set_dns_local_ip4(data, va_arg(param, char *)); + break; + case CURLOPT_DNS_LOCAL_IP6: + result = Curl_set_dns_local_ip6(data, va_arg(param, char *)); + break; + + case CURLOPT_TCP_KEEPALIVE: + data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_TCP_KEEPIDLE: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepidle = arg; + break; + case CURLOPT_TCP_KEEPINTVL: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.tcp_keepintvl = arg; + break; + case CURLOPT_TCP_FASTOPEN: +#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ + defined(TCP_FASTOPEN_CONNECT) + data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE; +#else + result = CURLE_NOT_BUILT_IN; +#endif + break; + case CURLOPT_SSL_ENABLE_NPN: + data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_SSL_ENABLE_ALPN: + data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + +#ifdef USE_UNIX_SOCKETS + case CURLOPT_UNIX_SOCKET_PATH: + data->set.abstract_unix_socket = FALSE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; + case CURLOPT_ABSTRACT_UNIX_SOCKET: + data->set.abstract_unix_socket = TRUE; + result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], + va_arg(param, char *)); + break; +#endif + + case CURLOPT_PATH_AS_IS: + data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_PIPEWAIT: + data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_STREAM_WEIGHT: +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + arg = va_arg(param, long); + if((arg >= 1) && (arg <= 256)) + data->set.stream_weight = (int)arg; + break; +#endif + case CURLOPT_STREAM_DEPENDS: + case CURLOPT_STREAM_DEPENDS_E: + { +#ifndef USE_NGHTTP2 + return CURLE_NOT_BUILT_IN; +#else + struct Curl_easy *dep = va_arg(param, struct Curl_easy *); + if(!dep || GOOD_EASY_HANDLE(dep)) { + if(data->set.stream_depends_on) { + Curl_http2_remove_child(data->set.stream_depends_on, data); + } + Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E)); + } + break; +#endif + } + case CURLOPT_CONNECT_TO: + data->set.connect_to = va_arg(param, struct curl_slist *); + break; + case CURLOPT_SUPPRESS_CONNECT_HEADERS: + data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_SSH_COMPRESSION: + data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE; + break; + case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.happy_eyeballs_timeout = arg; + break; + case CURLOPT_DNS_SHUFFLE_ADDRESSES: + data->set.dns_shuffle_addresses = (0 != va_arg(param, long)) ? TRUE:FALSE; + break; + case CURLOPT_DISALLOW_USERNAME_IN_URL: + data->set.disallow_username_in_url = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + case CURLOPT_DOH_URL: + result = Curl_setstropt(&data->set.str[STRING_DOH], + va_arg(param, char *)); + data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE; + break; + case CURLOPT_UPKEEP_INTERVAL_MS: + arg = va_arg(param, long); + if(arg < 0) + return CURLE_BAD_FUNCTION_ARGUMENT; + data->set.upkeep_interval_ms = arg; + break; + case CURLOPT_TRAILERFUNCTION: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_callback = va_arg(param, curl_trailer_callback); +#endif + break; + case CURLOPT_TRAILERDATA: +#ifndef CURL_DISABLE_HTTP + data->set.trailer_data = va_arg(param, void *); +#endif + break; +#ifdef USE_ALTSVC + case CURLOPT_ALTSVC: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + argptr = va_arg(param, char *); + result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); + if(result) + return result; + (void)Curl_altsvc_load(data->asi, argptr); + break; + case CURLOPT_ALTSVC_CTRL: + if(!data->asi) { + data->asi = Curl_altsvc_init(); + if(!data->asi) + return CURLE_OUT_OF_MEMORY; + } + arg = va_arg(param, long); + result = Curl_altsvc_ctrl(data->asi, arg); + if(result) + return result; + break; +#endif + default: + /* unknown tag and its companion, just ignore: */ + result = CURLE_UNKNOWN_OPTION; + break; + } + + return result; +} + +/* + * curl_easy_setopt() is the external interface for setting options on an + * easy handle. + * + * NOTE: This is one of few API functions that are allowed to be called from + * within a callback. + */ + +#undef curl_easy_setopt +CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) +{ + va_list arg; + CURLcode result; + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + va_start(arg, tag); + + result = vsetopt(data, tag, arg); + + va_end(arg); + return result; +} diff --git a/external/curl prx/src/setopt.cb b/external/curl prx/src/setopt.cb new file mode 100644 index 0000000..77556d2 --- /dev/null +++ b/external/curl prx/src/setopt.cb @@ -0,0 +1,21 @@ +#include +#include + + +CURLcode vsetopt(struct Curl_easy *data, CURLoption option, va_list param); + +CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) +{ + va_list arg; + CURLcode result; + + if(!data) + return CURLE_BAD_FUNCTION_ARGUMENT; + + va_start(arg, tag); + + result = vsetopt(data, tag, arg); + + va_end(arg); + return result; +} diff --git a/external/curl prx/src/strerror.c b/external/curl prx/src/strerror.c new file mode 100644 index 0000000..e273f37 --- /dev/null +++ b/external/curl prx/src/strerror.c @@ -0,0 +1,1102 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 2004 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#ifdef HAVE_STRERROR_R +# if (!defined(HAVE_POSIX_STRERROR_R) && \ + !defined(HAVE_GLIBC_STRERROR_R) && \ + !defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_GLIBC_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R)) || \ + (defined(HAVE_POSIX_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R)) +# error "strerror_r MUST be either POSIX, glibc or vxworks-style" +# endif +#endif + +#include + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_WINDOWS_SSPI +#include "curl_sspi.h" +#endif + +#include "strerror.h" +/* The last 3 #include files should be in this order */ +#include "curl_printf.h" +#include "curl_memory.h" +#include "memdebug.h" + +#if defined(WIN32) || defined(_WIN32_WCE) +#define PRESERVE_WINDOWS_ERROR_CODE +#endif + +const char * +curl_easy_strerror(CURLcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLE_OK: + return "No error"; + + case CURLE_UNSUPPORTED_PROTOCOL: + return "Unsupported protocol"; + + case CURLE_FAILED_INIT: + return "Failed initialization"; + + case CURLE_URL_MALFORMAT: + return "URL using bad/illegal format or missing URL"; + + case CURLE_NOT_BUILT_IN: + return "A requested feature, protocol or option was not found built-in in" + " this libcurl due to a build-time decision."; + + case CURLE_COULDNT_RESOLVE_PROXY: + return "Couldn't resolve proxy name"; + + case CURLE_COULDNT_RESOLVE_HOST: + return "Couldn't resolve host name"; + + case CURLE_COULDNT_CONNECT: + return "Couldn't connect to server"; + + case CURLE_WEIRD_SERVER_REPLY: + return "Weird server reply"; + + case CURLE_REMOTE_ACCESS_DENIED: + return "Access denied to remote resource"; + + case CURLE_FTP_ACCEPT_FAILED: + return "FTP: The server failed to connect to data port"; + + case CURLE_FTP_ACCEPT_TIMEOUT: + return "FTP: Accepting server connect has timed out"; + + case CURLE_FTP_PRET_FAILED: + return "FTP: The server did not accept the PRET command."; + + case CURLE_FTP_WEIRD_PASS_REPLY: + return "FTP: unknown PASS reply"; + + case CURLE_FTP_WEIRD_PASV_REPLY: + return "FTP: unknown PASV reply"; + + case CURLE_FTP_WEIRD_227_FORMAT: + return "FTP: unknown 227 response format"; + + case CURLE_FTP_CANT_GET_HOST: + return "FTP: can't figure out the host in the PASV response"; + + case CURLE_HTTP2: + return "Error in the HTTP2 framing layer"; + + case CURLE_FTP_COULDNT_SET_TYPE: + return "FTP: couldn't set file type"; + + case CURLE_PARTIAL_FILE: + return "Transferred a partial file"; + + case CURLE_FTP_COULDNT_RETR_FILE: + return "FTP: couldn't retrieve (RETR failed) the specified file"; + + case CURLE_QUOTE_ERROR: + return "Quote command returned error"; + + case CURLE_HTTP_RETURNED_ERROR: + return "HTTP response code said error"; + + case CURLE_WRITE_ERROR: + return "Failed writing received data to disk/application"; + + case CURLE_UPLOAD_FAILED: + return "Upload failed (at start/before it took off)"; + + case CURLE_READ_ERROR: + return "Failed to open/read local data from file/application"; + + case CURLE_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLE_OPERATION_TIMEDOUT: + return "Timeout was reached"; + + case CURLE_FTP_PORT_FAILED: + return "FTP: command PORT failed"; + + case CURLE_FTP_COULDNT_USE_REST: + return "FTP: command REST failed"; + + case CURLE_RANGE_ERROR: + return "Requested range was not delivered by the server"; + + case CURLE_HTTP_POST_ERROR: + return "Internal problem setting up the POST"; + + case CURLE_SSL_CONNECT_ERROR: + return "SSL connect error"; + + case CURLE_BAD_DOWNLOAD_RESUME: + return "Couldn't resume download"; + + case CURLE_FILE_COULDNT_READ_FILE: + return "Couldn't read a file:// file"; + + case CURLE_LDAP_CANNOT_BIND: + return "LDAP: cannot bind"; + + case CURLE_LDAP_SEARCH_FAILED: + return "LDAP: search failed"; + + case CURLE_FUNCTION_NOT_FOUND: + return "A required function in the library was not found"; + + case CURLE_ABORTED_BY_CALLBACK: + return "Operation was aborted by an application callback"; + + case CURLE_BAD_FUNCTION_ARGUMENT: + return "A libcurl function was given a bad argument"; + + case CURLE_INTERFACE_FAILED: + return "Failed binding local connection end"; + + case CURLE_TOO_MANY_REDIRECTS : + return "Number of redirects hit maximum amount"; + + case CURLE_UNKNOWN_OPTION: + return "An unknown option was passed in to libcurl"; + + case CURLE_TELNET_OPTION_SYNTAX : + return "Malformed telnet option"; + + case CURLE_GOT_NOTHING: + return "Server returned nothing (no headers, no data)"; + + case CURLE_SSL_ENGINE_NOTFOUND: + return "SSL crypto engine not found"; + + case CURLE_SSL_ENGINE_SETFAILED: + return "Can not set SSL crypto engine as default"; + + case CURLE_SSL_ENGINE_INITFAILED: + return "Failed to initialise SSL crypto engine"; + + case CURLE_SEND_ERROR: + return "Failed sending data to the peer"; + + case CURLE_RECV_ERROR: + return "Failure when receiving data from the peer"; + + case CURLE_SSL_CERTPROBLEM: + return "Problem with the local SSL certificate"; + + case CURLE_SSL_CIPHER: + return "Couldn't use specified SSL cipher"; + + case CURLE_PEER_FAILED_VERIFICATION: + return "SSL peer certificate or SSH remote key was not OK"; + + case CURLE_SSL_CACERT_BADFILE: + return "Problem with the SSL CA cert (path? access rights?)"; + + case CURLE_BAD_CONTENT_ENCODING: + return "Unrecognized or bad HTTP Content or Transfer-Encoding"; + + case CURLE_LDAP_INVALID_URL: + return "Invalid LDAP URL"; + + case CURLE_FILESIZE_EXCEEDED: + return "Maximum file size exceeded"; + + case CURLE_USE_SSL_FAILED: + return "Requested SSL level failed"; + + case CURLE_SSL_SHUTDOWN_FAILED: + return "Failed to shut down the SSL connection"; + + case CURLE_SSL_CRL_BADFILE: + return "Failed to load CRL file (path? access rights?, format?)"; + + case CURLE_SSL_ISSUER_ERROR: + return "Issuer check against peer certificate failed"; + + case CURLE_SEND_FAIL_REWIND: + return "Send failed since rewinding of the data stream failed"; + + case CURLE_LOGIN_DENIED: + return "Login denied"; + + case CURLE_TFTP_NOTFOUND: + return "TFTP: File Not Found"; + + case CURLE_TFTP_PERM: + return "TFTP: Access Violation"; + + case CURLE_REMOTE_DISK_FULL: + return "Disk full or allocation exceeded"; + + case CURLE_TFTP_ILLEGAL: + return "TFTP: Illegal operation"; + + case CURLE_TFTP_UNKNOWNID: + return "TFTP: Unknown transfer ID"; + + case CURLE_REMOTE_FILE_EXISTS: + return "Remote file already exists"; + + case CURLE_TFTP_NOSUCHUSER: + return "TFTP: No such user"; + + case CURLE_CONV_FAILED: + return "Conversion failed"; + + case CURLE_CONV_REQD: + return "Caller must register CURLOPT_CONV_ callback options"; + + case CURLE_REMOTE_FILE_NOT_FOUND: + return "Remote file not found"; + + case CURLE_SSH: + return "Error in the SSH layer"; + + case CURLE_AGAIN: + return "Socket not ready for send/recv"; + + case CURLE_RTSP_CSEQ_ERROR: + return "RTSP CSeq mismatch or invalid CSeq"; + + case CURLE_RTSP_SESSION_ERROR: + return "RTSP session error"; + + case CURLE_FTP_BAD_FILE_LIST: + return "Unable to parse FTP file list"; + + case CURLE_CHUNK_FAILED: + return "Chunk callback failed"; + + case CURLE_NO_CONNECTION_AVAILABLE: + return "The max connection limit is reached"; + + case CURLE_SSL_PINNEDPUBKEYNOTMATCH: + return "SSL public key does not match pinned public key"; + + case CURLE_SSL_INVALIDCERTSTATUS: + return "SSL server certificate status verification FAILED"; + + case CURLE_HTTP2_STREAM: + return "Stream error in the HTTP/2 framing layer"; + + case CURLE_RECURSIVE_API_CALL: + return "API function called from within callback"; + + /* error codes not used by current libcurl */ + case CURLE_OBSOLETE20: + case CURLE_OBSOLETE24: + case CURLE_OBSOLETE29: + case CURLE_OBSOLETE32: + case CURLE_OBSOLETE40: + case CURLE_OBSOLETE44: + case CURLE_OBSOLETE46: + case CURLE_OBSOLETE50: + case CURLE_OBSOLETE51: + case CURLE_OBSOLETE57: + case CURL_LAST: + break; + } + /* + * By using a switch, gcc -Wall will complain about enum values + * which do not appear, helping keep this function up-to-date. + * By using gcc -Wall -Werror, you can't forget. + * + * A table would not have the same benefit. Most compilers will + * generate code very similar to a table in any case, so there + * is little performance gain from a table. And something is broken + * for the user's application, anyways, so does it matter how fast + * it _doesn't_ work? + * + * The line number for the error will be near this comment, which + * is why it is here, and not at the start of the switch. + */ + return "Unknown error"; +#else + if(!error) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_multi_strerror(CURLMcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLM_CALL_MULTI_PERFORM: + return "Please call curl_multi_perform() soon"; + + case CURLM_OK: + return "No error"; + + case CURLM_BAD_HANDLE: + return "Invalid multi handle"; + + case CURLM_BAD_EASY_HANDLE: + return "Invalid easy handle"; + + case CURLM_OUT_OF_MEMORY: + return "Out of memory"; + + case CURLM_INTERNAL_ERROR: + return "Internal error"; + + case CURLM_BAD_SOCKET: + return "Invalid socket argument"; + + case CURLM_UNKNOWN_OPTION: + return "Unknown option"; + + case CURLM_ADDED_ALREADY: + return "The easy handle is already added to a multi handle"; + + case CURLM_RECURSIVE_API_CALL: + return "API function called from within callback"; + + case CURLM_LAST: + break; + } + + return "Unknown error"; +#else + if(error == CURLM_OK) + return "No error"; + else + return "Error"; +#endif +} + +const char * +curl_share_strerror(CURLSHcode error) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(error) { + case CURLSHE_OK: + return "No error"; + + case CURLSHE_BAD_OPTION: + return "Unknown share option"; + + case CURLSHE_IN_USE: + return "Share currently in use"; + + case CURLSHE_INVALID: + return "Invalid share handle"; + + case CURLSHE_NOMEM: + return "Out of memory"; + + case CURLSHE_NOT_BUILT_IN: + return "Feature not enabled in this library"; + + case CURLSHE_LAST: + break; + } + + return "CURLSHcode unknown"; +#else + if(error == CURLSHE_OK) + return "No error"; + else + return "Error"; +#endif +} + +#ifdef USE_WINSOCK + +/* This function handles most / all (?) Winsock errors curl is able to produce. + */ +static const char * +get_winsock_error (int err, char *buf, size_t len) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *p; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + switch(err) { + case WSAEINTR: + p = "Call interrupted"; + break; + case WSAEBADF: + p = "Bad file"; + break; + case WSAEACCES: + p = "Bad access"; + break; + case WSAEFAULT: + p = "Bad argument"; + break; + case WSAEINVAL: + p = "Invalid arguments"; + break; + case WSAEMFILE: + p = "Out of file descriptors"; + break; + case WSAEWOULDBLOCK: + p = "Call would block"; + break; + case WSAEINPROGRESS: + case WSAEALREADY: + p = "Blocking call in progress"; + break; + case WSAENOTSOCK: + p = "Descriptor is not a socket"; + break; + case WSAEDESTADDRREQ: + p = "Need destination address"; + break; + case WSAEMSGSIZE: + p = "Bad message size"; + break; + case WSAEPROTOTYPE: + p = "Bad protocol"; + break; + case WSAENOPROTOOPT: + p = "Protocol option is unsupported"; + break; + case WSAEPROTONOSUPPORT: + p = "Protocol is unsupported"; + break; + case WSAESOCKTNOSUPPORT: + p = "Socket is unsupported"; + break; + case WSAEOPNOTSUPP: + p = "Operation not supported"; + break; + case WSAEAFNOSUPPORT: + p = "Address family not supported"; + break; + case WSAEPFNOSUPPORT: + p = "Protocol family not supported"; + break; + case WSAEADDRINUSE: + p = "Address already in use"; + break; + case WSAEADDRNOTAVAIL: + p = "Address not available"; + break; + case WSAENETDOWN: + p = "Network down"; + break; + case WSAENETUNREACH: + p = "Network unreachable"; + break; + case WSAENETRESET: + p = "Network has been reset"; + break; + case WSAECONNABORTED: + p = "Connection was aborted"; + break; + case WSAECONNRESET: + p = "Connection was reset"; + break; + case WSAENOBUFS: + p = "No buffer space"; + break; + case WSAEISCONN: + p = "Socket is already connected"; + break; + case WSAENOTCONN: + p = "Socket is not connected"; + break; + case WSAESHUTDOWN: + p = "Socket has been shut down"; + break; + case WSAETOOMANYREFS: + p = "Too many references"; + break; + case WSAETIMEDOUT: + p = "Timed out"; + break; + case WSAECONNREFUSED: + p = "Connection refused"; + break; + case WSAELOOP: + p = "Loop??"; + break; + case WSAENAMETOOLONG: + p = "Name too long"; + break; + case WSAEHOSTDOWN: + p = "Host down"; + break; + case WSAEHOSTUNREACH: + p = "Host unreachable"; + break; + case WSAENOTEMPTY: + p = "Not empty"; + break; + case WSAEPROCLIM: + p = "Process limit reached"; + break; + case WSAEUSERS: + p = "Too many users"; + break; + case WSAEDQUOT: + p = "Bad quota"; + break; + case WSAESTALE: + p = "Something is stale"; + break; + case WSAEREMOTE: + p = "Remote error"; + break; +#ifdef WSAEDISCON /* missing in SalfordC! */ + case WSAEDISCON: + p = "Disconnected"; + break; +#endif + /* Extended Winsock errors */ + case WSASYSNOTREADY: + p = "Winsock library is not ready"; + break; + case WSANOTINITIALISED: + p = "Winsock library not initialised"; + break; + case WSAVERNOTSUPPORTED: + p = "Winsock version not supported"; + break; + + /* getXbyY() errors (already handled in herrmsg): + * Authoritative Answer: Host not found */ + case WSAHOST_NOT_FOUND: + p = "Host not found"; + break; + + /* Non-Authoritative: Host not found, or SERVERFAIL */ + case WSATRY_AGAIN: + p = "Host not found, try again"; + break; + + /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + case WSANO_RECOVERY: + p = "Unrecoverable error in call to nameserver"; + break; + + /* Valid name, no data record of requested type */ + case WSANO_DATA: + p = "No data record of requested type"; + break; + + default: + return NULL; + } +#else + if(!err) + return NULL; + else + p = "error"; +#endif + strncpy(buf, p, len); + buf [len-1] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} +#endif /* USE_WINSOCK */ + +/* + * Our thread-safe and smart strerror() replacement. + * + * The 'err' argument passed in to this function MUST be a true errno number + * as reported on this system. We do no range checking on the number before + * we pass it to the "number-to-message" conversion function and there might + * be systems that don't do proper range checking in there themselves. + * + * We don't do range checking (on systems other than Windows) since there is + * no good reliable and portable way to do it. + */ +const char *Curl_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + char *p; + size_t max; + + DEBUGASSERT(err >= 0); + + max = buflen - 1; + *buf = '\0'; + +#ifdef USE_WINSOCK + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL); + wcstombs(buf, wbuf, max); + } +#else + /* 'sys_nerr' is the maximum errno number, it is not widely portable */ + if(err >= 0 && err < sys_nerr) + strncpy(buf, strerror(err), max); + else { + if(!get_winsock_error(err, buf, max) && + !FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, + LANG_NEUTRAL, buf, (DWORD)max, NULL)) + msnprintf(buf, max, "Unknown error %d (%#x)", err, err); + } +#endif + +#else /* not USE_WINSOCK coming up */ + +#if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) + /* + * The POSIX-style strerror_r() may set errno to ERANGE if insufficient + * storage is supplied via 'strerrbuf' and 'buflen' to hold the generated + * message string, or EINVAL if 'errnum' is not a valid error number. + */ + if(0 != strerror_r(err, buf, max)) { + if('\0' == buf[0]) + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_GLIBC_STRERROR_R) + /* + * The glibc-style strerror_r() only *might* use the buffer we pass to + * the function, but it always returns the error message as a pointer, + * so we must copy that string unconditionally (if non-NULL). + */ + { + char buffer[256]; + char *msg = strerror_r(err, buffer, sizeof(buffer)); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#elif defined(HAVE_STRERROR_R) && defined(HAVE_VXWORKS_STRERROR_R) + /* + * The vxworks-style strerror_r() does use the buffer we pass to the function. + * The buffer size should be at least NAME_MAX (256) + */ + { + char buffer[256]; + if(OK == strerror_r(err, buffer)) + strncpy(buf, buffer, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#else + { + char *msg = strerror(err); + if(msg) + strncpy(buf, msg, max); + else + msnprintf(buf, max, "Unknown error %d", err); + } +#endif + +#endif /* end of ! USE_WINSOCK */ + + buf[max] = '\0'; /* make sure the string is zero terminated */ + + /* strip trailing '\r\n' or '\n'. */ + p = strrchr(buf, '\n'); + if(p && (p - buf) >= 2) + *p = '\0'; + p = strrchr(buf, '\r'); + if(p && (p - buf) >= 1) + *p = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} + +#ifdef USE_WINDOWS_SSPI +const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + const char *txt; + char *outbuf; + size_t outmax; +#ifndef CURL_DISABLE_VERBOSE_STRINGS + char txtbuf[80]; + char msgbuf[256]; + char *p, *str, *msg = NULL; + bool msg_formatted = FALSE; +#endif + + outbuf = buf; + outmax = buflen - 1; + *outbuf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + + switch(err) { + case SEC_E_OK: + txt = "No error"; + break; + case CRYPT_E_REVOKED: + txt = "CRYPT_E_REVOKED"; + break; + case SEC_E_ALGORITHM_MISMATCH: + txt = "SEC_E_ALGORITHM_MISMATCH"; + break; + case SEC_E_BAD_BINDINGS: + txt = "SEC_E_BAD_BINDINGS"; + break; + case SEC_E_BAD_PKGID: + txt = "SEC_E_BAD_PKGID"; + break; + case SEC_E_BUFFER_TOO_SMALL: + txt = "SEC_E_BUFFER_TOO_SMALL"; + break; + case SEC_E_CANNOT_INSTALL: + txt = "SEC_E_CANNOT_INSTALL"; + break; + case SEC_E_CANNOT_PACK: + txt = "SEC_E_CANNOT_PACK"; + break; + case SEC_E_CERT_EXPIRED: + txt = "SEC_E_CERT_EXPIRED"; + break; + case SEC_E_CERT_UNKNOWN: + txt = "SEC_E_CERT_UNKNOWN"; + break; + case SEC_E_CERT_WRONG_USAGE: + txt = "SEC_E_CERT_WRONG_USAGE"; + break; + case SEC_E_CONTEXT_EXPIRED: + txt = "SEC_E_CONTEXT_EXPIRED"; + break; + case SEC_E_CROSSREALM_DELEGATION_FAILURE: + txt = "SEC_E_CROSSREALM_DELEGATION_FAILURE"; + break; + case SEC_E_CRYPTO_SYSTEM_INVALID: + txt = "SEC_E_CRYPTO_SYSTEM_INVALID"; + break; + case SEC_E_DECRYPT_FAILURE: + txt = "SEC_E_DECRYPT_FAILURE"; + break; + case SEC_E_DELEGATION_POLICY: + txt = "SEC_E_DELEGATION_POLICY"; + break; + case SEC_E_DELEGATION_REQUIRED: + txt = "SEC_E_DELEGATION_REQUIRED"; + break; + case SEC_E_DOWNGRADE_DETECTED: + txt = "SEC_E_DOWNGRADE_DETECTED"; + break; + case SEC_E_ENCRYPT_FAILURE: + txt = "SEC_E_ENCRYPT_FAILURE"; + break; + case SEC_E_ILLEGAL_MESSAGE: + txt = "SEC_E_ILLEGAL_MESSAGE"; + break; + case SEC_E_INCOMPLETE_CREDENTIALS: + txt = "SEC_E_INCOMPLETE_CREDENTIALS"; + break; + case SEC_E_INCOMPLETE_MESSAGE: + txt = "SEC_E_INCOMPLETE_MESSAGE"; + break; + case SEC_E_INSUFFICIENT_MEMORY: + txt = "SEC_E_INSUFFICIENT_MEMORY"; + break; + case SEC_E_INTERNAL_ERROR: + txt = "SEC_E_INTERNAL_ERROR"; + break; + case SEC_E_INVALID_HANDLE: + txt = "SEC_E_INVALID_HANDLE"; + break; + case SEC_E_INVALID_PARAMETER: + txt = "SEC_E_INVALID_PARAMETER"; + break; + case SEC_E_INVALID_TOKEN: + txt = "SEC_E_INVALID_TOKEN"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED: + txt = "SEC_E_ISSUING_CA_UNTRUSTED"; + break; + case SEC_E_ISSUING_CA_UNTRUSTED_KDC: + txt = "SEC_E_ISSUING_CA_UNTRUSTED_KDC"; + break; + case SEC_E_KDC_CERT_EXPIRED: + txt = "SEC_E_KDC_CERT_EXPIRED"; + break; + case SEC_E_KDC_CERT_REVOKED: + txt = "SEC_E_KDC_CERT_REVOKED"; + break; + case SEC_E_KDC_INVALID_REQUEST: + txt = "SEC_E_KDC_INVALID_REQUEST"; + break; + case SEC_E_KDC_UNABLE_TO_REFER: + txt = "SEC_E_KDC_UNABLE_TO_REFER"; + break; + case SEC_E_KDC_UNKNOWN_ETYPE: + txt = "SEC_E_KDC_UNKNOWN_ETYPE"; + break; + case SEC_E_LOGON_DENIED: + txt = "SEC_E_LOGON_DENIED"; + break; + case SEC_E_MAX_REFERRALS_EXCEEDED: + txt = "SEC_E_MAX_REFERRALS_EXCEEDED"; + break; + case SEC_E_MESSAGE_ALTERED: + txt = "SEC_E_MESSAGE_ALTERED"; + break; + case SEC_E_MULTIPLE_ACCOUNTS: + txt = "SEC_E_MULTIPLE_ACCOUNTS"; + break; + case SEC_E_MUST_BE_KDC: + txt = "SEC_E_MUST_BE_KDC"; + break; + case SEC_E_NOT_OWNER: + txt = "SEC_E_NOT_OWNER"; + break; + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + txt = "SEC_E_NO_AUTHENTICATING_AUTHORITY"; + break; + case SEC_E_NO_CREDENTIALS: + txt = "SEC_E_NO_CREDENTIALS"; + break; + case SEC_E_NO_IMPERSONATION: + txt = "SEC_E_NO_IMPERSONATION"; + break; + case SEC_E_NO_IP_ADDRESSES: + txt = "SEC_E_NO_IP_ADDRESSES"; + break; + case SEC_E_NO_KERB_KEY: + txt = "SEC_E_NO_KERB_KEY"; + break; + case SEC_E_NO_PA_DATA: + txt = "SEC_E_NO_PA_DATA"; + break; + case SEC_E_NO_S4U_PROT_SUPPORT: + txt = "SEC_E_NO_S4U_PROT_SUPPORT"; + break; + case SEC_E_NO_TGT_REPLY: + txt = "SEC_E_NO_TGT_REPLY"; + break; + case SEC_E_OUT_OF_SEQUENCE: + txt = "SEC_E_OUT_OF_SEQUENCE"; + break; + case SEC_E_PKINIT_CLIENT_FAILURE: + txt = "SEC_E_PKINIT_CLIENT_FAILURE"; + break; + case SEC_E_PKINIT_NAME_MISMATCH: + txt = "SEC_E_PKINIT_NAME_MISMATCH"; + break; + case SEC_E_POLICY_NLTM_ONLY: + txt = "SEC_E_POLICY_NLTM_ONLY"; + break; + case SEC_E_QOP_NOT_SUPPORTED: + txt = "SEC_E_QOP_NOT_SUPPORTED"; + break; + case SEC_E_REVOCATION_OFFLINE_C: + txt = "SEC_E_REVOCATION_OFFLINE_C"; + break; + case SEC_E_REVOCATION_OFFLINE_KDC: + txt = "SEC_E_REVOCATION_OFFLINE_KDC"; + break; + case SEC_E_SECPKG_NOT_FOUND: + txt = "SEC_E_SECPKG_NOT_FOUND"; + break; + case SEC_E_SECURITY_QOS_FAILED: + txt = "SEC_E_SECURITY_QOS_FAILED"; + break; + case SEC_E_SHUTDOWN_IN_PROGRESS: + txt = "SEC_E_SHUTDOWN_IN_PROGRESS"; + break; + case SEC_E_SMARTCARD_CERT_EXPIRED: + txt = "SEC_E_SMARTCARD_CERT_EXPIRED"; + break; + case SEC_E_SMARTCARD_CERT_REVOKED: + txt = "SEC_E_SMARTCARD_CERT_REVOKED"; + break; + case SEC_E_SMARTCARD_LOGON_REQUIRED: + txt = "SEC_E_SMARTCARD_LOGON_REQUIRED"; + break; + case SEC_E_STRONG_CRYPTO_NOT_SUPPORTED: + txt = "SEC_E_STRONG_CRYPTO_NOT_SUPPORTED"; + break; + case SEC_E_TARGET_UNKNOWN: + txt = "SEC_E_TARGET_UNKNOWN"; + break; + case SEC_E_TIME_SKEW: + txt = "SEC_E_TIME_SKEW"; + break; + case SEC_E_TOO_MANY_PRINCIPALS: + txt = "SEC_E_TOO_MANY_PRINCIPALS"; + break; + case SEC_E_UNFINISHED_CONTEXT_DELETED: + txt = "SEC_E_UNFINISHED_CONTEXT_DELETED"; + break; + case SEC_E_UNKNOWN_CREDENTIALS: + txt = "SEC_E_UNKNOWN_CREDENTIALS"; + break; + case SEC_E_UNSUPPORTED_FUNCTION: + txt = "SEC_E_UNSUPPORTED_FUNCTION"; + break; + case SEC_E_UNSUPPORTED_PREAUTH: + txt = "SEC_E_UNSUPPORTED_PREAUTH"; + break; + case SEC_E_UNTRUSTED_ROOT: + txt = "SEC_E_UNTRUSTED_ROOT"; + break; + case SEC_E_WRONG_CREDENTIAL_HANDLE: + txt = "SEC_E_WRONG_CREDENTIAL_HANDLE"; + break; + case SEC_E_WRONG_PRINCIPAL: + txt = "SEC_E_WRONG_PRINCIPAL"; + break; + case SEC_I_COMPLETE_AND_CONTINUE: + txt = "SEC_I_COMPLETE_AND_CONTINUE"; + break; + case SEC_I_COMPLETE_NEEDED: + txt = "SEC_I_COMPLETE_NEEDED"; + break; + case SEC_I_CONTEXT_EXPIRED: + txt = "SEC_I_CONTEXT_EXPIRED"; + break; + case SEC_I_CONTINUE_NEEDED: + txt = "SEC_I_CONTINUE_NEEDED"; + break; + case SEC_I_INCOMPLETE_CREDENTIALS: + txt = "SEC_I_INCOMPLETE_CREDENTIALS"; + break; + case SEC_I_LOCAL_LOGON: + txt = "SEC_I_LOCAL_LOGON"; + break; + case SEC_I_NO_LSA_CONTEXT: + txt = "SEC_I_NO_LSA_CONTEXT"; + break; + case SEC_I_RENEGOTIATE: + txt = "SEC_I_RENEGOTIATE"; + break; + case SEC_I_SIGNATURE_NEEDED: + txt = "SEC_I_SIGNATURE_NEEDED"; + break; + default: + txt = "Unknown error"; + } + + if(err == SEC_E_OK) + strncpy(outbuf, txt, outmax); + else if(err == SEC_E_ILLEGAL_MESSAGE) + msnprintf(outbuf, outmax, + "SEC_E_ILLEGAL_MESSAGE (0x%08X) - This error usually occurs " + "when a fatal SSL/TLS alert is received (e.g. handshake failed)." + " More detail may be available in the Windows System event log.", + err); + else { + str = txtbuf; + msnprintf(txtbuf, sizeof(txtbuf), "%s (0x%08X)", txt, err); + txtbuf[sizeof(txtbuf)-1] = '\0'; + +#ifdef _WIN32_WCE + { + wchar_t wbuf[256]; + wbuf[0] = L'\0'; + + if(FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + wbuf, sizeof(wbuf)/sizeof(wchar_t), NULL)) { + wcstombs(msgbuf, wbuf, sizeof(msgbuf)-1); + msg_formatted = TRUE; + } + } +#else + if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, err, LANG_NEUTRAL, + msgbuf, sizeof(msgbuf)-1, NULL)) { + msg_formatted = TRUE; + } +#endif + if(msg_formatted) { + msgbuf[sizeof(msgbuf)-1] = '\0'; + /* strip trailing '\r\n' or '\n' */ + p = strrchr(msgbuf, '\n'); + if(p && (p - msgbuf) >= 2) + *p = '\0'; + p = strrchr(msgbuf, '\r'); + if(p && (p - msgbuf) >= 1) + *p = '\0'; + msg = msgbuf; + } + if(msg) + msnprintf(outbuf, outmax, "%s - %s", str, msg); + else + strncpy(outbuf, str, outmax); + } + +#else + + if(err == SEC_E_OK) + txt = "No error"; + else + txt = "Error"; + + strncpy(outbuf, txt, outmax); + +#endif + + outbuf[outmax] = '\0'; + + if(errno != old_errno) + errno = old_errno; + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return outbuf; +} +#endif /* USE_WINDOWS_SSPI */ diff --git a/external/curl prx/src/version.c b/external/curl prx/src/version.c new file mode 100644 index 0000000..5808f7c --- /dev/null +++ b/external/curl prx/src/version.c @@ -0,0 +1,463 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +#include "curl_setup.h" + +#include +#include "urldata.h" +#include "vtls/vtls.h" +#include "http2.h" +#include "ssh.h" +#include "curl_printf.h" + +#ifdef USE_ARES +# if defined(CURL_STATICLIB) && !defined(CARES_STATICLIB) && \ + (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) +# define CARES_STATICLIB +# endif +# include +#endif + +#ifdef USE_LIBIDN2 +#include +#endif + +#ifdef USE_LIBPSL +#include +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#include +#endif + +#ifdef USE_LIBRTMP +#include +#endif + +#ifdef USE_LIBSSH2 +#include +#endif + +#ifdef HAVE_LIBSSH2_VERSION +/* get it run-time if possible */ +#define CURL_LIBSSH2_VERSION libssh2_version(0) +#else +/* use build-time if run-time not possible */ +#define CURL_LIBSSH2_VERSION LIBSSH2_VERSION +#endif + +#ifdef HAVE_ZLIB_H +#include +#ifdef __SYMBIAN32__ +/* zlib pollutes the namespace with this definition */ +#undef WIN32 +#endif +#endif + +#ifdef HAVE_BROTLI +#include +#endif + +void Curl_version_init(void); + +/* For thread safety purposes this function is called by global_init so that + the static data in both version functions is initialized. */ +void Curl_version_init(void) +{ + curl_version(); + curl_version_info(CURLVERSION_NOW); +} + +#ifdef HAVE_BROTLI +static size_t brotli_version(char *buf, size_t bufsz) +{ + uint32_t brotli_version = BrotliDecoderVersion(); + unsigned int major = brotli_version >> 24; + unsigned int minor = (brotli_version & 0x00FFFFFF) >> 12; + unsigned int patch = brotli_version & 0x00000FFF; + + return msnprintf(buf, bufsz, "%u.%u.%u", major, minor, patch); +} +#endif + +char *curl_version(void) +{ + static bool initialized; + static char version[200]; + char *ptr = version; + size_t len; + size_t left = sizeof(version); + + if(initialized) + return version; + + strcpy(ptr, LIBCURL_NAME "/" LIBCURL_VERSION); + len = strlen(ptr); + left -= len; + ptr += len; + + if(left > 1) { + len = Curl_ssl_version(ptr + 1, left - 1); + + if(len > 0) { + *ptr = ' '; + left -= ++len; + ptr += len; + } + } + +#ifdef HAVE_LIBZ + len = msnprintf(ptr, left, " zlib/%s", zlibVersion()); + left -= len; + ptr += len; +#endif +#ifdef HAVE_BROTLI + len = msnprintf(ptr, left, "%s", " brotli/"); + left -= len; + ptr += len; + len = brotli_version(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_ARES + /* this function is only present in c-ares, not in the original ares */ + len = msnprintf(ptr, left, " c-ares/%s", ares_version(NULL)); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBIDN2 + if(idn2_check_version(IDN2_VERSION)) { + len = msnprintf(ptr, left, " libidn2/%s", idn2_check_version(NULL)); + left -= len; + ptr += len; + } +#endif +#ifdef USE_LIBPSL + len = msnprintf(ptr, left, " libpsl/%s", psl_get_version()); + left -= len; + ptr += len; +#endif +#ifdef USE_WIN32_IDN + len = msnprintf(ptr, left, " WinIDN"); + left -= len; + ptr += len; +#endif +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + len = msnprintf(ptr, left, " iconv/%d.%d", + _LIBICONV_VERSION >> 8, _LIBICONV_VERSION & 255); +#else + /* version unknown */ + len = msnprintf(ptr, left, " iconv"); +#endif /* _LIBICONV_VERSION */ + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH2 + len = msnprintf(ptr, left, " libssh2/%s", CURL_LIBSSH2_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBSSH + len = msnprintf(ptr, left, " libssh/%s", CURL_LIBSSH_VERSION); + left -= len; + ptr += len; +#endif +#ifdef USE_NGHTTP2 + len = Curl_http2_ver(ptr, left); + left -= len; + ptr += len; +#endif +#ifdef USE_LIBRTMP + { + char suff[2]; + if(RTMP_LIB_VERSION & 0xff) { + suff[0] = (RTMP_LIB_VERSION & 0xff) + 'a' - 1; + suff[1] = '\0'; + } + else + suff[0] = '\0'; + + msnprintf(ptr, left, " librtmp/%d.%d%s", + RTMP_LIB_VERSION >> 16, (RTMP_LIB_VERSION >> 8) & 0xff, + suff); +/* + If another lib version is added below this one, this code would + also have to do: + + len = what msnprintf() returned + + left -= len; + ptr += len; +*/ + } +#endif + + /* Silent scan-build even if librtmp is not enabled. */ + (void) left; + (void) ptr; + + initialized = true; + return version; +} + +/* data for curl_version_info + + Keep the list sorted alphabetically. It is also written so that each + protocol line has its own #if line to make things easier on the eye. + */ + +static const char * const protocols[] = { +#ifndef CURL_DISABLE_DICT + "dict", +#endif +#ifndef CURL_DISABLE_FILE + "file", +#endif +#ifndef CURL_DISABLE_FTP + "ftp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_FTP) + "ftps", +#endif +#ifndef CURL_DISABLE_GOPHER + "gopher", +#endif +#ifndef CURL_DISABLE_HTTP + "http", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP) + "https", +#endif +#ifndef CURL_DISABLE_IMAP + "imap", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_IMAP) + "imaps", +#endif +#ifndef CURL_DISABLE_LDAP + "ldap", +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + "ldaps", +#endif +#endif +#ifndef CURL_DISABLE_POP3 + "pop3", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_POP3) + "pop3s", +#endif +#ifdef USE_LIBRTMP + "rtmp", +#endif +#ifndef CURL_DISABLE_RTSP + "rtsp", +#endif +#if defined(USE_LIBSSH) || defined(USE_LIBSSH2) + "scp", + "sftp", +#endif +#if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \ + (CURL_SIZEOF_CURL_OFF_T > 4) && \ + (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)) + "smb", +# ifdef USE_SSL + "smbs", +# endif +#endif +#ifndef CURL_DISABLE_SMTP + "smtp", +#endif +#if defined(USE_SSL) && !defined(CURL_DISABLE_SMTP) + "smtps", +#endif +#ifndef CURL_DISABLE_TELNET + "telnet", +#endif +#ifndef CURL_DISABLE_TFTP + "tftp", +#endif + + NULL +}; + +static curl_version_info_data version_info = { + CURLVERSION_NOW, + LIBCURL_VERSION, + LIBCURL_VERSION_NUM, + "ORBISOS", /* as found by configure or set by hand at build-time */ + 0 /* features is 0 by default */ +#ifdef ENABLE_IPV6 + | CURL_VERSION_IPV6 +#endif +#ifdef USE_SSL + | CURL_VERSION_SSL +#endif +#ifdef USE_NTLM + | CURL_VERSION_NTLM +#endif +#if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \ + defined(NTLM_WB_ENABLED) + | CURL_VERSION_NTLM_WB +#endif +#ifdef USE_SPNEGO + | CURL_VERSION_SPNEGO +#endif +#ifdef USE_KERBEROS5 + | CURL_VERSION_KERBEROS5 +#endif +#ifdef HAVE_GSSAPI + | CURL_VERSION_GSSAPI +#endif +#ifdef USE_WINDOWS_SSPI + | CURL_VERSION_SSPI +#endif +#ifdef HAVE_LIBZ + | CURL_VERSION_LIBZ +#endif +#ifdef DEBUGBUILD + | CURL_VERSION_DEBUG +#endif +#ifdef CURLDEBUG + | CURL_VERSION_CURLDEBUG +#endif +#ifdef CURLRES_ASYNCH + | CURL_VERSION_ASYNCHDNS +#endif +#if (CURL_SIZEOF_CURL_OFF_T > 4) && \ + ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) + | CURL_VERSION_LARGEFILE +#endif +#if defined(CURL_DOES_CONVERSIONS) + | CURL_VERSION_CONV +#endif +#if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP +#endif +#if defined(USE_NGHTTP2) + | CURL_VERSION_HTTP2 +#endif +#if defined(USE_UNIX_SOCKETS) + | CURL_VERSION_UNIX_SOCKETS +#endif +#if defined(USE_LIBPSL) + | CURL_VERSION_PSL +#endif +#if defined(CURL_WITH_MULTI_SSL) + | CURL_VERSION_MULTI_SSL +#endif +#if defined(HAVE_BROTLI) + | CURL_VERSION_BROTLI +#endif +#if defined(USE_ALTSVC) + | CURL_VERSION_ALTSVC +#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num, this is kept at zero */ + NULL, /* zlib_version */ + protocols, + NULL, /* c-ares version */ + 0, /* c-ares version numerical */ + NULL, /* libidn version */ + 0, /* iconv version */ + NULL, /* ssh lib version */ + 0, /* brotli_ver_num */ + NULL, /* brotli version */ +}; + +curl_version_info_data *curl_version_info(CURLversion stamp) +{ + static bool initialized; +#if defined(USE_LIBSSH) || defined(USE_LIBSSH2) + static char ssh_buffer[80]; +#endif +#ifdef USE_SSL + static char ssl_buffer[80]; +#endif +#ifdef HAVE_BROTLI + static char brotli_buffer[80]; +#endif + + if(initialized) + return &version_info; + +#ifdef USE_SSL + Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer)); + version_info.ssl_version = ssl_buffer; + if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY) + version_info.features |= CURL_VERSION_HTTPS_PROXY; + else + version_info.features &= ~CURL_VERSION_HTTPS_PROXY; +#endif + +#ifdef HAVE_LIBZ + version_info.libz_version = zlibVersion(); + /* libz left NULL if non-existing */ +#endif +#ifdef USE_ARES + { + int aresnum; + version_info.ares = ares_version(&aresnum); + version_info.ares_num = aresnum; + } +#endif +#ifdef USE_LIBIDN2 + /* This returns a version string if we use the given version or later, + otherwise it returns NULL */ + version_info.libidn = idn2_check_version(IDN2_VERSION); + if(version_info.libidn) + version_info.features |= CURL_VERSION_IDN; +#elif defined(USE_WIN32_IDN) + version_info.features |= CURL_VERSION_IDN; +#endif + +#if defined(HAVE_ICONV) && defined(CURL_DOES_CONVERSIONS) +#ifdef _LIBICONV_VERSION + version_info.iconv_ver_num = _LIBICONV_VERSION; +#else + /* version unknown */ + version_info.iconv_ver_num = -1; +#endif /* _LIBICONV_VERSION */ +#endif + +#if defined(USE_LIBSSH2) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh2/%s", LIBSSH2_VERSION); + version_info.libssh_version = ssh_buffer; +#elif defined(USE_LIBSSH) + msnprintf(ssh_buffer, sizeof(ssh_buffer), "libssh/%s", CURL_LIBSSH_VERSION); + version_info.libssh_version = ssh_buffer; +#endif + +#ifdef HAVE_BROTLI + version_info.brotli_ver_num = BrotliDecoderVersion(); + brotli_version(brotli_buffer, sizeof(brotli_buffer)); + version_info.brotli_version = brotli_buffer; +#endif + + (void)stamp; /* avoid compiler warnings, we don't use this */ + + initialized = true; + return &version_info; +} diff --git a/external/libdumper/LICENSE b/external/libdumper/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/external/libdumper/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/external/libdumper/Makefile b/external/libdumper/Makefile new file mode 100644 index 0000000..64e7638 --- /dev/null +++ b/external/libdumper/Makefile @@ -0,0 +1,23 @@ +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target := ps4_lib +OutPath := lib +TargetFile := libdumper +AllTarget = $(OutPath)/$(TargetFile).a + +include $(ORBISDEV)/make/ps4sdklib.mk +CompilerFlagsCpp += -std=c++17 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -D__ORBIS__=1 -D_ORBIS_ -DNDEBUG -D_BSD_SOURCE -fexceptions -frtti +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -Iinclude + + +$(OutPath)/$(TargetFile).a: $(ObjectFiles) + $(dirp) + $(archive) + +install: + @cp $(OutPath)/$(TargetFile).a $(DESTDIR)$(ORBISDEV)/usr/lib + @cp include/dumper.h $(DESTDIR)$(ORBISDEV)/usr/include + @echo "$(TargetFile) Installed!" + diff --git a/external/libdumper/README.md b/external/libdumper/README.md new file mode 100644 index 0000000..5541b8a --- /dev/null +++ b/external/libdumper/README.md @@ -0,0 +1,37 @@ +# dumper-testing + +Rewriting PS4 application dumper from scratch in C++. This repo will be deleted when a permanent repo is setup. Don't bother cloning unless you're going to be making immediate changes. + +**No code here is finished or guaranteed to work.** Goal is for readability first to allow easier collaboration until everything is working 100%, don't want to optimize it too early: + +1. Get it all working. For the first draft we will assume the asset is completely installed and is currently running on the system. +2. Refactor to make more sense. +3. More robust. Find/fix edge cases and have good, descriptive, error messages for issues that cannot be handled automatically. +4. Setup tests so we don't break anything trying to enhance preformance. +5. Performance. + +> "Move fast break things" + +**ANYONE** can contribute. Code is currently licensed under GPLv3, by submitting a pull request you agree to this term and agree to possible relicensing later. + +## Approximate order of completion +- [X] PKG +- [X] NpBind +- [X] SFO +- [X] PFS +- [X] Decrypt SELF +- [ ] FSELF +- [ ] RIF (For Additional Content w/o Data & Entitlment Keys) +- [ ] Dump + - [X] Base + - [X] Patch + - [X] Additional Content w/ Data + - [X] Theme + - [X] Retail Theme + Theme "Unlock" + - [X] Remaster (Build a script to diff the actual files with the original content PC side to make a patch PKG vs a Remaster?) + - [ ] Additional Content w/o Data + - [ ] Multi-Disc (Does it just work without changes?) +- [ ] GP4 + - [X] Basic GP4 Generation + - [ ] PlayGo Related Issues + - [ ] PFS Compress Option diff --git a/external/libdumper/include/common.hpp b/external/libdumper/include/common.hpp new file mode 100644 index 0000000..a027ef4 --- /dev/null +++ b/external/libdumper/include/common.hpp @@ -0,0 +1,37 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef COMMON_HPP_ +#define COMMON_HPP_ + +#include +#include +#include +#include "log.h" +#include + +#ifndef PAGE_SIZE +#define PAGE_SIZE 0x4000 +#endif + +#ifndef UNUSED +#define UNUSED(x) (void)(x) +#endif + +typedef enum orbisCommonDialogStatus { + COMMON_DIALOG_STATUS_NONE = 0, + COMMON_DIALOG_STATUS_INITIALIZED = 1, + COMMON_DIALOG_STATUS_RUNNING = 2, + COMMON_DIALOG_STATUS_FINISHED = 3 +} orbisCommonDialogStatus; + + +extern "C" { + extern orbisCommonDialogStatus sceMsgDialogUpdateStatus(void); + extern int32_t sceMsgDialogProgressBarSetMsg(int target, const char* barMsg); + extern int32_t sceMsgDialogProgressBarSetValue(int target, int rate); +} + +void ProgUpdate(int prog, const char* fmt, ...); + +#endif // COMMON_HPP_ diff --git a/external/libdumper/include/dump.hpp b/external/libdumper/include/dump.hpp new file mode 100644 index 0000000..1f271f9 --- /dev/null +++ b/external/libdumper/include/dump.hpp @@ -0,0 +1,14 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef DUMP_HPP_ +#define DUMP_HPP_ + +#include +#include "dumper.h" + +namespace dump { +bool __dump(const std::string& usb_device, const std::string& title_id, Dump_Options opt, const std::string& title); +} // namespace dump + +#endif // DUMP_HPP_ diff --git a/external/libdumper/include/dumper.h b/external/libdumper/include/dumper.h new file mode 100644 index 0000000..b22a83b --- /dev/null +++ b/external/libdumper/include/dumper.h @@ -0,0 +1,20 @@ +#pragma once +#ifndef DUMPER_H_ +#define DUMPER_H_ + +#include + +typedef enum Dump_Options { + BASE_GAME = 1, + GAME_PATCH = 2, + REMASTER = 3, + THEME = 4, + THEME_UNLOCK = 5, + ADDITIONAL_CONTENT_DATA = 6, + ADDITIONAL_CONTENT_NO_DATA = 7, + TOTAL_OF_OPTS = 7 +} Dump_Options; + +bool Dumper(std::string &dump_path, std::string &title_id, Dump_Options opt, std::string &title); + +#endif // RAYLIB_TILESON_H_ \ No newline at end of file diff --git a/external/libdumper/include/elf.hpp b/external/libdumper/include/elf.hpp new file mode 100644 index 0000000..4000871 --- /dev/null +++ b/external/libdumper/include/elf.hpp @@ -0,0 +1,123 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef ELF_HPP_ +#define ELF_HPP_ + +#include "elf_64.hpp" +#include "elf_common.hpp" + +#include "log.h" +#include +#include + +#define ELF_MAGIC 0x7F454C46 +#define SELF_MAGIC 0x4F153D1D + +#define MAP_SELF 0x80000 +#define PT_NID 0x61000000 + + +typedef struct _dirdesc { + int dd_fd; /* file descriptor associated with directory */ + long dd_loc; /* offset in current buffer */ + long dd_size; /* amount of data returned by getdirentries */ + char* dd_buf; /* data buffer */ + int dd_len; /* size of data buffer */ + long dd_seek; /* magic cookie returned by getdirentries */ + long dd_rewind; /* magic cookie for rewinding */ + int dd_flags; /* flags for readdir */ + struct pthread_mutex* dd_lock; /* lock */ + struct _telldir* dd_td; +} DIR; + +extern "C" +{ + extern struct dirent* readdir(DIR* dirp); + extern int closedir(DIR* dirp); + extern DIR* opendir(const char* filename); +} + + +namespace elf { + typedef struct { + uint32_t props; + uint32_t reserved; + uint64_t offset; + uint64_t file_size; + uint64_t memory_size; + } SelfEntry; + + // SELF Header from: https://www.psdevwiki.com/ps4/SELF_File_Format#SELF_Header_Structure + typedef struct { + uint32_t magic; /* File magic. */ + + // uint32_t unknown; /* Always 00 01 01 12. */ + uint8_t version; + uint8_t mode; + uint8_t endian; + uint8_t attr; + + unsigned char content_type; /* 1 on Self, 4 on PUP Entry. */ + unsigned char program_type; /* 0x0 PUP, 0x8 NPDRM Application, 0x9 PLUGIN, 0xC Kernel, 0xE Security Module, 0xF Secure Kernel */ + uint16_t padding; /* Padding. */ + uint16_t header_size; /* Header size. */ + uint16_t signature_size; /* Metadata size */ + uint64_t self_size; /* Size of SELF. */ + uint16_t num_of_segments; /* Number of Segments, 1 Kernel, 2 SL and Modules, 4 Kernel ELFs, 6 .selfs, 2 .sdll, 6 .sprx, 6 ShellCore, 6 eboot.bin, 2 sexe. */ + uint16_t flags; /* Always 0x22. */ + uint32_t reserved; /* Reserved. */ + } SelfHeader; + + // SCE Header from: https://www.psdevwiki.com/ps4/SELF_File_Format#SCE_Special + typedef struct { + uint64_t program_authority_id; + uint64_t program_type; + uint64_t app_version; + uint64_t fw_version; + unsigned char digest[0x20]; + } SceHeader; + + // SCE Header from: https://www.psdevwiki.com/ps4/SELF_File_Format#SCE_Special + typedef struct { + uint64_t program_authority_id; + uint64_t program_type; + uint64_t app_version; + uint64_t fw_version; + unsigned char digest[0x20]; + unsigned char padding[0x10]; // TODO: There is something here besides just padding...? + unsigned char content_id[0x14]; // TODO: Or is it 0x13 if you don't include the "-" + unsigned char unknown[0xC]; // TODO: There appears to be more here...? + } SceHeaderNpdrm; + + typedef struct { + int index; + uint64_t fileoff; + size_t bufsz; + size_t filesz; + int enc; + } SegmentBufInfo; + + +#define TRUE 1 +#define FALSE 0 + +#define DECRYPT_SIZE 0x100000 + + uint64_t get_sce_header_offset(const std::string& path); + SceHeader get_sce_header(const std::string& path); + SceHeaderNpdrm get_sce_header_npdrm(const std::string& path); + bool Check_ELF_Magic(const std::string& path, uint32_t FILE_MAGIC = ELF_MAGIC); + bool is_npdrm(const std::string& path); + std::string get_ptype(const std::string& path); + uint64_t get_paid(const std::string& path); + uint64_t get_app_version(const std::string& path); + uint64_t get_fw_version(const std::string& path); + std::vector get_digest(const std::string& path); + std::vector get_auth_info(const std::string& path); + bool is_valid_decrypt(const std::string& original, const std::string& decrypted); + void zero_section_header(const std::string& path); + bool decrypt_dir(const std::string& input, const std::string& output); +} // namespace elf + +#endif // ELF_HPP_ diff --git a/external/libdumper/include/elf_64.hpp b/external/libdumper/include/elf_64.hpp new file mode 100644 index 0000000..787b547 --- /dev/null +++ b/external/libdumper/include/elf_64.hpp @@ -0,0 +1,250 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: release/9.0.0/sys/sys/elf64.h 186667 2009-01-01 02:08:56Z obrien $ + */ + +#ifndef ELF_64_HPP_ +#define ELF_64_HPP_ + +#include "elf_common.hpp" + +#include + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info)&0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type)&0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info) << 32) >> 40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info) << 56) >> 56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data) << 8) + (Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info) >> 8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info)&0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type)&0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth)&0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif // ELF_STRUCTS_HPP_ diff --git a/external/libdumper/include/elf_common.hpp b/external/libdumper/include/elf_common.hpp new file mode 100644 index 0000000..60d4f06 --- /dev/null +++ b/external/libdumper/include/elf_common.hpp @@ -0,0 +1,967 @@ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: release/9.0.0/sys/sys/elf_common.h 221569 2011-05-07 01:05:31Z obrien $ + */ + +#ifndef ELF_COMMON_HPP_ +#define ELF_COMMON_HPP_ + +#include + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 \ + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit \ + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded \ + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded \ + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent \ + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose \ + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC \ + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller \ + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. \ + and MPRC of Peking University */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared \ + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object \ + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in \ + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to \ + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to \ + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of \ + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of \ + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated \ + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING \ + and less than DT_LOOS follow the rules for \ + the interpretation of the d_un union \ + as follows: even == 'd_ptr', odd == 'd_val' \ + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to \ + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of \ + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may \ + make reference to the $ORIGIN substitution \ + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in \ + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should \ + process all relocations for the object \ + containing this entry before transferring \ + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or \ + executable contains code using a static \ + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ + +#endif // ELF_COMMON_HPP_ diff --git a/external/libdumper/include/fself.hpp b/external/libdumper/include/fself.hpp new file mode 100644 index 0000000..ea20486 --- /dev/null +++ b/external/libdumper/include/fself.hpp @@ -0,0 +1,15 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef FSELF_HPP_ +#define FSELF_HPP_ + +#include +#include + +namespace fself { +bool is_fself(const std::string &path); +void make_fself(const std::string &input, const std::string &output, uint64_t paid, const std::string &ptype, uint64_t app_version, uint64_t fw_version, std::vector auth_info); +} + +#endif // FSELF_HPP_ diff --git a/external/libdumper/include/gp4.hpp b/external/libdumper/include/gp4.hpp new file mode 100644 index 0000000..f6d7d4c --- /dev/null +++ b/external/libdumper/include/gp4.hpp @@ -0,0 +1,25 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef GP4_HPP_ +#define GP4_HPP_ + +#include "pugixml.hpp" +#include "dumper.h" +#include +#include +#include + + +namespace gp4 { +void recursive_directory(const std::string &path, pugi::xml_node &node); +pugi::xml_document make_volume(const std::string &content_id, const std::string &volume_type, std::string c_date = "", std::string c_time = ""); +pugi::xml_document make_playgo(const std::string &playgo_xml); +pugi::xml_document make_files(const std::string& path, std::vector& elf_files, Dump_Options opt); +pugi::xml_document make_directories(const std::string& path); +pugi::xml_document assemble(const pugi::xml_document& volume, const pugi::xml_document& playgo, const pugi::xml_document& files, const pugi::xml_document& directories, const std::string& custom_version = ""); +bool write(const pugi::xml_document& xml, const std::string& path); +bool generate(const std::string& sfo_path, const std::string& output_path, const std::string& gp4_path, std::vector& self_files, Dump_Options opt); +} // namespace gp4 + +#endif // GP4_HPP_ diff --git a/external/libdumper/include/ini.h b/external/libdumper/include/ini.h new file mode 100644 index 0000000..78015d1 --- /dev/null +++ b/external/libdumper/include/ini.h @@ -0,0 +1,157 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef INI_H +#define INI_H + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See https://github.com/benhoyt/inih/issues/21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +/* Nonzero to call the handler at the start of each new section (with + name and value NULL). Default is to only call the handler on + each name=value pair. */ +#ifndef INI_CALL_HANDLER_ON_NEW_SECTION +#define INI_CALL_HANDLER_ON_NEW_SECTION 0 +#endif + +/* Nonzero to allow a name without a value (no '=' or ':' on the line) and + call the handler with value NULL in this case. Default is to treat + no-value lines as an error. */ +#ifndef INI_ALLOW_NO_VALUE +#define INI_ALLOW_NO_VALUE 0 +#endif + +/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory + allocation functions (INI_USE_STACK must also be 0). These functions must + have the same signatures as malloc/free/realloc and behave in a similar + way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */ +#ifndef INI_CUSTOM_ALLOCATOR +#define INI_CUSTOM_ALLOCATOR 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* INI_H */ diff --git a/external/libdumper/include/lang.h b/external/libdumper/include/lang.h new file mode 100644 index 0000000..e0b0487 --- /dev/null +++ b/external/libdumper/include/lang.h @@ -0,0 +1,30 @@ +#pragma once +enum Lang_ST { + DUMP_INFO, + APP_NAME, + TITLE_ID, + DUMPER_SC0, + DUMPING_TROPHIES, + CREATING_GP4, + DEC_BIN, + DEL_SEM, + EXT_PATCH, + EXT_GAME_FILES, + PROCESSING, + + //DO NOT DELETE THIS, ALWAYS KEEP AT THE BOTTOM + LANG_NUM_OF_STRINGS +}; + +typedef struct +{ + char* strings[LANG_NUM_OF_STRINGS]; +} DumperStrings; + + +#define LANG_DIR "/mnt/sandbox/pfsmnt/ITEM00001-app0/langs/%i/lang.ini" + +bool LoadDumperLangs(int LangCode); +char* getDumperLangSTR(enum Lang_ST str); +int32_t DumperGetLang(); +bool load_dumper_embdded_eng(); \ No newline at end of file diff --git a/external/libdumper/include/libshahash.h b/external/libdumper/include/libshahash.h new file mode 100644 index 0000000..80aa825 --- /dev/null +++ b/external/libdumper/include/libshahash.h @@ -0,0 +1,102 @@ +#ifndef _SHAHASH_H +#define _SHAHASH_H + +#include +#include + +#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus) +#if !defined(__LANGUAGE_ASSEMBLY) +extern "C" { +#endif +#endif + +#define BLOCK_BYTE_SIZE 64 +// left rotate +#define lrol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) +#define UNPACK32(x, str) \ +{ \ + *((str) + 3) = (uint8_t) ((x) ); \ + *((str) + 2) = (uint8_t) ((x) >> 8); \ + *((str) + 1) = (uint8_t) ((x) >> 16); \ + *((str) + 0) = (uint8_t) ((x) >> 24); \ +} + +#define PACK32(str, x) \ +{ \ + *(x) = ((uint32_t) *((str) + 3) ) \ + | ((uint32_t) *((str) + 2) << 8) \ + | ((uint32_t) *((str) + 1) << 16) \ + | ((uint32_t) *((str) + 0) << 24); \ +} + +#define SHA256_SCR(i) \ +{ \ + w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \ + + SHA256_F3(w[i - 15]) + w[i - 16]; \ +} + + +#define SHA256_DIGEST_SIZE ( 256 / 8) +#define SHA256_BLOCK_SIZE ( 512 / 8) + +#define SHFR(x, n) (x >> n) +#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n))) +#define CH(x, y, z) ((x & y) ^ (~x & z)) +#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z)) + +#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3)) +#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10)) + + +#define SHA1_ERROR_INVALID_POINTER -2142764288 +#define SHA1_ERROR_INVALID_STATE -2142764287 +#define SHA1_ERROR_UNINITIALIZED_CONTEXT -2142764286 + +#define SHA1_BLOCK_SIZE 64U +#define SHA1_DIGEST_SIZE 20U + +typedef struct Sha1Context { + uint32_t h[5]; + uint16_t usRemains; + uint16_t usComputed; + uint64_t ullTotalLen; + uint8_t buf[SHA1_BLOCK_SIZE]; + uint8_t result[SHA1_DIGEST_SIZE]; + uint8_t initialized; + uint8_t pad[3]; +} Sha1Context; + +typedef struct { + unsigned int tot_len; + unsigned int len; + unsigned char block[2 * SHA256_BLOCK_SIZE]; + uint32_t h[8]; +} SHA256_CTX; + +extern uint32_t sha256_k[64]; + +#if !defined(__LANGUAGE_ASSEMBLY) + +//SHA1 +int32_t Sha1Digest(const void *plain, uint32_t len, uint8_t *digest); +int32_t Sha1BlockInit(Sha1Context *pContext); +int32_t Sha1BlockUpdate(Sha1Context *pContext, const void *plain, uint32_t len); +int32_t Sha1BlockResult(Sha1Context *pContext, uint8_t *digest); + +//SHA256 +void SHA256_Init(SHA256_CTX* ctx); +void SHA256_Update(SHA256_CTX* ctx, const unsigned char* message, unsigned int len); +void SHA256_Final(SHA256_CTX* ctx, unsigned char *digest); +void SHA256(const unsigned char *message, unsigned int len, unsigned char* digest); + +#endif + +#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus) +#if !defined(__LANGUAGE_ASSEMBLY) +} +#endif +#endif + +#endif \ No newline at end of file diff --git a/external/libdumper/include/log.h b/external/libdumper/include/log.h new file mode 100644 index 0000000..7fd4baa --- /dev/null +++ b/external/libdumper/include/log.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2020 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See `log.c` for details. + */ +#pragma once + +#include +#include +#include +#include + +#define LOG_VERSION "0.1.0" + +typedef struct { + va_list ap; + const char* fmt; + const char* file; + struct tm* time; + void* udata; + int line; + int level; +} log_Event; + +typedef void (*log_LogFn)(log_Event* ev); +typedef void (*log_LockFn)(bool lock, void* udata); + +enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; + +#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) +#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) +#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) +#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) + +const char* log_level_string(int level); +void log_set_lock(log_LockFn fn, void* udata); +void log_set_level(int level); +void log_set_quiet(bool enable); +int log_add_callback(log_LogFn fn, void* udata, int level); +int log_add_fp(FILE* fp, int level); + +void log_log(int level, const char* file, int line, const char* fmt, ...); diff --git a/external/libdumper/include/npbind.hpp b/external/libdumper/include/npbind.hpp new file mode 100644 index 0000000..dbaefcf --- /dev/null +++ b/external/libdumper/include/npbind.hpp @@ -0,0 +1,57 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef NPBIND_HPP_ +#define NPBIND_HPP_ + +#include +#include + +#define NPBIND_MAGIC 0xD294A018 + +namespace npbind { +typedef struct { + uint32_t magic; + uint32_t version; + uint64_t file_size; + uint64_t entry_size; + uint64_t num_entries; + char padding[0x60]; +} NpBindHeader; + +typedef struct { + uint16_t type; + uint16_t size; + char data[0xC]; +} NpBindNpCommIdEntry; + +typedef struct { + uint16_t type; + uint16_t size; + char data[0xC]; +} NpBindTrophyNumberEntry; + +typedef struct { + uint16_t type; + uint16_t size; + unsigned char data[0xB0]; +} NpBindUnk1Entry; + +typedef struct { + uint16_t type; + uint16_t size; + unsigned char data[0x10]; +} NpBindUnk2Entry; + +typedef struct { + NpBindNpCommIdEntry npcommid; + NpBindTrophyNumberEntry trophy_number; + NpBindUnk1Entry unk1; + NpBindUnk2Entry unk2; + char padding[0x98]; +} NpBindEntry; + +std::vector read(const std::string &path); // Flawfinder: ignore +} // namespace npbind + +#endif // NPBIND_HPP_ diff --git a/external/libdumper/include/pfs.hpp b/external/libdumper/include/pfs.hpp new file mode 100644 index 0000000..677f665 --- /dev/null +++ b/external/libdumper/include/pfs.hpp @@ -0,0 +1,70 @@ +#ifndef PFS_HPP_ +#define PFS_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#define PFS_MAGIC 0x0B2A330100000000 + +#define PFS_DUMP_BUFFER 0x200000 + +namespace pfs { + typedef struct { + uint64_t version; + uint64_t magic; + uint32_t id[2]; + char fmode; + char clean; + char ronly; + char rsv; + uint16_t mode; + uint16_t unk1; + uint32_t blocksz; + uint32_t nbackup; + uint64_t nblock; + uint64_t ndinode; + uint64_t ndblock; + uint64_t ndinodeblock; + uint64_t superroot_ino; + } pfs_header; + + typedef struct { + uint16_t mode; + uint16_t nlink; + uint32_t flags; + uint64_t size; + uint64_t size_compressed; + uint64_t unix_time[4]; + uint32_t time_nsec[4]; + uint32_t uid; + uint32_t gid; + uint64_t spare[2]; + uint32_t blocks; + uint32_t db[12]; + uint32_t ib[5]; + } di_d32; + + typedef struct { + uint32_t ino; + uint32_t type; + uint32_t namelen; + uint32_t entsize; + } pfs_dirent_t; + + extern pfs_header* header; + extern size_t pfs_size; + extern size_t pfs_copied; + extern di_d32* inodes; + + void __parse_directory(uint32_t ino, uint32_t lev, const char* parent_name, bool dry_run, char* title = NULL, const char* tid = "CUSA0000"); + void calculate_pfs(uint32_t ino, uint32_t level, const std::string& output_path); + void dump_pfs(uint32_t ino, uint32_t level, const std::string& output_path, const char* tid = "CUSA0000", char* title = NULL); + bool extract(const std::string& pfs_path, const std::string& output_path, const char* tid = "CUSA0000", char* title = NULL); +} // namespace pfs + +#endif // PFS_HPP_ diff --git a/external/libdumper/include/pkg.hpp b/external/libdumper/include/pkg.hpp new file mode 100644 index 0000000..b01374e --- /dev/null +++ b/external/libdumper/include/pkg.hpp @@ -0,0 +1,77 @@ +#ifndef PKG_HPP_ +#define PKG_HPP_ + +#include + +#define PKG_MAGIC 0x7F434E54 + +namespace pkg { +// struct from LibOrbisPKG +typedef struct { + uint32_t magic; + uint32_t flags; + uint32_t unk_0x08; + uint32_t unk_0x0C; /* 0xF */ + uint32_t entry_count; + uint16_t sc_entry_count; + uint16_t entry_count_2; /* same as entry_count */ + uint32_t entry_table_offset; + uint32_t main_ent_data_size; + uint64_t body_offset; + uint64_t body_size; + unsigned char padding1[0x10]; + char content_id[0x30]; /* PKG_CONTENT_ID_SIZE */ + uint32_t drm_type; + uint32_t content_type; + uint32_t content_flags; + uint32_t promote_size; + uint32_t version_date; + uint32_t version_hash; + uint32_t unk_0x88; /* for delta patches only? */ + uint32_t unk_0x8C; /* for delta patches only? */ + uint32_t unk_0x90; /* for delta patches only? */ + uint32_t unk_0x94; /* for delta patches only? */ + uint32_t iro_tag; + uint32_t ekc_version; /* drm type version */ + unsigned char padding2[0x60]; + unsigned char sc_entries1_hash[0x20]; //PKG_HASH_SIZE + unsigned char sc_entries2_hash[0x20]; // PKG_HASH_SIZE + unsigned char digest_table_hash[0x20]; // PKG_HASH_SIZE + unsigned char body_digest[0x20]; // PKG_HASH_SIZE + unsigned char padding3[0x280]; + // TODO: I think these fields are actually members of element of container array + uint32_t unk_0x400; + uint32_t pfs_image_count; + uint64_t pfs_flags; + uint64_t pfs_image_offset; + uint64_t pfs_image_size; + uint64_t mount_image_offset; + uint64_t mount_image_size; + uint64_t package_size; + uint32_t pfs_signed_size; + uint32_t pfs_cache_size; + unsigned char pfs_image_digest[0x20]; // PKG_HASH_SIZE + unsigned char pfs_signed_digest[0x20]; // PKG_HASH_SIZE + uint64_t pfs_split_size_nth_0; + uint64_t pfs_split_size_nth_1; + unsigned char padding4[0xB50]; + unsigned char package_digest[32]; + unsigned char package_signature[256]; +} PkgHeader; + +// struct from LibOrbisPKG +typedef struct { + uint32_t id; + uint32_t name_table_offset; + uint32_t flags1; + uint32_t flags2; + uint32_t offset; + uint32_t size; + uint64_t padding; +} PkgTableEntry; + +std::string get_entry_name_by_type(uint32_t type); +bool extract_sc0(const std::string& pkg_path, const std::string& output_path, const std::string& tid, const std::string& title); +} // namespace pkg + +#endif // PKG_HPP_ diff --git a/external/libdumper/include/pugiconfig.hpp b/external/libdumper/include/pugiconfig.hpp new file mode 100644 index 0000000..405a66b --- /dev/null +++ b/external/libdumper/include/pugiconfig.hpp @@ -0,0 +1,77 @@ +/** + * pugixml parser - version 1.11 + * -------------------------------------------------------- + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef HEADER_PUGICONFIG_HPP +#define HEADER_PUGICONFIG_HPP + +// Uncomment this to enable wchar_t mode +// #define PUGIXML_WCHAR_MODE + +// Uncomment this to enable compact mode +// #define PUGIXML_COMPACT + +// Uncomment this to disable XPath +// #define PUGIXML_NO_XPATH + +// Uncomment this to disable STL +// #define PUGIXML_NO_STL + +// Uncomment this to disable exceptions +// #define PUGIXML_NO_EXCEPTIONS + +// Set this to control attributes for public classes/functions, i.e.: +// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL +// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL +// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall +// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead + +// Tune these constants to adjust memory-related behavior +// #define PUGIXML_MEMORY_PAGE_SIZE 32768 +// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 +// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 + +// Tune this constant to adjust max nesting for XPath queries +// #define PUGIXML_XPATH_DEPTH_LIMIT 1024 + +// Uncomment this to switch to header-only version +// #define PUGIXML_HEADER_ONLY + +// Uncomment this to enable long long support +// #define PUGIXML_HAS_LONG_LONG + +#endif + +/** + * Copyright (c) 2006-2020 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/external/libdumper/include/pugixml.hpp b/external/libdumper/include/pugixml.hpp new file mode 100644 index 0000000..ed234fb --- /dev/null +++ b/external/libdumper/include/pugixml.hpp @@ -0,0 +1,1501 @@ +/** + * pugixml parser - version 1.11 + * -------------------------------------------------------- + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef PUGIXML_VERSION +// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons +// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits +# define PUGIXML_VERSION 1110 +#endif + +// Include user configuration file (this can define various configuration macros) +#include "pugiconfig.hpp" + +#ifndef HEADER_PUGIXML_HPP +#define HEADER_PUGIXML_HPP + +// Include stddef.h for size_t and ptrdiff_t +#include + +// Include exception header for XPath +#if !defined(PUGIXML_NO_XPATH) && !defined(PUGIXML_NO_EXCEPTIONS) +# include +#endif + +// Include STL headers +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// Macro for deprecated features +#ifndef PUGIXML_DEPRECATED +# if defined(__GNUC__) +# define PUGIXML_DEPRECATED __attribute__((deprecated)) +# elif defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGIXML_DEPRECATED __declspec(deprecated) +# else +# define PUGIXML_DEPRECATED +# endif +#endif + +// If no API is defined, assume default +#ifndef PUGIXML_API +# define PUGIXML_API +#endif + +// If no API for classes is defined, assume default +#ifndef PUGIXML_CLASS +# define PUGIXML_CLASS PUGIXML_API +#endif + +// If no API for functions is defined, assume default +#ifndef PUGIXML_FUNCTION +# define PUGIXML_FUNCTION PUGIXML_API +#endif + +// If the platform is known to have long long support, enable long long functions +#ifndef PUGIXML_HAS_LONG_LONG +# if __cplusplus >= 201103 +# define PUGIXML_HAS_LONG_LONG +# elif defined(_MSC_VER) && _MSC_VER >= 1400 +# define PUGIXML_HAS_LONG_LONG +# endif +#endif + +// If the platform is known to have move semantics support, compile move ctor/operator implementation +#ifndef PUGIXML_HAS_MOVE +# if __cplusplus >= 201103 +# define PUGIXML_HAS_MOVE +# elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define PUGIXML_HAS_MOVE +# endif +#endif + +// If C++ is 2011 or higher, add 'noexcept' specifiers +#ifndef PUGIXML_NOEXCEPT +# if __cplusplus >= 201103 +# define PUGIXML_NOEXCEPT noexcept +# elif defined(_MSC_VER) && _MSC_VER >= 1900 +# define PUGIXML_NOEXCEPT noexcept +# else +# define PUGIXML_NOEXCEPT +# endif +#endif + +// Some functions can not be noexcept in compact mode +#ifdef PUGIXML_COMPACT +# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT +#else +# define PUGIXML_NOEXCEPT_IF_NOT_COMPACT PUGIXML_NOEXCEPT +#endif + +// If C++ is 2011 or higher, add 'override' qualifiers +#ifndef PUGIXML_OVERRIDE +# if __cplusplus >= 201103 +# define PUGIXML_OVERRIDE override +# elif defined(_MSC_VER) && _MSC_VER >= 1700 +# define PUGIXML_OVERRIDE override +# else +# define PUGIXML_OVERRIDE +# endif +#endif + +// If C++ is 2011 or higher, use 'nullptr' +#ifndef PUGIXML_NULL +# if __cplusplus >= 201103 +# define PUGIXML_NULL nullptr +# else +# define PUGIXML_NULL 0 +# endif +#endif + +// Character interface macros +#ifdef PUGIXML_WCHAR_MODE +# define PUGIXML_TEXT(t) L ## t +# define PUGIXML_CHAR wchar_t +#else +# define PUGIXML_TEXT(t) t +# define PUGIXML_CHAR char +#endif + +namespace pugi +{ + // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE + typedef PUGIXML_CHAR char_t; + +#ifndef PUGIXML_NO_STL + // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE + typedef std::basic_string, std::allocator > string_t; +#endif +} + +// The PugiXML namespace +namespace pugi +{ + // Tree node types + enum xml_node_type + { + node_null, // Empty (null) node handle + node_document, // A document tree's absolute root + node_element, // Element tag, i.e. '' + node_pcdata, // Plain character data, i.e. 'text' + node_cdata, // Character data, i.e. '' + node_comment, // Comment tag, i.e. '' + node_pi, // Processing instruction, i.e. '' + node_declaration, // Document declaration, i.e. '' + node_doctype // Document type declaration, i.e. '' + }; + + // Parsing options + + // Minimal parsing mode (equivalent to turning all other flags off). + // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. + const unsigned int parse_minimal = 0x0000; + + // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. + const unsigned int parse_pi = 0x0001; + + // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. + const unsigned int parse_comments = 0x0002; + + // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. + const unsigned int parse_cdata = 0x0004; + + // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. + // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata = 0x0008; + + // This flag determines if character and entity references are expanded during parsing. This flag is on by default. + const unsigned int parse_escapes = 0x0010; + + // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. + const unsigned int parse_eol = 0x0020; + + // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. + const unsigned int parse_wconv_attribute = 0x0040; + + // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. + const unsigned int parse_wnorm_attribute = 0x0080; + + // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. + const unsigned int parse_declaration = 0x0100; + + // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. + const unsigned int parse_doctype = 0x0200; + + // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only + // of whitespace is added to the DOM tree. + // This flag is off by default; turning it on may result in slower parsing and more memory consumption. + const unsigned int parse_ws_pcdata_single = 0x0400; + + // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. + const unsigned int parse_trim_pcdata = 0x0800; + + // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document + // is a valid document. This flag is off by default. + const unsigned int parse_fragment = 0x1000; + + // This flag determines if plain character data is be stored in the parent element's value. This significantly changes the structure of + // the document; this flag is only recommended for parsing documents with many PCDATA nodes in memory-constrained environments. + // This flag is off by default. + const unsigned int parse_embed_pcdata = 0x2000; + + // The default parsing mode. + // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; + + // The full parsing mode. + // Nodes of all types are added to the DOM tree, character/reference entities are expanded, + // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. + const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; + + // These flags determine the encoding of input data for XML document + enum xml_encoding + { + encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range + { + public: + typedef It const_iterator; + typedef It iterator; + + xml_object_range(It b, It e): _begin(b), _end(e) + { + } + + It begin() const { return _begin; } + It end() const { return _end; } + + bool empty() const { return _begin == _end; } + + private: + It _begin, _end; + }; + + // Writer interface for node printing (see xml_node::print) + class PUGIXML_CLASS xml_writer + { + public: + virtual ~xml_writer() {} + + // Write memory chunk into stream/file/whatever + virtual void write(const void* data, size_t size) = 0; + }; + + // xml_writer implementation for FILE* + class PUGIXML_CLASS xml_writer_file: public xml_writer + { + public: + // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio + xml_writer_file(void* file); + + virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; + + private: + void* file; + }; + + #ifndef PUGIXML_NO_STL + // xml_writer implementation for streams + class PUGIXML_CLASS xml_writer_stream: public xml_writer + { + public: + // Construct writer from an output stream object + xml_writer_stream(std::basic_ostream >& stream); + xml_writer_stream(std::basic_ostream >& stream); + + virtual void write(const void* data, size_t size) PUGIXML_OVERRIDE; + + private: + std::basic_ostream >* narrow_stream; + std::basic_ostream >* wide_stream; + }; + #endif + + // A light-weight handle for manipulating attributes in DOM tree + class PUGIXML_CLASS xml_attribute + { + friend class xml_attribute_iterator; + friend class xml_node; + + private: + xml_attribute_struct* _attr; + + typedef void (*unspecified_bool_type)(xml_attribute***); + + public: + // Default constructor. Constructs an empty attribute. + xml_attribute(); + + // Constructs attribute from internal pointer + explicit xml_attribute(xml_attribute_struct* attr); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped attribute pointers) + bool operator==(const xml_attribute& r) const; + bool operator!=(const xml_attribute& r) const; + bool operator<(const xml_attribute& r) const; + bool operator>(const xml_attribute& r) const; + bool operator<=(const xml_attribute& r) const; + bool operator>=(const xml_attribute& r) const; + + // Check if attribute is empty + bool empty() const; + + // Get attribute name/value, or "" if attribute is empty + const char_t* name() const; + const char_t* value() const; + + // Get attribute value, or the default value if attribute is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty + bool as_bool(bool def = false) const; + + // Set attribute name/value (returns false if attribute is empty or there is not enough memory) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set_value(int rhs); + bool set_value(unsigned int rhs); + bool set_value(long rhs); + bool set_value(unsigned long rhs); + bool set_value(double rhs); + bool set_value(double rhs, int precision); + bool set_value(float rhs); + bool set_value(float rhs, int precision); + bool set_value(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set_value(long long rhs); + bool set_value(unsigned long long rhs); + #endif + + // Set attribute value (equivalent to set_value without error checking) + xml_attribute& operator=(const char_t* rhs); + xml_attribute& operator=(int rhs); + xml_attribute& operator=(unsigned int rhs); + xml_attribute& operator=(long rhs); + xml_attribute& operator=(unsigned long rhs); + xml_attribute& operator=(double rhs); + xml_attribute& operator=(float rhs); + xml_attribute& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_attribute& operator=(long long rhs); + xml_attribute& operator=(unsigned long long rhs); + #endif + + // Get next/previous attribute in the attribute list of the parent node + xml_attribute next_attribute() const; + xml_attribute previous_attribute() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_attribute_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); +#endif + + // A light-weight handle for manipulating nodes in DOM tree + class PUGIXML_CLASS xml_node + { + friend class xml_attribute_iterator; + friend class xml_node_iterator; + friend class xml_named_node_iterator; + + protected: + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_node***); + + public: + // Default constructor. Constructs an empty node. + xml_node(); + + // Constructs node from internal pointer + explicit xml_node(xml_node_struct* p); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators (compares wrapped node pointers) + bool operator==(const xml_node& r) const; + bool operator!=(const xml_node& r) const; + bool operator<(const xml_node& r) const; + bool operator>(const xml_node& r) const; + bool operator<=(const xml_node& r) const; + bool operator>=(const xml_node& r) const; + + // Check if node is empty. + bool empty() const; + + // Get node type + xml_node_type type() const; + + // Get node name, or "" if node is empty or it has no name + const char_t* name() const; + + // Get node value, or "" if node is empty or it has no value + // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. + const char_t* value() const; + + // Get attribute list + xml_attribute first_attribute() const; + xml_attribute last_attribute() const; + + // Get children list + xml_node first_child() const; + xml_node last_child() const; + + // Get next/previous sibling in the children list of the parent node + xml_node next_sibling() const; + xml_node previous_sibling() const; + + // Get parent node + xml_node parent() const; + + // Get root of DOM tree this node belongs to + xml_node root() const; + + // Get text object for the current node + xml_text text() const; + + // Get child, attribute or next/previous sibling with the specified name + xml_node child(const char_t* name) const; + xml_attribute attribute(const char_t* name) const; + xml_node next_sibling(const char_t* name) const; + xml_node previous_sibling(const char_t* name) const; + + // Get attribute, starting the search from a hint (and updating hint so that searching for a sequence of attributes is fast) + xml_attribute attribute(const char_t* name, xml_attribute& hint) const; + + // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA + const char_t* child_value() const; + + // Get child value of child with specified name. Equivalent to child(name).child_value(). + const char_t* child_value(const char_t* name) const; + + // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) + bool set_name(const char_t* rhs); + bool set_value(const char_t* rhs); + + // Add attribute with specified name. Returns added attribute, or empty attribute on errors. + xml_attribute append_attribute(const char_t* name); + xml_attribute prepend_attribute(const char_t* name); + xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); + xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); + + // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. + xml_attribute append_copy(const xml_attribute& proto); + xml_attribute prepend_copy(const xml_attribute& proto); + xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); + xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); + + // Add child node with specified type. Returns added node, or empty node on errors. + xml_node append_child(xml_node_type type = node_element); + xml_node prepend_child(xml_node_type type = node_element); + xml_node insert_child_after(xml_node_type type, const xml_node& node); + xml_node insert_child_before(xml_node_type type, const xml_node& node); + + // Add child element with specified name. Returns added node, or empty node on errors. + xml_node append_child(const char_t* name); + xml_node prepend_child(const char_t* name); + xml_node insert_child_after(const char_t* name, const xml_node& node); + xml_node insert_child_before(const char_t* name, const xml_node& node); + + // Add a copy of the specified node as a child. Returns added node, or empty node on errors. + xml_node append_copy(const xml_node& proto); + xml_node prepend_copy(const xml_node& proto); + xml_node insert_copy_after(const xml_node& proto, const xml_node& node); + xml_node insert_copy_before(const xml_node& proto, const xml_node& node); + + // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. + xml_node append_move(const xml_node& moved); + xml_node prepend_move(const xml_node& moved); + xml_node insert_move_after(const xml_node& moved, const xml_node& node); + xml_node insert_move_before(const xml_node& moved, const xml_node& node); + + // Remove specified attribute + bool remove_attribute(const xml_attribute& a); + bool remove_attribute(const char_t* name); + + // Remove all attributes + bool remove_attributes(); + + // Remove specified child + bool remove_child(const xml_node& n); + bool remove_child(const char_t* name); + + // Remove all children + bool remove_children(); + + // Parses buffer as an XML document fragment and appends all nodes as children of the current node. + // Copies/converts the buffer, so it may be deleted or changed after the function returns. + // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. + xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Find attribute using predicate. Returns first attribute for which predicate returned true. + template xml_attribute find_attribute(Predicate pred) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) + if (pred(attrib)) + return attrib; + + return xml_attribute(); + } + + // Find child node using predicate. Returns first child for which predicate returned true. + template xml_node find_child(Predicate pred) const + { + if (!_root) return xml_node(); + + for (xml_node node = first_child(); node; node = node.next_sibling()) + if (pred(node)) + return node; + + return xml_node(); + } + + // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. + template xml_node find_node(Predicate pred) const + { + if (!_root) return xml_node(); + + xml_node cur = first_child(); + + while (cur._root && cur._root != _root) + { + if (pred(cur)) return cur; + + if (cur.first_child()) cur = cur.first_child(); + else if (cur.next_sibling()) cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); + + if (cur._root != _root) cur = cur.next_sibling(); + } + } + + return xml_node(); + } + + // Find child node by attribute name/value + xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; + xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; + + #ifndef PUGIXML_NO_STL + // Get the absolute node path from root as a text string. + string_t path(char_t delimiter = '/') const; + #endif + + // Search for a node by path consisting of node names and . or .. elements. + xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; + + // Recursively traverse subtree with xml_tree_walker + bool traverse(xml_tree_walker& walker); + + #ifndef PUGIXML_NO_XPATH + // Select single node by evaluating XPath query. Returns first node from the resulting node set. + xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + xpath_node select_node(const xpath_query& query) const; + + // Select node set by evaluating XPath query + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + xpath_node_set select_nodes(const xpath_query& query) const; + + // (deprecated: use select_node instead) Select single node by evaluating XPath query. + PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; + PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const; + + #endif + + // Print subtree using a writer object + void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + + #ifndef PUGIXML_NO_STL + // Print subtree to stream + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; + void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; + #endif + + // Child nodes iterators + typedef xml_node_iterator iterator; + + iterator begin() const; + iterator end() const; + + // Attribute iterators + typedef xml_attribute_iterator attribute_iterator; + + attribute_iterator attributes_begin() const; + attribute_iterator attributes_end() const; + + // Range-based for support + xml_object_range children() const; + xml_object_range children(const char_t* name) const; + xml_object_range attributes() const; + + // Get node offset in parsed file/string (in char_t units) for debugging purposes + ptrdiff_t offset_debug() const; + + // Get hash value (unique for handles to the same object) + size_t hash_value() const; + + // Get internal pointer + xml_node_struct* internal_object() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); +#endif + + // A helper for working with text inside PCDATA nodes + class PUGIXML_CLASS xml_text + { + friend class xml_node; + + xml_node_struct* _root; + + typedef void (*unspecified_bool_type)(xml_text***); + + explicit xml_text(xml_node_struct* root); + + xml_node_struct* _data_new(); + xml_node_struct* _data() const; + + public: + // Default constructor. Constructs an empty object. + xml_text(); + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Check if text object is empty + bool empty() const; + + // Get text, or "" if object is empty + const char_t* get() const; + + // Get text, or the default value if object is empty + const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; + + // Get text as a number, or the default value if conversion did not succeed or object is empty + int as_int(int def = 0) const; + unsigned int as_uint(unsigned int def = 0) const; + double as_double(double def = 0) const; + float as_float(float def = 0) const; + + #ifdef PUGIXML_HAS_LONG_LONG + long long as_llong(long long def = 0) const; + unsigned long long as_ullong(unsigned long long def = 0) const; + #endif + + // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty + bool as_bool(bool def = false) const; + + // Set text (returns false if object is empty or there is not enough memory) + bool set(const char_t* rhs); + + // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") + bool set(int rhs); + bool set(unsigned int rhs); + bool set(long rhs); + bool set(unsigned long rhs); + bool set(double rhs); + bool set(double rhs, int precision); + bool set(float rhs); + bool set(float rhs, int precision); + bool set(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + bool set(long long rhs); + bool set(unsigned long long rhs); + #endif + + // Set text (equivalent to set without error checking) + xml_text& operator=(const char_t* rhs); + xml_text& operator=(int rhs); + xml_text& operator=(unsigned int rhs); + xml_text& operator=(long rhs); + xml_text& operator=(unsigned long rhs); + xml_text& operator=(double rhs); + xml_text& operator=(float rhs); + xml_text& operator=(bool rhs); + + #ifdef PUGIXML_HAS_LONG_LONG + xml_text& operator=(long long rhs); + xml_text& operator=(unsigned long long rhs); + #endif + + // Get the data node (node_pcdata or node_cdata) for this object + xml_node data() const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); +#endif + + // Child node iterator (a bidirectional iterator over a collection of xml_node) + class PUGIXML_CLASS xml_node_iterator + { + friend class xml_node; + + private: + mutable xml_node _wrap; + xml_node _parent; + + xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_node_iterator(); + + // Construct an iterator which points to the specified node + xml_node_iterator(const xml_node& node); + + // Iterator operators + bool operator==(const xml_node_iterator& rhs) const; + bool operator!=(const xml_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + xml_node_iterator& operator++(); + xml_node_iterator operator++(int); + + xml_node_iterator& operator--(); + xml_node_iterator operator--(int); + }; + + // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) + class PUGIXML_CLASS xml_attribute_iterator + { + friend class xml_node; + + private: + mutable xml_attribute _wrap; + xml_node _parent; + + xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_attribute value_type; + typedef xml_attribute* pointer; + typedef xml_attribute& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_attribute_iterator(); + + // Construct an iterator which points to the specified attribute + xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); + + // Iterator operators + bool operator==(const xml_attribute_iterator& rhs) const; + bool operator!=(const xml_attribute_iterator& rhs) const; + + xml_attribute& operator*() const; + xml_attribute* operator->() const; + + xml_attribute_iterator& operator++(); + xml_attribute_iterator operator++(int); + + xml_attribute_iterator& operator--(); + xml_attribute_iterator operator--(int); + }; + + // Named node range helper + class PUGIXML_CLASS xml_named_node_iterator + { + friend class xml_node; + + public: + // Iterator traits + typedef ptrdiff_t difference_type; + typedef xml_node value_type; + typedef xml_node* pointer; + typedef xml_node& reference; + + #ifndef PUGIXML_NO_STL + typedef std::bidirectional_iterator_tag iterator_category; + #endif + + // Default constructor + xml_named_node_iterator(); + + // Construct an iterator which points to the specified node + xml_named_node_iterator(const xml_node& node, const char_t* name); + + // Iterator operators + bool operator==(const xml_named_node_iterator& rhs) const; + bool operator!=(const xml_named_node_iterator& rhs) const; + + xml_node& operator*() const; + xml_node* operator->() const; + + xml_named_node_iterator& operator++(); + xml_named_node_iterator operator++(int); + + xml_named_node_iterator& operator--(); + xml_named_node_iterator operator--(int); + + private: + mutable xml_node _wrap; + xml_node _parent; + const char_t* _name; + + xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); + }; + + // Abstract tree walker class (see xml_node::traverse) + class PUGIXML_CLASS xml_tree_walker + { + friend class xml_node; + + private: + int _depth; + + protected: + // Get current traversal depth + int depth() const; + + public: + xml_tree_walker(); + virtual ~xml_tree_walker(); + + // Callback that is called when traversal begins + virtual bool begin(xml_node& node); + + // Callback that is called for each node traversed + virtual bool for_each(xml_node& node) = 0; + + // Callback that is called when traversal ends + virtual bool end(xml_node& node); + }; + + // Parsing status, returned as part of xml_parse_result object + enum xml_parse_status + { + status_ok = 0, // No error + + status_file_not_found, // File was not found during load_file() + status_io_error, // Error reading from file/stream + status_out_of_memory, // Could not allocate memory + status_internal_error, // Internal error occurred + + status_unrecognized_tag, // Parser could not determine tag type + + status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction + status_bad_comment, // Parsing error occurred while parsing comment + status_bad_cdata, // Parsing error occurred while parsing CDATA section + status_bad_doctype, // Parsing error occurred while parsing document type declaration + status_bad_pcdata, // Parsing error occurred while parsing PCDATA section + status_bad_start_element, // Parsing error occurred while parsing start element tag + status_bad_attribute, // Parsing error occurred while parsing element attribute + status_bad_end_element, // Parsing error occurred while parsing end element tag + status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) + + status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) + + status_no_document_element // Parsing resulted in a document without element nodes + }; + + // Parsing result + struct PUGIXML_CLASS xml_parse_result + { + // Parsing status (see xml_parse_status) + xml_parse_status status; + + // Last parsed offset (in char_t units from start of input data) + ptrdiff_t offset; + + // Source document encoding + xml_encoding encoding; + + // Default constructor, initializes object to failed state + xml_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // Document class (DOM tree root) + class PUGIXML_CLASS xml_document: public xml_node + { + private: + char_t* _buffer; + + char _memory[192]; + + // Non-copyable semantics + xml_document(const xml_document&); + xml_document& operator=(const xml_document&); + + void _create(); + void _destroy(); + void _move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + + public: + // Default constructor, makes empty document + xml_document(); + + // Destructor, invalidates all node/attribute handles to this document + ~xml_document(); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + xml_document& operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT; + #endif + + // Removes all nodes, leaving the empty document + void reset(); + + // Removes all nodes, then copies the entire contents of the specified document + void reset(const xml_document& proto); + + #ifndef PUGIXML_NO_STL + // Load document from stream. + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); + #endif + + // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. + PUGIXML_DEPRECATED xml_parse_result load(const char_t* contents, unsigned int options = parse_default); + + // Load document from zero-terminated string. No encoding conversions are applied. + xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); + + // Load document from file + xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. + xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. + xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). + // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). + xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); + + // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). + void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + #ifndef PUGIXML_NO_STL + // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; + #endif + + // Save XML to file + bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; + + // Get document element + xml_node document_element() const; + }; + +#ifndef PUGIXML_NO_XPATH + // XPath query return type + enum xpath_value_type + { + xpath_type_none, // Unknown type (query failed to compile) + xpath_type_node_set, // Node set (xpath_node_set) + xpath_type_number, // Number + xpath_type_string, // String + xpath_type_boolean // Boolean + }; + + // XPath parsing result + struct PUGIXML_CLASS xpath_parse_result + { + // Error message (0 if no error) + const char* error; + + // Last parsed offset (in char_t units from string start) + ptrdiff_t offset; + + // Default constructor, initializes object to failed state + xpath_parse_result(); + + // Cast to bool operator + operator bool() const; + + // Get error description + const char* description() const; + }; + + // A single XPath variable + class PUGIXML_CLASS xpath_variable + { + friend class xpath_variable_set; + + protected: + xpath_value_type _type; + xpath_variable* _next; + + xpath_variable(xpath_value_type type); + + // Non-copyable semantics + xpath_variable(const xpath_variable&); + xpath_variable& operator=(const xpath_variable&); + + public: + // Get variable name + const char_t* name() const; + + // Get variable type + xpath_value_type type() const; + + // Get variable value; no type conversion is performed, default value (false, NaN, empty string, empty node set) is returned on type mismatch error + bool get_boolean() const; + double get_number() const; + const char_t* get_string() const; + const xpath_node_set& get_node_set() const; + + // Set variable value; no type conversion is performed, false is returned on type mismatch error + bool set(bool value); + bool set(double value); + bool set(const char_t* value); + bool set(const xpath_node_set& value); + }; + + // A set of XPath variables + class PUGIXML_CLASS xpath_variable_set + { + private: + xpath_variable* _data[64]; + + void _assign(const xpath_variable_set& rhs); + void _swap(xpath_variable_set& rhs); + + xpath_variable* _find(const char_t* name) const; + + static bool _clone(xpath_variable* var, xpath_variable** out_result); + static void _destroy(xpath_variable* var); + + public: + // Default constructor/destructor + xpath_variable_set(); + ~xpath_variable_set(); + + // Copy constructor/assignment operator + xpath_variable_set(const xpath_variable_set& rhs); + xpath_variable_set& operator=(const xpath_variable_set& rhs); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; + xpath_variable_set& operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Add a new variable or get the existing one, if the types match + xpath_variable* add(const char_t* name, xpath_value_type type); + + // Set value of an existing variable; no type conversion is performed, false is returned if there is no such variable or if types mismatch + bool set(const char_t* name, bool value); + bool set(const char_t* name, double value); + bool set(const char_t* name, const char_t* value); + bool set(const char_t* name, const xpath_node_set& value); + + // Get existing variable by name + xpath_variable* get(const char_t* name); + const xpath_variable* get(const char_t* name) const; + }; + + // A compiled XPath query object + class PUGIXML_CLASS xpath_query + { + private: + void* _impl; + xpath_parse_result _result; + + typedef void (*unspecified_bool_type)(xpath_query***); + + // Non-copyable semantics + xpath_query(const xpath_query&); + xpath_query& operator=(const xpath_query&); + + public: + // Construct a compiled object from XPath expression. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. + explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL); + + // Constructor + xpath_query(); + + // Destructor + ~xpath_query(); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT; + xpath_query& operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Get query expression return type + xpath_value_type return_type() const; + + // Evaluate expression as boolean value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + bool evaluate_boolean(const xpath_node& n) const; + + // Evaluate expression as double value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + double evaluate_number(const xpath_node& n) const; + + #ifndef PUGIXML_NO_STL + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + string_t evaluate_string(const xpath_node& n) const; + #endif + + // Evaluate expression as string value in the specified context; performs type conversion if necessary. + // At most capacity characters are written to the destination buffer, full result size is returned (includes terminating zero). + // If PUGIXML_NO_EXCEPTIONS is not defined, throws std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty set instead. + size_t evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node set instead. + xpath_node_set evaluate_node_set(const xpath_node& n) const; + + // Evaluate expression as node set in the specified context. + // Return first node in document order, or empty node if node set is empty. + // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on type mismatch and std::bad_alloc on out of memory errors. + // If PUGIXML_NO_EXCEPTIONS is defined, returns empty node instead. + xpath_node evaluate_node(const xpath_node& n) const; + + // Get parsing result (used to get compilation errors in PUGIXML_NO_EXCEPTIONS mode) + const xpath_parse_result& result() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + }; + + #ifndef PUGIXML_NO_EXCEPTIONS + #if defined(_MSC_VER) + // C4275 can be ignored in Visual C++ if you are deriving + // from a type in the Standard C++ Library + #pragma warning(push) + #pragma warning(disable: 4275) + #endif + // XPath exception class + class PUGIXML_CLASS xpath_exception: public std::exception + { + private: + xpath_parse_result _result; + + public: + // Construct exception from parse result + explicit xpath_exception(const xpath_parse_result& result); + + // Get error message + virtual const char* what() const throw() PUGIXML_OVERRIDE; + + // Get parse result + const xpath_parse_result& result() const; + }; + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + #endif + + // XPath node class (either xml_node or xml_attribute) + class PUGIXML_CLASS xpath_node + { + private: + xml_node _node; + xml_attribute _attribute; + + typedef void (*unspecified_bool_type)(xpath_node***); + + public: + // Default constructor; constructs empty XPath node + xpath_node(); + + // Construct XPath node from XML node/attribute + xpath_node(const xml_node& node); + xpath_node(const xml_attribute& attribute, const xml_node& parent); + + // Get node/attribute, if any + xml_node node() const; + xml_attribute attribute() const; + + // Get parent of contained node/attribute + xml_node parent() const; + + // Safe bool conversion operator + operator unspecified_bool_type() const; + + // Borland C++ workaround + bool operator!() const; + + // Comparison operators + bool operator==(const xpath_node& n) const; + bool operator!=(const xpath_node& n) const; + }; + +#ifdef __BORLANDC__ + // Borland C++ workaround + bool PUGIXML_FUNCTION operator&&(const xpath_node& lhs, bool rhs); + bool PUGIXML_FUNCTION operator||(const xpath_node& lhs, bool rhs); +#endif + + // A fixed-size collection of XPath nodes + class PUGIXML_CLASS xpath_node_set + { + public: + // Collection type + enum type_t + { + type_unsorted, // Not ordered + type_sorted, // Sorted by document order (ascending) + type_sorted_reverse // Sorted by document order (descending) + }; + + // Constant iterator type + typedef const xpath_node* const_iterator; + + // We define non-constant iterator to be the same as constant iterator so that various generic algorithms (i.e. boost foreach) work + typedef const xpath_node* iterator; + + // Default constructor. Constructs empty set. + xpath_node_set(); + + // Constructs a set from iterator range; data is not checked for duplicates and is not sorted according to provided type, so be careful + xpath_node_set(const_iterator begin, const_iterator end, type_t type = type_unsorted); + + // Destructor + ~xpath_node_set(); + + // Copy constructor/assignment operator + xpath_node_set(const xpath_node_set& ns); + xpath_node_set& operator=(const xpath_node_set& ns); + + #ifdef PUGIXML_HAS_MOVE + // Move semantics support + xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; + xpath_node_set& operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT; + #endif + + // Get collection type + type_t type() const; + + // Get collection size + size_t size() const; + + // Indexing operator + const xpath_node& operator[](size_t index) const; + + // Collection iterators + const_iterator begin() const; + const_iterator end() const; + + // Sort the collection in ascending/descending order by document order + void sort(bool reverse = false); + + // Get first node in the collection by document order + xpath_node first() const; + + // Check if collection is empty + bool empty() const; + + private: + type_t _type; + + xpath_node _storage[1]; + + xpath_node* _begin; + xpath_node* _end; + + void _assign(const_iterator begin, const_iterator end, type_t type); + void _move(xpath_node_set& rhs) PUGIXML_NOEXCEPT; + }; +#endif + +#ifndef PUGIXML_NO_STL + // Convert wide string to UTF8 + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); + + // Convert UTF8 to wide string + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); + std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); +#endif + + // Memory allocation function interface; returns pointer to allocated memory or NULL on failure + typedef void* (*allocation_function)(size_t size); + + // Memory deallocation function interface + typedef void (*deallocation_function)(void* ptr); + + // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. + void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); + + // Get current memory management functions + allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); + deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); + std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); +} +#endif + +#endif + +// Make sure implementation is included in header-only mode +// Use macro expansion in #include to work around QMake (QTBUG-11923) +#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) +# define PUGIXML_SOURCE "pugixml.cpp" +# include PUGIXML_SOURCE +#endif + +/** + * Copyright (c) 2006-2020 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/external/libdumper/include/sfo.hpp b/external/libdumper/include/sfo.hpp new file mode 100644 index 0000000..063eb20 --- /dev/null +++ b/external/libdumper/include/sfo.hpp @@ -0,0 +1,56 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#ifndef SFO_HPP_ +#define SFO_HPP_ + +#include +#include + +#define SFO_MAGIC 0x00505346 + +namespace sfo { +typedef struct { + uint32_t magic; + uint32_t version; + uint32_t key_table_offset; + uint32_t data_table_offset; + uint32_t num_entries; +} SfoHeader; + +typedef struct { + std::string key_name; + uint16_t key_offset; + uint16_t format; + uint32_t length; + uint32_t max_length; + uint32_t data_offset; + std::vector data; +} SfoData; + +typedef struct { + std::string key_name; + std::string value; +} SfoPubtoolinfoIndex; + +bool is_sfo(const std::string &path); +std::vector read(const std::string &path); +std::vector get_keys(const std::vector &data); +uint16_t get_format(const std::string &key, const std::vector &data); +uint32_t get_length(const std::string &key, const std::vector &data); +uint32_t get_max_length(const std::string &key, const std::vector &data); +std::vector get_value(const std::string &key, const std::vector &data); +std::vector read_pubtool_data(const std::vector &data); +std::vector get_pubtool_keys(const std::vector &data); +std::string get_pubtool_value(const std::string &key, const std::vector &data); +SfoData build_data(const std::string &key_name, const std::string &format, uint32_t length, uint32_t max_length, const std::vector &data); +SfoPubtoolinfoIndex build_pubtool_data(const std::string &key, const std::string &value); +std::vector add_data(const SfoData &add_data, const std::vector ¤t_data); +std::vector add_pubtool_data(const SfoPubtoolinfoIndex &add_data, const std::vector ¤t_data); +std::vector remove_key(const std::string &remove_key, const std::vector ¤t_data); +std::vector remove_pubtool_key(const std::string &remove_key, const std::vector ¤t_data); +bool compare_sfo_date(SfoData data_1, SfoData data_2); +void write(const std::vector &data, const std::string &path); +} // namespace sfo + +#endif // SFO_HPP_ diff --git a/external/libdumper/source/common.cpp b/external/libdumper/source/common.cpp new file mode 100644 index 0000000..52d4639 --- /dev/null +++ b/external/libdumper/source/common.cpp @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include "common.hpp" + +void ProgUpdate(int prog, const char* fmt, ...) +{ + char buff[300]; + memset(&buff[0], 0, sizeof(buff)); + + va_list args; + va_start(args, fmt); + vsnprintf(&buff[0], 299, fmt, args); + va_end(args); + + if (sceMsgDialogUpdateStatus() == COMMON_DIALOG_STATUS_RUNNING) + { + sceMsgDialogProgressBarSetMsg(0, (const char*)buff); + sceMsgDialogProgressBarSetValue(0, prog); + } +} diff --git a/external/libdumper/source/dump.cpp b/external/libdumper/source/dump.cpp new file mode 100644 index 0000000..9ce094a --- /dev/null +++ b/external/libdumper/source/dump.cpp @@ -0,0 +1,324 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "common.hpp" +#include "elf.hpp" +#include "fself.hpp" +#include "gp4.hpp" +#include "npbind.hpp" +#include "pfs.hpp" +#include "pkg.hpp" +#include "dumper.h" +#include "dump.hpp" + +#include +#include +#include +#include +#include +#include +#include "log.h" +extern "C" { +#include "lang.h" +} + +namespace dump { +bool __dump(const std::string &usb_device, const std::string &title_id, Dump_Options opt, const std::string& title) { + + + if (!LoadDumperLangs(DumperGetLang())) { + if (!LoadDumperLangs(0x01)) { + if(!load_dumper_embdded_eng()) + return false; + } + else + log_debug("Loaded the backup, lang %i failed to load", DumperGetLang()); + } + if (opt > TOTAL_OF_OPTS) + { + log_error("OPT is out of range: %i", opt); + return false; + } + + + std::string output_directory = title_id; + if (opt == GAME_PATCH) { + output_directory += "-patch"; // Add "-patch" to "patch" types so it doesn't overlap with "base" + } else if (opt == THEME_UNLOCK) { + output_directory += "-unlock"; // Add "-unlock" to theme type so we can differentiate between "install" and "unlock" PKGs + } + + // Create base path + std::filesystem::path output_path(usb_device); + output_path /= output_directory; + + // Make sure the base path is a directory or can be created + if (!std::filesystem::is_directory(output_path) && !std::filesystem::create_directories(output_path)) { + log_error("Unable to create output directory"); + return false; + } + + // Check for .dumping semaphore + std::filesystem::path dumping_semaphore(usb_device); + dumping_semaphore /= output_directory + ".dumping"; + if (std::filesystem::exists(dumping_semaphore)) { + log_error("This dump is currently dumping or closed unexpectedly! Please delete existing dump to enable dumping."); + } + + // Check for .complete semaphore + std::filesystem::path complete_semaphore(usb_device); + complete_semaphore /= output_directory + ".complete"; + if (std::filesystem::exists(complete_semaphore)) { + log_error("This dump has already been completed! Please delete existing dump to enable dumping."); + } + + + // Create .dumping semaphore + std::ofstream dumping_sem_touch(dumping_semaphore); + dumping_sem_touch.close(); + if (std::filesystem::exists(dumping_semaphore)) { + log_error("Unable to create dumping semaphore!"); + } + + + // Create "sce_sys" directory in the output directory + std::filesystem::path sce_sys_path(output_path); + sce_sys_path /= "sce_sys"; + if (!std::filesystem::is_directory(sce_sys_path) && !std::filesystem::create_directories(sce_sys_path)) { + log_error("Unable to create `sce_sys` directory"); + return false; + } + + std::filesystem::path pkg_path; + try { + + if (opt == THEME_UNLOCK || opt == ADDITIONAL_CONTENT_NO_DATA) { + std::filesystem::path param_destination(sce_sys_path); + param_destination /= "param.sfo"; + + if (opt == THEME_UNLOCK) { + // Copy theme install PKG + std::filesystem::path install_source("/user/addcont/I00000002"); + install_source /= title_id; + install_source /= "ac.pkg"; + + std::filesystem::path install_destination(usb_device); + install_destination /= title_id + "-install.pkg"; + + // Copy param.sfo + if (!std::filesystem::copy_file(install_source, install_destination, std::filesystem::copy_options::overwrite_existing)) { + log_error("Unable to copy %s", install_source.string().c_str()); + } + + std::filesystem::path param_source("/system_data/priv/appmeta/addcont/I00000002"); + param_source /= title_id; + param_source /= "param.sfo"; + + if (!std::filesystem::copy_file(param_source, param_destination, std::filesystem::copy_options::overwrite_existing)) { + log_error("Unable to copy %s", param_source.c_str()); + return false; + } + } + else { + // TODO: Find and copy... or create... "param.sfo" for "additional-content-no-data" at param_destination + } + } + else { // "base", "patch", "remaster", "theme", "additional-content-data" + // UnPKG + std::filesystem::path pkg_directory_path; + pkg_directory_path /= "/user"; + if (opt == BASE_GAME || opt == REMASTER) { + pkg_directory_path /= "app"; + pkg_directory_path /= title_id; + pkg_directory_path /= "app.pkg"; + } + else if (opt == GAME_PATCH) { + pkg_directory_path /= "patch"; + pkg_directory_path /= title_id; + pkg_directory_path /= "patch.pkg"; + } + else if (opt == THEME) { + pkg_directory_path /= "addcont/I00000002"; + pkg_directory_path /= title_id; + pkg_directory_path /= "ac.pkg"; + } + else if (opt == ADDITIONAL_CONTENT_DATA) { + pkg_directory_path /= "addcont"; + // This regex will match because of the checks at the beginning of the function + } + // Detect if on extended storage and make pkg_path + std::filesystem::path ext_path("/mnt/ext0"); + ext_path += pkg_directory_path; + + if (std::filesystem::exists(ext_path) && std::filesystem::is_regular_file(ext_path)) { + log_info("found ext hdd"); + pkg_path = ext_path; + } + else { + + pkg_path = pkg_directory_path; + } + } + } + catch (std::filesystem::filesystem_error& e) + { + log_error("SFO Opts failed"); + } + +ProgUpdate(8, "%s\n\n%s %s\n%s %s\n\n %s ...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME),title.c_str(), getDumperLangSTR(TITLE_ID), title_id.c_str(), getDumperLangSTR(DUMPER_SC0)); +try { + if (std::filesystem::exists(pkg_path)) { + if (!pkg::extract_sc0(pkg_path, sce_sys_path, title_id, title)) + { + log_error("pkg::extract_sc0(\"%s\",\"%s\") failed", pkg_path.c_str(), sce_sys_path.c_str()); + return false; + } + } + else { + log_error("Unable to open %s", pkg_path.string().c_str()); + return false; + } +} +catch (std::exception e) +{ + log_error("extracting sc0 failed"); + return false; +} + +ProgUpdate(10, "%s\n\n%s %s\n%s %s\n\n %s ...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME),title.c_str(), getDumperLangSTR(TITLE_ID), title_id.c_str(), getDumperLangSTR(DUMPING_TROPHIES)); + +try { + // Trophy "decryption" + std::filesystem::path npbind_file(sce_sys_path); + npbind_file /= "npbind.dat"; + if (std::filesystem::is_regular_file(npbind_file)) { + printf("npbind_file: %s\n", npbind_file.string().c_str()); + std::vector npbind_entries = npbind::read(npbind_file); // Flawfinder: ignore + for (auto&& entry : npbind_entries) { + std::filesystem::path src("/user/trophy/conf"); + src /= std::string(entry.npcommid.data); + src /= "TROPHY.TRP"; + + std::filesystem::path dst(sce_sys_path); + dst /= "trophy"; + // make folder if it doesnt exist OR ignore the error if it does exist + mkdir(dst.string().c_str(), 0777); + //BUG FIX above + uint32_t zerofill = 0; + if (std::strlen(entry.trophy_number.data) < 2) { // Flawfinder: ignore + zerofill = 2 - std::strlen(entry.trophy_number.data); // Flawfinder: ignore + } + dst /= "trophy" + std::string(zerofill, '0') + std::string(entry.trophy_number.data) + ".trp"; + + ProgUpdate(11, "%s\n\n%s %s\n%s %s\n\n %s %s...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title.c_str(), getDumperLangSTR(TITLE_ID), title_id.c_str(), getDumperLangSTR(DUMPING_TROPHIES), src.c_str()); + if (std::filesystem::exists(src)) { + log_debug("[%s] Dumping Trophy %s to %s ...", title_id.c_str(), src.string().c_str(), dst.string().c_str()); + if (!std::filesystem::copy_file(src, dst, std::filesystem::copy_options::overwrite_existing)) { + log_error("Unable to copy %s", src.string().c_str()); + } + else + log_info("Successfully Copied trophy"); + } + else { + log_error("Unable to open %s", src.string().c_str()); + return false; + } + } + } +} +catch (std::filesystem::filesystem_error& e) +{ + log_error("Dumping Trophy failed"); + return false; +} + + if(std::filesystem::exists("/mnt/usb0/trophy_flag")) + return true; + + // UnPFS + std::filesystem::path pfs_path("/mnt/sandbox/pfsmnt"); + pfs_path /= title_id; + if (opt == BASE_GAME || opt == REMASTER) { + pfs_path += "-app0-nest"; + } else if (opt == GAME_PATCH) { + pfs_path += "-patch0-nest"; + } else if (opt == THEME || opt == ADDITIONAL_CONTENT_DATA) { + pfs_path += "-ac-nest"; + } + pfs_path /= "pfs_image.dat"; + try { + if (std::filesystem::exists(pfs_path)) { + if (!pfs::extract(pfs_path.string(), output_path.string(), title_id.c_str(), (char*)title.c_str())) { + return false; + } + } + else { + log_error("Unable to open %s", pfs_path.string().c_str()); + return false; + } + } + catch (std::exception e) + { + log_error("Extracting PFS failed"); + return false; + } + + + + // Vector of strings for locations of SELF files for decryption + std::vector self_files; + + // Generate GP4 + + std::filesystem::path sfo_path(sce_sys_path); + sfo_path /= "param.sfo"; + + std::filesystem::path gp4_path(output_path); + gp4_path /= output_directory + ".gp4"; + + +ProgUpdate(98, "%s\n\n%s %s\n%s %s\n\n %s ...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title.c_str(), getDumperLangSTR(TITLE_ID), title_id.c_str(), getDumperLangSTR(CREATING_GP4)); +try { + if (!gp4::generate(sfo_path.string(), output_path.string(), gp4_path.string(), self_files, opt)) + return false; +} +catch (const std::exception& e) +{ + log_error("Gerneating GP4 failed"); +} + + + // Decrypt ELF files and make into FSELFs +std::string encrypted_path("/mnt/sandbox/pfsmnt/"); +if (opt == BASE_GAME) { + encrypted_path += title_id + "-app0/"; +} +else if (opt == GAME_PATCH) { + encrypted_path += title_id + "-patch0/"; +} +else if (opt == THEME_UNLOCK) { + encrypted_path += title_id + "-ac/"; +} + +log_info("Step %i", __LINE__); +std::string decrypted_path(output_path); + +ProgUpdate(99, "%s\n\n%s %s\n%s %s\n\n %s %s...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title.c_str(), getDumperLangSTR(TITLE_ID), title_id.c_str(), getDumperLangSTR(DEC_BIN), encrypted_path.c_str()); +log_debug("Decrypting Bins in %s ...", encrypted_path.c_str()); + +elf::decrypt_dir(encrypted_path, decrypted_path); + + // Delete .dumping semaphore +if (!std::filesystem::remove(dumping_semaphore)) + log_error("Unable to delete dumping semaphore"); + +// Create .complete semaphore +std::ofstream complete_sem_touch(complete_semaphore); +complete_sem_touch.close(); +if (std::filesystem::exists(complete_semaphore)) + log_error("Unable to create completion semaphore!"); + + + return true; +} +} // namespace dump \ No newline at end of file diff --git a/external/libdumper/source/elf.cpp b/external/libdumper/source/elf.cpp new file mode 100644 index 0000000..28f0700 --- /dev/null +++ b/external/libdumper/source/elf.cpp @@ -0,0 +1,865 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "elf.hpp" +#include "common.hpp" +#include "elf_64.hpp" +#include "elf_common.hpp" + +#include +#include +#include +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libshahash.h" +#include + +#define KB(x) ((size_t) (x) << 10) +#define MB(x) ((size_t) (x) << 20) + +namespace elf { + uint64_t get_sce_header_offset(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: "); + } + + // Check to make sure file is a SELF + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + self_input.close(); + log_error("Input path is not a SELF!"); + } + + // Read SELF header + SelfHeader self_header; + self_input.read((char*)&self_header, sizeof(self_header)); // Flawfinder: ignore + if (!self_input.good()) { + // Should never reach here... will affect coverage % + self_input.close(); + log_error("Error reading SELF header!"); + } + + // Calculate ELF header offset from the number of SELF segments + uint64_t elf_header_offset = sizeof(self_header) + self_header.num_of_segments * sizeof(SelfEntry); + + // Read ELF header + Elf64_Ehdr elf_header; + self_input.seekg(elf_header_offset, self_input.beg); + self_input.read((char*)&elf_header, sizeof(elf_header)); // Flawfinder: ignore + if (!self_input.good()) { + self_input.close(); + log_error("Error reading ELF header!"); + } + self_input.close(); + + // Check ELF magic + // Can this be less bad/robust? + unsigned char elf_magic[4]; + elf_magic[0] = (ELF_MAGIC >> 24) & 0xFF; + elf_magic[1] = (ELF_MAGIC >> 16) & 0xFF; + elf_magic[2] = (ELF_MAGIC >> 8) & 0xFF; + elf_magic[3] = (ELF_MAGIC >> 0) & 0xFF; + + if (std::memcmp(elf_header.e_ident, elf_magic, 4) != 0) { + log_error("Error reading ELF magic!"); + } + + // Calculate SCE header offset from number of ELF entries + uint64_t sce_header_offset = elf_header_offset + elf_header.e_ehsize + elf_header.e_phnum * elf_header.e_phentsize; + + // Align + while (sce_header_offset % 0x10 != 0) { + sce_header_offset++; + } + + return sce_header_offset; + } + + SceHeader get_sce_header(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path)) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + // Check to make sure file is a SELF + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + self_input.close(); + log_error("Input path is not a SELF!"); + } + + // Calculate SCE header offset from number of ELF entries + uint64_t sce_header_offset = get_sce_header_offset(path); + + self_input.seekg(sce_header_offset, self_input.beg); + SceHeader sce_header; + self_input.read((char*)&sce_header, sizeof(sce_header)); // Flawfinder: ignore + if (!self_input.good()) { + self_input.close(); + log_error("Error reading SCE header!"); + } + + return sce_header; + } + + SceHeaderNpdrm get_sce_header_npdrm(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + // Check to make sure file is a SELF + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + self_input.close(); + log_error("Input path is not a SELF!"); + } + + // Calculate SCE header offset from number of ELF entries + uint64_t sce_header_offset = get_sce_header_offset(path); + + self_input.seekg(sce_header_offset, self_input.beg); + SceHeaderNpdrm sce_header; + self_input.read((char*)&sce_header, sizeof(sce_header)); // Flawfinder: ignore + if (!self_input.good()) { + self_input.close(); + log_error("Error reading SCE header!"); + } + + return sce_header; + } + + + bool Check_ELF_Magic(const std::string& path, uint32_t FILE_MAGIC) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path)) { + log_error("Input path does not exist or is not a file!"); + } + + // Read SELF header + uint32_t magic; + + // Open path + int elf = sceKernelOpen(path.c_str(), O_RDONLY, 0); + if (elf < 0) return false; + + sceKernelLseek(elf, 0, SEEK_SET); + sceKernelRead(elf, &magic, sizeof(uint32_t)); + + sceKernelClose(elf); + + return (__builtin_bswap32(magic) == FILE_MAGIC); + + } + + bool is_npdrm(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + // Check if the file is a SELF + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + self_input.close(); + log_error("Input path is not a SELF!"); + } + + // Read SELF header + SelfHeader self_header; + self_input.read((char*)&self_header, sizeof(self_header)); // Flawfinder: ignore + if (!self_input.good()) { + // Should never reach here... will affect coverage % + self_input.close(); + log_error("Error reading SELF header!"); + } + + uint64_t program_type = self_header.program_type; + while (program_type >= 0x10) { + program_type -= 0x10; + } + + // TODO: Is it just npdrm_exec that are considered NPDRM or is npdrm_dynlib as well? What about fake? + if (program_type == 0x4) { + return true; + } + + return false; + } + + std::string get_ptype(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF. If it's not it *should* not have a SCE header + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + + uint64_t program_type; + if (is_npdrm(path)) { + program_type = get_sce_header_npdrm(path).program_type; + } + else { + program_type = get_sce_header(path).program_type; + } + + std::string output; + switch (program_type) { + case 0x1: + output = "fake"; + break; + case 0x4: + output = "npdrm_exec"; + break; + case 0x5: + output = "npdrm_dynlib"; + break; + case 0x8: + output = "system_exec"; + break; + case 0x9: + output = "system_dynlib"; // Includes mono libraries + break; + case 0xC: + output = "host_kernel"; + break; + case 0xE: + output = "secure_module"; + break; + case 0xF: + output = "secure_kernel"; + break; + default: + log_error("Unknown ptype!"); + break; + } + + return output; + } + + + uint64_t get_paid(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF. If it's not it *should* not have a SCE header + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + + if (is_npdrm(path)) { + return get_sce_header_npdrm(path).program_authority_id; + } + + return get_sce_header(path).program_authority_id; + } + + uint64_t get_app_version(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF. If it's not it *should* not have a SCE header + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + + if (is_npdrm(path)) { + return get_sce_header_npdrm(path).app_version; + } + + return get_sce_header(path).app_version; + } + + uint64_t get_fw_version(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF. If it's not it *should* not have a SCE header + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + + if (is_npdrm(path)) { + return get_sce_header_npdrm(path).fw_version; + } + + return get_sce_header(path).fw_version; + } + + std::vector get_digest(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF. If it's not it *should* not have a SCE header + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + + std::vector digest; + if (is_npdrm(path)) { + SceHeaderNpdrm sce_header = get_sce_header_npdrm(path); + for (size_t i = 0; i < sizeof(sce_header.digest); i++) { + digest.push_back(sce_header.digest[i]); + } + } + else { + SceHeader sce_header = get_sce_header(path); + for (size_t i = 0; i < sizeof(sce_header.digest); i++) { + digest.push_back(sce_header.digest[i]); + } + } + + return digest; + } + + // https://www.psdevwiki.com/ps4/Auth_Info + std::vector get_auth_info(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path (To check permissions) + std::ifstream self_input(path, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + self_input.close(); + + // Check if the file is a SELF + if (!Check_ELF_Magic(path, SELF_MAGIC)) { + log_error("Input path is not a SELF!"); + } + +#if defined(__ORBIS__) + // TODO: + // This may be better as a Mira fuctions to expose the required kernel functions as getting the auth_info is done in kernel + // int kern_get_self_auth_info(struct thread* td, const char* path, int pathseg, char* info); + // int self_kget_auth_info(struct thread *td, struct path_kmethod_uap_t *uap) { + // char auth_info[0x88]; + // memset(auth_info, 0, sizeof(auth_info)); + // + // const char *path = uap->path; + // int res = kern_get_self_auth_info(td, path, (int)UIO_SYSSPACE, auth_info); + // if (res == 0) { + // khexdump("AUTH_INFO", auth_info, 0x88); + // kdprintf("END_AUTH_INFO\n"); + // } else { + // kdprintf("Failed to get AUTH_INFO\n"); + // } + // } +#elif defined(__TEST__) + // TODO: Some sort of output to know the above code is functioning as much as can be expected +#else + // TODO: Some sort of output to know the above code is functioning as much as can be expected +#endif + + std::vector blah; + + return blah; + } + + bool is_valid_decrypt(const std::string& original_path, const std::string& decrypted_path) { + // Check for empty or pure whitespace path + if (original_path.empty() || std::all_of(original_path.begin(), original_path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty original path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(original_path.c_str())) { + log_error("Input original path does not exist or is not a file!"); + } + + // Open path + std::ifstream original_self(original_path, std::ios::in | std::ios::binary); + if (!original_self || !original_self.good()) { + original_self.close(); + log_error("Cannot open file: %s", original_path.c_str()); + } + original_self.close(); + + // Check if file is a SELF + if (!Check_ELF_Magic(original_path, SELF_MAGIC)) { + log_error("Input original path is not a SELF!"); + } + + // Check for empty or pure whitespace path + if (decrypted_path.empty() || std::all_of(decrypted_path.begin(), decrypted_path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty decrypted path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(decrypted_path.c_str())) { + log_error("Input decrypted path does not exist or is not a file!"); + } + + // Open path + std::ifstream decrypted_elf(decrypted_path, std::ios::in | std::ios::binary); + if (!decrypted_elf || !decrypted_elf.good()) { + decrypted_elf.close(); + log_error("Cannot open file: %s", decrypted_path.c_str()); + } + + // Check if file is an ELF + if (!Check_ELF_Magic(decrypted_path)) { + decrypted_elf.close(); + log_error("Input decrypted path is not an ELF!"); + } + + // Read digest + unsigned char digest[32]; + std::vector original_digest_from_self = get_digest(original_path); + for (size_t i = 0; i < sizeof(digest); i++) { + digest[i] = original_digest_from_self[i]; + } + + unsigned char calculated_digest[sizeof(digest)]; + + SHA256_CTX context; + SHA256_Init(&context); + + while (decrypted_elf.good()) { + unsigned char buffer[PAGE_SIZE]; + decrypted_elf.read((char*)buffer, sizeof(buffer)); // Flawfinder: ignore + + SHA256_Update(&context, buffer, decrypted_elf.gcount()); + } + decrypted_elf.close(); + + SHA256_Final(&context, calculated_digest); +#if 1 + + char sha_digest[33] = { 0 }; + char sha_calcdigest[33] = { 0 }; + + for (int i = 0; i < 32; ++i) { + snprintf(&sha_digest[i], 32, "%0x", (unsigned int)digest[i]); + } + + + for (int i = 0; i < 32; ++i) { + snprintf(&sha_calcdigest[i], 32, "%0x", (unsigned int)calculated_digest[i]); + } + + log_info("[libshahash][SHA256] ELF Digest Hash: %s Calc'd Digest Hash: %s", sha_digest, sha_calcdigest); +#endif + + if (std::memcmp(calculated_digest, digest, sizeof(digest)) != 0) { + log_info("File %s has failed validation", decrypted_path.c_str()); + return false; + } + else + log_info("File %s Successfully validated", decrypted_path.c_str()); + + return true; + } + + // This is done in other dumpers but is it necessary? + void zero_section_header(const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path.c_str())) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream elf_path(path, std::ios::in | std::ios::binary); + if (!elf_path || !elf_path.good()) { + elf_path.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + // Check if file is an ELF + if (!Check_ELF_Magic(path, ELF_MAGIC)) { + elf_path.close(); + log_error("Input path is not an ELF!"); + } + + elf_path.seekg(0, elf_path.beg); + Elf64_Ehdr elf_header; + elf_path.seekg(0, elf_path.beg); + elf_path.read((char*)&elf_header, sizeof(elf_header)); // Flawfinder: ignore + if (!elf_path.good()) { + // Should never reach here... will affect coverage % + elf_path.close(); + log_error("Error reading ELF header!"); + } + elf_path.close(); + + // Zero section headers as they are invalid + elf_header.e_shoff = 0; + elf_header.e_shnum = 0; + elf_header.e_shentsize = 0; + elf_header.e_shstrndx = 0; + + std::ofstream output_file(path, std::ios::in | std::ios::out | std::ios::binary); + if (!output_file || !output_file.good()) { + // Should never reach here... will affect coverage % + output_file.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + output_file.seekp(0, output_file.beg); + output_file.write((char*)&elf_header, sizeof(elf_header)); + output_file.close(); + } + + + bool write_decrypt_segment_to(int fdr, int fdw, uint64_t index, uint64_t offset, size_t size) + { + + uint64_t outSize = size; + uint64_t realOffset = (index << 32) | offset; + while (outSize > 0) + { + size_t bytes = (outSize > DECRYPT_SIZE) ? DECRYPT_SIZE : outSize; + uint8_t* addr = (uint8_t*)mmap(0, bytes, PROT_READ, MAP_PRIVATE | 0x80000, fdr, realOffset); + if (addr != MAP_FAILED) + { + write(fdw, addr, bytes); + munmap(addr, bytes); + } + else + { + log_error("mmap segment [%lu] err(%d) : %s", index, errno, strerror(errno)); + return false; + } + + outSize -= bytes; + realOffset += bytes; + } + return true; + } + + int is_segment_in_other_segment(Elf64_Phdr* phdr, int index, Elf64_Phdr* phdrs, int num) { + for (int i = 0; i < num; i += 1) { + Elf64_Phdr* p = &phdrs[i]; + if (i != index) { + if (p->p_filesz > 0) { + if ((phdr->p_offset >= p->p_offset) && ((phdr->p_offset + phdr->p_filesz) <= (p->p_offset + p->p_filesz))) { + return TRUE; + } + } + } + } + return FALSE; + } + + + SegmentBufInfo* parse_phdr(Elf64_Phdr* phdrs, int num, int* segBufNum) { + SegmentBufInfo* infos = (SegmentBufInfo*)malloc(sizeof(SegmentBufInfo) * num); + int segindex = 0; + for (int i = 0; i < num; i += 1) { + Elf64_Phdr* phdr = &phdrs[i]; + + + if (phdr->p_filesz > 0) { + if ((!is_segment_in_other_segment(phdr, i, phdrs, num)) || (phdr->p_type == 0x6fffff01)) { + SegmentBufInfo* info = &infos[segindex]; + segindex += 1; + info->index = i; + info->bufsz = (phdr->p_filesz + (phdr->p_align - 1)) & (~(phdr->p_align - 1)); + info->filesz = phdr->p_filesz; + info->fileoff = phdr->p_offset; + info->enc = (phdr->p_type != 0x6fffff01) ? TRUE : FALSE; + + } + } + } + *segBufNum = segindex; + return infos; + } + + bool do_dump(const char* saveFile, int fd, SegmentBufInfo* segBufs, int segBufNum, Elf64_Ehdr* ehdr) { + + unlink(saveFile); + + int sf = sceKernelOpen(saveFile, O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (sf > 0) { + size_t elfsz = 0x40 + ehdr->e_phnum * sizeof(Elf64_Phdr); + write(sf, ehdr, elfsz); + + for (int i = 0; i < segBufNum; i += 1) { + + + if (segBufs[i].enc) + { + lseek(sf, segBufs[i].fileoff, SEEK_SET); + if (!write_decrypt_segment_to(fd, sf, segBufs[i].index, 0, segBufs[i].filesz)) + { + log_error("write_decrypt_segment_to failed for %s", saveFile); + sceKernelClose(sf); + return true; + } + } + else + { + + if (segBufs[i].bufsz > MB(10)) + log_error("segBufs[i].bufsz > MB(10)"); + + uint8_t* buf = (uint8_t*)malloc(segBufs[i].bufsz); + memset(buf, 0, segBufs[i].bufsz); + + lseek(fd, -segBufs[i].filesz, SEEK_END); + read(fd, buf, segBufs[i].filesz); + lseek(sf, segBufs[i].fileoff, SEEK_SET); + write(sf, buf, segBufs[i].filesz); + + free(buf); + } + } + sceKernelClose(sf); + } + else + log_error("open %s err : %x", saveFile, sf); + + + + return false; + } + + int decrypt_and_dump_self(const char* selfFile, const char* saveFile) { + + int fd = sceKernelOpen(selfFile, O_RDONLY, 0); + if (fd > 0) { + void* addr = mmap(0, 0x4000, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (addr != MAP_FAILED) { + log_info("mmap %s : %p, fd: %i", selfFile, addr, fd); + + uint16_t snum = *(uint16_t*)((uint8_t*)addr + 0x18); + Elf64_Ehdr* ehdr = (Elf64_Ehdr*)((uint8_t*)addr + 0x20 + snum * 0x20); + + // shdr fix + ehdr->e_shoff = ehdr->e_shentsize = ehdr->e_shnum = ehdr->e_shstrndx = 0; + + Elf64_Phdr* phdrs = (Elf64_Phdr*)((uint8_t*)ehdr + 0x40); + + + int segBufNum = 0; + SegmentBufInfo* segBufs = parse_phdr(phdrs, ehdr->e_phnum, &segBufNum); + bool flag = do_dump(saveFile, fd, segBufs, segBufNum, ehdr); + log_info("flag: %i", flag); + free(segBufs); + munmap(addr, 0x4000); + + sceKernelClose(fd); + return flag; + } + else { + log_fatal("mmap file %s err : %s", selfFile, strerror(errno)); + sceKernelClose(fd); + return true; + } + sceKernelClose(fd); + } + else { + log_fatal("open %s err : %s", selfFile, strerror(errno)); + return true; + } + } + + + // The following code inspired from: + // - https://github.com/AlexAltea/orbital + // - https://github.com/xvortex/ps4-dumper-vtx + bool decrypt_dir(const std::string& input, const std::string& output) { + + DIR* dir; + struct dirent* dp; + struct stat info; + char src_path[1024], dst_path[1024]; + + dir = opendir(input.c_str()); + if (!dir) + return true; + + while ((dp = readdir(dir)) != NULL) + { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + { + // do nothing (straight logic) + } + else + { + snprintf(src_path, 1023, "%s/%s", input.c_str(), dp->d_name); + snprintf(dst_path, 1023, "%s/%s", output.c_str(), dp->d_name); + if (!stat(src_path, &info)) + { + if (S_ISDIR(info.st_mode)) + { + mkdir(src_path, 0777); + decrypt_dir(src_path, dst_path); + } + else + if (S_ISREG(info.st_mode)) + { + + if (Check_ELF_Magic(src_path, SELF_MAGIC)) + { + + if (decrypt_and_dump_self(src_path, dst_path)) + { + //if (!is_valid_decrypt(src_path, dst_path)) + log_error("failed to decrypt %s -> %s", src_path, dst_path); + } + + } + else + log_info("file: %s is NOT a self", src_path); + + } + } + } + } + closedir(dir); + + return true; + + + } +} // namespace elf diff --git a/external/libdumper/source/fself.cpp b/external/libdumper/source/fself.cpp new file mode 100644 index 0000000..6a3dd13 --- /dev/null +++ b/external/libdumper/source/fself.cpp @@ -0,0 +1,82 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "fself.hpp" +#include "common.hpp" +#include "elf.hpp" + +#include +#include +#include +#include +#include "log.h" +#include + +namespace fself { +bool is_fself(const std::string &path) { + // TODO + + UNUSED(path); + + return false; +} + +void make_fself(const std::string &input, const std::string &output, uint64_t paid, const std::string &ptype, uint64_t app_version, uint64_t fw_version, std::vector auth_info) { + // Check for empty or pure whitespace path + if (input.empty() || std::all_of(input.begin(), input.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty input path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(input)) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream self_input(input, std::ios::in | std::ios::binary); + if (!self_input || !self_input.good()) { + self_input.close(); + log_error("Cannot open file: %s",input.c_str()); + } + + + // Check for empty or pure whitespace path + if (output.empty() || std::all_of(output.begin(), output.end(), [](char c) { return std::isspace(c); })) { + self_input.close(); + log_error("Empty output path argument!"); + } + + std::filesystem::path output_path(output); + + // Exists, but is not a file + if (std::filesystem::exists(output_path) && !std::filesystem::is_regular_file(output_path)) { + self_input.close(); + log_error("Oputput object exists but is not a file!"); + } + + // paid, app_version and fw_version are unsigned and any value between 0x0 and 0xFFFFFFFFFFFFFFFF is valid so we do not have to check range + + if (ptype != "fake" && ptype != "npdrm_exec" && ptype != "npdrm_dynlib" && ptype != "system_exec" && ptype != "system_dynlib" && ptype != "host_kernel" && ptype != "secure_module" && ptype != "secure_kernel") { + self_input.close(); + log_error("Invalid ptype!"); + } + + // Should be 0x110 in size and 0-9a-fA-F + if (auth_info.size() != 0x110) { + self_input.close(); + log_error("Auth info is invalid length!"); + } + if (std::all_of(output.begin(), output.end(), [](char c) { return std::isxdigit(c); })) { + self_input.close(); + log_error("Auth info is not hex!"); + } + + // Input may not be "correct" but it's valid at this point + + // TODO + self_input.close(); + UNUSED(paid); + UNUSED(app_version); + UNUSED(fw_version); +} +} // namespace fself diff --git a/external/libdumper/source/gp4.cpp b/external/libdumper/source/gp4.cpp new file mode 100644 index 0000000..0209e58 --- /dev/null +++ b/external/libdumper/source/gp4.cpp @@ -0,0 +1,417 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "common.hpp" +#include "elf.hpp" // `bool is_self(const std::string &path);` +#include "sfo.hpp" +#include "dump.hpp" +#include "pugixml.hpp" + +#include +#include +// #include // TODO: Not including doesn't generate and error even though "strftime" is used? +#include +#include +#include +#include +#include "log.h" +#include +#include +#include + +namespace gp4 { + +void recursive_directory(const std::string &path, pugi::xml_node &node) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + for (auto &&p : std::filesystem::directory_iterator(path)) { + if (std::filesystem::is_directory(p.path())) { + + //check for sce_sys/about + log_info("folder %s", std::string(p.path()).c_str()); + if (strstr(std::string(p.path()).c_str(), "sce_sys/about") != NULL) { + log_info("continuing..."); + continue; + } + + pugi::xml_node dir_node = node.append_child("dir"); + + std::string temp_path = p.path(); + temp_path.erase(0, path.size()); + while (temp_path.back() == '/') { + temp_path.pop_back(); + } + while (temp_path.at(0) == '/') { + temp_path.erase(0, 1); + } + + dir_node.append_attribute("targ_name") = temp_path.c_str(); + + + recursive_directory(p.path(), dir_node); + } + } +} +pugi::xml_document make_volume(const std::string& content_id, const std::string& volume_type, std::string c_date, std::string c_time) { + // Check input + + if (c_date.empty()) { + log_fatal("Malformed c_date"); + } + + if (c_time.empty()) { + log_fatal("Malformed c_time"); + } + + if (volume_type != "pkg_ps4_app" && volume_type != "pkg_ps4_patch" && volume_type != "pkg_ps4_remaster" && volume_type != "pkg_ps4_theme" && volume_type != "additional-content-data" && volume_type != "additional-content-no-data") { + log_fatal("Unknown volume type"); + } + + // Generate XML + pugi::xml_document doc; + + pugi::xml_node volume_node = doc.append_child("volume"); + pugi::xml_node volume_type_node = volume_node.append_child("volume_type"); + volume_type_node.append_child(pugi::node_pcdata).set_value(volume_type.c_str()); + pugi::xml_node volume_ts_node = volume_node.append_child("volume_ts"); + + // Get current time for volume_ts... and possibly c_date + std::time_t t = std::time(0); + std::tm* timeinfo = std::localtime(&t); + + char buffer[20]; + std::memset(buffer, '\0', sizeof(buffer)); + std::strftime(buffer, 20, "%Y-%m-%d %H:%M:%S", timeinfo); + volume_ts_node.append_child(pugi::node_pcdata).set_value(buffer); + + pugi::xml_node package_node = volume_node.append_child("package"); + package_node.append_attribute("content_id") = content_id.c_str(); + package_node.append_attribute("passcode") = "00000000000000000000000000000000"; + if (volume_type == "additional-content-data" || volume_type == "additional-content-no-data") { + // TODO: Attempt to get entitlement_key based on content_id + package_node.append_attribute("entitlement_key") = ""; + } + if(volume_type == "pkg_ps4_patch") + package_node.append_attribute("storage_type") = "digital25"; + else + package_node.append_attribute("storage_type") = "digital50"; + + package_node.append_attribute("app_type") = "full"; + + // Set c_date + std::string new_time = std::string("actual_datetime"); + if (!c_date.empty()) { + new_time = c_date; + if (!c_time.empty()) { + // TODO: Append time to new_time + } + } + package_node.append_attribute("c_date") = new_time.c_str(); + + return doc; +} + +pugi::xml_document make_playgo(const std::string& playgo_xml) { + pugi::xml_document doc; + + // TODO: pugixml kills attributes in the node itself... get them back/add to default build + + // Return external XML if it exists + if (std::filesystem::exists(playgo_xml) && std::filesystem::is_regular_file(playgo_xml) && doc.load_file(playgo_xml.c_str())) { + return doc; + } + + // Build default + pugi::xml_node psproject_node = doc.append_child("psproject"); + psproject_node.append_attribute("fmt") = "playgo-manifest"; + psproject_node.append_attribute("version") = "1000"; // TODO: Will this be correct? + + pugi::xml_node volume_node = psproject_node.append_child("volume"); + + pugi::xml_node chunk_info_node = volume_node.append_child("chunk_info"); + chunk_info_node.append_attribute("chunk_count") = "1"; + chunk_info_node.append_attribute("scenario_count") = "1"; + + pugi::xml_node chunks_node = chunk_info_node.append_child("chunks"); + + pugi::xml_node chunk_node = chunks_node.append_child("chunk"); + chunk_node.append_attribute("id") = "0"; + chunk_node.append_attribute("label") = "Chunk #0"; + + pugi::xml_node scenarios_node = chunk_info_node.append_child("scenarios"); + scenarios_node.append_attribute("default_id") = "0"; + + pugi::xml_node scenario_node = scenarios_node.append_child("scenario"); + scenario_node.append_attribute("id") = "0"; + scenario_node.append_attribute("type") = "sp"; + scenario_node.append_attribute("initial_chunk_count") = "1"; + scenario_node.append_attribute("label") = "Scenario #0"; + + return doc; +} + +pugi::xml_document make_files(const std::string& path, std::vector& elf_files, Dump_Options opt) { + // Check for empty or pure whitespace path + bool is_illegal = false; + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_fatal("Empty path argument!"); + } + // Generate XML + pugi::xml_document doc; + const char* gp4_path; + pugi::xml_node files_node = doc.append_child("files"); + files_node.append_attribute("img_no") = "0"; // TODO: PlayGo + + // Files to skip when making GP4 + std::vector skip_files = { + "sce_discmap.plt", + "sce_discmap_patch.plt", + "sce_sys/about/right.sprx", // Cannot be included for official PKG tools + "sce_sys/icon0.dds", + "sce_sys/license.dat", + "sce_sys/license.info", + "sce_sys/pic0.dds", + "sce_sys/pic1.dds", + "sce_sys/playgo-chunk.dat", + "sce_sys/playgo-chunk.sha", + "sce_sys/playgo-manifest.xml", + "sce_sys/psreserved.dat", + "sce_sys/origin-deltainfo.dat" + }; + + for (uint64_t i = 0; i < 100; i++) { + std::stringstream ss_image; + ss_image << "sce_sys/icon0_" << std::dec << std::setfill('0') << std::setw(2) << i << ".dds"; + skip_files.push_back(ss_image.str()); + ss_image.str(std::string()); + ss_image << "sce_sys/pic0_" << std::dec << std::setfill('0') << std::setw(2) << i << ".dds"; + skip_files.push_back(ss_image.str()); + ss_image.str(std::string()); + ss_image << "sce_sys/pic1_" << std::dec << std::setfill('0') << std::setw(2) << i << ".dds"; + skip_files.push_back(ss_image.str()); + } + + for (auto&& p : std::filesystem::recursive_directory_iterator(path)) { + if (std::filesystem::is_regular_file(p.path())) { + bool self; + if ((self = elf::Check_ELF_Magic(p.path(), SELF_MAGIC))) { + elf_files.push_back(p.path()); + } + // 20 is sizeof("/mnt/usb0/CUSA00000") + // 26 is sizeof("/mnt/usb0/CUSA00000-patch") + // 27 is sizeof("/mnt/usb0/CUSA00000-unlock") + // TODO: + // - Add proper PlayGo options + // - Add PFS Compression option + if(opt == GAME_PATCH) + gp4_path = std::string(p.path()).c_str() + 26; + else if (opt == THEME_UNLOCK) + gp4_path = std::string(p.path()).c_str() + 27; + else + gp4_path = std::string(p.path()).c_str() + 20; + + if (strstr(gp4_path, "sce_sys") != NULL) { + for (int i = 0; i < skip_files.size(); i++) { + if (strcmp(gp4_path, skip_files[i].c_str()) == 0) + { + log_info("Found Illegal file %s skipping...", skip_files[i].c_str()); + is_illegal = true; + break; + } + } + } + else if (strstr(gp4_path, skip_files[0].c_str()) != NULL || strstr(gp4_path, skip_files[1].c_str()) != NULL) + { // sce_discmap.plt sce_discmap_path.plt + // file skip + log_info("Found Illegal file %s skipping...", gp4_path); + is_illegal = true; + } + + if (!is_illegal) { + log_info("Adding %s to GP4", gp4_path); + pugi::xml_node file_node = files_node.append_child("file"); + file_node.append_attribute("targ_path") = gp4_path; + file_node.append_attribute("orig_path") = gp4_path; + } + is_illegal = false; + } + } + + return doc; +} + +pugi::xml_document make_directories(const std::string& path) { + // Generate XML + pugi::xml_document doc; + + pugi::xml_node rootdir_node = doc.append_child("rootdir"); + + recursive_directory(path, rootdir_node); + + return doc; +} + +pugi::xml_document assemble(const pugi::xml_document& volume, const pugi::xml_document& playgo, const pugi::xml_document& files, const pugi::xml_document& directories, const std::string& custom_version = "") { + // Generate XML + pugi::xml_document doc; + + // TODO: Set XML node attributes + + pugi::xml_node psproject_node = doc.append_child("psproject"); + psproject_node.append_attribute("fmt") = "gp4"; + if (!custom_version.empty()) { + psproject_node.append_attribute("version") = custom_version.c_str(); + } + else { + if (playgo.child("psproject").attribute("version").empty()) { + psproject_node.append_attribute("version") = "1000"; // TODO: Will this be correct? + } + else { + psproject_node.append_attribute("version") = playgo.child("psproject").attribute("version").value(); // TODO: Will this be correct? + } + } + + psproject_node.append_copy(volume.child("volume")); + psproject_node.child("volume").append_copy(playgo.child("psproject").child("volume").child("chunk_info")); + + psproject_node.child("volume").child("chunk_info").prepend_child("chunks"); + uint64_t chunk_count = 1; + if (!psproject_node.child("volume").child("chunk_info").attribute("chunk_count").empty()) { + chunk_count = std::strtoull(psproject_node.child("volume").child("chunk_info").attribute("chunk_count").value(), NULL, 10); + } + + for (uint64_t i = 0; i < chunk_count; i++) { + pugi::xml_node chunk_node = psproject_node.child("volume").child("chunk_info").child("chunks").append_child("chunk"); + std::stringstream ss_id; + std::stringstream ss_label; + + ss_id << "" << std::dec << i; + ss_label << "Chunk #" << std::dec << i; // TODO: The labels are not what they actually are, need to see if they are stored in other playgo files + + chunk_node.append_attribute("id") = ss_id.str().c_str(); + chunk_node.append_attribute("label") = ss_label.str().c_str(); + } + + // Remove `initial_chunk_count_disc` from each `scenario` if it exists... we aren't a disc anymore + for (pugi::xml_node scenarios : psproject_node.child("volume").child("chunk_info")) { + for (pugi::xml_node scenario : scenarios.children("scenario")) { + scenario.remove_attribute("initial_chunk_count_disc"); + } + } + + psproject_node.append_copy(files.child("files")); + psproject_node.append_copy(directories.child("rootdir")); + return doc; +} + +void write(const pugi::xml_document& xml, const std::string& path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_fatal("Empty output path argument!"); + } + + std::filesystem::path output_path(path); + + // Exists, but is not a file + if (std::filesystem::exists(output_path) && !std::filesystem::is_regular_file(output_path)) { + log_fatal("Output object exists but is not a file!"); + } + + // Open path + std::ofstream output_file(output_path, std::ios::out | std::ios::trunc | std::ios::binary); + if (!output_file || !output_file.good()) { + output_file.close(); + log_fatal("Cannot open file: %s" , std::string(output_path).c_str()); + } + + xml.save(output_file); + + output_file.close(); +} + +void generate(const std::string& sfo_path, const std::string& output_path, const std::string& gp4_path, std::vector& self_files, Dump_Options opt) { + char buff[100]; + + std::vector sfo_data = sfo::read(sfo_path); // Flawfinder: ignore + std::vector sfo_keys = sfo::get_keys(sfo_data); + + if (!std::count(sfo_keys.begin(), sfo_keys.end(), std::string("CONTENT_ID"))) { + log_fatal("param.sfo does not contain `CONTENT_ID`!"); + } + + std::vector pubtool_data = sfo::read_pubtool_data(sfo_data); + std::vector pubtool_keys; + if (std::count(sfo_keys.begin(), sfo_keys.end(), std::string("PUBTOOLINFO"))) { + pubtool_keys = sfo::get_pubtool_keys(pubtool_data); + } + + std::vector temp_content_id = sfo::get_value("CONTENT_ID", sfo_data); + std::string content_id(temp_content_id.begin(), temp_content_id.end()); + + std::string c_date; // "YYYY-MM-DD" + if (std::count(pubtool_keys.begin(), pubtool_keys.end(), std::string("c_date"))) { + try { + c_date = sfo::get_pubtool_value("c_date", pubtool_data); + sprintf(&buff[0], "%.4s-%.2s-%.2s", c_date.c_str(), c_date.c_str() + 4, c_date.c_str() + 6); + c_date = std::string(buff); + } + catch (...) { + } // get_pubtool_value throws if key is not found but we don't care and c_date will remain empty + } + + std::string c_time; // "XXXXXX" + if (std::count(pubtool_keys.begin(), pubtool_keys.end(), std::string("c_time"))) { + try { + c_time = sfo::get_pubtool_value("c_time", pubtool_data); + } + catch (...) { + } // get_pubtool_value throws if key is not found but we don't care and c_time will remain empty + } + + // Get content type string for GP4 + std::string content_type; + if (opt == BASE_GAME) { + content_type = "pkg_ps4_app"; + } + else if (opt == GAME_PATCH) { + content_type = "pkg_ps4_patch"; + } + else if (opt == REMASTER) { + content_type = "pkg_ps4_remaster"; + } + else if (opt == THEME) { + content_type = "pkg_ps4_theme"; + } + else if (opt == THEME_UNLOCK) { + content_type = "pkg_ps4_ac_nodata"; // Use "pkg_ps4_ac_nodata" as the GP4 is only used for the "unlock" PKG in this case + } + else if (opt == ADDITIONAL_CONTENT_DATA) { + content_type = "pkg_ps4_ac_data"; + } + else if (opt == ADDITIONAL_CONTENT_NO_DATA) { + content_type = "pkg_ps4_ac_nodata"; + } + // Generate actual GP4 file + pugi::xml_document volume_xml = make_volume(content_id, content_type, c_date, c_time); + pugi::xml_document files_xml = make_files(output_path, self_files, opt); + pugi::xml_document directories_xml = make_directories(output_path); + pugi::xml_document playgo_xml; + pugi::xml_document assembled_xml; + + std::filesystem::path playgo_xml_path(output_path); + playgo_xml_path /= "sce_sys"; + playgo_xml_path /= "playgo-manifest.xml"; + if (std::filesystem::is_regular_file(playgo_xml_path)) { + playgo_xml = make_playgo(playgo_xml_path); + assembled_xml = assemble(volume_xml, playgo_xml, files_xml, directories_xml); + } + else { + assembled_xml = assemble(volume_xml, playgo_xml, files_xml, directories_xml, "1000"); // TODO: Version number? + } + + write(assembled_xml, gp4_path); +} +} // namespace gp4 \ No newline at end of file diff --git a/external/libdumper/source/ini.c b/external/libdumper/source/ini.c new file mode 100644 index 0000000..f8a3ea3 --- /dev/null +++ b/external/libdumper/source/ini.c @@ -0,0 +1,298 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include + +#include "ini.h" + +#if !INI_USE_STACK +#if INI_CUSTOM_ALLOCATOR +#include +void* ini_malloc(size_t size); +void ini_free(void* ptr); +void* ini_realloc(void* ptr, size_t size); +#else +#include +#define ini_malloc malloc +#define ini_free free +#define ini_realloc realloc +#endif +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to NUL at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Similar to strncpy, but ensures dest (size bytes) is + NUL-terminated, and doesn't pad with NULs. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */ + size_t i; + for (i = 0; i < size - 1 && src[i]; i++) + dest[i] = src[i]; + dest[i] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + size_t max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC && !INI_USE_STACK + char* new_line; + size_t offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)ini_malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, (int)max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC && !INI_USE_STACK + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = ini_realloc(line, max_line); + if (!new_line) { + ini_free(line); + return -2; + } + line = new_line; + if (reader(line + offset, (int)(max_line - offset), stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; +#if INI_CALL_HANDLER_ON_NEW_SECTION + if (!HANDLER(user, section, NULL, NULL) && !error) + error = lineno; +#endif + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ +#if INI_ALLOW_NO_VALUE + *end = '\0'; + name = rstrip(start); + if (!HANDLER(user, section, name, NULL) && !error) + error = lineno; +#else + error = lineno; +#endif + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + ini_free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/external/libdumper/source/lang.c b/external/libdumper/source/lang.c new file mode 100644 index 0000000..b1965bb --- /dev/null +++ b/external/libdumper/source/lang.c @@ -0,0 +1,167 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "lang.h" +#include "log.h" +#include +#include "ini.h" + +static DumperStrings* args; +static bool lang_is_dumper_initialized = false; +// +//https://github.com/Al-Azif/ps4-payload-guest/blob/main/src/Language.cpp +// +int sceSystemServiceParamGetInt(int i, int32_t *lang); +int32_t DumperGetLang() { + int32_t lang; + + if (sceSystemServiceParamGetInt(1, &lang) != 0) { + log_error("Unable to qet language code"); + return 0x1; + } + + return lang; +} + +char* getDumperLangSTR(enum Lang_ST str) +{ + + if (lang_is_dumper_initialized) { + if (str > LANG_NUM_OF_STRINGS) { + return "ERROR"; + } + else + { + if (args->strings[str] != NULL) + return args->strings[str]; + else + return "ERROR"; + } + } + else + return "ERROR: Lang has not loaded"; +} + + +static int load_lang_dumper_ini(void* user, const char* section, const char* name, + const char* value) +{ + + DumperStrings* set = (DumperStrings*)user; + + +#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + + if (MATCH("DUMPER", "DUMP_INFO")) { + snprintf(set->strings[DUMP_INFO], 255, "%s", value); + log_debug("%s ", set->strings[DUMP_INFO]); + } + else if (MATCH("DUMPER", "APP_NAME")) { + snprintf(set->strings[APP_NAME], 255, "%s", value); + log_debug("%s ", set->strings[APP_NAME]); + } + else if (MATCH("DUMPER", "TITLE_ID")) { + snprintf(set->strings[TITLE_ID], 255, "%s", value); + log_debug("%s ", set->strings[TITLE_ID]); + } + else if (MATCH("DUMPER", "DUMPER_SC0")) { + snprintf(set->strings[DUMPER_SC0], 255, "%s", value); + } + else if (MATCH("DUMPER", "DUMPING_TROPHIES")) { + snprintf(set->strings[DUMPING_TROPHIES], 255, "%s", value); + } + else if (MATCH("DUMPER", "CREATING_GP4")) { + snprintf(set->strings[CREATING_GP4], 255, "%s", value); + } + if (MATCH("DUMPER", "DEC_BIN")) { + snprintf(set->strings[DEC_BIN], 255, "%s", value);// + } + else if (MATCH("DUMPER", "DEL_SEM")) { + snprintf(set->strings[DEL_SEM], 255, "%s", value);// + } + else if (MATCH("DUMPER", "EXT_PATCH")) { + snprintf(set->strings[EXT_PATCH], 255, "%s", value); + } + if (MATCH("DUMPER", "EXT_GAME_FILES")) { + snprintf(set->strings[EXT_GAME_FILES], 255, "%s", value); + } + else if (MATCH("DUMPER", "PROCESSING")) { + snprintf(set->strings[PROCESSING], 255, "%s", value); + } + + + return 1; + +} + +bool exists(const char* path) +{ + int dfd = open(path, 0, 0); // try to open dir + if (dfd < 0) { + log_info("path %s, errno %s", path, strerror(errno)); + return false; + } + else + close(dfd); + + + return true; +} + +bool load_dumper_embdded_eng() +{ + //mem should already be allocated as this is the last opt + if (args != NULL) { + int error = ini_parse("/user/app/ITEM00001/lang.ini", load_lang_dumper_ini, args); + if (error) { + log_error("Bad config file (first error on line %d)!", error); + return false; + } + else + lang_is_dumper_initialized = true; + + } + else + return false; + + return true; +} + +bool LoadDumperLangs(int LangCode) +{ + if (!lang_is_dumper_initialized) { + //dont leak or realloc on fail + if (args == NULL) + args = (DumperStrings*)malloc(sizeof(DumperStrings)); + if (args != NULL) { + for (int i = 0; i < LANG_NUM_OF_STRINGS; i++) { + args->strings[i] = calloc(256, sizeof(char)); + if (args->strings[i] == NULL) { + log_info( "Failed to load Language(s)... Failed to allocate args->strings[%i]", i); + return false; + } + } + + char tmp[100]; + snprintf(tmp, 99, LANG_DIR, LangCode); + + int error = ini_parse(tmp, load_lang_dumper_ini, args); + if (error) { + log_error("Bad config file (first error on line %d)!", error); + return false; + } + else + lang_is_dumper_initialized = true; + } + else + return false; + } + + return true; +} \ No newline at end of file diff --git a/external/libdumper/source/libshahash.c b/external/libdumper/source/libshahash.c new file mode 100644 index 0000000..7b22884 --- /dev/null +++ b/external/libdumper/source/libshahash.c @@ -0,0 +1,416 @@ +/* + * FIPS 180-2 SHA-224/256/384/512 implementation + * Last update: 02/02/2007 + * Issue date: 04/30/2005 + * + * Copyright (C) 2013, Con Kolivas + * Copyright (C) 2005, 2007 Olivier Gay + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include +#include +#include +#include "libshahash.h" + + +uint32_t sha256_h0[8] = + {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; + +uint32_t sha256_k[64] = + {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2}; + +/* SHA-256 functions */ +void sha256_transf(SHA256_CTX *ctx, const unsigned char *message, + unsigned int block_nb) +{ + uint32_t w[64]; + uint32_t wv[8]; + uint32_t t1, t2; + const unsigned char *sub_block; + int i; + + int j; + + for (i = 0; i < (int) block_nb; i++) { + sub_block = message + (i << 6); + + for (j = 0; j < 16; j++) { + PACK32(&sub_block[j << 2], &w[j]); + } + + for (j = 16; j < 64; j++) { + SHA256_SCR(j); + } + + for (j = 0; j < 8; j++) { + wv[j] = ctx->h[j]; + } + + for (j = 0; j < 64; j++) { + t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6]) + + sha256_k[j] + w[j]; + t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]); + wv[7] = wv[6]; + wv[6] = wv[5]; + wv[5] = wv[4]; + wv[4] = wv[3] + t1; + wv[3] = wv[2]; + wv[2] = wv[1]; + wv[1] = wv[0]; + wv[0] = t1 + t2; + } + + for (j = 0; j < 8; j++) { + ctx->h[j] += wv[j]; + } + } +} + +void SHA256(const unsigned char *message, unsigned int len, unsigned char *digest) +{ + SHA256_CTX ctx; + + SHA256_Init(&ctx); + SHA256_Update(&ctx, message, len); + SHA256_Final(&ctx, digest); +} + +void SHA256_Init(SHA256_CTX *ctx) +{ + int i; + for (i = 0; i < 8; i++) { + ctx->h[i] = sha256_h0[i]; + } + + ctx->len = 0; + ctx->tot_len = 0; +} + +void SHA256_Update(SHA256_CTX *ctx, const unsigned char *message, + unsigned int len) +{ + unsigned int block_nb; + unsigned int new_len, rem_len, tmp_len; + const unsigned char *shifted_message; + + tmp_len = SHA256_BLOCK_SIZE - ctx->len; + rem_len = len < tmp_len ? len : tmp_len; + + memcpy(&ctx->block[ctx->len], message, rem_len); + + if (ctx->len + len < SHA256_BLOCK_SIZE) { + ctx->len += len; + return; + } + + new_len = len - rem_len; + block_nb = new_len / SHA256_BLOCK_SIZE; + + shifted_message = message + rem_len; + + sha256_transf(ctx, ctx->block, 1); + sha256_transf(ctx, shifted_message, block_nb); + + rem_len = new_len % SHA256_BLOCK_SIZE; + + memcpy(ctx->block, &shifted_message[block_nb << 6], + rem_len); + + ctx->len = rem_len; + ctx->tot_len += (block_nb + 1) << 6; +} + +void SHA256_Final(SHA256_CTX *ctx, unsigned char *digest) +{ + unsigned int block_nb; + unsigned int pm_len; + unsigned int len_b; + + int i; + + block_nb = (1 + ((SHA256_BLOCK_SIZE - 9) + < (ctx->len % SHA256_BLOCK_SIZE))); + + len_b = (ctx->tot_len + ctx->len) << 3; + pm_len = block_nb << 6; + + memset(ctx->block + ctx->len, 0, pm_len - ctx->len); + ctx->block[ctx->len] = 0x80; + UNPACK32(len_b, ctx->block + pm_len - 4); + + sha256_transf(ctx, ctx->block, block_nb); + + for (i = 0 ; i < 8; i++) { + UNPACK32(ctx->h[i], &digest[i << 2]); + } +} +// END OF SHA256 https://github.com/sasanj/libsha256/blob/master/src/sha2.c +// Start SHA1 https://github.com/mmxsrup/libsha1/blob/master/sha1.c +void Sha1Core(uint32_t *blk, uint32_t *h); +static __inline__ void Sha1SwapEndian(uint32_t *dst, const uint32_t *src, uint32_t len); +static __inline__ void Sha1Memcpy(void *pDst, const void *pSrc, uint32_t uiSize); + +static const uint32_t K[4] = { + 0x5A827999U, + 0x6ED9EBA1U, + 0x8F1BBCDCU, + 0xCA62C1D6U +}; + +#define lrotate(x, bits) ((x << bits) | (x >> (32-bits))) + +void Sha1Core(uint32_t *blk, uint32_t *h) +{ + uint32_t s, temp, a, b, c, d, e; + a = h[0]; + b = h[1]; + c = h[2]; + d = h[3]; + e = h[4]; + + for(uint32_t t = 0; t < 80; t++) { + s = t & 15; + if(t>=16) { + blk[s] = lrotate((blk[(s+13) & 15] ^ blk[(s+8) & 15] ^ blk[(s+2) & 15] ^ blk[s]), 1); + } + temp = lrotate(a, 5) + e + blk[s]; + if(t<20) { + temp += ((b & c) | ((~b) & d)) + K[0]; + } else if(t<40) { + temp += (b ^ c ^ d) + K[1]; + } else if(t<60) { + temp += ((b & c) | (b & d) | (c & d)) + K[2]; + } else { + temp += (b ^ c ^ d) + K[3]; + } + e = d; + d = c; + c = lrotate(b, 30); + b = a; + a = temp; + } + h[0] += a; + h[1] += b; + h[2] += c; + h[3] += d; + h[4] += e; + + return; +} + + +static __inline__ void Sha1SwapEndian(uint32_t *dst, const uint32_t *src, uint32_t len) +{ + uint32_t i; + for (i=0; ih[0] = 0x67452301U; + pContext->h[1] = 0xEFCDAB89U; + pContext->h[2] = 0x98BADCFEU; + pContext->h[3] = 0x10325476U; + pContext->h[4] = 0xC3D2E1F0U; + pContext->usRemains = 0; + pContext->usComputed = 0; + pContext->ullTotalLen = 0; + pContext->initialized = 1; + return (0); +} + + + +int32_t Sha1BlockUpdate(Sha1Context *pContext, const void *plain, uint32_t len) +{ + union { + uint8_t b[SHA1_BLOCK_SIZE]; + uint32_t ui[SHA1_BLOCK_SIZE / 4]; + } blk; + uint32_t n; + + if (!pContext || !plain) { + return (SHA1_ERROR_INVALID_POINTER); + } + if (pContext->initialized != 1) { + return (SHA1_ERROR_UNINITIALIZED_CONTEXT); + } + if (pContext->usRemains >= SHA1_BLOCK_SIZE) { + return (SHA1_ERROR_INVALID_STATE); + } + + pContext->ullTotalLen += len; + n = pContext->usRemains + len; + + while (n >= SHA1_BLOCK_SIZE) { + if (pContext->usRemains > 0) { + uint32_t cont = SHA1_BLOCK_SIZE - pContext->usRemains; + Sha1Memcpy(blk.b, pContext->buf, pContext->usRemains); + Sha1Memcpy(&blk.b[pContext->usRemains], plain, cont); + pContext->usRemains = 0; + plain = (const uint8_t *)plain + cont; + } else { + Sha1Memcpy(blk.b, plain, SHA1_BLOCK_SIZE); + plain = (const uint8_t *)plain + SHA1_BLOCK_SIZE; + } + Sha1SwapEndian(blk.ui, blk.ui, (SHA1_BLOCK_SIZE / 4)); + + Sha1Core(blk.ui, pContext->h); + + n -= SHA1_BLOCK_SIZE; + } + if (n > 0) { + Sha1Memcpy(&pContext->buf[pContext->usRemains], plain, (n - pContext->usRemains)); + } + pContext->usRemains = (uint16_t)n; + pContext->usComputed = 0; + return (0); +} + + + + +int32_t Sha1BlockResult(Sha1Context *pContext, uint8_t *digest) +{ + if (!pContext || !digest) { + return (SHA1_ERROR_INVALID_POINTER); + } + if (pContext->initialized != 1) { + return (SHA1_ERROR_UNINITIALIZED_CONTEXT); + } + if (pContext->usComputed==0) { + union { + uint8_t b[SHA1_BLOCK_SIZE]; + uint32_t ui[SHA1_BLOCK_SIZE / 4]; + } blk; + uint32_t h[5]; + + uint32_t n; + uint32_t i; + n = pContext->usRemains; + + for (i=0; i<(SHA1_BLOCK_SIZE / 4); i++) { + blk.ui[i] = 0; + } + Sha1Memcpy(blk.b, pContext->buf, n); + blk.b[n] = 0x80; + + Sha1Memcpy(h, pContext->h, sizeof(h)); + if (n >= (SHA1_BLOCK_SIZE - 8)) { + Sha1SwapEndian(blk.ui, blk.ui, (SHA1_BLOCK_SIZE / 4)); + + + Sha1Core(blk.ui, h); + + for (i=0; i<(SHA1_BLOCK_SIZE / 4); i++) { + blk.ui[i] = 0; + } + } + for (i=0; i<8; i++) { + blk.b[56 + i] = (uint8_t)((pContext->ullTotalLen<<3) >> ((7 - i)*8)); + } + Sha1SwapEndian(blk.ui, blk.ui, (SHA1_BLOCK_SIZE / 4)); + + Sha1Core(blk.ui, h); + + Sha1SwapEndian(h, h, 5); + Sha1Memcpy(pContext->result, h, SHA1_DIGEST_SIZE); + pContext->usComputed = 1; + } + Sha1Memcpy(digest, pContext->result, SHA1_DIGEST_SIZE); + return (0); +} + +//END OF SHA1 https://github.com/mmxsrup/libsha1/blob/master/sha1.c \ No newline at end of file diff --git a/external/libdumper/source/log.cpp b/external/libdumper/source/log.cpp new file mode 100644 index 0000000..5890af2 --- /dev/null +++ b/external/libdumper/source/log.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "log.h" + +#define MAX_CALLBACKS 32 + +typedef struct { + log_LogFn fn; + void* udata; + int level; +} Callback; + +static struct { + void* udata; + log_LockFn lock; + int level; + bool quiet; + Callback callbacks[MAX_CALLBACKS]; +} L; + + +static const char* level_strings[] = { + "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" +}; + +#ifdef LOG_USE_COLOR +static const char* level_colors[] = { + "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m" +}; +#endif + +#define __ORBIS__ 1 + +#ifdef __ORBIS__ +#define DGB_CHANNEL_TTYL 0 +int sceKernelDebugOutText(int DBG_CHANNEL, char* text[400]); +#endif + +extern "C" { + + extern int syscall(int ...); + + int sys_mdbg_service(int numb, char* str, int opt) + { + return syscall(601, numb, str, opt); + } +} + + +static void stdout_callback(log_Event* ev) { + char buf[16]; + char format_buf[400]; + char print_buf[400]; + buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0'; + + vsnprintf(format_buf, 399, ev->fmt, ev->ap); + + snprintf((char*)print_buf, 399, "%s %-5s %s:%d: %s\n", buf, level_strings[ev->level], ev->file, ev->line, format_buf); + +#ifdef __ORBIS__ + sys_mdbg_service(7, print_buf, 0); +#else + log_info("%s\n" print_buf); +#endif +} + + +static void file_callback(log_Event* ev) { + char buf[64]; + buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0'; + fprintf( + (FILE*)ev->udata, "%s %-5s %s:%d: ", + buf, level_strings[ev->level], ev->file, ev->line); + vfprintf((FILE*)ev->udata, ev->fmt, ev->ap); + fprintf((FILE*)ev->udata, "\n"); + fflush((FILE*)ev->udata); +} + + +static void lock(void) { + if (L.lock) { L.lock(true, L.udata); } +} + + +static void unlock(void) { + if (L.lock) { L.lock(false, L.udata); } +} + + +const char* log_level_string(int level) { + return level_strings[level]; +} + + +void log_set_lock(log_LockFn fn, void* udata) { + L.lock = fn; + L.udata = udata; +} + + +void log_set_level(int level) { + L.level = level; +} + + +void log_set_quiet(bool enable) { + L.quiet = enable; +} + + +int log_add_callback(log_LogFn fn, void* udata, int level) { + for (int i = 0; i < MAX_CALLBACKS; i++) { + if (!L.callbacks[i].fn) { + L.callbacks[i] = (Callback){ fn, udata, level }; + return 0; + } + } + return -1; +} + + +int log_add_fp(FILE* fp, int level) { + return log_add_callback(file_callback, fp, level); +} + + +static void init_event(log_Event* ev, void* udata) { + if (!ev->time) { + time_t t = time(NULL); + ev->time = localtime(&t); + } + ev->udata = udata; +} + + +void log_log(int level, const char* file, int line, const char* fmt, ...) { + log_Event ev = { + .fmt = fmt, + .file = file, + .line = line, + .level = level, + }; + + lock(); + + if (!L.quiet && level >= L.level) { + init_event(&ev, stderr); + va_start(ev.ap, fmt); + stdout_callback(&ev); + va_end(ev.ap); + } + + for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { + Callback* cb = &L.callbacks[i]; + if (level >= cb->level) { + init_event(&ev, cb->udata); + va_start(ev.ap, fmt); + cb->fn(&ev); + va_end(ev.ap); + } + } + + unlock(); +} diff --git a/external/libdumper/source/main.cpp b/external/libdumper/source/main.cpp new file mode 100644 index 0000000..5f28cd2 --- /dev/null +++ b/external/libdumper/source/main.cpp @@ -0,0 +1,26 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "common.hpp" +#include "dump.hpp" +#include "dumper.h" +#include +#include + +#define DUMPER_LOG "/user/app/ITEM00001/logs/if_dumper.log" + + +bool Dumper(std::string &dump_path, std::string &title_id, Dump_Options opt, std::string &title) +{ + /*-- INIT LOGGING FUNCS --*/ + unlink(DUMPER_LOG); + log_set_quiet(false); + log_set_level(LOG_DEBUG); + FILE* fp = fopen(DUMPER_LOG, "w"); + if(fp != NULL) + log_add_fp(fp, LOG_DEBUG); + + log_info("LibDumper Started with path: %s tid: %s title: %s opt: %i", dump_path.c_str(), title_id.c_str(), title.c_str(), opt); + return dump::__dump(dump_path, title_id, opt, title); +} + diff --git a/external/libdumper/source/npbind.cpp b/external/libdumper/source/npbind.cpp new file mode 100644 index 0000000..8633a25 --- /dev/null +++ b/external/libdumper/source/npbind.cpp @@ -0,0 +1,116 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "npbind.hpp" +#include "common.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "libshahash.h" + +namespace npbind { +std::vector read(const std::string &path) { // Flawfinder: ignore + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path)) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream npbind_input(path, std::ios::in | std::ios::binary); + if (!npbind_input || !npbind_input.good()) { + npbind_input.close(); + log_error("Cannot open file: %s", path.c_str()); + } + + // Check file magic (Read in whole header) + NpBindHeader header; + npbind_input.read((char *)&header, sizeof(header)); // Flawfinder: ignore + if (!npbind_input.good()) { + npbind_input.close(); + log_error("Error reading header!"); + } + if (__builtin_bswap32(header.magic) != NPBIND_MAGIC) { + npbind_input.close(); + log_error("Input path is not a npbind.dat!"); + } + + // Read in body(s) + std::vector entries; + for (uint64_t i = 0; i < __builtin_bswap64(header.num_entries); i++) { + NpBindEntry temp_entry; + npbind_input.read((char *)&temp_entry, __builtin_bswap64(header.entry_size)); // Flawfinder: ignore + if (!npbind_input.good()) { + npbind_input.close(); + log_error("Error reading entries!"); + } + entries.push_back(temp_entry); + } + + // Read digest + unsigned char digest[20]; + npbind_input.seekg(-sizeof(digest), npbind_input.end); // Make sure we are in the right place + npbind_input.read((char *)&digest, sizeof(digest)); // Flawfinder: ignore + if (!npbind_input.good()) { + // Should never reach here... will affect coverage % + npbind_input.close(); + log_error("Error reading digest!"); + } + npbind_input.close(); + + // Check digest + unsigned char calculated_digest[sizeof(digest)]; + + std::stringstream ss; + ss.write(reinterpret_cast(&header), sizeof(header)); + + for (uint64_t i = 0; i < __builtin_bswap64(header.num_entries); i++) { + ss.write(reinterpret_cast(&entries[i]), sizeof(NpBindEntry)); + } + + unsigned char data_to_hash[ss.str().size()]; + for (size_t i = 0; i < ss.str().size(); i++) { + data_to_hash[i] = ss.str().c_str()[i]; + } + + Sha1Context context; + Sha1BlockInit(&context); + Sha1BlockUpdate(&context, data_to_hash, ss.str().size()); + Sha1BlockResult(&context, calculated_digest); + +#if 0 + printf("\[SHA1] Digest: "); + + for (int i = 0; i < 20; i++) + printf("%x", digest[i]); + + printf("\n"); + + + printf("\[SHA1] calculated_digest: "); + + for (int i = 0; i < 20; i++) + printf("%x", calculated_digest[i]); + + printf("\n"); +#endif + + if (std::memcmp(calculated_digest, digest, sizeof(digest)) != 0) { + log_info("[SHA1] File %s has failed validation", path.c_str()); + } + else + log_info("[SHA1] File %s Successfully validated", path.c_str()); + + return entries; +} +} // namespace npbind diff --git a/external/libdumper/source/pfs.cpp b/external/libdumper/source/pfs.cpp new file mode 100644 index 0000000..21348ec --- /dev/null +++ b/external/libdumper/source/pfs.cpp @@ -0,0 +1,221 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "pkg.hpp" +#include "common.hpp" +#include "log.h" +extern "C" { +#include "lang.h" +} + +#include +#include +#include +#include +#include +#include "pfs.hpp" +#include + +uint32_t pfs_progress = 10; + +namespace pfs { + pfs_header* header; + uint64_t pfs_size; + uint64_t pfs_copied; + di_d32* inodes; + + char* copy_buffer = NULL; + int pfs; + + void memcpy_to_file(const char* fname, uint64_t ptr, uint64_t size) + { + uint64_t bytes; + uint64_t ix = 0; + + int fd = sceKernelOpen(fname, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0777); + log_info("---- name: %s, ptr %p, sz %zu, FD: %i", fname, ptr, size, fd); + if (fd > 0) + { + while (size > 0) + { + bytes = (size > PFS_DUMP_BUFFER) ? PFS_DUMP_BUFFER : size; + log_info("copying %llu bytes ix: %i size: %llu pfs prog: %llu/%llu", bytes, ix, size, pfs_copied, pfs_size); + sceKernelLseek(pfs, ptr + ix * PFS_DUMP_BUFFER, SEEK_SET); + sceKernelRead(pfs, copy_buffer, bytes); + sceKernelWrite(fd, copy_buffer, bytes); + size -= bytes; + ix++; + pfs_copied += bytes; + if (pfs_copied > pfs_size) pfs_copied = pfs_size; + pfs_progress = (uint64_t)(((float)pfs_copied / pfs_size) * 100.f); + + } + log_info("Close(fd): %x", sceKernelClose(fd)); + } + else + { + log_error("Cannot copy file |%s|\n\nError: %x!", fname, fd); + } + } + + void __parse_directory(uint32_t ino, uint32_t lev, const char* parent_name, bool dry_run, char* title, const char* tid) + { + for (uint32_t z = 0; z < inodes[ino].blocks; z++) + { + uint32_t db = inodes[ino].db[0] + z; + uint64_t pos = (uint64_t)header->blocksz * db; + uint64_t size = inodes[ino].size; + uint64_t top = pos + size; + + while (pos < top) + { + pfs_dirent_t* ent = (pfs_dirent_t*)malloc(sizeof(pfs_dirent_t)); + sceKernelLseek(pfs, pos, SEEK_SET); + sceKernelRead(pfs, ent, sizeof(pfs_dirent_t)); + + if (ent->type == 0) + { + free(ent); + break; + } + + char* name = (char*)malloc(ent->namelen + 1); + memset(name, 0, ent->namelen + 1); + if (lev > 0) + { + sceKernelLseek(pfs, pos + sizeof(pfs_dirent_t), SEEK_SET); + sceKernelRead(pfs, name, ent->namelen); + } + + + char* fname = (char*)malloc(strlen(parent_name) + ent->namelen + 2); + if (parent_name != NULL) + sprintf(fname, "%s/%s", parent_name, name); + else + sprintf(fname, "%s", name); + + if ((ent->type == 2) && (lev > 0)) + { + if (!dry_run) { + if (strstr(fname, "patch")) + ProgUpdate(pfs_progress, "%s\n\n%s %s\n%s %s\n\n%s\n %s...\n", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title, getDumperLangSTR(TITLE_ID), tid, getDumperLangSTR(EXT_PATCH), fname); + else + ProgUpdate(pfs_progress, "%s\n\n%s %s\n%s %s\n\n%s\n %s...\n", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title, getDumperLangSTR(TITLE_ID), tid, getDumperLangSTR(EXT_GAME_FILES), fname); + } + if (dry_run) + pfs_size += inodes[ent->ino].size; + else + memcpy_to_file(fname, (uint64_t)header->blocksz * inodes[ent->ino].db[0], inodes[ent->ino].size); + + log_info("%s -- prog %i", fname, pfs_progress); + } + else + if (ent->type == 3) + { + log_info(">scan dir %s", name); + mkdir(fname, 0777); + __parse_directory(ent->ino, lev + 1, fname, dry_run, title, tid); + } + + pos += ent->entsize; + + free(ent); + free(name); + free(fname); + } + } + } + + void dump_pfs(uint32_t ino, uint32_t level, const std::string& output_path, const char* tid, char* title) { + __parse_directory(ino, level, output_path.c_str(), false, title, tid); + } + + void calculate_pfs(uint32_t ino, uint32_t level, const std::string& output_path) { + __parse_directory(ino, level, output_path.c_str(), true); + } + + bool extract(const std::string& pfs_path, const std::string& output_path, const char* tid, char* title) + { + pfs_progress = 11; + + pfs = sceKernelOpen(pfs_path.c_str(), O_RDONLY, 0); + if (pfs < 0) { + log_fatal("could not open %s", pfs_path.c_str()); + return false; + } + + + if ((copy_buffer = (char*)malloc(PFS_DUMP_BUFFER)) != NULL) + { + + if ((header = (pfs_header*)malloc(sizeof(pfs_header))) != NULL) + { + sceKernelLseek(pfs, 0, SEEK_SET); + sceKernelRead(pfs, header, sizeof(pfs_header)); + + if (__builtin_bswap64(header->magic) != PFS_MAGIC) { + log_fatal("MAGIC != PFS_MAGIC"); + sceKernelClose(pfs); + free(copy_buffer); + free(header); + return false; + } + + if ((inodes = (di_d32*)malloc(sizeof(di_d32) * header->ndinode)) != NULL) + { + + uint32_t ix = 0; + + ProgUpdate(20, "%s\n\n%s %s\n%s %s\n\n %s ...", getDumperLangSTR(DUMP_INFO), getDumperLangSTR(APP_NAME), title, getDumperLangSTR(TITLE_ID), tid, getDumperLangSTR(PROCESSING)); + + for (uint32_t i = 0; i < header->ndinodeblock; i++) + { + for (uint32_t j = 0; (j < (header->blocksz / sizeof(di_d32))) && (ix < header->ndinode); j++) + { + sceKernelLseek(pfs, (uint64_t)header->blocksz * (i + 1) + sizeof(di_d32) * j, SEEK_SET); + sceKernelRead(pfs, &inodes[ix], sizeof(di_d32)); + + ix++; + } + } + + pfs_size = 0; + pfs_copied = 0; + + calculate_pfs((uint32_t)header->superroot_ino, (uint32_t)0, output_path); + dump_pfs((uint32_t)header->superroot_ino, (uint32_t)0, output_path, tid, title); + + free(header); + free(inodes); + free(copy_buffer); + sceKernelClose(pfs); + } + else + { + free(copy_buffer); + free(header); + sceKernelClose(pfs); + log_fatal("Buffer is NULL"); + return false; + } + } + else + { + free(copy_buffer); + log_fatal("Buffer is NULL"); + return false; + } + } + else + { + + log_fatal("Buffer is NULL"); + return false; + } + + return true; + } + +} // namespace pfs + + diff --git a/external/libdumper/source/pkg.cpp b/external/libdumper/source/pkg.cpp new file mode 100644 index 0000000..0d90916 --- /dev/null +++ b/external/libdumper/source/pkg.cpp @@ -0,0 +1,260 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "pkg.hpp" +#include "common.hpp" + +#include +#include +#include +#include +#include +#include +#include "log.h" +#include +#include +#include +#include + +namespace pkg { +std::string get_entry_name_by_type(uint32_t type) { + std::stringstream ss; + + if (type == 0x0400) { + ss << "license.dat"; + } else if (type == 0x0401) { + ss << "license.info"; + } else if (type == 0x0402) { + ss << "nptitle.dat.encrypted"; + } else if (type == 0x0403) { + ss << "npbind.dat.encrypted"; + } else if (type == 0x0404) { + ss << "selfinfo.dat"; + } else if (type == 0x0406) { + ss << "imageinfo.dat"; + } else if (type == 0x0407) { + ss << "target-deltainfo.dat"; + } else if (type == 0x0408) { + ss << "origin-deltainfo.dat"; + } else if (type == 0x0409) { + ss << "psreserved.dat"; + } else if (type == 0x1000) { + ss << "param.sfo"; + } else if (type == 0x1001) { + ss << "playgo-chunk.dat"; + } else if (type == 0x1002) { + ss << "playgo-chunk.sha"; + } else if (type == 0x1003) { + ss << "playgo-manifest.xml"; + } else if (type == 0x1004) { + ss << "pronunciation.xml"; + } else if (type == 0x1005) { + ss << "pronunciation.sig"; + } else if (type == 0x1006) { + ss << "pic1.png"; + } else if (type == 0x1007) { + ss << "pubtoolinfo.dat"; + } else if (type == 0x1008) { + ss << "app/playgo-chunk.dat"; + } else if (type == 0x1009) { + ss << "app/playgo-chunk.sha"; + } else if (type == 0x100A) { + ss << "app/playgo-manifest.xml"; + } else if (type == 0x100B) { + ss << "shareparam.json"; + } else if (type == 0x100C) { + ss << "shareoverlayimage.png"; + } else if (type == 0x100D) { + ss << "save_data.png"; + } else if (type == 0x100E) { + ss << "shareprivacyguardimage.png"; + } else if (type == 0x1200) { + ss << "icon0.png"; + } else if ((type >= 0x1201) && (type <= 0x121F)) { + ss << "icon0_" << std::setfill('0') << std::setw(2) << type - 0x1201 << ".png"; + } else if (type == 0x1220) { + ss << "pic0.png"; + } else if (type == 0x1240) { + ss << "snd0.at9"; + } else if ((type >= 0x1241) && (type <= 0x125F)) { + ss << "pic1_" << std::setfill('0') << std::setw(2) << type - 0x1241 << ".png"; + } else if (type == 0x1260) { + ss << "changeinfo/changeinfo.xml"; + } else if ((type >= 0x1261) && (type <= 0x127F)) { + ss << "changeinfo/changeinfo_" << std::setfill('0') << std::setw(2) << type - 0x1261 << ".xml"; + } else if (type == 0x1280) { + ss << "icon0.dds"; + } else if ((type >= 0x1281) && (type <= 0x129F)) { + ss << "icon0_" << std::setfill('0') << std::setw(2) << type - 0x1281 << ".dds"; + } else if (type == 0x12A0) { + ss << "pic0.dds"; + } else if (type == 0x12C0) { + ss << "pic1.dds"; + } else if ((type >= 0x12C1) && (type <= 0x12DF)) { + ss << "pic1_" << std::setfill('0') << std::setw(2) << type - 0x12C1 << ".dds"; + } else if ((type >= 0x1400) && (type <= 0x147F)) { + ss << "trophy/trophy" << std::setfill('0') << std::setw(2) << type - 0x1400 << ".trp.encrypted"; + } else if ((type >= 0x1600) && (type <= 0x1609)) { + ss << "keymap_rp/" << std::setfill('0') << std::setw(3) << type - 0x15FF << ".png"; + } else if ((type >= 0x1610) && (type <= 0x16F5)) { + ss << "keymap_rp/" << std::setfill('0') << std::setw(2) << (type - 0x1610) / 10 << "/" << std::setfill('0') << std::setw(3) << (((type - 0x160F) % 10) ? (type - 0x160F) % 10 : 10) << ".png"; + } + + return ss.str(); +} + +bool extract_sc0(const std::string &pkg_path, const std::string &output_path, const std::string& tid, const std::string& title) { + // Check for empty or pure whitespace path + if (pkg_path.empty() || std::all_of(pkg_path.begin(), pkg_path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty input path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(pkg_path)) { + log_error("Input path does not exist or is not a file!"); + return false; + } + + // Open path + std::ifstream pkg_input(pkg_path, std::ios::in | std::ios::binary); + if (!pkg_input || !pkg_input.good()) { + pkg_input.close(); + log_error("Cannot open input file: %s" ,pkg_path.c_str()); + } + + // Check file magic (Read in whole header) + PkgHeader header; + pkg_input.read((char *)&header, sizeof(header)); // Flawfinder: ignore + if (!pkg_input.good()) { + pkg_input.close(); + log_error("Error reading PKG header!"); + return false; + } + if (__builtin_bswap32(header.magic) != PKG_MAGIC) { + pkg_input.close(); + log_error("Input path is not a PKG!"); + return false; + } + + + + // Read PKG entry table entries + std::vector entries; + pkg_input.seekg(__builtin_bswap32(header.entry_table_offset), pkg_input.beg); + for (uint32_t i = 0; i < __builtin_bswap32(header.entry_count); i++) { + PkgTableEntry temp_entry; + pkg_input.read((char *)&temp_entry, sizeof(temp_entry)); // Flawfinder: ignore + if (!pkg_input.good()) { + pkg_input.close(); + log_error("Error reading entry table!"); + return false; + } + entries.push_back(temp_entry); + } + + + // Check for empty or pure whitespace path + if (output_path.empty() || std::all_of(output_path.begin(), output_path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty output path argument!"); + return false; + } + + // Make sure output directory path exists or can be created + if (!std::filesystem::is_directory(output_path) && !std::filesystem::create_directories(output_path)) { + pkg_input.close(); + log_error("Unable to open/create output directory"); + return false; + } + + + + // Extract sc0 entries + for (auto &&entry : entries) { + std::string entry_name = get_entry_name_by_type(__builtin_bswap32(entry.id)); + if (!entry_name.empty()) { + std::filesystem::path temp_output_path(output_path); + temp_output_path /= entry_name; + + printf("Step %s\n", temp_output_path.string().c_str()); + + pkg_input.seekg(__builtin_bswap32(entry.offset), pkg_input.beg); + char* buf = (char*)malloc(__builtin_bswap32(entry.size)); + if (buf != nullptr) + { + pkg_input.read(buf, __builtin_bswap32(entry.size)); // Flawfinder: ignore + if (!pkg_input.good()) { + pkg_input.close(); + log_error("Error reading entry data!"); + return false; + } + } + else { + printf("buf null\n"); + return false; + } + + std::string temp_output_dir = temp_output_path; + + const size_t last_slash_idx = temp_output_dir.rfind('/'); + if (std::string::npos != last_slash_idx) + { + temp_output_dir = temp_output_dir.substr(0, last_slash_idx); + } + + + if (!std::filesystem::is_directory(temp_output_dir) && mkdir(temp_output_dir.c_str(), 0777) == 0) { + // pkg_input.close(); + log_error("Unable to open/create output subdirectory"); + } + + + // Write to file + //unlink anyways idc + unlink(temp_output_path.c_str()); + int fd = open(temp_output_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (fd >= 0) { + + write(fd, buf, __builtin_bswap32(entry.size)); + close(fd); + } + else { + + printf("Write to file failed\n"); + pkg_input.close(); + return false; + } + + + free(buf); + + } + } + pkg_input.close(); + + std::string npbind_out = output_path + "/npbind.dat"; + std::string nptitle_out = output_path + "/nptitle.dat"; + std::string npbind_in = "/system_data/priv/appmeta/" + tid + "/npbind.dat"; + std::string nptitle_in = "/system_data/priv/appmeta/" + tid + "/nptitle.dat"; + + if (std::filesystem::is_regular_file(npbind_in)) { + if (!std::filesystem::copy_file(npbind_in, npbind_out, std::filesystem::copy_options::overwrite_existing)) { + log_error("Unable to copy %s to %s", npbind_out.c_str(), npbind_in.c_str()); + } + else + log_info("Copied npbind succssfully"); + } + if (std::filesystem::is_regular_file(nptitle_in)) { + if (!std::filesystem::copy_file(nptitle_in, nptitle_out, std::filesystem::copy_options::overwrite_existing)) { + log_error("Unable to copy %s to %s", nptitle_out.c_str(), nptitle_in.c_str()); + } + else + log_info("Copied nptitle succssfully"); + } + + + + printf("UNPKG ENDED %i\n", __LINE__); + + return true; +} +} // namespace pkg diff --git a/external/libdumper/source/pugixml.cpp b/external/libdumper/source/pugixml.cpp new file mode 100644 index 0000000..3f18afc --- /dev/null +++ b/external/libdumper/source/pugixml.cpp @@ -0,0 +1,13027 @@ +/** + * pugixml parser - version 1.11 + * -------------------------------------------------------- + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ + * + * This library is distributed under the MIT License. See notice at the end + * of this file. + * + * This work is based on the pugxml parser, which is: + * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) + */ + +#ifndef SOURCE_PUGIXML_CPP +#define SOURCE_PUGIXML_CPP + +#include "pugixml.hpp" + +#include +#include +#include +#include +#include + +#ifdef PUGIXML_WCHAR_MODE +# include +#endif + +#ifndef PUGIXML_NO_XPATH +# include +# include +#endif + +#ifndef PUGIXML_NO_STL +# include +# include +# include +#endif + +// For placement new +#include + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4127) // conditional expression is constant +# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) +# pragma warning(disable: 4702) // unreachable code +# pragma warning(disable: 4996) // this function or variable may be unsafe +#endif + +#if defined(_MSC_VER) && defined(__c2__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" // this function or variable may be unsafe +#endif + +#ifdef __INTEL_COMPILER +# pragma warning(disable: 177) // function was declared but never referenced +# pragma warning(disable: 279) // controlling expression is constant +# pragma warning(disable: 1478 1786) // function was declared "deprecated" +# pragma warning(disable: 1684) // conversion from pointer to same-sized integral type +#endif + +#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY) +# pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away +#endif + +#ifdef __BORLANDC__ +# pragma option push +# pragma warn -8008 // condition is always false +# pragma warn -8066 // unreachable code +#endif + +#ifdef __SNC__ +// Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug +# pragma diag_suppress=178 // function was declared but never referenced +# pragma diag_suppress=237 // controlling expression is constant +#endif + +#ifdef __TI_COMPILER_VERSION__ +# pragma diag_suppress 179 // function was declared but never referenced +#endif + +// Inlining controls +#if defined(_MSC_VER) && _MSC_VER >= 1300 +# define PUGI__NO_INLINE __declspec(noinline) +#elif defined(__GNUC__) +# define PUGI__NO_INLINE __attribute__((noinline)) +#else +# define PUGI__NO_INLINE +#endif + +// Branch weight controls +#if defined(__GNUC__) && !defined(__c2__) +# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) +#else +# define PUGI__UNLIKELY(cond) (cond) +#endif + +// Simple static assertion +#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } + +// Digital Mars C++ bug workaround for passing char loaded from memory via stack +#ifdef __DMC__ +# define PUGI__DMC_VOLATILE volatile +#else +# define PUGI__DMC_VOLATILE +#endif + +// Integer sanitizer workaround; we only apply this for clang since gcc8 has no_sanitize but not unsigned-integer-overflow and produces "attribute directive ignored" warnings +#if defined(__clang__) && defined(__has_attribute) +# if __has_attribute(no_sanitize) +# define PUGI__UNSIGNED_OVERFLOW __attribute__((no_sanitize("unsigned-integer-overflow"))) +# else +# define PUGI__UNSIGNED_OVERFLOW +# endif +#else +# define PUGI__UNSIGNED_OVERFLOW +#endif + +// Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) +#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) +using std::memcpy; +using std::memmove; +using std::memset; +#endif + +// Some MinGW/GCC versions have headers that erroneously omit LLONG_MIN/LLONG_MAX/ULLONG_MAX definitions from limits.h in some configurations +#if defined(PUGIXML_HAS_LONG_LONG) && defined(__GNUC__) && !defined(LLONG_MAX) && !defined(LLONG_MIN) && !defined(ULLONG_MAX) +# define LLONG_MIN (-LLONG_MAX - 1LL) +# define LLONG_MAX __LONG_LONG_MAX__ +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +#endif + +// In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features +#if defined(_MSC_VER) && !defined(__S3E__) +# define PUGI__MSVC_CRT_VERSION _MSC_VER +#endif + +// Not all platforms have snprintf; we define a wrapper that uses snprintf if possible. This only works with buffers with a known size. +#if __cplusplus >= 201103 +# define PUGI__SNPRINTF(buf, ...) snprintf(buf, sizeof(buf), __VA_ARGS__) +#elif defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 +# define PUGI__SNPRINTF(buf, ...) _snprintf_s(buf, _countof(buf), _TRUNCATE, __VA_ARGS__) +#else +# define PUGI__SNPRINTF sprintf +#endif + +// We put implementation details into an anonymous namespace in source mode, but have to keep it in non-anonymous namespace in header-only mode to prevent binary bloat. +#ifdef PUGIXML_HEADER_ONLY +# define PUGI__NS_BEGIN namespace pugi { namespace impl { +# define PUGI__NS_END } } +# define PUGI__FN inline +# define PUGI__FN_NO_INLINE inline +#else +# if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces +# define PUGI__NS_BEGIN namespace pugi { namespace impl { +# define PUGI__NS_END } } +# else +# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace { +# define PUGI__NS_END } } } +# endif +# define PUGI__FN +# define PUGI__FN_NO_INLINE PUGI__NO_INLINE +#endif + +// uintptr_t +#if (defined(_MSC_VER) && _MSC_VER < 1600) || (defined(__BORLANDC__) && __BORLANDC__ < 0x561) +namespace pugi +{ +# ifndef _UINTPTR_T_DEFINED + typedef size_t uintptr_t; +# endif + + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +} +#else +# include +#endif + +// Memory allocation +PUGI__NS_BEGIN + PUGI__FN void* default_allocate(size_t size) + { + return malloc(size); + } + + PUGI__FN void default_deallocate(void* ptr) + { + free(ptr); + } + + template + struct xml_memory_management_function_storage + { + static allocation_function allocate; + static deallocation_function deallocate; + }; + + // Global allocation functions are stored in class statics so that in header mode linker deduplicates them + // Without a template<> we'll get multiple definitions of the same static + template allocation_function xml_memory_management_function_storage::allocate = default_allocate; + template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; + + typedef xml_memory_management_function_storage xml_memory; +PUGI__NS_END + +// String utilities +PUGI__NS_BEGIN + // Get string length + PUGI__FN size_t strlength(const char_t* s) + { + assert(s); + + #ifdef PUGIXML_WCHAR_MODE + return wcslen(s); + #else + return strlen(s); + #endif + } + + // Compare two strings + PUGI__FN bool strequal(const char_t* src, const char_t* dst) + { + assert(src && dst); + + #ifdef PUGIXML_WCHAR_MODE + return wcscmp(src, dst) == 0; + #else + return strcmp(src, dst) == 0; + #endif + } + + // Compare lhs with [rhs_begin, rhs_end) + PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) + { + for (size_t i = 0; i < count; ++i) + if (lhs[i] != rhs[i]) + return false; + + return lhs[count] == 0; + } + + // Get length of wide string, even if CRT lacks wide character support + PUGI__FN size_t strlength_wide(const wchar_t* s) + { + assert(s); + + #ifdef PUGIXML_WCHAR_MODE + return wcslen(s); + #else + const wchar_t* end = s; + while (*end) end++; + return static_cast(end - s); + #endif + } +PUGI__NS_END + +// auto_ptr-like object for exception recovery +PUGI__NS_BEGIN + template struct auto_deleter + { + typedef void (*D)(T*); + + T* data; + D deleter; + + auto_deleter(T* data_, D deleter_): data(data_), deleter(deleter_) + { + } + + ~auto_deleter() + { + if (data) deleter(data); + } + + T* release() + { + T* result = data; + data = 0; + return result; + } + }; +PUGI__NS_END + +#ifdef PUGIXML_COMPACT +PUGI__NS_BEGIN + class compact_hash_table + { + public: + compact_hash_table(): _items(0), _capacity(0), _count(0) + { + } + + void clear() + { + if (_items) + { + xml_memory::deallocate(_items); + _items = 0; + _capacity = 0; + _count = 0; + } + } + + void* find(const void* key) + { + if (_capacity == 0) return 0; + + item_t* item = get_item(key); + assert(item); + assert(item->key == key || (item->key == 0 && item->value == 0)); + + return item->value; + } + + void insert(const void* key, void* value) + { + assert(_capacity != 0 && _count < _capacity - _capacity / 4); + + item_t* item = get_item(key); + assert(item); + + if (item->key == 0) + { + _count++; + item->key = key; + } + + item->value = value; + } + + bool reserve(size_t extra = 16) + { + if (_count + extra >= _capacity - _capacity / 4) + return rehash(_count + extra); + + return true; + } + + private: + struct item_t + { + const void* key; + void* value; + }; + + item_t* _items; + size_t _capacity; + + size_t _count; + + bool rehash(size_t count); + + item_t* get_item(const void* key) + { + assert(key); + assert(_capacity > 0); + + size_t hashmod = _capacity - 1; + size_t bucket = hash(key) & hashmod; + + for (size_t probe = 0; probe <= hashmod; ++probe) + { + item_t& probe_item = _items[bucket]; + + if (probe_item.key == key || probe_item.key == 0) + return &probe_item; + + // hash collision, quadratic probing + bucket = (bucket + probe + 1) & hashmod; + } + + assert(false && "Hash table is full"); // unreachable + return 0; + } + + static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key) + { + unsigned int h = static_cast(reinterpret_cast(key) & 0xffffffff); + + // MurmurHash3 32-bit finalizer + h ^= h >> 16; + h *= 0x85ebca6bu; + h ^= h >> 13; + h *= 0xc2b2ae35u; + h ^= h >> 16; + + return h; + } + }; + + PUGI__FN_NO_INLINE bool compact_hash_table::rehash(size_t count) + { + size_t capacity = 32; + while (count >= capacity - capacity / 4) + capacity *= 2; + + compact_hash_table rt; + rt._capacity = capacity; + rt._items = static_cast(xml_memory::allocate(sizeof(item_t) * capacity)); + + if (!rt._items) + return false; + + memset(rt._items, 0, sizeof(item_t) * capacity); + + for (size_t i = 0; i < _capacity; ++i) + if (_items[i].key) + rt.insert(_items[i].key, _items[i].value); + + if (_items) + xml_memory::deallocate(_items); + + _capacity = capacity; + _items = rt._items; + + assert(_count == rt._count); + + return true; + } + +PUGI__NS_END +#endif + +PUGI__NS_BEGIN +#ifdef PUGIXML_COMPACT + static const uintptr_t xml_memory_block_alignment = 4; +#else + static const uintptr_t xml_memory_block_alignment = sizeof(void*); +#endif + + // extra metadata bits + static const uintptr_t xml_memory_page_contents_shared_mask = 64; + static const uintptr_t xml_memory_page_name_allocated_mask = 32; + static const uintptr_t xml_memory_page_value_allocated_mask = 16; + static const uintptr_t xml_memory_page_type_mask = 15; + + // combined masks for string uniqueness + static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; + static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; + +#ifdef PUGIXML_COMPACT + #define PUGI__GETHEADER_IMPL(object, page, flags) // unused + #define PUGI__GETPAGE_IMPL(header) (header).get_page() +#else + #define PUGI__GETHEADER_IMPL(object, page, flags) (((reinterpret_cast(object) - reinterpret_cast(page)) << 8) | (flags)) + // this macro casts pointers through void* to avoid 'cast increases required alignment of target type' warnings + #define PUGI__GETPAGE_IMPL(header) static_cast(const_cast(static_cast(reinterpret_cast(&header) - (header >> 8)))) +#endif + + #define PUGI__GETPAGE(n) PUGI__GETPAGE_IMPL((n)->header) + #define PUGI__NODETYPE(n) static_cast((n)->header & impl::xml_memory_page_type_mask) + + struct xml_allocator; + + struct xml_memory_page + { + static xml_memory_page* construct(void* memory) + { + xml_memory_page* result = static_cast(memory); + + result->allocator = 0; + result->prev = 0; + result->next = 0; + result->busy_size = 0; + result->freed_size = 0; + + #ifdef PUGIXML_COMPACT + result->compact_string_base = 0; + result->compact_shared_parent = 0; + result->compact_page_marker = 0; + #endif + + return result; + } + + xml_allocator* allocator; + + xml_memory_page* prev; + xml_memory_page* next; + + size_t busy_size; + size_t freed_size; + + #ifdef PUGIXML_COMPACT + char_t* compact_string_base; + void* compact_shared_parent; + uint32_t* compact_page_marker; + #endif + }; + + static const size_t xml_memory_page_size = + #ifdef PUGIXML_MEMORY_PAGE_SIZE + (PUGIXML_MEMORY_PAGE_SIZE) + #else + 32768 + #endif + - sizeof(xml_memory_page); + + struct xml_memory_string_header + { + uint16_t page_offset; // offset from page->data + uint16_t full_size; // 0 if string occupies whole page + }; + + struct xml_allocator + { + xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) + { + #ifdef PUGIXML_COMPACT + _hash = 0; + #endif + } + + xml_memory_page* allocate_page(size_t data_size) + { + size_t size = sizeof(xml_memory_page) + data_size; + + // allocate block with some alignment, leaving memory for worst-case padding + void* memory = xml_memory::allocate(size); + if (!memory) return 0; + + // prepare page structure + xml_memory_page* page = xml_memory_page::construct(memory); + assert(page); + + assert(this == _root->allocator); + page->allocator = this; + + return page; + } + + static void deallocate_page(xml_memory_page* page) + { + xml_memory::deallocate(page); + } + + void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); + + void* allocate_memory(size_t size, xml_memory_page*& out_page) + { + if (PUGI__UNLIKELY(_busy_size + size > xml_memory_page_size)) + return allocate_memory_oob(size, out_page); + + void* buf = reinterpret_cast(_root) + sizeof(xml_memory_page) + _busy_size; + + _busy_size += size; + + out_page = _root; + + return buf; + } + + #ifdef PUGIXML_COMPACT + void* allocate_object(size_t size, xml_memory_page*& out_page) + { + void* result = allocate_memory(size + sizeof(uint32_t), out_page); + if (!result) return 0; + + // adjust for marker + ptrdiff_t offset = static_cast(result) - reinterpret_cast(out_page->compact_page_marker); + + if (PUGI__UNLIKELY(static_cast(offset) >= 256 * xml_memory_block_alignment)) + { + // insert new marker + uint32_t* marker = static_cast(result); + + *marker = static_cast(reinterpret_cast(marker) - reinterpret_cast(out_page)); + out_page->compact_page_marker = marker; + + // since we don't reuse the page space until we reallocate it, we can just pretend that we freed the marker block + // this will make sure deallocate_memory correctly tracks the size + out_page->freed_size += sizeof(uint32_t); + + return marker + 1; + } + else + { + // roll back uint32_t part + _busy_size -= sizeof(uint32_t); + + return result; + } + } + #else + void* allocate_object(size_t size, xml_memory_page*& out_page) + { + return allocate_memory(size, out_page); + } + #endif + + void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) + { + if (page == _root) page->busy_size = _busy_size; + + assert(ptr >= reinterpret_cast(page) + sizeof(xml_memory_page) && ptr < reinterpret_cast(page) + sizeof(xml_memory_page) + page->busy_size); + (void)!ptr; + + page->freed_size += size; + assert(page->freed_size <= page->busy_size); + + if (page->freed_size == page->busy_size) + { + if (page->next == 0) + { + assert(_root == page); + + // top page freed, just reset sizes + page->busy_size = 0; + page->freed_size = 0; + + #ifdef PUGIXML_COMPACT + // reset compact state to maximize efficiency + page->compact_string_base = 0; + page->compact_shared_parent = 0; + page->compact_page_marker = 0; + #endif + + _busy_size = 0; + } + else + { + assert(_root != page); + assert(page->prev); + + // remove from the list + page->prev->next = page->next; + page->next->prev = page->prev; + + // deallocate + deallocate_page(page); + } + } + } + + char_t* allocate_string(size_t length) + { + static const size_t max_encoded_offset = (1 << 16) * xml_memory_block_alignment; + + PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); + + // allocate memory for string and header block + size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); + + // round size up to block alignment boundary + size_t full_size = (size + (xml_memory_block_alignment - 1)) & ~(xml_memory_block_alignment - 1); + + xml_memory_page* page; + xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); + + if (!header) return 0; + + // setup header + ptrdiff_t page_offset = reinterpret_cast(header) - reinterpret_cast(page) - sizeof(xml_memory_page); + + assert(page_offset % xml_memory_block_alignment == 0); + assert(page_offset >= 0 && static_cast(page_offset) < max_encoded_offset); + header->page_offset = static_cast(static_cast(page_offset) / xml_memory_block_alignment); + + // full_size == 0 for large strings that occupy the whole page + assert(full_size % xml_memory_block_alignment == 0); + assert(full_size < max_encoded_offset || (page->busy_size == full_size && page_offset == 0)); + header->full_size = static_cast(full_size < max_encoded_offset ? full_size / xml_memory_block_alignment : 0); + + // round-trip through void* to avoid 'cast increases required alignment of target type' warning + // header is guaranteed a pointer-sized alignment, which should be enough for char_t + return static_cast(static_cast(header + 1)); + } + + void deallocate_string(char_t* string) + { + // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings + // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string + + // get header + xml_memory_string_header* header = static_cast(static_cast(string)) - 1; + assert(header); + + // deallocate + size_t page_offset = sizeof(xml_memory_page) + header->page_offset * xml_memory_block_alignment; + xml_memory_page* page = reinterpret_cast(static_cast(reinterpret_cast(header) - page_offset)); + + // if full_size == 0 then this string occupies the whole page + size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size * xml_memory_block_alignment; + + deallocate_memory(header, full_size, page); + } + + bool reserve() + { + #ifdef PUGIXML_COMPACT + return _hash->reserve(); + #else + return true; + #endif + } + + xml_memory_page* _root; + size_t _busy_size; + + #ifdef PUGIXML_COMPACT + compact_hash_table* _hash; + #endif + }; + + PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) + { + const size_t large_allocation_threshold = xml_memory_page_size / 4; + + xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); + out_page = page; + + if (!page) return 0; + + if (size <= large_allocation_threshold) + { + _root->busy_size = _busy_size; + + // insert page at the end of linked list + page->prev = _root; + _root->next = page; + _root = page; + + _busy_size = size; + } + else + { + // insert page before the end of linked list, so that it is deleted as soon as possible + // the last page is not deleted even if it's empty (see deallocate_memory) + assert(_root->prev); + + page->prev = _root->prev; + page->next = _root; + + _root->prev->next = page; + _root->prev = page; + + page->busy_size = size; + } + + return reinterpret_cast(page) + sizeof(xml_memory_page); + } +PUGI__NS_END + +#ifdef PUGIXML_COMPACT +PUGI__NS_BEGIN + static const uintptr_t compact_alignment_log2 = 2; + static const uintptr_t compact_alignment = 1 << compact_alignment_log2; + + class compact_header + { + public: + compact_header(xml_memory_page* page, unsigned int flags) + { + PUGI__STATIC_ASSERT(xml_memory_block_alignment == compact_alignment); + + ptrdiff_t offset = (reinterpret_cast(this) - reinterpret_cast(page->compact_page_marker)); + assert(offset % compact_alignment == 0 && static_cast(offset) < 256 * compact_alignment); + + _page = static_cast(offset >> compact_alignment_log2); + _flags = static_cast(flags); + } + + void operator&=(uintptr_t mod) + { + _flags &= static_cast(mod); + } + + void operator|=(uintptr_t mod) + { + _flags |= static_cast(mod); + } + + uintptr_t operator&(uintptr_t mod) const + { + return _flags & mod; + } + + xml_memory_page* get_page() const + { + // round-trip through void* to silence 'cast increases required alignment of target type' warnings + const char* page_marker = reinterpret_cast(this) - (_page << compact_alignment_log2); + const char* page = page_marker - *reinterpret_cast(static_cast(page_marker)); + + return const_cast(reinterpret_cast(static_cast(page))); + } + + private: + unsigned char _page; + unsigned char _flags; + }; + + PUGI__FN xml_memory_page* compact_get_page(const void* object, int header_offset) + { + const compact_header* header = reinterpret_cast(static_cast(object) - header_offset); + + return header->get_page(); + } + + template PUGI__FN_NO_INLINE T* compact_get_value(const void* object) + { + return static_cast(compact_get_page(object, header_offset)->allocator->_hash->find(object)); + } + + template PUGI__FN_NO_INLINE void compact_set_value(const void* object, T* value) + { + compact_get_page(object, header_offset)->allocator->_hash->insert(object, value); + } + + template class compact_pointer + { + public: + compact_pointer(): _data(0) + { + } + + void operator=(const compact_pointer& rhs) + { + *this = rhs + 0; + } + + void operator=(T* value) + { + if (value) + { + // value is guaranteed to be compact-aligned; 'this' is not + // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*) + // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to + // compensate for arithmetic shift rounding for negative values + ptrdiff_t diff = reinterpret_cast(value) - reinterpret_cast(this); + ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) - start; + + if (static_cast(offset) <= 253) + _data = static_cast(offset + 1); + else + { + compact_set_value(this, value); + + _data = 255; + } + } + else + _data = 0; + } + + operator T*() const + { + if (_data) + { + if (_data < 255) + { + uintptr_t base = reinterpret_cast(this) & ~(compact_alignment - 1); + + return reinterpret_cast(base + (_data - 1 + start) * compact_alignment); + } + else + return compact_get_value(this); + } + else + return 0; + } + + T* operator->() const + { + return *this; + } + + private: + unsigned char _data; + }; + + template class compact_pointer_parent + { + public: + compact_pointer_parent(): _data(0) + { + } + + void operator=(const compact_pointer_parent& rhs) + { + *this = rhs + 0; + } + + void operator=(T* value) + { + if (value) + { + // value is guaranteed to be compact-aligned; 'this' is not + // our decoding is based on 'this' aligned to compact alignment downwards (see operator T*) + // so for negative offsets (e.g. -3) we need to adjust the diff by compact_alignment - 1 to + // compensate for arithmetic shift behavior for negative values + ptrdiff_t diff = reinterpret_cast(value) - reinterpret_cast(this); + ptrdiff_t offset = ((diff + int(compact_alignment - 1)) >> compact_alignment_log2) + 65533; + + if (static_cast(offset) <= 65533) + { + _data = static_cast(offset + 1); + } + else + { + xml_memory_page* page = compact_get_page(this, header_offset); + + if (PUGI__UNLIKELY(page->compact_shared_parent == 0)) + page->compact_shared_parent = value; + + if (page->compact_shared_parent == value) + { + _data = 65534; + } + else + { + compact_set_value(this, value); + + _data = 65535; + } + } + } + else + { + _data = 0; + } + } + + operator T*() const + { + if (_data) + { + if (_data < 65534) + { + uintptr_t base = reinterpret_cast(this) & ~(compact_alignment - 1); + + return reinterpret_cast(base + (_data - 1 - 65533) * compact_alignment); + } + else if (_data == 65534) + return static_cast(compact_get_page(this, header_offset)->compact_shared_parent); + else + return compact_get_value(this); + } + else + return 0; + } + + T* operator->() const + { + return *this; + } + + private: + uint16_t _data; + }; + + template class compact_string + { + public: + compact_string(): _data(0) + { + } + + void operator=(const compact_string& rhs) + { + *this = rhs + 0; + } + + void operator=(char_t* value) + { + if (value) + { + xml_memory_page* page = compact_get_page(this, header_offset); + + if (PUGI__UNLIKELY(page->compact_string_base == 0)) + page->compact_string_base = value; + + ptrdiff_t offset = value - page->compact_string_base; + + if (static_cast(offset) < (65535 << 7)) + { + // round-trip through void* to silence 'cast increases required alignment of target type' warnings + uint16_t* base = reinterpret_cast(static_cast(reinterpret_cast(this) - base_offset)); + + if (*base == 0) + { + *base = static_cast((offset >> 7) + 1); + _data = static_cast((offset & 127) + 1); + } + else + { + ptrdiff_t remainder = offset - ((*base - 1) << 7); + + if (static_cast(remainder) <= 253) + { + _data = static_cast(remainder + 1); + } + else + { + compact_set_value(this, value); + + _data = 255; + } + } + } + else + { + compact_set_value(this, value); + + _data = 255; + } + } + else + { + _data = 0; + } + } + + operator char_t*() const + { + if (_data) + { + if (_data < 255) + { + xml_memory_page* page = compact_get_page(this, header_offset); + + // round-trip through void* to silence 'cast increases required alignment of target type' warnings + const uint16_t* base = reinterpret_cast(static_cast(reinterpret_cast(this) - base_offset)); + assert(*base); + + ptrdiff_t offset = ((*base - 1) << 7) + (_data - 1); + + return page->compact_string_base + offset; + } + else + { + return compact_get_value(this); + } + } + else + return 0; + } + + private: + unsigned char _data; + }; +PUGI__NS_END +#endif + +#ifdef PUGIXML_COMPACT +namespace pugi +{ + struct xml_attribute_struct + { + xml_attribute_struct(impl::xml_memory_page* page): header(page, 0), namevalue_base(0) + { + PUGI__STATIC_ASSERT(sizeof(xml_attribute_struct) == 8); + } + + impl::compact_header header; + + uint16_t namevalue_base; + + impl::compact_string<4, 2> name; + impl::compact_string<5, 3> value; + + impl::compact_pointer prev_attribute_c; + impl::compact_pointer next_attribute; + }; + + struct xml_node_struct + { + xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(page, type), namevalue_base(0) + { + PUGI__STATIC_ASSERT(sizeof(xml_node_struct) == 12); + } + + impl::compact_header header; + + uint16_t namevalue_base; + + impl::compact_string<4, 2> name; + impl::compact_string<5, 3> value; + + impl::compact_pointer_parent parent; + + impl::compact_pointer first_child; + + impl::compact_pointer prev_sibling_c; + impl::compact_pointer next_sibling; + + impl::compact_pointer first_attribute; + }; +} +#else +namespace pugi +{ + struct xml_attribute_struct + { + xml_attribute_struct(impl::xml_memory_page* page): name(0), value(0), prev_attribute_c(0), next_attribute(0) + { + header = PUGI__GETHEADER_IMPL(this, page, 0); + } + + uintptr_t header; + + char_t* name; + char_t* value; + + xml_attribute_struct* prev_attribute_c; + xml_attribute_struct* next_attribute; + }; + + struct xml_node_struct + { + xml_node_struct(impl::xml_memory_page* page, xml_node_type type): name(0), value(0), parent(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) + { + header = PUGI__GETHEADER_IMPL(this, page, type); + } + + uintptr_t header; + + char_t* name; + char_t* value; + + xml_node_struct* parent; + + xml_node_struct* first_child; + + xml_node_struct* prev_sibling_c; + xml_node_struct* next_sibling; + + xml_attribute_struct* first_attribute; + }; +} +#endif + +PUGI__NS_BEGIN + struct xml_extra_buffer + { + char_t* buffer; + xml_extra_buffer* next; + }; + + struct xml_document_struct: public xml_node_struct, public xml_allocator + { + xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) + { + } + + const char_t* buffer; + + xml_extra_buffer* extra_buffers; + + #ifdef PUGIXML_COMPACT + compact_hash_table hash; + #endif + }; + + template inline xml_allocator& get_allocator(const Object* object) + { + assert(object); + + return *PUGI__GETPAGE(object)->allocator; + } + + template inline xml_document_struct& get_document(const Object* object) + { + assert(object); + + return *static_cast(PUGI__GETPAGE(object)->allocator); + } +PUGI__NS_END + +// Low-level DOM operations +PUGI__NS_BEGIN + inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) + { + xml_memory_page* page; + void* memory = alloc.allocate_object(sizeof(xml_attribute_struct), page); + if (!memory) return 0; + + return new (memory) xml_attribute_struct(page); + } + + inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) + { + xml_memory_page* page; + void* memory = alloc.allocate_object(sizeof(xml_node_struct), page); + if (!memory) return 0; + + return new (memory) xml_node_struct(page, type); + } + + inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) + { + if (a->header & impl::xml_memory_page_name_allocated_mask) + alloc.deallocate_string(a->name); + + if (a->header & impl::xml_memory_page_value_allocated_mask) + alloc.deallocate_string(a->value); + + alloc.deallocate_memory(a, sizeof(xml_attribute_struct), PUGI__GETPAGE(a)); + } + + inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) + { + if (n->header & impl::xml_memory_page_name_allocated_mask) + alloc.deallocate_string(n->name); + + if (n->header & impl::xml_memory_page_value_allocated_mask) + alloc.deallocate_string(n->value); + + for (xml_attribute_struct* attr = n->first_attribute; attr; ) + { + xml_attribute_struct* next = attr->next_attribute; + + destroy_attribute(attr, alloc); + + attr = next; + } + + for (xml_node_struct* child = n->first_child; child; ) + { + xml_node_struct* next = child->next_sibling; + + destroy_node(child, alloc); + + child = next; + } + + alloc.deallocate_memory(n, sizeof(xml_node_struct), PUGI__GETPAGE(n)); + } + + inline void append_node(xml_node_struct* child, xml_node_struct* node) + { + child->parent = node; + + xml_node_struct* head = node->first_child; + + if (head) + { + xml_node_struct* tail = head->prev_sibling_c; + + tail->next_sibling = child; + child->prev_sibling_c = tail; + head->prev_sibling_c = child; + } + else + { + node->first_child = child; + child->prev_sibling_c = child; + } + } + + inline void prepend_node(xml_node_struct* child, xml_node_struct* node) + { + child->parent = node; + + xml_node_struct* head = node->first_child; + + if (head) + { + child->prev_sibling_c = head->prev_sibling_c; + head->prev_sibling_c = child; + } + else + child->prev_sibling_c = child; + + child->next_sibling = head; + node->first_child = child; + } + + inline void insert_node_after(xml_node_struct* child, xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + child->parent = parent; + + if (node->next_sibling) + node->next_sibling->prev_sibling_c = child; + else + parent->first_child->prev_sibling_c = child; + + child->next_sibling = node->next_sibling; + child->prev_sibling_c = node; + + node->next_sibling = child; + } + + inline void insert_node_before(xml_node_struct* child, xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + child->parent = parent; + + if (node->prev_sibling_c->next_sibling) + node->prev_sibling_c->next_sibling = child; + else + parent->first_child = child; + + child->prev_sibling_c = node->prev_sibling_c; + child->next_sibling = node; + + node->prev_sibling_c = child; + } + + inline void remove_node(xml_node_struct* node) + { + xml_node_struct* parent = node->parent; + + if (node->next_sibling) + node->next_sibling->prev_sibling_c = node->prev_sibling_c; + else + parent->first_child->prev_sibling_c = node->prev_sibling_c; + + if (node->prev_sibling_c->next_sibling) + node->prev_sibling_c->next_sibling = node->next_sibling; + else + parent->first_child = node->next_sibling; + + node->parent = 0; + node->prev_sibling_c = 0; + node->next_sibling = 0; + } + + inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + xml_attribute_struct* head = node->first_attribute; + + if (head) + { + xml_attribute_struct* tail = head->prev_attribute_c; + + tail->next_attribute = attr; + attr->prev_attribute_c = tail; + head->prev_attribute_c = attr; + } + else + { + node->first_attribute = attr; + attr->prev_attribute_c = attr; + } + } + + inline void prepend_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + xml_attribute_struct* head = node->first_attribute; + + if (head) + { + attr->prev_attribute_c = head->prev_attribute_c; + head->prev_attribute_c = attr; + } + else + attr->prev_attribute_c = attr; + + attr->next_attribute = head; + node->first_attribute = attr; + } + + inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) + { + if (place->next_attribute) + place->next_attribute->prev_attribute_c = attr; + else + node->first_attribute->prev_attribute_c = attr; + + attr->next_attribute = place->next_attribute; + attr->prev_attribute_c = place; + place->next_attribute = attr; + } + + inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) + { + if (place->prev_attribute_c->next_attribute) + place->prev_attribute_c->next_attribute = attr; + else + node->first_attribute = attr; + + attr->prev_attribute_c = place->prev_attribute_c; + attr->next_attribute = place; + place->prev_attribute_c = attr; + } + + inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) + { + if (attr->next_attribute) + attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; + else + node->first_attribute->prev_attribute_c = attr->prev_attribute_c; + + if (attr->prev_attribute_c->next_attribute) + attr->prev_attribute_c->next_attribute = attr->next_attribute; + else + node->first_attribute = attr->next_attribute; + + attr->prev_attribute_c = 0; + attr->next_attribute = 0; + } + + PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) + { + if (!alloc.reserve()) return 0; + + xml_node_struct* child = allocate_node(alloc, type); + if (!child) return 0; + + append_node(child, node); + + return child; + } + + PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) + { + if (!alloc.reserve()) return 0; + + xml_attribute_struct* attr = allocate_attribute(alloc); + if (!attr) return 0; + + append_attribute(attr, node); + + return attr; + } +PUGI__NS_END + +// Helper classes for code generation +PUGI__NS_BEGIN + struct opt_false + { + enum { value = 0 }; + }; + + struct opt_true + { + enum { value = 1 }; + }; +PUGI__NS_END + +// Unicode utilities +PUGI__NS_BEGIN + inline uint16_t endian_swap(uint16_t value) + { + return static_cast(((value & 0xff) << 8) | (value >> 8)); + } + + inline uint32_t endian_swap(uint32_t value) + { + return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); + } + + struct utf8_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) return result + 1; + // U+0080..U+07FF + else if (ch < 0x800) return result + 2; + // U+0800..U+FFFF + else return result + 3; + } + + static value_type high(value_type result, uint32_t) + { + // U+10000..U+10FFFF + return result + 4; + } + }; + + struct utf8_writer + { + typedef uint8_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + // U+0000..U+007F + if (ch < 0x80) + { + *result = static_cast(ch); + return result + 1; + } + // U+0080..U+07FF + else if (ch < 0x800) + { + result[0] = static_cast(0xC0 | (ch >> 6)); + result[1] = static_cast(0x80 | (ch & 0x3F)); + return result + 2; + } + // U+0800..U+FFFF + else + { + result[0] = static_cast(0xE0 | (ch >> 12)); + result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[2] = static_cast(0x80 | (ch & 0x3F)); + return result + 3; + } + } + + static value_type high(value_type result, uint32_t ch) + { + // U+10000..U+10FFFF + result[0] = static_cast(0xF0 | (ch >> 18)); + result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); + result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); + result[3] = static_cast(0x80 | (ch & 0x3F)); + return result + 4; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf16_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 2; + } + }; + + struct utf16_writer + { + typedef uint16_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = static_cast(ch); + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + uint32_t msh = static_cast(ch - 0x10000) >> 10; + uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; + + result[0] = static_cast(0xD800 + msh); + result[1] = static_cast(0xDC00 + lsh); + + return result + 2; + } + + static value_type any(value_type result, uint32_t ch) + { + return (ch < 0x10000) ? low(result, ch) : high(result, ch); + } + }; + + struct utf32_counter + { + typedef size_t value_type; + + static value_type low(value_type result, uint32_t) + { + return result + 1; + } + + static value_type high(value_type result, uint32_t) + { + return result + 1; + } + }; + + struct utf32_writer + { + typedef uint32_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + + static value_type any(value_type result, uint32_t ch) + { + *result = ch; + + return result + 1; + } + }; + + struct latin1_writer + { + typedef uint8_t* value_type; + + static value_type low(value_type result, uint32_t ch) + { + *result = static_cast(ch > 255 ? '?' : ch); + + return result + 1; + } + + static value_type high(value_type result, uint32_t ch) + { + (void)ch; + + *result = '?'; + + return result + 1; + } + }; + + struct utf8_decoder + { + typedef uint8_t type; + + template static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits) + { + const uint8_t utf8_byte_mask = 0x3f; + + while (size) + { + uint8_t lead = *data; + + // 0xxxxxxx -> U+0000..U+007F + if (lead < 0x80) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + + // process aligned single-byte (ascii) blocks + if ((reinterpret_cast(data) & 3) == 0) + { + // round-trip through void* to silence 'cast increases required alignment of target type' warnings + while (size >= 4 && (*static_cast(static_cast(data)) & 0x80808080) == 0) + { + result = Traits::low(result, data[0]); + result = Traits::low(result, data[1]); + result = Traits::low(result, data[2]); + result = Traits::low(result, data[3]); + data += 4; + size -= 4; + } + } + } + // 110xxxxx -> U+0080..U+07FF + else if (static_cast(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); + data += 2; + size -= 2; + } + // 1110xxxx -> U+0800-U+FFFF + else if (static_cast(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) + { + result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); + data += 3; + size -= 3; + } + // 11110xxx -> U+10000..U+10FFFF + else if (static_cast(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) + { + result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); + data += 4; + size -= 4; + } + // 10xxxxxx or 11111xxx -> invalid + else + { + data += 1; + size -= 1; + } + } + + return result; + } + }; + + template struct utf16_decoder + { + typedef uint16_t type; + + template static inline typename Traits::value_type process(const uint16_t* data, size_t size, typename Traits::value_type result, Traits) + { + while (size) + { + uint16_t lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+D7FF + if (lead < 0xD800) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + } + // U+E000..U+FFFF + else if (static_cast(lead - 0xE000) < 0x2000) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + } + // surrogate pair lead + else if (static_cast(lead - 0xD800) < 0x400 && size >= 2) + { + uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; + + if (static_cast(next - 0xDC00) < 0x400) + { + result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); + data += 2; + size -= 2; + } + else + { + data += 1; + size -= 1; + } + } + else + { + data += 1; + size -= 1; + } + } + + return result; + } + }; + + template struct utf32_decoder + { + typedef uint32_t type; + + template static inline typename Traits::value_type process(const uint32_t* data, size_t size, typename Traits::value_type result, Traits) + { + while (size) + { + uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; + + // U+0000..U+FFFF + if (lead < 0x10000) + { + result = Traits::low(result, lead); + data += 1; + size -= 1; + } + // U+10000..U+10FFFF + else + { + result = Traits::high(result, lead); + data += 1; + size -= 1; + } + } + + return result; + } + }; + + struct latin1_decoder + { + typedef uint8_t type; + + template static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits) + { + while (size) + { + result = Traits::low(result, *data); + data += 1; + size -= 1; + } + + return result; + } + }; + + template struct wchar_selector; + + template <> struct wchar_selector<2> + { + typedef uint16_t type; + typedef utf16_counter counter; + typedef utf16_writer writer; + typedef utf16_decoder decoder; + }; + + template <> struct wchar_selector<4> + { + typedef uint32_t type; + typedef utf32_counter counter; + typedef utf32_writer writer; + typedef utf32_decoder decoder; + }; + + typedef wchar_selector::counter wchar_counter; + typedef wchar_selector::writer wchar_writer; + + struct wchar_decoder + { + typedef wchar_t type; + + template static inline typename Traits::value_type process(const wchar_t* data, size_t size, typename Traits::value_type result, Traits traits) + { + typedef wchar_selector::decoder decoder; + + return decoder::process(reinterpret_cast(data), size, result, traits); + } + }; + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) + { + for (size_t i = 0; i < length; ++i) + result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); + } +#endif +PUGI__NS_END + +PUGI__NS_BEGIN + enum chartype_t + { + ct_parse_pcdata = 1, // \0, &, \r, < + ct_parse_attr = 2, // \0, &, \r, ', " + ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab + ct_space = 8, // \r, \n, space, tab + ct_parse_cdata = 16, // \0, ], >, \r + ct_parse_comment = 32, // \0, -, >, \r + ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . + ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : + }; + + static const unsigned char chartype_table[256] = + { + 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 + 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 + 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 + + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, + 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 + }; + + enum chartypex_t + { + ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > + ctx_special_attr = 2, // Any symbol >= 0 and < 32, &, <, ", ' + ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ + ctx_digit = 8, // 0-9 + ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . + }; + + static const unsigned char chartypex_table[256] = + { + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3, // 0-15 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 + 0, 0, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 1, 0, // 48-63 + + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 + 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 + }; + +#ifdef PUGIXML_WCHAR_MODE + #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) +#else + #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) +#endif + + #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) + #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) + + PUGI__FN bool is_little_endian() + { + unsigned int ui = 1; + + return *reinterpret_cast(&ui) == 1; + } + + PUGI__FN xml_encoding get_wchar_encoding() + { + PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); + + if (sizeof(wchar_t) == 2) + return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + else + return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + } + + PUGI__FN bool parse_declaration_encoding(const uint8_t* data, size_t size, const uint8_t*& out_encoding, size_t& out_length) + { + #define PUGI__SCANCHAR(ch) { if (offset >= size || data[offset] != ch) return false; offset++; } + #define PUGI__SCANCHARTYPE(ct) { while (offset < size && PUGI__IS_CHARTYPE(data[offset], ct)) offset++; } + + // check if we have a non-empty XML declaration + if (size < 6 || !((data[0] == '<') & (data[1] == '?') & (data[2] == 'x') & (data[3] == 'm') & (data[4] == 'l') && PUGI__IS_CHARTYPE(data[5], ct_space))) + return false; + + // scan XML declaration until the encoding field + for (size_t i = 6; i + 1 < size; ++i) + { + // declaration can not contain ? in quoted values + if (data[i] == '?') + return false; + + if (data[i] == 'e' && data[i + 1] == 'n') + { + size_t offset = i; + + // encoding follows the version field which can't contain 'en' so this has to be the encoding if XML is well formed + PUGI__SCANCHAR('e'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('c'); PUGI__SCANCHAR('o'); + PUGI__SCANCHAR('d'); PUGI__SCANCHAR('i'); PUGI__SCANCHAR('n'); PUGI__SCANCHAR('g'); + + // S? = S? + PUGI__SCANCHARTYPE(ct_space); + PUGI__SCANCHAR('='); + PUGI__SCANCHARTYPE(ct_space); + + // the only two valid delimiters are ' and " + uint8_t delimiter = (offset < size && data[offset] == '"') ? '"' : '\''; + + PUGI__SCANCHAR(delimiter); + + size_t start = offset; + + out_encoding = data + offset; + + PUGI__SCANCHARTYPE(ct_symbol); + + out_length = offset - start; + + PUGI__SCANCHAR(delimiter); + + return true; + } + } + + return false; + + #undef PUGI__SCANCHAR + #undef PUGI__SCANCHARTYPE + } + + PUGI__FN xml_encoding guess_buffer_encoding(const uint8_t* data, size_t size) + { + // skip encoding autodetection if input buffer is too small + if (size < 4) return encoding_utf8; + + uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; + + // look for BOM in first few bytes + if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; + if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; + if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; + if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; + if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; + + // look for <, (contents); + + return guess_buffer_encoding(data, size); + } + + PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + size_t length = size / sizeof(char_t); + + if (is_mutable) + { + out_buffer = static_cast(const_cast(contents)); + out_length = length; + } + else + { + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + if (contents) + memcpy(buffer, contents, length * sizeof(char_t)); + else + assert(length == 0); + + buffer[length] = 0; + + out_buffer = buffer; + out_length = length + 1; + } + + return true; + } + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) + { + return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || + (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); + } + + PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + const char_t* data = static_cast(contents); + size_t length = size / sizeof(char_t); + + if (is_mutable) + { + char_t* buffer = const_cast(data); + + convert_wchar_endian_swap(buffer, data, length); + + out_buffer = buffer; + out_length = length; + } + else + { + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + convert_wchar_endian_swap(buffer, data, length); + buffer[length] = 0; + + out_buffer = buffer; + out_length = length + 1; + } + + return true; + } + + template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + { + const typename D::type* data = static_cast(contents); + size_t data_length = size / sizeof(typename D::type); + + // first pass: get length in wchar_t units + size_t length = D::process(data, data_length, 0, wchar_counter()); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf16 input to wchar_t + wchar_writer::value_type obegin = reinterpret_cast(buffer); + wchar_writer::value_type oend = D::process(data, data_length, obegin, wchar_writer()); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // get native encoding + xml_encoding wchar_encoding = get_wchar_encoding(); + + // fast path: no conversion required + if (encoding == wchar_encoding) + return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // only endian-swapping is required + if (need_endian_swap_utf(encoding, wchar_encoding)) + return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf8 + if (encoding == encoding_utf8) + return convert_buffer_generic(out_buffer, out_length, contents, size, utf8_decoder()); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()) : + convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()) : + convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()); + } + + // source encoding is latin1 + if (encoding == encoding_latin1) + return convert_buffer_generic(out_buffer, out_length, contents, size, latin1_decoder()); + + assert(false && "Invalid encoding"); // unreachable + return false; + } +#else + template PUGI__FN bool convert_buffer_generic(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, D) + { + const typename D::type* data = static_cast(contents); + size_t data_length = size / sizeof(typename D::type); + + // first pass: get length in utf8 units + size_t length = D::process(data, data_length, 0, utf8_counter()); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert utf16 input to utf8 + uint8_t* obegin = reinterpret_cast(buffer); + uint8_t* oend = D::process(data, data_length, obegin, utf8_writer()); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) + { + for (size_t i = 0; i < size; ++i) + if (data[i] > 127) + return i; + + return size; + } + + PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) + { + const uint8_t* data = static_cast(contents); + size_t data_length = size; + + // get size of prefix that does not need utf8 conversion + size_t prefix_length = get_latin1_7bit_prefix_length(data, data_length); + assert(prefix_length <= data_length); + + const uint8_t* postfix = data + prefix_length; + size_t postfix_length = data_length - prefix_length; + + // if no conversion is needed, just return the original buffer + if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // first pass: get length in utf8 units + size_t length = prefix_length + latin1_decoder::process(postfix, postfix_length, 0, utf8_counter()); + + // allocate buffer of suitable length + char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!buffer) return false; + + // second pass: convert latin1 input to utf8 + memcpy(buffer, data, prefix_length); + + uint8_t* obegin = reinterpret_cast(buffer); + uint8_t* oend = latin1_decoder::process(postfix, postfix_length, obegin + prefix_length, utf8_writer()); + + assert(oend == obegin + length); + *oend = 0; + + out_buffer = buffer; + out_length = length + 1; + + return true; + } + + PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) + { + // fast path: no conversion required + if (encoding == encoding_utf8) + return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); + + // source encoding is utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return (native_encoding == encoding) ? + convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()) : + convert_buffer_generic(out_buffer, out_length, contents, size, utf16_decoder()); + } + + // source encoding is utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return (native_encoding == encoding) ? + convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()) : + convert_buffer_generic(out_buffer, out_length, contents, size, utf32_decoder()); + } + + // source encoding is latin1 + if (encoding == encoding_latin1) + return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); + + assert(false && "Invalid encoding"); // unreachable + return false; + } +#endif + + PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) + { + // get length in utf8 characters + return wchar_decoder::process(str, length, 0, utf8_counter()); + } + + PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) + { + // convert to utf8 + uint8_t* begin = reinterpret_cast(buffer); + uint8_t* end = wchar_decoder::process(str, length, begin, utf8_writer()); + + assert(begin + size == end); + (void)!end; + (void)!size; + } + +#ifndef PUGIXML_NO_STL + PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) + { + // first pass: get length in utf8 characters + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + std::string result; + result.resize(size); + + // second pass: convert to utf8 + if (size > 0) as_utf8_end(&result[0], size, str, length); + + return result; + } + + PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) + { + const uint8_t* data = reinterpret_cast(str); + + // first pass: get length in wchar_t units + size_t length = utf8_decoder::process(data, size, 0, wchar_counter()); + + // allocate resulting string + std::basic_string result; + result.resize(length); + + // second pass: convert to wchar_t + if (length > 0) + { + wchar_writer::value_type begin = reinterpret_cast(&result[0]); + wchar_writer::value_type end = utf8_decoder::process(data, size, begin, wchar_writer()); + + assert(begin + length == end); + (void)!end; + } + + return result; + } +#endif + + template + inline bool strcpy_insitu_allow(size_t length, const Header& header, uintptr_t header_mask, char_t* target) + { + // never reuse shared memory + if (header & xml_memory_page_contents_shared_mask) return false; + + size_t target_length = strlength(target); + + // always reuse document buffer memory if possible + if ((header & header_mask) == 0) return target_length >= length; + + // reuse heap memory if waste is not too great + const size_t reuse_threshold = 32; + + return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); + } + + template + PUGI__FN bool strcpy_insitu(String& dest, Header& header, uintptr_t header_mask, const char_t* source, size_t source_length) + { + if (source_length == 0) + { + // empty string and null pointer are equivalent, so just deallocate old memory + xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; + + if (header & header_mask) alloc->deallocate_string(dest); + + // mark the string as not allocated + dest = 0; + header &= ~header_mask; + + return true; + } + else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest)) + { + // we can reuse old buffer, so just copy the new data (including zero terminator) + memcpy(dest, source, source_length * sizeof(char_t)); + dest[source_length] = 0; + + return true; + } + else + { + xml_allocator* alloc = PUGI__GETPAGE_IMPL(header)->allocator; + + if (!alloc->reserve()) return false; + + // allocate new buffer + char_t* buf = alloc->allocate_string(source_length + 1); + if (!buf) return false; + + // copy the string (including zero terminator) + memcpy(buf, source, source_length * sizeof(char_t)); + buf[source_length] = 0; + + // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) + if (header & header_mask) alloc->deallocate_string(dest); + + // the string is now allocated, so set the flag + dest = buf; + header |= header_mask; + + return true; + } + } + + struct gap + { + char_t* end; + size_t size; + + gap(): end(0), size(0) + { + } + + // Push new gap, move s count bytes further (skipping the gap). + // Collapse previous gap. + void push(char_t*& s, size_t count) + { + if (end) // there was a gap already; collapse it + { + // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + } + + s += count; // end of current gap + + // "merge" two gaps + end = s; + size += count; + } + + // Collapse all gaps, return past-the-end pointer + char_t* flush(char_t* s) + { + if (end) + { + // Move [old_gap_end, current_pos) to [old_gap_start, ...) + assert(s >= end); + memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); + + return s - size; + } + else return s; + } + }; + + PUGI__FN char_t* strconv_escape(char_t* s, gap& g) + { + char_t* stre = s + 1; + + switch (*stre) + { + case '#': // &#... + { + unsigned int ucsc = 0; + + if (stre[1] == 'x') // &#x... (hex code) + { + stre += 2; + + char_t ch = *stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(ch - '0') <= 9) + ucsc = 16 * ucsc + (ch - '0'); + else if (static_cast((ch | ' ') - 'a') <= 5) + ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + else // &#... (dec code) + { + char_t ch = *++stre; + + if (ch == ';') return stre; + + for (;;) + { + if (static_cast(ch - '0') <= 9) + ucsc = 10 * ucsc + (ch - '0'); + else if (ch == ';') + break; + else // cancel + return stre; + + ch = *++stre; + } + + ++stre; + } + + #ifdef PUGIXML_WCHAR_MODE + s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); + #else + s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); + #endif + + g.push(s, stre - s); + return stre; + } + + case 'a': // &a + { + ++stre; + + if (*stre == 'm') // &am + { + if (*++stre == 'p' && *++stre == ';') // & + { + *s++ = '&'; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + else if (*stre == 'p') // &ap + { + if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' + { + *s++ = '\''; + ++stre; + + g.push(s, stre - s); + return stre; + } + } + break; + } + + case 'g': // &g + { + if (*++stre == 't' && *++stre == ';') // > + { + *s++ = '>'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + case 'l': // &l + { + if (*++stre == 't' && *++stre == ';') // < + { + *s++ = '<'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + case 'q': // &q + { + if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " + { + *s++ = '"'; + ++stre; + + g.push(s, stre - s); + return stre; + } + break; + } + + default: + break; + } + + return stre; + } + + // Parser utilities + #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) + #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } + #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) + #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, *alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } + #define PUGI__POPNODE() { cursor = cursor->parent; } + #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } + #define PUGI__SCANWHILE(X) { while (X) ++s; } + #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } } + #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } + #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) + #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } + + PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here + { + *g.flush(s) = 0; + + return s + (s[2] == '>' ? 3 : 2); + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); + + if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == 0) + { + return 0; + } + else ++s; + } + } + + typedef char_t* (*strconv_pcdata_t)(char_t*); + + template struct strconv_pcdata_impl + { + static char_t* parse(char_t* s) + { + gap g; + + char_t* begin = s; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata)); + + if (*s == '<') // PCDATA ends here + { + char_t* end = g.flush(s); + + if (opt_trim::value) + while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + --end; + + *end = 0; + + return s + 1; + } + else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair + { + *s++ = '\n'; // replace first one with 0x0a + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (*s == 0) + { + char_t* end = g.flush(s); + + if (opt_trim::value) + while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) + --end; + + *end = 0; + + return s; + } + else ++s; + } + } + }; + + PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) + { + PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); + + switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (trim eol escapes); this simultaneously checks 3 options from assertion above + { + case 0: return strconv_pcdata_impl::parse; + case 1: return strconv_pcdata_impl::parse; + case 2: return strconv_pcdata_impl::parse; + case 3: return strconv_pcdata_impl::parse; + case 4: return strconv_pcdata_impl::parse; + case 5: return strconv_pcdata_impl::parse; + case 6: return strconv_pcdata_impl::parse; + case 7: return strconv_pcdata_impl::parse; + default: assert(false); return 0; // unreachable + } + } + + typedef char_t* (*strconv_attribute_t)(char_t*, char_t); + + template struct strconv_attribute_impl + { + static char_t* parse_wnorm(char_t* s, char_t end_quote) + { + gap g; + + // trim leading whitespaces + if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s; + + do ++str; + while (PUGI__IS_CHARTYPE(*str, ct_space)); + + g.push(s, str - s); + } + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); + + if (*s == end_quote) + { + char_t* str = g.flush(s); + + do *str-- = 0; + while (PUGI__IS_CHARTYPE(*str, ct_space)); + + return s + 1; + } + else if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + *s++ = ' '; + + if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + char_t* str = s + 1; + while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; + + g.push(s, str - s); + } + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_wconv(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (PUGI__IS_CHARTYPE(*s, ct_space)) + { + if (*s == '\r') + { + *s++ = ' '; + + if (*s == '\n') g.push(s, 1); + } + else *s++ = ' '; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_eol(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (*s == '\r') + { + *s++ = '\n'; + + if (*s == '\n') g.push(s, 1); + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + + static char_t* parse_simple(char_t* s, char_t end_quote) + { + gap g; + + while (true) + { + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); + + if (*s == end_quote) + { + *g.flush(s) = 0; + + return s + 1; + } + else if (opt_escape::value && *s == '&') + { + s = strconv_escape(s, g); + } + else if (!*s) + { + return 0; + } + else ++s; + } + } + }; + + PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) + { + PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); + + switch ((optmask >> 4) & 15) // get bitmask for flags (wnorm wconv eol escapes); this simultaneously checks 4 options from assertion above + { + case 0: return strconv_attribute_impl::parse_simple; + case 1: return strconv_attribute_impl::parse_simple; + case 2: return strconv_attribute_impl::parse_eol; + case 3: return strconv_attribute_impl::parse_eol; + case 4: return strconv_attribute_impl::parse_wconv; + case 5: return strconv_attribute_impl::parse_wconv; + case 6: return strconv_attribute_impl::parse_wconv; + case 7: return strconv_attribute_impl::parse_wconv; + case 8: return strconv_attribute_impl::parse_wnorm; + case 9: return strconv_attribute_impl::parse_wnorm; + case 10: return strconv_attribute_impl::parse_wnorm; + case 11: return strconv_attribute_impl::parse_wnorm; + case 12: return strconv_attribute_impl::parse_wnorm; + case 13: return strconv_attribute_impl::parse_wnorm; + case 14: return strconv_attribute_impl::parse_wnorm; + case 15: return strconv_attribute_impl::parse_wnorm; + default: assert(false); return 0; // unreachable + } + } + + inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) + { + xml_parse_result result; + result.status = status; + result.offset = offset; + + return result; + } + + struct xml_parser + { + xml_allocator* alloc; + char_t* error_offset; + xml_parse_status error_status; + + xml_parser(xml_allocator* alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) + { + } + + // DOCTYPE consists of nested sections of the following possible types: + // , , "...", '...' + // + // + // First group can not contain nested groups + // Second group can contain nested groups of the same type + // Third group can contain all other groups + char_t* parse_doctype_primitive(char_t* s) + { + if (*s == '"' || *s == '\'') + { + // quoted string + char_t ch = *s++; + PUGI__SCANFOR(*s == ch); + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s++; + } + else if (s[0] == '<' && s[1] == '?') + { + // + s += 2; + PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s += 2; + } + else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') + { + s += 4; + PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype + if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); + + s += 3; + } + else PUGI__THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_doctype_ignore(char_t* s) + { + size_t depth = 0; + + assert(s[0] == '<' && s[1] == '!' && s[2] == '['); + s += 3; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] == '[') + { + // nested ignore section + s += 3; + depth++; + } + else if (s[0] == ']' && s[1] == ']' && s[2] == '>') + { + // ignore section end + s += 3; + + if (depth == 0) + return s; + + depth--; + } + else s++; + } + + PUGI__THROW_ERROR(status_bad_doctype, s); + } + + char_t* parse_doctype_group(char_t* s, char_t endch) + { + size_t depth = 0; + + assert((s[0] == '<' || s[0] == 0) && s[1] == '!'); + s += 2; + + while (*s) + { + if (s[0] == '<' && s[1] == '!' && s[2] != '-') + { + if (s[2] == '[') + { + // ignore + s = parse_doctype_ignore(s); + if (!s) return s; + } + else + { + // some control group + s += 2; + depth++; + } + } + else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') + { + // unknown tag (forbidden), or some primitive group + s = parse_doctype_primitive(s); + if (!s) return s; + } + else if (*s == '>') + { + if (depth == 0) + return s; + + depth--; + s++; + } + else s++; + } + + if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); + + return s; + } + + char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) + { + // parse node contents, starting with exclamation mark + ++s; + + if (*s == '-') // 'value = s; // Save the offset. + } + + if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) + { + s = strconv_comment(s, endch); + + if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); + } + else + { + // Scan for terminating '-->'. + PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_comment, s); + + if (PUGI__OPTSET(parse_comments)) + *s = 0; // Zero-terminate this segment at the first terminating '-'. + + s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. + } + } + else PUGI__THROW_ERROR(status_bad_comment, s); + } + else if (*s == '[') + { + // 'value = s; // Save the offset. + + if (PUGI__OPTSET(parse_eol)) + { + s = strconv_cdata(s, endch); + + if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); + } + else + { + // Scan for terminating ']]>'. + PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_cdata, s); + + *s++ = 0; // Zero-terminate this segment. + } + } + else // Flagged for discard, but we still have to scan for the terminator. + { + // Scan for terminating ']]>'. + PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); + PUGI__CHECK_ERROR(status_bad_cdata, s); + + ++s; + } + + s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. + } + else PUGI__THROW_ERROR(status_bad_cdata, s); + } + else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E')) + { + s -= 2; + + if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); + + char_t* mark = s + 9; + + s = parse_doctype_group(s, endch); + if (!s) return s; + + assert((*s == 0 && endch == '>') || *s == '>'); + if (*s) *s++ = 0; + + if (PUGI__OPTSET(parse_doctype)) + { + while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; + + PUGI__PUSHNODE(node_doctype); + + cursor->value = mark; + } + } + else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); + else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); + else PUGI__THROW_ERROR(status_unrecognized_tag, s); + + return s; + } + + char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) + { + // load into registers + xml_node_struct* cursor = ref_cursor; + char_t ch = 0; + + // parse node contents, starting with question mark + ++s; + + // read PI target + char_t* target = s; + + if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); + + PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); + PUGI__CHECK_ERROR(status_bad_pi, s); + + // determine node type; stricmp / strcasecmp is not portable + bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; + + if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) + { + if (declaration) + { + // disallow non top-level declarations + if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); + + PUGI__PUSHNODE(node_declaration); + } + else + { + PUGI__PUSHNODE(node_pi); + } + + cursor->name = target; + + PUGI__ENDSEG(); + + // parse value/attributes + if (ch == '?') + { + // empty node + if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); + s += (*s == '>'); + + PUGI__POPNODE(); + } + else if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + PUGI__SKIPWS(); + + // scan for tag end + char_t* value = s; + + PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); + PUGI__CHECK_ERROR(status_bad_pi, s); + + if (declaration) + { + // replace ending ? with / so that 'element' terminates properly + *s = '/'; + + // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES + s = value; + } + else + { + // store value and step over > + cursor->value = value; + + PUGI__POPNODE(); + + PUGI__ENDSEG(); + + s += (*s == '>'); + } + } + else PUGI__THROW_ERROR(status_bad_pi, s); + } + else + { + // scan for tag end + PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); + PUGI__CHECK_ERROR(status_bad_pi, s); + + s += (s[1] == '>' ? 2 : 1); + } + + // store from registers + ref_cursor = cursor; + + return s; + } + + char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch) + { + strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); + strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); + + char_t ch = 0; + xml_node_struct* cursor = root; + char_t* mark = s; + + while (*s != 0) + { + if (*s == '<') + { + ++s; + + LOC_TAG: + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' + { + PUGI__PUSHNODE(node_element); // Append a new node to the tree. + + cursor->name = s; + + PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + + if (ch == '>') + { + // end of tag + } + else if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + LOC_ATTRIBUTES: + while (true) + { + PUGI__SKIPWS(); // Eat any whitespace. + + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... + { + xml_attribute_struct* a = append_new_attribute(cursor, *alloc); // Make space for this attribute. + if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); + + a->name = s; // Save the offset. + + PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. + PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. + + if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + PUGI__SKIPWS(); // Eat any whitespace. + + ch = *s; + ++s; + } + + if (ch == '=') // '<... #=...' + { + PUGI__SKIPWS(); // Eat any whitespace. + + if (*s == '"' || *s == '\'') // '<... #="...' + { + ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. + ++s; // Step over the quote. + a->value = s; // Save the offset. + + s = strconv_attribute(s, ch); + + if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); + + // After this line the loop continues from the start; + // Whitespaces, / and > are ok, symbols and EOF are wrong, + // everything else will be detected + if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); + } + else PUGI__THROW_ERROR(status_bad_attribute, s); + } + else PUGI__THROW_ERROR(status_bad_attribute, s); + } + else if (*s == '/') + { + ++s; + + if (*s == '>') + { + PUGI__POPNODE(); + s++; + break; + } + else if (*s == 0 && endch == '>') + { + PUGI__POPNODE(); + break; + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '>') + { + ++s; + + break; + } + else if (*s == 0 && endch == '>') + { + break; + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + + // !!! + } + else if (ch == '/') // '<#.../' + { + if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); + + PUGI__POPNODE(); // Pop. + + s += (*s == '>'); + } + else if (ch == 0) + { + // we stepped over null terminator, backtrack & handle closing tag + --s; + + if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); + } + else PUGI__THROW_ERROR(status_bad_start_element, s); + } + else if (*s == '/') + { + ++s; + + mark = s; + + char_t* name = cursor->name; + if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, mark); + + while (PUGI__IS_CHARTYPE(*s, ct_symbol)) + { + if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, mark); + } + + if (*name) + { + if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); + else PUGI__THROW_ERROR(status_end_element_mismatch, mark); + } + + PUGI__POPNODE(); // Pop. + + PUGI__SKIPWS(); + + if (*s == 0) + { + if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + } + else + { + if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); + ++s; + } + } + else if (*s == '?') // 'first_child) continue; + } + } + + if (!PUGI__OPTSET(parse_trim_pcdata)) + s = mark; + + if (cursor->parent || PUGI__OPTSET(parse_fragment)) + { + if (PUGI__OPTSET(parse_embed_pcdata) && cursor->parent && !cursor->first_child && !cursor->value) + { + cursor->value = s; // Save the offset. + } + else + { + PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. + + cursor->value = s; // Save the offset. + + PUGI__POPNODE(); // Pop since this is a standalone. + } + + s = strconv_pcdata(s); + + if (!*s) break; + } + else + { + PUGI__SCANFOR(*s == '<'); // '...<' + if (!*s) break; + + ++s; + } + + // We're after '<' + goto LOC_TAG; + } + } + + // check that last tag is closed + if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s); + + return s; + } + + #ifdef PUGIXML_WCHAR_MODE + static char_t* parse_skip_bom(char_t* s) + { + unsigned int bom = 0xfeff; + return (s[0] == static_cast(bom)) ? s + 1 : s; + } + #else + static char_t* parse_skip_bom(char_t* s) + { + return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s; + } + #endif + + static bool has_element_node_siblings(xml_node_struct* node) + { + while (node) + { + if (PUGI__NODETYPE(node) == node_element) return true; + + node = node->next_sibling; + } + + return false; + } + + static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk) + { + // early-out for empty documents + if (length == 0) + return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); + + // get last child of the root before parsing + xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c + 0 : 0; + + // create parser on stack + xml_parser parser(static_cast(xmldoc)); + + // save last character and make buffer zero-terminated (speeds up parsing) + char_t endch = buffer[length - 1]; + buffer[length - 1] = 0; + + // skip BOM to make sure it does not end up as part of parse output + char_t* buffer_data = parse_skip_bom(buffer); + + // perform actual parsing + parser.parse_tree(buffer_data, root, optmsk, endch); + + xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); + assert(result.offset >= 0 && static_cast(result.offset) <= length); + + if (result) + { + // since we removed last character, we have to handle the only possible false positive (stray <) + if (endch == '<') + return make_parse_result(status_unrecognized_tag, length - 1); + + // check if there are any element nodes parsed + xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling + 0 : root->first_child+ 0; + + if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) + return make_parse_result(status_no_document_element, length - 1); + } + else + { + // roll back offset if it occurs on a null terminator in the source buffer + if (result.offset > 0 && static_cast(result.offset) == length - 1 && endch == 0) + result.offset--; + } + + return result; + } + }; + + // Output facilities + PUGI__FN xml_encoding get_write_native_encoding() + { + #ifdef PUGIXML_WCHAR_MODE + return get_wchar_encoding(); + #else + return encoding_utf8; + #endif + } + + PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) + { + // replace wchar encoding with utf implementation + if (encoding == encoding_wchar) return get_wchar_encoding(); + + // replace utf16 encoding with utf16 with specific endianness + if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + // replace utf32 encoding with utf32 with specific endianness + if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + // only do autodetection if no explicit encoding is requested + if (encoding != encoding_auto) return encoding; + + // assume utf8 encoding + return encoding_utf8; + } + + template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T) + { + PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); + + typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); + + return static_cast(end - dest) * sizeof(*dest); + } + + template PUGI__FN size_t convert_buffer_output_generic(typename T::value_type dest, const char_t* data, size_t length, D, T, bool opt_swap) + { + PUGI__STATIC_ASSERT(sizeof(char_t) == sizeof(typename D::type)); + + typename T::value_type end = D::process(reinterpret_cast(data), length, dest, T()); + + if (opt_swap) + { + for (typename T::value_type i = dest; i != end; ++i) + *i = endian_swap(*i); + } + + return static_cast(end - dest) * sizeof(*dest); + } + +#ifdef PUGIXML_WCHAR_MODE + PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + { + if (length < 1) return 0; + + // discard last character if it's the lead of a surrogate pair + return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; + } + + PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + { + // only endian-swapping is required + if (need_endian_swap_utf(encoding, get_wchar_encoding())) + { + convert_wchar_endian_swap(r_char, data, length); + + return length * sizeof(char_t); + } + + // convert to utf8 + if (encoding == encoding_utf8) + return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), utf8_writer()); + + // convert to utf16 + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return convert_buffer_output_generic(r_u16, data, length, wchar_decoder(), utf16_writer(), native_encoding != encoding); + } + + // convert to utf32 + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return convert_buffer_output_generic(r_u32, data, length, wchar_decoder(), utf32_writer(), native_encoding != encoding); + } + + // convert to latin1 + if (encoding == encoding_latin1) + return convert_buffer_output_generic(r_u8, data, length, wchar_decoder(), latin1_writer()); + + assert(false && "Invalid encoding"); // unreachable + return 0; + } +#else + PUGI__FN size_t get_valid_length(const char_t* data, size_t length) + { + if (length < 5) return 0; + + for (size_t i = 1; i <= 4; ++i) + { + uint8_t ch = static_cast(data[length - i]); + + // either a standalone character or a leading one + if ((ch & 0xc0) != 0x80) return length - i; + } + + // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk + return length; + } + + PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) + { + if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; + + return convert_buffer_output_generic(r_u16, data, length, utf8_decoder(), utf16_writer(), native_encoding != encoding); + } + + if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) + { + xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; + + return convert_buffer_output_generic(r_u32, data, length, utf8_decoder(), utf32_writer(), native_encoding != encoding); + } + + if (encoding == encoding_latin1) + return convert_buffer_output_generic(r_u8, data, length, utf8_decoder(), latin1_writer()); + + assert(false && "Invalid encoding"); // unreachable + return 0; + } +#endif + + class xml_buffered_writer + { + xml_buffered_writer(const xml_buffered_writer&); + xml_buffered_writer& operator=(const xml_buffered_writer&); + + public: + xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) + { + PUGI__STATIC_ASSERT(bufcapacity >= 8); + } + + size_t flush() + { + flush(buffer, bufsize); + bufsize = 0; + return 0; + } + + void flush(const char_t* data, size_t size) + { + if (size == 0) return; + + // fast path, just write data + if (encoding == get_write_native_encoding()) + writer.write(data, size * sizeof(char_t)); + else + { + // convert chunk + size_t result = convert_buffer_output(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding); + assert(result <= sizeof(scratch)); + + // write data + writer.write(scratch.data_u8, result); + } + } + + void write_direct(const char_t* data, size_t length) + { + // flush the remaining buffer contents + flush(); + + // handle large chunks + if (length > bufcapacity) + { + if (encoding == get_write_native_encoding()) + { + // fast path, can just write data chunk + writer.write(data, length * sizeof(char_t)); + return; + } + + // need to convert in suitable chunks + while (length > bufcapacity) + { + // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer + // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) + size_t chunk_size = get_valid_length(data, bufcapacity); + assert(chunk_size); + + // convert chunk and write + flush(data, chunk_size); + + // iterate + data += chunk_size; + length -= chunk_size; + } + + // small tail is copied below + bufsize = 0; + } + + memcpy(buffer + bufsize, data, length * sizeof(char_t)); + bufsize += length; + } + + void write_buffer(const char_t* data, size_t length) + { + size_t offset = bufsize; + + if (offset + length <= bufcapacity) + { + memcpy(buffer + offset, data, length * sizeof(char_t)); + bufsize = offset + length; + } + else + { + write_direct(data, length); + } + } + + void write_string(const char_t* data) + { + // write the part of the string that fits in the buffer + size_t offset = bufsize; + + while (*data && offset < bufcapacity) + buffer[offset++] = *data++; + + // write the rest + if (offset < bufcapacity) + { + bufsize = offset; + } + else + { + // backtrack a bit if we have split the codepoint + size_t length = offset - bufsize; + size_t extra = length - get_valid_length(data - length, length); + + bufsize = offset - extra; + + write_direct(data - extra, strlength(data) + extra); + } + } + + void write(char_t d0) + { + size_t offset = bufsize; + if (offset > bufcapacity - 1) offset = flush(); + + buffer[offset + 0] = d0; + bufsize = offset + 1; + } + + void write(char_t d0, char_t d1) + { + size_t offset = bufsize; + if (offset > bufcapacity - 2) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + bufsize = offset + 2; + } + + void write(char_t d0, char_t d1, char_t d2) + { + size_t offset = bufsize; + if (offset > bufcapacity - 3) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + bufsize = offset + 3; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3) + { + size_t offset = bufsize; + if (offset > bufcapacity - 4) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + bufsize = offset + 4; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) + { + size_t offset = bufsize; + if (offset > bufcapacity - 5) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + buffer[offset + 4] = d4; + bufsize = offset + 5; + } + + void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) + { + size_t offset = bufsize; + if (offset > bufcapacity - 6) offset = flush(); + + buffer[offset + 0] = d0; + buffer[offset + 1] = d1; + buffer[offset + 2] = d2; + buffer[offset + 3] = d3; + buffer[offset + 4] = d4; + buffer[offset + 5] = d5; + bufsize = offset + 6; + } + + // utf8 maximum expansion: x4 (-> utf32) + // utf16 maximum expansion: x2 (-> utf32) + // utf32 maximum expansion: x1 + enum + { + bufcapacitybytes = + #ifdef PUGIXML_MEMORY_OUTPUT_STACK + PUGIXML_MEMORY_OUTPUT_STACK + #else + 10240 + #endif + , + bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4) + }; + + char_t buffer[bufcapacity]; + + union + { + uint8_t data_u8[4 * bufcapacity]; + uint16_t data_u16[2 * bufcapacity]; + uint32_t data_u32[bufcapacity]; + char_t data_char[bufcapacity]; + } scratch; + + xml_writer& writer; + size_t bufsize; + xml_encoding encoding; + }; + + PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) + { + while (*s) + { + const char_t* prev = s; + + // While *s is a usual symbol + PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); + + writer.write_buffer(prev, static_cast(s - prev)); + + switch (*s) + { + case 0: break; + case '&': + writer.write('&', 'a', 'm', 'p', ';'); + ++s; + break; + case '<': + writer.write('&', 'l', 't', ';'); + ++s; + break; + case '>': + writer.write('&', 'g', 't', ';'); + ++s; + break; + case '"': + if (flags & format_attribute_single_quote) + writer.write('"'); + else + writer.write('&', 'q', 'u', 'o', 't', ';'); + ++s; + break; + case '\'': + if (flags & format_attribute_single_quote) + writer.write('&', 'a', 'p', 'o', 's', ';'); + else + writer.write('\''); + ++s; + break; + default: // s is not a usual symbol + { + unsigned int ch = static_cast(*s++); + assert(ch < 32); + + if (!(flags & format_skip_control_chars)) + writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); + } + } + } + } + + PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) + { + if (flags & format_no_escapes) + writer.write_string(s); + else + text_output_escaped(writer, s, type, flags); + } + + PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) + { + do + { + writer.write('<', '!', '[', 'C', 'D'); + writer.write('A', 'T', 'A', '['); + + const char_t* prev = s; + + // look for ]]> sequence - we can't output it as is since it terminates CDATA + while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; + + // skip ]] if we stopped at ]]>, > will go to the next CDATA section + if (*s) s += 2; + + writer.write_buffer(prev, static_cast(s - prev)); + + writer.write(']', ']', '>'); + } + while (*s); + } + + PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) + { + switch (indent_length) + { + case 1: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0]); + break; + } + + case 2: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1]); + break; + } + + case 3: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1], indent[2]); + break; + } + + case 4: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write(indent[0], indent[1], indent[2], indent[3]); + break; + } + + default: + { + for (unsigned int i = 0; i < depth; ++i) + writer.write_buffer(indent, indent_length); + } + } + } + + PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) + { + writer.write('<', '!', '-', '-'); + + while (*s) + { + const char_t* prev = s; + + // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body + while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s; + + writer.write_buffer(prev, static_cast(s - prev)); + + if (*s) + { + assert(*s == '-'); + + writer.write('-', ' '); + ++s; + } + } + + writer.write('-', '-', '>'); + } + + PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s) + { + while (*s) + { + const char_t* prev = s; + + // look for ?> sequence - we can't output it since ?> terminates PI + while (*s && !(s[0] == '?' && s[1] == '>')) ++s; + + writer.write_buffer(prev, static_cast(s - prev)); + + if (*s) + { + assert(s[0] == '?' && s[1] == '>'); + + writer.write('?', ' ', '>'); + s += 2; + } + } + } + + PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t enquotation_char = (flags & format_attribute_single_quote) ? '\'' : '"'; + + for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) + { + if ((flags & (format_indent_attributes | format_raw)) == format_indent_attributes) + { + writer.write('\n'); + + text_output_indent(writer, indent, indent_length, depth + 1); + } + else + { + writer.write(' '); + } + + writer.write_string(a->name ? a->name + 0 : default_name); + writer.write('=', enquotation_char); + + if (a->value) + text_output(writer, a->value, ctx_special_attr, flags); + + writer.write(enquotation_char); + } + } + + PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t* name = node->name ? node->name + 0 : default_name; + + writer.write('<'); + writer.write_string(name); + + if (node->first_attribute) + node_output_attributes(writer, node, indent, indent_length, flags, depth); + + // element nodes can have value if parse_embed_pcdata was used + if (!node->value) + { + if (!node->first_child) + { + if (flags & format_no_empty_element_tags) + { + writer.write('>', '<', '/'); + writer.write_string(name); + writer.write('>'); + + return false; + } + else + { + if ((flags & format_raw) == 0) + writer.write(' '); + + writer.write('/', '>'); + + return false; + } + } + else + { + writer.write('>'); + + return true; + } + } + else + { + writer.write('>'); + + text_output(writer, node->value, ctx_special_pcdata, flags); + + if (!node->first_child) + { + writer.write('<', '/'); + writer.write_string(name); + writer.write('>'); + + return false; + } + else + { + return true; + } + } + } + + PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t* name = node->name ? node->name + 0 : default_name; + + writer.write('<', '/'); + writer.write_string(name); + writer.write('>'); + } + + PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) + { + const char_t* default_name = PUGIXML_TEXT(":anonymous"); + + switch (PUGI__NODETYPE(node)) + { + case node_pcdata: + text_output(writer, node->value ? node->value + 0 : PUGIXML_TEXT(""), ctx_special_pcdata, flags); + break; + + case node_cdata: + text_output_cdata(writer, node->value ? node->value + 0 : PUGIXML_TEXT("")); + break; + + case node_comment: + node_output_comment(writer, node->value ? node->value + 0 : PUGIXML_TEXT("")); + break; + + case node_pi: + writer.write('<', '?'); + writer.write_string(node->name ? node->name + 0 : default_name); + + if (node->value) + { + writer.write(' '); + node_output_pi_value(writer, node->value); + } + + writer.write('?', '>'); + break; + + case node_declaration: + writer.write('<', '?'); + writer.write_string(node->name ? node->name + 0 : default_name); + node_output_attributes(writer, node, PUGIXML_TEXT(""), 0, flags | format_raw, 0); + writer.write('?', '>'); + break; + + case node_doctype: + writer.write('<', '!', 'D', 'O', 'C'); + writer.write('T', 'Y', 'P', 'E'); + + if (node->value) + { + writer.write(' '); + writer.write_string(node->value); + } + + writer.write('>'); + break; + + default: + assert(false && "Invalid node type"); // unreachable + } + } + + enum indent_flags_t + { + indent_newline = 1, + indent_indent = 2 + }; + + PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) + { + size_t indent_length = ((flags & (format_indent | format_indent_attributes)) && (flags & format_raw) == 0) ? strlength(indent) : 0; + unsigned int indent_flags = indent_indent; + + xml_node_struct* node = root; + + do + { + assert(node); + + // begin writing current node + if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) + { + node_output_simple(writer, node, flags); + + indent_flags = 0; + } + else + { + if ((indent_flags & indent_newline) && (flags & format_raw) == 0) + writer.write('\n'); + + if ((indent_flags & indent_indent) && indent_length) + text_output_indent(writer, indent, indent_length, depth); + + if (PUGI__NODETYPE(node) == node_element) + { + indent_flags = indent_newline | indent_indent; + + if (node_output_start(writer, node, indent, indent_length, flags, depth)) + { + // element nodes can have value if parse_embed_pcdata was used + if (node->value) + indent_flags = 0; + + node = node->first_child; + depth++; + continue; + } + } + else if (PUGI__NODETYPE(node) == node_document) + { + indent_flags = indent_indent; + + if (node->first_child) + { + node = node->first_child; + continue; + } + } + else + { + node_output_simple(writer, node, flags); + + indent_flags = indent_newline | indent_indent; + } + } + + // continue to the next node + while (node != root) + { + if (node->next_sibling) + { + node = node->next_sibling; + break; + } + + node = node->parent; + + // write closing node + if (PUGI__NODETYPE(node) == node_element) + { + depth--; + + if ((indent_flags & indent_newline) && (flags & format_raw) == 0) + writer.write('\n'); + + if ((indent_flags & indent_indent) && indent_length) + text_output_indent(writer, indent, indent_length, depth); + + node_output_end(writer, node); + + indent_flags = indent_newline | indent_indent; + } + } + } + while (node != root); + + if ((indent_flags & indent_newline) && (flags & format_raw) == 0) + writer.write('\n'); + } + + PUGI__FN bool has_declaration(xml_node_struct* node) + { + for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) + { + xml_node_type type = PUGI__NODETYPE(child); + + if (type == node_declaration) return true; + if (type == node_element) return false; + } + + return false; + } + + PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) + { + for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) + if (a == attr) + return true; + + return false; + } + + PUGI__FN bool allow_insert_attribute(xml_node_type parent) + { + return parent == node_element || parent == node_declaration; + } + + PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child) + { + if (parent != node_document && parent != node_element) return false; + if (child == node_document || child == node_null) return false; + if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; + + return true; + } + + PUGI__FN bool allow_move(xml_node parent, xml_node child) + { + // check that child can be a child of parent + if (!allow_insert_child(parent.type(), child.type())) + return false; + + // check that node is not moved between documents + if (parent.root() != child.root()) + return false; + + // check that new parent is not in the child subtree + xml_node cur = parent; + + while (cur) + { + if (cur == child) + return false; + + cur = cur.parent(); + } + + return true; + } + + template + PUGI__FN void node_copy_string(String& dest, Header& header, uintptr_t header_mask, char_t* source, Header& source_header, xml_allocator* alloc) + { + assert(!dest && (header & header_mask) == 0); + + if (source) + { + if (alloc && (source_header & header_mask) == 0) + { + dest = source; + + // since strcpy_insitu can reuse document buffer memory we need to mark both source and dest as shared + header |= xml_memory_page_contents_shared_mask; + source_header |= xml_memory_page_contents_shared_mask; + } + else + strcpy_insitu(dest, header, header_mask, source, strlength(source)); + } + } + + PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) + { + node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); + node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); + + for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) + { + xml_attribute_struct* da = append_new_attribute(dn, get_allocator(dn)); + + if (da) + { + node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); + node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); + } + } + } + + PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) + { + xml_allocator& alloc = get_allocator(dn); + xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; + + node_copy_contents(dn, sn, shared_alloc); + + xml_node_struct* dit = dn; + xml_node_struct* sit = sn->first_child; + + while (sit && sit != sn) + { + // loop invariant: dit is inside the subtree rooted at dn + assert(dit); + + // when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop + if (sit != dn) + { + xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); + + if (copy) + { + node_copy_contents(copy, sit, shared_alloc); + + if (sit->first_child) + { + dit = copy; + sit = sit->first_child; + continue; + } + } + } + + // continue to the next node + do + { + if (sit->next_sibling) + { + sit = sit->next_sibling; + break; + } + + sit = sit->parent; + dit = dit->parent; + + // loop invariant: dit is inside the subtree rooted at dn while sit is inside sn + assert(sit == sn || dit); + } + while (sit != sn); + } + + assert(!sit || dit == dn->parent); + } + + PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) + { + xml_allocator& alloc = get_allocator(da); + xml_allocator* shared_alloc = (&alloc == &get_allocator(sa)) ? &alloc : 0; + + node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); + node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); + } + + inline bool is_text_node(xml_node_struct* node) + { + xml_node_type type = PUGI__NODETYPE(node); + + return type == node_pcdata || type == node_cdata; + } + + // get value with conversion functions + template PUGI__FN PUGI__UNSIGNED_OVERFLOW U string_to_integer(const char_t* value, U minv, U maxv) + { + U result = 0; + const char_t* s = value; + + while (PUGI__IS_CHARTYPE(*s, ct_space)) + s++; + + bool negative = (*s == '-'); + + s += (*s == '+' || *s == '-'); + + bool overflow = false; + + if (s[0] == '0' && (s[1] | ' ') == 'x') + { + s += 2; + + // since overflow detection relies on length of the sequence skip leading zeros + while (*s == '0') + s++; + + const char_t* start = s; + + for (;;) + { + if (static_cast(*s - '0') < 10) + result = result * 16 + (*s - '0'); + else if (static_cast((*s | ' ') - 'a') < 6) + result = result * 16 + ((*s | ' ') - 'a' + 10); + else + break; + + s++; + } + + size_t digits = static_cast(s - start); + + overflow = digits > sizeof(U) * 2; + } + else + { + // since overflow detection relies on length of the sequence skip leading zeros + while (*s == '0') + s++; + + const char_t* start = s; + + for (;;) + { + if (static_cast(*s - '0') < 10) + result = result * 10 + (*s - '0'); + else + break; + + s++; + } + + size_t digits = static_cast(s - start); + + PUGI__STATIC_ASSERT(sizeof(U) == 8 || sizeof(U) == 4 || sizeof(U) == 2); + + const size_t max_digits10 = sizeof(U) == 8 ? 20 : sizeof(U) == 4 ? 10 : 5; + const char_t max_lead = sizeof(U) == 8 ? '1' : sizeof(U) == 4 ? '4' : '6'; + const size_t high_bit = sizeof(U) * 8 - 1; + + overflow = digits >= max_digits10 && !(digits == max_digits10 && (*start < max_lead || (*start == max_lead && result >> high_bit))); + } + + if (negative) + { + // Workaround for crayc++ CC-3059: Expected no overflow in routine. + #ifdef _CRAYC + return (overflow || result > ~minv + 1) ? minv : ~result + 1; + #else + return (overflow || result > 0 - minv) ? minv : 0 - result; + #endif + } + else + return (overflow || result > maxv) ? maxv : result; + } + + PUGI__FN int get_value_int(const char_t* value) + { + return string_to_integer(value, static_cast(INT_MIN), INT_MAX); + } + + PUGI__FN unsigned int get_value_uint(const char_t* value) + { + return string_to_integer(value, 0, UINT_MAX); + } + + PUGI__FN double get_value_double(const char_t* value) + { + #ifdef PUGIXML_WCHAR_MODE + return wcstod(value, 0); + #else + return strtod(value, 0); + #endif + } + + PUGI__FN float get_value_float(const char_t* value) + { + #ifdef PUGIXML_WCHAR_MODE + return static_cast(wcstod(value, 0)); + #else + return static_cast(strtod(value, 0)); + #endif + } + + PUGI__FN bool get_value_bool(const char_t* value) + { + // only look at first char + char_t first = *value; + + // 1*, t* (true), T* (True), y* (yes), Y* (YES) + return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long get_value_llong(const char_t* value) + { + return string_to_integer(value, static_cast(LLONG_MIN), LLONG_MAX); + } + + PUGI__FN unsigned long long get_value_ullong(const char_t* value) + { + return string_to_integer(value, 0, ULLONG_MAX); + } +#endif + + template PUGI__FN PUGI__UNSIGNED_OVERFLOW char_t* integer_to_string(char_t* begin, char_t* end, U value, bool negative) + { + char_t* result = end - 1; + U rest = negative ? 0 - value : value; + + do + { + *result-- = static_cast('0' + (rest % 10)); + rest += 10; + } + while (rest); + + assert(result >= begin); + (void)begin; + + *result = '-'; + + return result + !negative; + } + + // set value with conversion functions + template + PUGI__FN bool set_value_ascii(String& dest, Header& header, uintptr_t header_mask, char* buf) + { + #ifdef PUGIXML_WCHAR_MODE + char_t wbuf[128]; + assert(strlen(buf) < sizeof(wbuf) / sizeof(wbuf[0])); + + size_t offset = 0; + for (; buf[offset]; ++offset) wbuf[offset] = buf[offset]; + + return strcpy_insitu(dest, header, header_mask, wbuf, offset); + #else + return strcpy_insitu(dest, header, header_mask, buf, strlen(buf)); + #endif + } + + template + PUGI__FN bool set_value_integer(String& dest, Header& header, uintptr_t header_mask, U value, bool negative) + { + char_t buf[64]; + char_t* end = buf + sizeof(buf) / sizeof(buf[0]); + char_t* begin = integer_to_string(buf, end, value, negative); + + return strcpy_insitu(dest, header, header_mask, begin, end - begin); + } + + template + PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value, int precision) + { + char buf[128]; + PUGI__SNPRINTF(buf, "%.*g", precision, double(value)); + + return set_value_ascii(dest, header, header_mask, buf); + } + + template + PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value, int precision) + { + char buf[128]; + PUGI__SNPRINTF(buf, "%.*g", precision, value); + + return set_value_ascii(dest, header, header_mask, buf); + } + + template + PUGI__FN bool set_value_bool(String& dest, Header& header, uintptr_t header_mask, bool value) + { + return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"), value ? 4 : 5); + } + + PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) + { + // check input buffer + if (!contents && size) return make_parse_result(status_io_error); + + // get actual encoding + xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); + + // get private buffer + char_t* buffer = 0; + size_t length = 0; + + // coverity[var_deref_model] + if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); + + // delete original buffer if we performed a conversion + if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); + + // grab onto buffer if it's our buffer, user is responsible for deallocating contents himself + if (own || buffer != contents) *out_buffer = buffer; + + // store buffer for offset_debug + doc->buffer = buffer; + + // parse + xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options); + + // remember encoding + res.encoding = buffer_encoding; + + return res; + } + + // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick + PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) + { + #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + // there are 64-bit versions of fseek/ftell, let's use them + typedef __int64 length_type; + + _fseeki64(file, 0, SEEK_END); + length_type length = _ftelli64(file); + _fseeki64(file, 0, SEEK_SET); + #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) + // there are 64-bit versions of fseek/ftell, let's use them + typedef off64_t length_type; + + fseeko64(file, 0, SEEK_END); + length_type length = ftello64(file); + fseeko64(file, 0, SEEK_SET); + #else + // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. + typedef long length_type; + + fseek(file, 0, SEEK_END); + length_type length = ftell(file); + fseek(file, 0, SEEK_SET); + #endif + + // check for I/O errors + if (length < 0) return status_io_error; + + // check for overflow + size_t result = static_cast(length); + + if (static_cast(result) != length) return status_out_of_memory; + + // finalize + out_result = result; + + return status_ok; + } + + // This function assumes that buffer has extra sizeof(char_t) writable bytes after size + PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) + { + // We only need to zero-terminate if encoding conversion does not do it for us + #ifdef PUGIXML_WCHAR_MODE + xml_encoding wchar_encoding = get_wchar_encoding(); + + if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding)) + { + size_t length = size / sizeof(char_t); + + static_cast(buffer)[length] = 0; + return (length + 1) * sizeof(char_t); + } + #else + if (encoding == encoding_utf8) + { + static_cast(buffer)[size] = 0; + return size + 1; + } + #endif + + return size; + } + + PUGI__FN xml_parse_result load_file_impl(xml_document_struct* doc, FILE* file, unsigned int options, xml_encoding encoding, char_t** out_buffer) + { + if (!file) return make_parse_result(status_file_not_found); + + // get file size (can result in I/O errors) + size_t size = 0; + xml_parse_status size_status = get_file_size(file, size); + if (size_status != status_ok) return make_parse_result(size_status); + + size_t max_suffix_size = sizeof(char_t); + + // allocate buffer for the whole file + char* contents = static_cast(xml_memory::allocate(size + max_suffix_size)); + if (!contents) return make_parse_result(status_out_of_memory); + + // read file in memory + size_t read_size = fread(contents, 1, size, file); + + if (read_size != size) + { + xml_memory::deallocate(contents); + return make_parse_result(status_io_error); + } + + xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size); + + return load_buffer_impl(doc, doc, contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding, true, true, out_buffer); + } + + PUGI__FN void close_file(FILE* file) + { + fclose(file); + } + +#ifndef PUGIXML_NO_STL + template struct xml_stream_chunk + { + static xml_stream_chunk* create() + { + void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); + if (!memory) return 0; + + return new (memory) xml_stream_chunk(); + } + + static void destroy(xml_stream_chunk* chunk) + { + // free chunk chain + while (chunk) + { + xml_stream_chunk* next_ = chunk->next; + + xml_memory::deallocate(chunk); + + chunk = next_; + } + } + + xml_stream_chunk(): next(0), size(0) + { + } + + xml_stream_chunk* next; + size_t size; + + T data[xml_memory_page_size / sizeof(T)]; + }; + + template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + { + auto_deleter > chunks(0, xml_stream_chunk::destroy); + + // read file to a chunk list + size_t total = 0; + xml_stream_chunk* last = 0; + + while (!stream.eof()) + { + // allocate new chunk + xml_stream_chunk* chunk = xml_stream_chunk::create(); + if (!chunk) return status_out_of_memory; + + // append chunk to list + if (last) last = last->next = chunk; + else chunks.data = last = chunk; + + // read data to chunk + stream.read(chunk->data, static_cast(sizeof(chunk->data) / sizeof(T))); + chunk->size = static_cast(stream.gcount()) * sizeof(T); + + // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors + if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; + + // guard against huge files (chunk size is small enough to make this overflow check work) + if (total + chunk->size < total) return status_out_of_memory; + total += chunk->size; + } + + size_t max_suffix_size = sizeof(char_t); + + // copy chunk list to a contiguous buffer + char* buffer = static_cast(xml_memory::allocate(total + max_suffix_size)); + if (!buffer) return status_out_of_memory; + + char* write = buffer; + + for (xml_stream_chunk* chunk = chunks.data; chunk; chunk = chunk->next) + { + assert(write + chunk->size <= buffer + total); + memcpy(write, chunk->data, chunk->size); + write += chunk->size; + } + + assert(write == buffer + total); + + // return buffer + *out_buffer = buffer; + *out_size = total; + + return status_ok; + } + + template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) + { + // get length of remaining data in stream + typename std::basic_istream::pos_type pos = stream.tellg(); + stream.seekg(0, std::ios::end); + std::streamoff length = stream.tellg() - pos; + stream.seekg(pos); + + if (stream.fail() || pos < 0) return status_io_error; + + // guard against huge files + size_t read_length = static_cast(length); + + if (static_cast(read_length) != length || length < 0) return status_out_of_memory; + + size_t max_suffix_size = sizeof(char_t); + + // read stream data into memory (guard against stream exceptions with buffer holder) + auto_deleter buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate); + if (!buffer.data) return status_out_of_memory; + + stream.read(static_cast(buffer.data), static_cast(read_length)); + + // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors + if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; + + // return buffer + size_t actual_length = static_cast(stream.gcount()); + assert(actual_length <= read_length); + + *out_buffer = buffer.release(); + *out_size = actual_length * sizeof(T); + + return status_ok; + } + + template PUGI__FN xml_parse_result load_stream_impl(xml_document_struct* doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding, char_t** out_buffer) + { + void* buffer = 0; + size_t size = 0; + xml_parse_status status = status_ok; + + // if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits) + if (stream.fail()) return make_parse_result(status_io_error); + + // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory) + if (stream.tellg() < 0) + { + stream.clear(); // clear error flags that could be set by a failing tellg + status = load_stream_data_noseek(stream, &buffer, &size); + } + else + status = load_stream_data_seek(stream, &buffer, &size); + + if (status != status_ok) return make_parse_result(status); + + xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size); + + return load_buffer_impl(doc, doc, buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding, true, true, out_buffer); + } +#endif + +#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) + PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return _wfopen_s(&file, path, mode) == 0 ? file : 0; +#else + return _wfopen(path, mode); +#endif + } +#else + PUGI__FN char* convert_path_heap(const wchar_t* str) + { + assert(str); + + // first pass: get length in utf8 characters + size_t length = strlength_wide(str); + size_t size = as_utf8_begin(str, length); + + // allocate resulting string + char* result = static_cast(xml_memory::allocate(size + 1)); + if (!result) return 0; + + // second pass: convert to utf8 + as_utf8_end(result, size, str, length); + + // zero-terminate + result[size] = 0; + + return result; + } + + PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) + { + // there is no standard function to open wide paths, so our best bet is to try utf8 path + char* path_utf8 = convert_path_heap(path); + if (!path_utf8) return 0; + + // convert mode to ASCII (we mirror _wfopen interface) + char mode_ascii[4] = {0}; + for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); + + // try to open the utf8 path + FILE* result = fopen(path_utf8, mode_ascii); + + // free dummy buffer + xml_memory::deallocate(path_utf8); + + return result; + } +#endif + + PUGI__FN FILE* open_file(const char* path, const char* mode) + { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return fopen_s(&file, path, mode) == 0 ? file : 0; +#else + return fopen(path, mode); +#endif + } + + PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) + { + if (!file) return false; + + xml_writer_file writer(file); + doc.save(writer, indent, flags, encoding); + + return ferror(file) == 0; + } + + struct name_null_sentry + { + xml_node_struct* node; + char_t* name; + + name_null_sentry(xml_node_struct* node_): node(node_), name(node_->name) + { + node->name = 0; + } + + ~name_null_sentry() + { + node->name = name; + } + }; +PUGI__NS_END + +namespace pugi +{ + PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) + { + } + + PUGI__FN void xml_writer_file::write(const void* data, size_t size) + { + size_t result = fwrite(data, 1, size, static_cast(file)); + (void)!result; // unfortunately we can't do proper error handling here + } + +#ifndef PUGIXML_NO_STL + PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) + { + } + + PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) + { + } + + PUGI__FN void xml_writer_stream::write(const void* data, size_t size) + { + if (narrow_stream) + { + assert(!wide_stream); + narrow_stream->write(reinterpret_cast(data), static_cast(size)); + } + else + { + assert(wide_stream); + assert(size % sizeof(wchar_t) == 0); + + wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); + } + } +#endif + + PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) + { + } + + PUGI__FN xml_tree_walker::~xml_tree_walker() + { + } + + PUGI__FN int xml_tree_walker::depth() const + { + return _depth; + } + + PUGI__FN bool xml_tree_walker::begin(xml_node&) + { + return true; + } + + PUGI__FN bool xml_tree_walker::end(xml_node&) + { + return true; + } + + PUGI__FN xml_attribute::xml_attribute(): _attr(0) + { + } + + PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) + { + } + + PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) + { + } + + PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const + { + return _attr ? unspecified_bool_xml_attribute : 0; + } + + PUGI__FN bool xml_attribute::operator!() const + { + return !_attr; + } + + PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const + { + return (_attr == r._attr); + } + + PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const + { + return (_attr != r._attr); + } + + PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const + { + return (_attr < r._attr); + } + + PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const + { + return (_attr > r._attr); + } + + PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const + { + return (_attr <= r._attr); + } + + PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const + { + return (_attr >= r._attr); + } + + PUGI__FN xml_attribute xml_attribute::next_attribute() const + { + return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); + } + + PUGI__FN xml_attribute xml_attribute::previous_attribute() const + { + return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); + } + + PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const + { + return (_attr && _attr->value) ? _attr->value + 0 : def; + } + + PUGI__FN int xml_attribute::as_int(int def) const + { + return (_attr && _attr->value) ? impl::get_value_int(_attr->value) : def; + } + + PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const + { + return (_attr && _attr->value) ? impl::get_value_uint(_attr->value) : def; + } + + PUGI__FN double xml_attribute::as_double(double def) const + { + return (_attr && _attr->value) ? impl::get_value_double(_attr->value) : def; + } + + PUGI__FN float xml_attribute::as_float(float def) const + { + return (_attr && _attr->value) ? impl::get_value_float(_attr->value) : def; + } + + PUGI__FN bool xml_attribute::as_bool(bool def) const + { + return (_attr && _attr->value) ? impl::get_value_bool(_attr->value) : def; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_attribute::as_llong(long long def) const + { + return (_attr && _attr->value) ? impl::get_value_llong(_attr->value) : def; + } + + PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const + { + return (_attr && _attr->value) ? impl::get_value_ullong(_attr->value) : def; + } +#endif + + PUGI__FN bool xml_attribute::empty() const + { + return !_attr; + } + + PUGI__FN const char_t* xml_attribute::name() const + { + return (_attr && _attr->name) ? _attr->name + 0 : PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_attribute::value() const + { + return (_attr && _attr->value) ? _attr->value + 0 : PUGIXML_TEXT(""); + } + + PUGI__FN size_t xml_attribute::hash_value() const + { + return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); + } + + PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const + { + return _attr; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(long rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) + { + set_value(rhs); + return *this; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) + { + set_value(rhs); + return *this; + } + + PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) + { + set_value(rhs); + return *this; + } +#endif + + PUGI__FN bool xml_attribute::set_name(const char_t* rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); + } + + PUGI__FN bool xml_attribute::set_value(const char_t* rhs) + { + if (!_attr) return false; + + return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); + } + + PUGI__FN bool xml_attribute::set_value(int rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); + } + + PUGI__FN bool xml_attribute::set_value(unsigned int rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); + } + + PUGI__FN bool xml_attribute::set_value(long rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); + } + + PUGI__FN bool xml_attribute::set_value(unsigned long rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); + } + + PUGI__FN bool xml_attribute::set_value(double rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision); + } + + PUGI__FN bool xml_attribute::set_value(double rhs, int precision) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); + } + + PUGI__FN bool xml_attribute::set_value(float rhs) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision); + } + + PUGI__FN bool xml_attribute::set_value(float rhs, int precision) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); + } + + PUGI__FN bool xml_attribute::set_value(bool rhs) + { + if (!_attr) return false; + + return impl::set_value_bool(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_attribute::set_value(long long rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0); + } + + PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) + { + if (!_attr) return false; + + return impl::set_value_integer(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, false); + } +#endif + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_node::xml_node(): _root(0) + { + } + + PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) + { + } + + PUGI__FN static void unspecified_bool_xml_node(xml_node***) + { + } + + PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const + { + return _root ? unspecified_bool_xml_node : 0; + } + + PUGI__FN bool xml_node::operator!() const + { + return !_root; + } + + PUGI__FN xml_node::iterator xml_node::begin() const + { + return iterator(_root ? _root->first_child + 0 : 0, _root); + } + + PUGI__FN xml_node::iterator xml_node::end() const + { + return iterator(0, _root); + } + + PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const + { + return attribute_iterator(_root ? _root->first_attribute + 0 : 0, _root); + } + + PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const + { + return attribute_iterator(0, _root); + } + + PUGI__FN xml_object_range xml_node::children() const + { + return xml_object_range(begin(), end()); + } + + PUGI__FN xml_object_range xml_node::children(const char_t* name_) const + { + return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); + } + + PUGI__FN xml_object_range xml_node::attributes() const + { + return xml_object_range(attributes_begin(), attributes_end()); + } + + PUGI__FN bool xml_node::operator==(const xml_node& r) const + { + return (_root == r._root); + } + + PUGI__FN bool xml_node::operator!=(const xml_node& r) const + { + return (_root != r._root); + } + + PUGI__FN bool xml_node::operator<(const xml_node& r) const + { + return (_root < r._root); + } + + PUGI__FN bool xml_node::operator>(const xml_node& r) const + { + return (_root > r._root); + } + + PUGI__FN bool xml_node::operator<=(const xml_node& r) const + { + return (_root <= r._root); + } + + PUGI__FN bool xml_node::operator>=(const xml_node& r) const + { + return (_root >= r._root); + } + + PUGI__FN bool xml_node::empty() const + { + return !_root; + } + + PUGI__FN const char_t* xml_node::name() const + { + return (_root && _root->name) ? _root->name + 0 : PUGIXML_TEXT(""); + } + + PUGI__FN xml_node_type xml_node::type() const + { + return _root ? PUGI__NODETYPE(_root) : node_null; + } + + PUGI__FN const char_t* xml_node::value() const + { + return (_root && _root->value) ? _root->value + 0 : PUGIXML_TEXT(""); + } + + PUGI__FN xml_node xml_node::child(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const + { + if (!_root) return xml_attribute(); + + for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) + if (i->name && impl::strequal(name_, i->name)) + return xml_attribute(i); + + return xml_attribute(); + } + + PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_node xml_node::next_sibling() const + { + return _root ? xml_node(_root->next_sibling) : xml_node(); + } + + PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) + if (i->name && impl::strequal(name_, i->name)) return xml_node(i); + + return xml_node(); + } + + PUGI__FN xml_attribute xml_node::attribute(const char_t* name_, xml_attribute& hint_) const + { + xml_attribute_struct* hint = hint_._attr; + + // if hint is not an attribute of node, behavior is not defined + assert(!hint || (_root && impl::is_attribute_of(hint, _root))); + + if (!_root) return xml_attribute(); + + // optimistically search from hint up until the end + for (xml_attribute_struct* i = hint; i; i = i->next_attribute) + if (i->name && impl::strequal(name_, i->name)) + { + // update hint to maximize efficiency of searching for consecutive attributes + hint_._attr = i->next_attribute; + + return xml_attribute(i); + } + + // wrap around and search from the first attribute until the hint + // 'j' null pointer check is technically redundant, but it prevents a crash in case the assertion above fails + for (xml_attribute_struct* j = _root->first_attribute; j && j != hint; j = j->next_attribute) + if (j->name && impl::strequal(name_, j->name)) + { + // update hint to maximize efficiency of searching for consecutive attributes + hint_._attr = j->next_attribute; + + return xml_attribute(j); + } + + return xml_attribute(); + } + + PUGI__FN xml_node xml_node::previous_sibling() const + { + if (!_root) return xml_node(); + + if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); + else return xml_node(); + } + + PUGI__FN xml_node xml_node::parent() const + { + return _root ? xml_node(_root->parent) : xml_node(); + } + + PUGI__FN xml_node xml_node::root() const + { + return _root ? xml_node(&impl::get_document(_root)) : xml_node(); + } + + PUGI__FN xml_text xml_node::text() const + { + return xml_text(_root); + } + + PUGI__FN const char_t* xml_node::child_value() const + { + if (!_root) return PUGIXML_TEXT(""); + + // element nodes can have value if parse_embed_pcdata was used + if (PUGI__NODETYPE(_root) == node_element && _root->value) + return _root->value; + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (impl::is_text_node(i) && i->value) + return i->value; + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const + { + return child(name_).child_value(); + } + + PUGI__FN xml_attribute xml_node::first_attribute() const + { + return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); + } + + PUGI__FN xml_attribute xml_node::last_attribute() const + { + return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); + } + + PUGI__FN xml_node xml_node::first_child() const + { + return _root ? xml_node(_root->first_child) : xml_node(); + } + + PUGI__FN xml_node xml_node::last_child() const + { + return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); + } + + PUGI__FN bool xml_node::set_name(const char_t* rhs) + { + xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; + + if (type_ != node_element && type_ != node_pi && type_ != node_declaration) + return false; + + return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs, impl::strlength(rhs)); + } + + PUGI__FN bool xml_node::set_value(const char_t* rhs) + { + xml_node_type type_ = _root ? PUGI__NODETYPE(_root) : node_null; + + if (type_ != node_pcdata && type_ != node_cdata && type_ != node_comment && type_ != node_pi && type_ != node_doctype) + return false; + + return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)); + } + + PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::append_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::prepend_attribute(a._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_after(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) + { + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_before(a._attr, attr._attr, _root); + + a.set_name(name_); + + return a; + } + + PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::append_attribute(a._attr, _root); + impl::node_copy_attribute(a._attr, proto._attr); + + return a; + } + + PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) + { + if (!proto) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::prepend_attribute(a._attr, _root); + impl::node_copy_attribute(a._attr, proto._attr); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_after(a._attr, attr._attr, _root); + impl::node_copy_attribute(a._attr, proto._attr); + + return a; + } + + PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) + { + if (!proto) return xml_attribute(); + if (!impl::allow_insert_attribute(type())) return xml_attribute(); + if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_attribute(); + + xml_attribute a(impl::allocate_attribute(alloc)); + if (!a) return xml_attribute(); + + impl::insert_attribute_before(a._attr, attr._attr, _root); + impl::node_copy_attribute(a._attr, proto._attr); + + return a; + } + + PUGI__FN xml_node xml_node::append_child(xml_node_type type_) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::append_node(n._root, _root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::prepend_node(n._root, _root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::insert_node_before(n._root, node._root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) + { + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::insert_node_after(n._root, node._root); + + if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); + + return n; + } + + PUGI__FN xml_node xml_node::append_child(const char_t* name_) + { + xml_node result = append_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) + { + xml_node result = prepend_child(node_element); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) + { + xml_node result = insert_child_after(node_element, node); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) + { + xml_node result = insert_child_before(node_element, node); + + result.set_name(name_); + + return result; + } + + PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::append_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::prepend_node(n._root, _root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::insert_node_after(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) + { + xml_node_type type_ = proto.type(); + if (!impl::allow_insert_child(type(), type_)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + xml_node n(impl::allocate_node(alloc, type_)); + if (!n) return xml_node(); + + impl::insert_node_before(n._root, node._root); + impl::node_copy_tree(n._root, proto._root); + + return n; + } + + PUGI__FN xml_node xml_node::append_move(const xml_node& moved) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::append_node(moved._root, _root); + + return moved; + } + + PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::prepend_node(moved._root, _root); + + return moved; + } + + PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + if (moved._root == node._root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::insert_node_after(moved._root, node._root); + + return moved; + } + + PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) + { + if (!impl::allow_move(*this, moved)) return xml_node(); + if (!node._root || node._root->parent != _root) return xml_node(); + if (moved._root == node._root) return xml_node(); + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return xml_node(); + + // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers + impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; + + impl::remove_node(moved._root); + impl::insert_node_before(moved._root, node._root); + + return moved; + } + + PUGI__FN bool xml_node::remove_attribute(const char_t* name_) + { + return remove_attribute(attribute(name_)); + } + + PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) + { + if (!_root || !a._attr) return false; + if (!impl::is_attribute_of(a._attr, _root)) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + impl::remove_attribute(a._attr, _root); + impl::destroy_attribute(a._attr, alloc); + + return true; + } + + PUGI__FN bool xml_node::remove_attributes() + { + if (!_root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + for (xml_attribute_struct* attr = _root->first_attribute; attr; ) + { + xml_attribute_struct* next = attr->next_attribute; + + impl::destroy_attribute(attr, alloc); + + attr = next; + } + + _root->first_attribute = 0; + + return true; + } + + PUGI__FN bool xml_node::remove_child(const char_t* name_) + { + return remove_child(child(name_)); + } + + PUGI__FN bool xml_node::remove_child(const xml_node& n) + { + if (!_root || !n._root || n._root->parent != _root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + impl::remove_node(n._root); + impl::destroy_node(n._root, alloc); + + return true; + } + + PUGI__FN bool xml_node::remove_children() + { + if (!_root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + for (xml_node_struct* cur = _root->first_child; cur; ) + { + xml_node_struct* next = cur->next_sibling; + + impl::destroy_node(cur, alloc); + + cur = next; + } + + _root->first_child = 0; + + return true; + } + + PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + // append_buffer is only valid for elements/documents + if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); + + // get document node + impl::xml_document_struct* doc = &impl::get_document(_root); + + // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense + doc->header |= impl::xml_memory_page_contents_shared_mask; + + // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) + impl::xml_memory_page* page = 0; + impl::xml_extra_buffer* extra = static_cast(doc->allocate_memory(sizeof(impl::xml_extra_buffer) + sizeof(void*), page)); + (void)page; + + if (!extra) return impl::make_parse_result(status_out_of_memory); + + #ifdef PUGIXML_COMPACT + // align the memory block to a pointer boundary; this is required for compact mode where memory allocations are only 4b aligned + // note that this requires up to sizeof(void*)-1 additional memory, which the allocation above takes into account + extra = reinterpret_cast((reinterpret_cast(extra) + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1)); + #endif + + // add extra buffer to the list + extra->buffer = 0; + extra->next = doc->extra_buffers; + doc->extra_buffers = extra; + + // name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level + impl::name_null_sentry sentry(_root); + + return impl::load_buffer_impl(doc, _root, const_cast(contents), size, options, encoding, false, false, &extra->buffer); + } + + PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (i->name && impl::strequal(name_, i->name)) + { + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) + return xml_node(i); + } + + return xml_node(); + } + + PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const + { + if (!_root) return xml_node(); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) + if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value + 0 : PUGIXML_TEXT(""))) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN string_t xml_node::path(char_t delimiter) const + { + if (!_root) return string_t(); + + size_t offset = 0; + + for (xml_node_struct* i = _root; i; i = i->parent) + { + offset += (i != _root); + offset += i->name ? impl::strlength(i->name) : 0; + } + + string_t result; + result.resize(offset); + + for (xml_node_struct* j = _root; j; j = j->parent) + { + if (j != _root) + result[--offset] = delimiter; + + if (j->name) + { + size_t length = impl::strlength(j->name); + + offset -= length; + memcpy(&result[offset], j->name, length * sizeof(char_t)); + } + } + + assert(offset == 0); + + return result; + } +#endif + + PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const + { + xml_node context = path_[0] == delimiter ? root() : *this; + + if (!context._root) return xml_node(); + + const char_t* path_segment = path_; + + while (*path_segment == delimiter) ++path_segment; + + const char_t* path_segment_end = path_segment; + + while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; + + if (path_segment == path_segment_end) return context; + + const char_t* next_segment = path_segment_end; + + while (*next_segment == delimiter) ++next_segment; + + if (*path_segment == '.' && path_segment + 1 == path_segment_end) + return context.first_element_by_path(next_segment, delimiter); + else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) + return context.parent().first_element_by_path(next_segment, delimiter); + else + { + for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling) + { + if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) + { + xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); + + if (subsearch) return subsearch; + } + } + + return xml_node(); + } + } + + PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) + { + walker._depth = -1; + + xml_node arg_begin(_root); + if (!walker.begin(arg_begin)) return false; + + xml_node_struct* cur = _root ? _root->first_child + 0 : 0; + + if (cur) + { + ++walker._depth; + + do + { + xml_node arg_for_each(cur); + if (!walker.for_each(arg_for_each)) + return false; + + if (cur->first_child) + { + ++walker._depth; + cur = cur->first_child; + } + else if (cur->next_sibling) + cur = cur->next_sibling; + else + { + while (!cur->next_sibling && cur != _root && cur->parent) + { + --walker._depth; + cur = cur->parent; + } + + if (cur != _root) + cur = cur->next_sibling; + } + } + while (cur && cur != _root); + } + + assert(walker._depth == -1); + + xml_node arg_end(_root); + return walker.end(arg_end); + } + + PUGI__FN size_t xml_node::hash_value() const + { + return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); + } + + PUGI__FN xml_node_struct* xml_node::internal_object() const + { + return _root; + } + + PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + if (!_root) return; + + impl::xml_buffered_writer buffered_writer(writer, encoding); + + impl::node_output(buffered_writer, _root, indent, flags, depth); + + buffered_writer.flush(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding, depth); + } + + PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const + { + xml_writer_stream writer(stream); + + print(writer, indent, flags, encoding_wchar, depth); + } +#endif + + PUGI__FN ptrdiff_t xml_node::offset_debug() const + { + if (!_root) return -1; + + impl::xml_document_struct& doc = impl::get_document(_root); + + // we can determine the offset reliably only if there is exactly once parse buffer + if (!doc.buffer || doc.extra_buffers) return -1; + + switch (type()) + { + case node_document: + return 0; + + case node_element: + case node_declaration: + case node_pi: + return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1; + + case node_pcdata: + case node_cdata: + case node_comment: + case node_doctype: + return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1; + + default: + assert(false && "Invalid node type"); // unreachable + return -1; + } + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) + { + } + + PUGI__FN xml_node_struct* xml_text::_data() const + { + if (!_root || impl::is_text_node(_root)) return _root; + + // element nodes can have value if parse_embed_pcdata was used + if (PUGI__NODETYPE(_root) == node_element && _root->value) + return _root; + + for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) + if (impl::is_text_node(node)) + return node; + + return 0; + } + + PUGI__FN xml_node_struct* xml_text::_data_new() + { + xml_node_struct* d = _data(); + if (d) return d; + + return xml_node(_root).append_child(node_pcdata).internal_object(); + } + + PUGI__FN xml_text::xml_text(): _root(0) + { + } + + PUGI__FN static void unspecified_bool_xml_text(xml_text***) + { + } + + PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const + { + return _data() ? unspecified_bool_xml_text : 0; + } + + PUGI__FN bool xml_text::operator!() const + { + return !_data(); + } + + PUGI__FN bool xml_text::empty() const + { + return _data() == 0; + } + + PUGI__FN const char_t* xml_text::get() const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? d->value + 0 : PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* xml_text::as_string(const char_t* def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? d->value + 0 : def; + } + + PUGI__FN int xml_text::as_int(int def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_int(d->value) : def; + } + + PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_uint(d->value) : def; + } + + PUGI__FN double xml_text::as_double(double def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_double(d->value) : def; + } + + PUGI__FN float xml_text::as_float(float def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_float(d->value) : def; + } + + PUGI__FN bool xml_text::as_bool(bool def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_bool(d->value) : def; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN long long xml_text::as_llong(long long def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_llong(d->value) : def; + } + + PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const + { + xml_node_struct* d = _data(); + + return (d && d->value) ? impl::get_value_ullong(d->value) : def; + } +#endif + + PUGI__FN bool xml_text::set(const char_t* rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, impl::strlength(rhs)) : false; + } + + PUGI__FN bool xml_text::set(int rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; + } + + PUGI__FN bool xml_text::set(unsigned int rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; + } + + PUGI__FN bool xml_text::set(long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; + } + + PUGI__FN bool xml_text::set(unsigned long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; + } + + PUGI__FN bool xml_text::set(float rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision) : false; + } + + PUGI__FN bool xml_text::set(float rhs, int precision) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; + } + + PUGI__FN bool xml_text::set(double rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision) : false; + } + + PUGI__FN bool xml_text::set(double rhs, int precision) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; + } + + PUGI__FN bool xml_text::set(bool rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_bool(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN bool xml_text::set(long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, rhs < 0) : false; + } + + PUGI__FN bool xml_text::set(unsigned long long rhs) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_integer(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, false) : false; + } +#endif + + PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(int rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(long rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned long rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(double rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(float rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(bool rhs) + { + set(rhs); + return *this; + } + +#ifdef PUGIXML_HAS_LONG_LONG + PUGI__FN xml_text& xml_text::operator=(long long rhs) + { + set(rhs); + return *this; + } + + PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) + { + set(rhs); + return *this; + } +#endif + + PUGI__FN xml_node xml_text::data() const + { + return xml_node(_data()); + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xml_text& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN xml_node_iterator::xml_node_iterator() + { + } + + PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) + { + } + + PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const + { + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const + { + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_node& xml_node_iterator::operator*() const + { + assert(_wrap._root); + return _wrap; + } + + PUGI__FN xml_node* xml_node_iterator::operator->() const + { + assert(_wrap._root); + return const_cast(&_wrap); // BCC5 workaround + } + + PUGI__FN xml_node_iterator& xml_node_iterator::operator++() + { + assert(_wrap._root); + _wrap._root = _wrap._root->next_sibling; + return *this; + } + + PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) + { + xml_node_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN xml_node_iterator& xml_node_iterator::operator--() + { + _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); + return *this; + } + + PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) + { + xml_node_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator() + { + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) + { + } + + PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) + { + } + + PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const + { + return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const + { + return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const + { + assert(_wrap._attr); + return _wrap; + } + + PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const + { + assert(_wrap._attr); + return const_cast(&_wrap); // BCC5 workaround + } + + PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator++() + { + assert(_wrap._attr); + _wrap._attr = _wrap._attr->next_attribute; + return *this; + } + + PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) + { + xml_attribute_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN xml_attribute_iterator& xml_attribute_iterator::operator--() + { + _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); + return *this; + } + + PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) + { + xml_attribute_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) + { + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) + { + } + + PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) + { + } + + PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const + { + return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; + } + + PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const + { + return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; + } + + PUGI__FN xml_node& xml_named_node_iterator::operator*() const + { + assert(_wrap._root); + return _wrap; + } + + PUGI__FN xml_node* xml_named_node_iterator::operator->() const + { + assert(_wrap._root); + return const_cast(&_wrap); // BCC5 workaround + } + + PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator++() + { + assert(_wrap._root); + _wrap = _wrap.next_sibling(_name); + return *this; + } + + PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) + { + xml_named_node_iterator temp = *this; + ++*this; + return temp; + } + + PUGI__FN xml_named_node_iterator& xml_named_node_iterator::operator--() + { + if (_wrap._root) + _wrap = _wrap.previous_sibling(_name); + else + { + _wrap = _parent.last_child(); + + if (!impl::strequal(_wrap.name(), _name)) + _wrap = _wrap.previous_sibling(_name); + } + + return *this; + } + + PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) + { + xml_named_node_iterator temp = *this; + --*this; + return temp; + } + + PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) + { + } + + PUGI__FN xml_parse_result::operator bool() const + { + return status == status_ok; + } + + PUGI__FN const char* xml_parse_result::description() const + { + switch (status) + { + case status_ok: return "No error"; + + case status_file_not_found: return "File was not found"; + case status_io_error: return "Error reading from file/stream"; + case status_out_of_memory: return "Could not allocate memory"; + case status_internal_error: return "Internal error occurred"; + + case status_unrecognized_tag: return "Could not determine tag type"; + + case status_bad_pi: return "Error parsing document declaration/processing instruction"; + case status_bad_comment: return "Error parsing comment"; + case status_bad_cdata: return "Error parsing CDATA section"; + case status_bad_doctype: return "Error parsing document type declaration"; + case status_bad_pcdata: return "Error parsing PCDATA section"; + case status_bad_start_element: return "Error parsing start element tag"; + case status_bad_attribute: return "Error parsing element attribute"; + case status_bad_end_element: return "Error parsing end element tag"; + case status_end_element_mismatch: return "Start-end tags mismatch"; + + case status_append_invalid_root: return "Unable to append nodes: root is not an element or document"; + + case status_no_document_element: return "No document element found"; + + default: return "Unknown error"; + } + } + + PUGI__FN xml_document::xml_document(): _buffer(0) + { + _create(); + } + + PUGI__FN xml_document::~xml_document() + { + _destroy(); + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN xml_document::xml_document(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT: _buffer(0) + { + _create(); + _move(rhs); + } + + PUGI__FN xml_document& xml_document::operator=(xml_document&& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT + { + if (this == &rhs) return *this; + + _destroy(); + _create(); + _move(rhs); + + return *this; + } +#endif + + PUGI__FN void xml_document::reset() + { + _destroy(); + _create(); + } + + PUGI__FN void xml_document::reset(const xml_document& proto) + { + reset(); + + impl::node_copy_tree(_root, proto._root); + } + + PUGI__FN void xml_document::_create() + { + assert(!_root); + + #ifdef PUGIXML_COMPACT + // space for page marker for the first page (uint32_t), rounded up to pointer size; assumes pointers are at least 32-bit + const size_t page_offset = sizeof(void*); + #else + const size_t page_offset = 0; + #endif + + // initialize sentinel page + PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + page_offset <= sizeof(_memory)); + + // prepare page structure + impl::xml_memory_page* page = impl::xml_memory_page::construct(_memory); + assert(page); + + page->busy_size = impl::xml_memory_page_size; + + // setup first page marker + #ifdef PUGIXML_COMPACT + // round-trip through void* to avoid 'cast increases required alignment of target type' warning + page->compact_page_marker = reinterpret_cast(static_cast(reinterpret_cast(page) + sizeof(impl::xml_memory_page))); + *page->compact_page_marker = sizeof(impl::xml_memory_page); + #endif + + // allocate new root + _root = new (reinterpret_cast(page) + sizeof(impl::xml_memory_page) + page_offset) impl::xml_document_struct(page); + _root->prev_sibling_c = _root; + + // setup sentinel page + page->allocator = static_cast(_root); + + // setup hash table pointer in allocator + #ifdef PUGIXML_COMPACT + page->allocator->_hash = &static_cast(_root)->hash; + #endif + + // verify the document allocation + assert(reinterpret_cast(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); + } + + PUGI__FN void xml_document::_destroy() + { + assert(_root); + + // destroy static storage + if (_buffer) + { + impl::xml_memory::deallocate(_buffer); + _buffer = 0; + } + + // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator) + for (impl::xml_extra_buffer* extra = static_cast(_root)->extra_buffers; extra; extra = extra->next) + { + if (extra->buffer) impl::xml_memory::deallocate(extra->buffer); + } + + // destroy dynamic storage, leave sentinel page (it's in static memory) + impl::xml_memory_page* root_page = PUGI__GETPAGE(_root); + assert(root_page && !root_page->prev); + assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); + + for (impl::xml_memory_page* page = root_page->next; page; ) + { + impl::xml_memory_page* next = page->next; + + impl::xml_allocator::deallocate_page(page); + + page = next; + } + + #ifdef PUGIXML_COMPACT + // destroy hash table + static_cast(_root)->hash.clear(); + #endif + + _root = 0; + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN void xml_document::_move(xml_document& rhs) PUGIXML_NOEXCEPT_IF_NOT_COMPACT + { + impl::xml_document_struct* doc = static_cast(_root); + impl::xml_document_struct* other = static_cast(rhs._root); + + // save first child pointer for later; this needs hash access + xml_node_struct* other_first_child = other->first_child; + + #ifdef PUGIXML_COMPACT + // reserve space for the hash table up front; this is the only operation that can fail + // if it does, we have no choice but to throw (if we have exceptions) + if (other_first_child) + { + size_t other_children = 0; + for (xml_node_struct* node = other_first_child; node; node = node->next_sibling) + other_children++; + + // in compact mode, each pointer assignment could result in a hash table request + // during move, we have to relocate document first_child and parents of all children + // normally there's just one child and its parent has a pointerless encoding but + // we assume the worst here + if (!other->_hash->reserve(other_children + 1)) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif + } + } + #endif + + // move allocation state + // note that other->_root may point to the embedded document page, in which case we should keep original (empty) state + if (other->_root != PUGI__GETPAGE(other)) + { + doc->_root = other->_root; + doc->_busy_size = other->_busy_size; + } + + // move buffer state + doc->buffer = other->buffer; + doc->extra_buffers = other->extra_buffers; + _buffer = rhs._buffer; + + #ifdef PUGIXML_COMPACT + // move compact hash; note that the hash table can have pointers to other but they will be "inactive", similarly to nodes removed with remove_child + doc->hash = other->hash; + doc->_hash = &doc->hash; + + // make sure we don't access other hash up until the end when we reinitialize other document + other->_hash = 0; + #endif + + // move page structure + impl::xml_memory_page* doc_page = PUGI__GETPAGE(doc); + assert(doc_page && !doc_page->prev && !doc_page->next); + + impl::xml_memory_page* other_page = PUGI__GETPAGE(other); + assert(other_page && !other_page->prev); + + // relink pages since root page is embedded into xml_document + if (impl::xml_memory_page* page = other_page->next) + { + assert(page->prev == other_page); + + page->prev = doc_page; + + doc_page->next = page; + other_page->next = 0; + } + + // make sure pages point to the correct document state + for (impl::xml_memory_page* page = doc_page->next; page; page = page->next) + { + assert(page->allocator == other); + + page->allocator = doc; + + #ifdef PUGIXML_COMPACT + // this automatically migrates most children between documents and prevents ->parent assignment from allocating + if (page->compact_shared_parent == other) + page->compact_shared_parent = doc; + #endif + } + + // move tree structure + assert(!doc->first_child); + + doc->first_child = other_first_child; + + for (xml_node_struct* node = other_first_child; node; node = node->next_sibling) + { + #ifdef PUGIXML_COMPACT + // most children will have migrated when we reassigned compact_shared_parent + assert(node->parent == other || node->parent == doc); + + node->parent = doc; + #else + assert(node->parent == other); + node->parent = doc; + #endif + } + + // reset other document + new (other) impl::xml_document_struct(PUGI__GETPAGE(other)); + rhs._buffer = 0; + } +#endif + +#ifndef PUGIXML_NO_STL + PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_stream_impl(static_cast(_root), stream, options, encoding, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) + { + reset(); + + return impl::load_stream_impl(static_cast(_root), stream, options, encoding_wchar, &_buffer); + } +#endif + + PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) + { + // Force native encoding (skip autodetection) + #ifdef PUGIXML_WCHAR_MODE + xml_encoding encoding = encoding_wchar; + #else + xml_encoding encoding = encoding_utf8; + #endif + + return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); + } + + PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) + { + return load_string(contents, options); + } + + PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) + { + reset(); + + using impl::auto_deleter; // MSVC7 workaround + auto_deleter file(impl::open_file(path_, "rb"), impl::close_file); + + return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) + { + reset(); + + using impl::auto_deleter; // MSVC7 workaround + auto_deleter file(impl::open_file_wide(path_, L"rb"), impl::close_file); + + return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, const_cast(contents), size, options, encoding, false, false, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, false, &_buffer); + } + + PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) + { + reset(); + + return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, true, &_buffer); + } + + PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + impl::xml_buffered_writer buffered_writer(writer, encoding); + + if ((flags & format_write_bom) && encoding != encoding_latin1) + { + // BOM always represents the codepoint U+FEFF, so just write it in native encoding + #ifdef PUGIXML_WCHAR_MODE + unsigned int bom = 0xfeff; + buffered_writer.write(static_cast(bom)); + #else + buffered_writer.write('\xef', '\xbb', '\xbf'); + #endif + } + + if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) + { + buffered_writer.write_string(PUGIXML_TEXT("'); + if (!(flags & format_raw)) buffered_writer.write('\n'); + } + + impl::node_output(buffered_writer, _root, indent, flags, 0); + + buffered_writer.flush(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding); + } + + PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const + { + xml_writer_stream writer(stream); + + save(writer, indent, flags, encoding_wchar); + } +#endif + + PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + using impl::auto_deleter; // MSVC7 workaround + auto_deleter file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); + + return impl::save_file_impl(*this, file.data, indent, flags, encoding); + } + + PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const + { + using impl::auto_deleter; // MSVC7 workaround + auto_deleter file(impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"), impl::close_file); + + return impl::save_file_impl(*this, file.data, indent, flags, encoding); + } + + PUGI__FN xml_node xml_document::document_element() const + { + assert(_root); + + for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) + if (PUGI__NODETYPE(i) == node_element) + return xml_node(i); + + return xml_node(); + } + +#ifndef PUGIXML_NO_STL + PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) + { + assert(str); + + return impl::as_utf8_impl(str, impl::strlength_wide(str)); + } + + PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) + { + return impl::as_utf8_impl(str.c_str(), str.size()); + } + + PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) + { + assert(str); + + return impl::as_wide_impl(str, strlen(str)); + } + + PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) + { + return impl::as_wide_impl(str.c_str(), str.size()); + } +#endif + + PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) + { + impl::xml_memory::allocate = allocate; + impl::xml_memory::deallocate = deallocate; + } + + PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() + { + return impl::xml_memory::allocate; + } + + PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() + { + return impl::xml_memory::deallocate; + } +} + +#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) +namespace std +{ + // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) +namespace std +{ + // Workarounds for (non-standard) iterator category detection + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) + { + return std::bidirectional_iterator_tag(); + } + + PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) + { + return std::bidirectional_iterator_tag(); + } +} +#endif + +#ifndef PUGIXML_NO_XPATH +// STL replacements +PUGI__NS_BEGIN + struct equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs == rhs; + } + }; + + struct not_equal_to + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs != rhs; + } + }; + + struct less + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs < rhs; + } + }; + + struct less_equal + { + template bool operator()(const T& lhs, const T& rhs) const + { + return lhs <= rhs; + } + }; + + template inline void swap(T& lhs, T& rhs) + { + T temp = lhs; + lhs = rhs; + rhs = temp; + } + + template PUGI__FN I min_element(I begin, I end, const Pred& pred) + { + I result = begin; + + for (I it = begin + 1; it != end; ++it) + if (pred(*it, *result)) + result = it; + + return result; + } + + template PUGI__FN void reverse(I begin, I end) + { + while (end - begin > 1) + swap(*begin++, *--end); + } + + template PUGI__FN I unique(I begin, I end) + { + // fast skip head + while (end - begin > 1 && *begin != *(begin + 1)) + begin++; + + if (begin == end) + return begin; + + // last written element + I write = begin++; + + // merge unique elements + while (begin != end) + { + if (*begin != *write) + *++write = *begin++; + else + begin++; + } + + // past-the-end (write points to live element) + return write + 1; + } + + template PUGI__FN void insertion_sort(T* begin, T* end, const Pred& pred) + { + if (begin == end) + return; + + for (T* it = begin + 1; it != end; ++it) + { + T val = *it; + T* hole = it; + + // move hole backwards + while (hole > begin && pred(val, *(hole - 1))) + { + *hole = *(hole - 1); + hole--; + } + + // fill hole with element + *hole = val; + } + } + + template inline I median3(I first, I middle, I last, const Pred& pred) + { + if (pred(*middle, *first)) + swap(middle, first); + if (pred(*last, *middle)) + swap(last, middle); + if (pred(*middle, *first)) + swap(middle, first); + + return middle; + } + + template PUGI__FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) + { + // invariant: array is split into 4 groups: = < ? > (each variable denotes the boundary between the groups) + T* eq = begin; + T* lt = begin; + T* gt = end; + + while (lt < gt) + { + if (pred(*lt, pivot)) + lt++; + else if (*lt == pivot) + swap(*eq++, *lt++); + else + swap(*lt, *--gt); + } + + // we now have just 4 groups: = < >; move equal elements to the middle + T* eqbeg = gt; + + for (T* it = begin; it != eq; ++it) + swap(*it, *--eqbeg); + + *out_eqbeg = eqbeg; + *out_eqend = gt; + } + + template PUGI__FN void sort(I begin, I end, const Pred& pred) + { + // sort large chunks + while (end - begin > 16) + { + // find median element + I middle = begin + (end - begin) / 2; + I median = median3(begin, middle, end - 1, pred); + + // partition in three chunks (< = >) + I eqbeg, eqend; + partition3(begin, end, *median, pred, &eqbeg, &eqend); + + // loop on larger half + if (eqbeg - begin > end - eqend) + { + sort(eqend, end, pred); + end = eqbeg; + } + else + { + sort(begin, eqbeg, pred); + begin = eqend; + } + } + + // insertion sort small chunk + insertion_sort(begin, end, pred); + } + + PUGI__FN bool hash_insert(const void** table, size_t size, const void* key) + { + assert(key); + + unsigned int h = static_cast(reinterpret_cast(key)); + + // MurmurHash3 32-bit finalizer + h ^= h >> 16; + h *= 0x85ebca6bu; + h ^= h >> 13; + h *= 0xc2b2ae35u; + h ^= h >> 16; + + size_t hashmod = size - 1; + size_t bucket = h & hashmod; + + for (size_t probe = 0; probe <= hashmod; ++probe) + { + if (table[bucket] == 0) + { + table[bucket] = key; + return true; + } + + if (table[bucket] == key) + return false; + + // hash collision, quadratic probing + bucket = (bucket + probe + 1) & hashmod; + } + + assert(false && "Hash table is full"); // unreachable + return false; + } +PUGI__NS_END + +// Allocator used for AST and evaluation stacks +PUGI__NS_BEGIN + static const size_t xpath_memory_page_size = + #ifdef PUGIXML_MEMORY_XPATH_PAGE_SIZE + PUGIXML_MEMORY_XPATH_PAGE_SIZE + #else + 4096 + #endif + ; + + static const uintptr_t xpath_memory_block_alignment = sizeof(double) > sizeof(void*) ? sizeof(double) : sizeof(void*); + + struct xpath_memory_block + { + xpath_memory_block* next; + size_t capacity; + + union + { + char data[xpath_memory_page_size]; + double alignment; + }; + }; + + struct xpath_allocator + { + xpath_memory_block* _root; + size_t _root_size; + bool* _error; + + xpath_allocator(xpath_memory_block* root, bool* error = 0): _root(root), _root_size(0), _error(error) + { + } + + void* allocate(size_t size) + { + // round size up to block alignment boundary + size = (size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); + + if (_root_size + size <= _root->capacity) + { + void* buf = &_root->data[0] + _root_size; + _root_size += size; + return buf; + } + else + { + // make sure we have at least 1/4th of the page free after allocation to satisfy subsequent allocation requests + size_t block_capacity_base = sizeof(_root->data); + size_t block_capacity_req = size + block_capacity_base / 4; + size_t block_capacity = (block_capacity_base > block_capacity_req) ? block_capacity_base : block_capacity_req; + + size_t block_size = block_capacity + offsetof(xpath_memory_block, data); + + xpath_memory_block* block = static_cast(xml_memory::allocate(block_size)); + if (!block) + { + if (_error) *_error = true; + return 0; + } + + block->next = _root; + block->capacity = block_capacity; + + _root = block; + _root_size = size; + + return block->data; + } + } + + void* reallocate(void* ptr, size_t old_size, size_t new_size) + { + // round size up to block alignment boundary + old_size = (old_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); + new_size = (new_size + xpath_memory_block_alignment - 1) & ~(xpath_memory_block_alignment - 1); + + // we can only reallocate the last object + assert(ptr == 0 || static_cast(ptr) + old_size == &_root->data[0] + _root_size); + + // try to reallocate the object inplace + if (ptr && _root_size - old_size + new_size <= _root->capacity) + { + _root_size = _root_size - old_size + new_size; + return ptr; + } + + // allocate a new block + void* result = allocate(new_size); + if (!result) return 0; + + // we have a new block + if (ptr) + { + // copy old data (we only support growing) + assert(new_size >= old_size); + memcpy(result, ptr, old_size); + + // free the previous page if it had no other objects + assert(_root->data == result); + assert(_root->next); + + if (_root->next->data == ptr) + { + // deallocate the whole page, unless it was the first one + xpath_memory_block* next = _root->next->next; + + if (next) + { + xml_memory::deallocate(_root->next); + _root->next = next; + } + } + } + + return result; + } + + void revert(const xpath_allocator& state) + { + // free all new pages + xpath_memory_block* cur = _root; + + while (cur != state._root) + { + xpath_memory_block* next = cur->next; + + xml_memory::deallocate(cur); + + cur = next; + } + + // restore state + _root = state._root; + _root_size = state._root_size; + } + + void release() + { + xpath_memory_block* cur = _root; + assert(cur); + + while (cur->next) + { + xpath_memory_block* next = cur->next; + + xml_memory::deallocate(cur); + + cur = next; + } + } + }; + + struct xpath_allocator_capture + { + xpath_allocator_capture(xpath_allocator* alloc): _target(alloc), _state(*alloc) + { + } + + ~xpath_allocator_capture() + { + _target->revert(_state); + } + + xpath_allocator* _target; + xpath_allocator _state; + }; + + struct xpath_stack + { + xpath_allocator* result; + xpath_allocator* temp; + }; + + struct xpath_stack_data + { + xpath_memory_block blocks[2]; + xpath_allocator result; + xpath_allocator temp; + xpath_stack stack; + bool oom; + + xpath_stack_data(): result(blocks + 0, &oom), temp(blocks + 1, &oom), oom(false) + { + blocks[0].next = blocks[1].next = 0; + blocks[0].capacity = blocks[1].capacity = sizeof(blocks[0].data); + + stack.result = &result; + stack.temp = &temp; + } + + ~xpath_stack_data() + { + result.release(); + temp.release(); + } + }; +PUGI__NS_END + +// String class +PUGI__NS_BEGIN + class xpath_string + { + const char_t* _buffer; + bool _uses_heap; + size_t _length_heap; + + static char_t* duplicate_string(const char_t* string, size_t length, xpath_allocator* alloc) + { + char_t* result = static_cast(alloc->allocate((length + 1) * sizeof(char_t))); + if (!result) return 0; + + memcpy(result, string, length * sizeof(char_t)); + result[length] = 0; + + return result; + } + + xpath_string(const char_t* buffer, bool uses_heap_, size_t length_heap): _buffer(buffer), _uses_heap(uses_heap_), _length_heap(length_heap) + { + } + + public: + static xpath_string from_const(const char_t* str) + { + return xpath_string(str, false, 0); + } + + static xpath_string from_heap_preallocated(const char_t* begin, const char_t* end) + { + assert(begin <= end && *end == 0); + + return xpath_string(begin, true, static_cast(end - begin)); + } + + static xpath_string from_heap(const char_t* begin, const char_t* end, xpath_allocator* alloc) + { + assert(begin <= end); + + if (begin == end) + return xpath_string(); + + size_t length = static_cast(end - begin); + const char_t* data = duplicate_string(begin, length, alloc); + + return data ? xpath_string(data, true, length) : xpath_string(); + } + + xpath_string(): _buffer(PUGIXML_TEXT("")), _uses_heap(false), _length_heap(0) + { + } + + void append(const xpath_string& o, xpath_allocator* alloc) + { + // skip empty sources + if (!*o._buffer) return; + + // fast append for constant empty target and constant source + if (!*_buffer && !_uses_heap && !o._uses_heap) + { + _buffer = o._buffer; + } + else + { + // need to make heap copy + size_t target_length = length(); + size_t source_length = o.length(); + size_t result_length = target_length + source_length; + + // allocate new buffer + char_t* result = static_cast(alloc->reallocate(_uses_heap ? const_cast(_buffer) : 0, (target_length + 1) * sizeof(char_t), (result_length + 1) * sizeof(char_t))); + if (!result) return; + + // append first string to the new buffer in case there was no reallocation + if (!_uses_heap) memcpy(result, _buffer, target_length * sizeof(char_t)); + + // append second string to the new buffer + memcpy(result + target_length, o._buffer, source_length * sizeof(char_t)); + result[result_length] = 0; + + // finalize + _buffer = result; + _uses_heap = true; + _length_heap = result_length; + } + } + + const char_t* c_str() const + { + return _buffer; + } + + size_t length() const + { + return _uses_heap ? _length_heap : strlength(_buffer); + } + + char_t* data(xpath_allocator* alloc) + { + // make private heap copy + if (!_uses_heap) + { + size_t length_ = strlength(_buffer); + const char_t* data_ = duplicate_string(_buffer, length_, alloc); + + if (!data_) return 0; + + _buffer = data_; + _uses_heap = true; + _length_heap = length_; + } + + return const_cast(_buffer); + } + + bool empty() const + { + return *_buffer == 0; + } + + bool operator==(const xpath_string& o) const + { + return strequal(_buffer, o._buffer); + } + + bool operator!=(const xpath_string& o) const + { + return !strequal(_buffer, o._buffer); + } + + bool uses_heap() const + { + return _uses_heap; + } + }; +PUGI__NS_END + +PUGI__NS_BEGIN + PUGI__FN bool starts_with(const char_t* string, const char_t* pattern) + { + while (*pattern && *string == *pattern) + { + string++; + pattern++; + } + + return *pattern == 0; + } + + PUGI__FN const char_t* find_char(const char_t* s, char_t c) + { + #ifdef PUGIXML_WCHAR_MODE + return wcschr(s, c); + #else + return strchr(s, c); + #endif + } + + PUGI__FN const char_t* find_substring(const char_t* s, const char_t* p) + { + #ifdef PUGIXML_WCHAR_MODE + // MSVC6 wcsstr bug workaround (if s is empty it always returns 0) + return (*p == 0) ? s : wcsstr(s, p); + #else + return strstr(s, p); + #endif + } + + // Converts symbol to lower case, if it is an ASCII one + PUGI__FN char_t tolower_ascii(char_t ch) + { + return static_cast(ch - 'A') < 26 ? static_cast(ch | ' ') : ch; + } + + PUGI__FN xpath_string string_value(const xpath_node& na, xpath_allocator* alloc) + { + if (na.attribute()) + return xpath_string::from_const(na.attribute().value()); + else + { + xml_node n = na.node(); + + switch (n.type()) + { + case node_pcdata: + case node_cdata: + case node_comment: + case node_pi: + return xpath_string::from_const(n.value()); + + case node_document: + case node_element: + { + xpath_string result; + + // element nodes can have value if parse_embed_pcdata was used + if (n.value()[0]) + result.append(xpath_string::from_const(n.value()), alloc); + + xml_node cur = n.first_child(); + + while (cur && cur != n) + { + if (cur.type() == node_pcdata || cur.type() == node_cdata) + result.append(xpath_string::from_const(cur.value()), alloc); + + if (cur.first_child()) + cur = cur.first_child(); + else if (cur.next_sibling()) + cur = cur.next_sibling(); + else + { + while (!cur.next_sibling() && cur != n) + cur = cur.parent(); + + if (cur != n) cur = cur.next_sibling(); + } + } + + return result; + } + + default: + return xpath_string(); + } + } + } + + PUGI__FN bool node_is_before_sibling(xml_node_struct* ln, xml_node_struct* rn) + { + assert(ln->parent == rn->parent); + + // there is no common ancestor (the shared parent is null), nodes are from different documents + if (!ln->parent) return ln < rn; + + // determine sibling order + xml_node_struct* ls = ln; + xml_node_struct* rs = rn; + + while (ls && rs) + { + if (ls == rn) return true; + if (rs == ln) return false; + + ls = ls->next_sibling; + rs = rs->next_sibling; + } + + // if rn sibling chain ended ln must be before rn + return !rs; + } + + PUGI__FN bool node_is_before(xml_node_struct* ln, xml_node_struct* rn) + { + // find common ancestor at the same depth, if any + xml_node_struct* lp = ln; + xml_node_struct* rp = rn; + + while (lp && rp && lp->parent != rp->parent) + { + lp = lp->parent; + rp = rp->parent; + } + + // parents are the same! + if (lp && rp) return node_is_before_sibling(lp, rp); + + // nodes are at different depths, need to normalize heights + bool left_higher = !lp; + + while (lp) + { + lp = lp->parent; + ln = ln->parent; + } + + while (rp) + { + rp = rp->parent; + rn = rn->parent; + } + + // one node is the ancestor of the other + if (ln == rn) return left_higher; + + // find common ancestor... again + while (ln->parent != rn->parent) + { + ln = ln->parent; + rn = rn->parent; + } + + return node_is_before_sibling(ln, rn); + } + + PUGI__FN bool node_is_ancestor(xml_node_struct* parent, xml_node_struct* node) + { + while (node && node != parent) node = node->parent; + + return parent && node == parent; + } + + PUGI__FN const void* document_buffer_order(const xpath_node& xnode) + { + xml_node_struct* node = xnode.node().internal_object(); + + if (node) + { + if ((get_document(node).header & xml_memory_page_contents_shared_mask) == 0) + { + if (node->name && (node->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return node->name; + if (node->value && (node->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return node->value; + } + + return 0; + } + + xml_attribute_struct* attr = xnode.attribute().internal_object(); + + if (attr) + { + if ((get_document(attr).header & xml_memory_page_contents_shared_mask) == 0) + { + if ((attr->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0) return attr->name; + if ((attr->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0) return attr->value; + } + + return 0; + } + + return 0; + } + + struct document_order_comparator + { + bool operator()(const xpath_node& lhs, const xpath_node& rhs) const + { + // optimized document order based check + const void* lo = document_buffer_order(lhs); + const void* ro = document_buffer_order(rhs); + + if (lo && ro) return lo < ro; + + // slow comparison + xml_node ln = lhs.node(), rn = rhs.node(); + + // compare attributes + if (lhs.attribute() && rhs.attribute()) + { + // shared parent + if (lhs.parent() == rhs.parent()) + { + // determine sibling order + for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute()) + if (a == rhs.attribute()) + return true; + + return false; + } + + // compare attribute parents + ln = lhs.parent(); + rn = rhs.parent(); + } + else if (lhs.attribute()) + { + // attributes go after the parent element + if (lhs.parent() == rhs.node()) return false; + + ln = lhs.parent(); + } + else if (rhs.attribute()) + { + // attributes go after the parent element + if (rhs.parent() == lhs.node()) return true; + + rn = rhs.parent(); + } + + if (ln == rn) return false; + + if (!ln || !rn) return ln < rn; + + return node_is_before(ln.internal_object(), rn.internal_object()); + } + }; + + PUGI__FN double gen_nan() + { + #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) + PUGI__STATIC_ASSERT(sizeof(float) == sizeof(uint32_t)); + typedef uint32_t UI; // BCC5 workaround + union { float f; UI i; } u; + u.i = 0x7fc00000; + return double(u.f); + #else + // fallback + const volatile double zero = 0.0; + return zero / zero; + #endif + } + + PUGI__FN bool is_nan(double value) + { + #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + return !!_isnan(value); + #elif defined(fpclassify) && defined(FP_NAN) + return fpclassify(value) == FP_NAN; + #else + // fallback + const volatile double v = value; + return v != v; + #endif + } + + PUGI__FN const char_t* convert_number_to_string_special(double value) + { + #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) + if (_finite(value)) return (value == 0) ? PUGIXML_TEXT("0") : 0; + if (_isnan(value)) return PUGIXML_TEXT("NaN"); + return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + #elif defined(fpclassify) && defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO) + switch (fpclassify(value)) + { + case FP_NAN: + return PUGIXML_TEXT("NaN"); + + case FP_INFINITE: + return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + + case FP_ZERO: + return PUGIXML_TEXT("0"); + + default: + return 0; + } + #else + // fallback + const volatile double v = value; + + if (v == 0) return PUGIXML_TEXT("0"); + if (v != v) return PUGIXML_TEXT("NaN"); + if (v * 2 == v) return value > 0 ? PUGIXML_TEXT("Infinity") : PUGIXML_TEXT("-Infinity"); + return 0; + #endif + } + + PUGI__FN bool convert_number_to_boolean(double value) + { + return (value != 0 && !is_nan(value)); + } + + PUGI__FN void truncate_zeros(char* begin, char* end) + { + while (begin != end && end[-1] == '0') end--; + + *end = 0; + } + + // gets mantissa digits in the form of 0.xxxxx with 0. implied and the exponent +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) + PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) + { + // get base values + int sign, exponent; + _ecvt_s(buffer, sizeof(buffer), value, DBL_DIG + 1, &exponent, &sign); + + // truncate redundant zeros + truncate_zeros(buffer, buffer + strlen(buffer)); + + // fill results + *out_mantissa = buffer; + *out_exponent = exponent; + } +#else + PUGI__FN void convert_number_to_mantissa_exponent(double value, char (&buffer)[32], char** out_mantissa, int* out_exponent) + { + // get a scientific notation value with IEEE DBL_DIG decimals + PUGI__SNPRINTF(buffer, "%.*e", DBL_DIG, value); + + // get the exponent (possibly negative) + char* exponent_string = strchr(buffer, 'e'); + assert(exponent_string); + + int exponent = atoi(exponent_string + 1); + + // extract mantissa string: skip sign + char* mantissa = buffer[0] == '-' ? buffer + 1 : buffer; + assert(mantissa[0] != '0' && mantissa[1] == '.'); + + // divide mantissa by 10 to eliminate integer part + mantissa[1] = mantissa[0]; + mantissa++; + exponent++; + + // remove extra mantissa digits and zero-terminate mantissa + truncate_zeros(mantissa, exponent_string); + + // fill results + *out_mantissa = mantissa; + *out_exponent = exponent; + } +#endif + + PUGI__FN xpath_string convert_number_to_string(double value, xpath_allocator* alloc) + { + // try special number conversion + const char_t* special = convert_number_to_string_special(value); + if (special) return xpath_string::from_const(special); + + // get mantissa + exponent form + char mantissa_buffer[32]; + + char* mantissa; + int exponent; + convert_number_to_mantissa_exponent(value, mantissa_buffer, &mantissa, &exponent); + + // allocate a buffer of suitable length for the number + size_t result_size = strlen(mantissa_buffer) + (exponent > 0 ? exponent : -exponent) + 4; + char_t* result = static_cast(alloc->allocate(sizeof(char_t) * result_size)); + if (!result) return xpath_string(); + + // make the number! + char_t* s = result; + + // sign + if (value < 0) *s++ = '-'; + + // integer part + if (exponent <= 0) + { + *s++ = '0'; + } + else + { + while (exponent > 0) + { + assert(*mantissa == 0 || static_cast(*mantissa - '0') <= 9); + *s++ = *mantissa ? *mantissa++ : '0'; + exponent--; + } + } + + // fractional part + if (*mantissa) + { + // decimal point + *s++ = '.'; + + // extra zeroes from negative exponent + while (exponent < 0) + { + *s++ = '0'; + exponent++; + } + + // extra mantissa digits + while (*mantissa) + { + assert(static_cast(*mantissa - '0') <= 9); + *s++ = *mantissa++; + } + } + + // zero-terminate + assert(s < result + result_size); + *s = 0; + + return xpath_string::from_heap_preallocated(result, s); + } + + PUGI__FN bool check_string_to_number_format(const char_t* string) + { + // parse leading whitespace + while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + + // parse sign + if (*string == '-') ++string; + + if (!*string) return false; + + // if there is no integer part, there should be a decimal part with at least one digit + if (!PUGI__IS_CHARTYPEX(string[0], ctx_digit) && (string[0] != '.' || !PUGI__IS_CHARTYPEX(string[1], ctx_digit))) return false; + + // parse integer part + while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + + // parse decimal part + if (*string == '.') + { + ++string; + + while (PUGI__IS_CHARTYPEX(*string, ctx_digit)) ++string; + } + + // parse trailing whitespace + while (PUGI__IS_CHARTYPE(*string, ct_space)) ++string; + + return *string == 0; + } + + PUGI__FN double convert_string_to_number(const char_t* string) + { + // check string format + if (!check_string_to_number_format(string)) return gen_nan(); + + // parse string + #ifdef PUGIXML_WCHAR_MODE + return wcstod(string, 0); + #else + return strtod(string, 0); + #endif + } + + PUGI__FN bool convert_string_to_number_scratch(char_t (&buffer)[32], const char_t* begin, const char_t* end, double* out_result) + { + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!scratch) return false; + } + + // copy string to zero-terminated buffer and perform conversion + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + *out_result = convert_string_to_number(scratch); + + // free dummy buffer + if (scratch != buffer) xml_memory::deallocate(scratch); + + return true; + } + + PUGI__FN double round_nearest(double value) + { + return floor(value + 0.5); + } + + PUGI__FN double round_nearest_nzero(double value) + { + // same as round_nearest, but returns -0 for [-0.5, -0] + // ceil is used to differentiate between +0 and -0 (we return -0 for [-0.5, -0] and +0 for +0) + return (value >= -0.5 && value <= 0) ? ceil(value) : floor(value + 0.5); + } + + PUGI__FN const char_t* qualified_name(const xpath_node& node) + { + return node.attribute() ? node.attribute().name() : node.node().name(); + } + + PUGI__FN const char_t* local_name(const xpath_node& node) + { + const char_t* name = qualified_name(node); + const char_t* p = find_char(name, ':'); + + return p ? p + 1 : name; + } + + struct namespace_uri_predicate + { + const char_t* prefix; + size_t prefix_length; + + namespace_uri_predicate(const char_t* name) + { + const char_t* pos = find_char(name, ':'); + + prefix = pos ? name : 0; + prefix_length = pos ? static_cast(pos - name) : 0; + } + + bool operator()(xml_attribute a) const + { + const char_t* name = a.name(); + + if (!starts_with(name, PUGIXML_TEXT("xmlns"))) return false; + + return prefix ? name[5] == ':' && strequalrange(name + 6, prefix, prefix_length) : name[5] == 0; + } + }; + + PUGI__FN const char_t* namespace_uri(xml_node node) + { + namespace_uri_predicate pred = node.name(); + + xml_node p = node; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) + { + namespace_uri_predicate pred = attr.name(); + + // Default namespace does not apply to attributes + if (!pred.prefix) return PUGIXML_TEXT(""); + + xml_node p = parent; + + while (p) + { + xml_attribute a = p.find_attribute(pred); + + if (a) return a.value(); + + p = p.parent(); + } + + return PUGIXML_TEXT(""); + } + + PUGI__FN const char_t* namespace_uri(const xpath_node& node) + { + return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node()); + } + + PUGI__FN char_t* normalize_space(char_t* buffer) + { + char_t* write = buffer; + + for (char_t* it = buffer; *it; ) + { + char_t ch = *it++; + + if (PUGI__IS_CHARTYPE(ch, ct_space)) + { + // replace whitespace sequence with single space + while (PUGI__IS_CHARTYPE(*it, ct_space)) it++; + + // avoid leading spaces + if (write != buffer) *write++ = ' '; + } + else *write++ = ch; + } + + // remove trailing space + if (write != buffer && PUGI__IS_CHARTYPE(write[-1], ct_space)) write--; + + // zero-terminate + *write = 0; + + return write; + } + + PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length) + { + char_t* write = buffer; + + while (*buffer) + { + PUGI__DMC_VOLATILE char_t ch = *buffer++; + + const char_t* pos = find_char(from, ch); + + if (!pos) + *write++ = ch; // do not process + else if (static_cast(pos - from) < to_length) + *write++ = to[pos - from]; // replace + } + + // zero-terminate + *write = 0; + + return write; + } + + PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to) + { + unsigned char table[128] = {0}; + + while (*from) + { + unsigned int fc = static_cast(*from); + unsigned int tc = static_cast(*to); + + if (fc >= 128 || tc >= 128) + return 0; + + // code=128 means "skip character" + if (!table[fc]) + table[fc] = static_cast(tc ? tc : 128); + + from++; + if (tc) to++; + } + + for (int i = 0; i < 128; ++i) + if (!table[i]) + table[i] = static_cast(i); + + void* result = alloc->allocate(sizeof(table)); + if (!result) return 0; + + memcpy(result, table, sizeof(table)); + + return static_cast(result); + } + + PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table) + { + char_t* write = buffer; + + while (*buffer) + { + char_t ch = *buffer++; + unsigned int index = static_cast(ch); + + if (index < 128) + { + unsigned char code = table[index]; + + // code=128 means "skip character" (table size is 128 so 128 can be a special value) + // this code skips these characters without extra branches + *write = static_cast(code); + write += 1 - (code >> 7); + } + else + { + *write++ = ch; + } + } + + // zero-terminate + *write = 0; + + return write; + } + + inline bool is_xpath_attribute(const char_t* name) + { + return !(starts_with(name, PUGIXML_TEXT("xmlns")) && (name[5] == 0 || name[5] == ':')); + } + + struct xpath_variable_boolean: xpath_variable + { + xpath_variable_boolean(): xpath_variable(xpath_type_boolean), value(false) + { + } + + bool value; + char_t name[1]; + }; + + struct xpath_variable_number: xpath_variable + { + xpath_variable_number(): xpath_variable(xpath_type_number), value(0) + { + } + + double value; + char_t name[1]; + }; + + struct xpath_variable_string: xpath_variable + { + xpath_variable_string(): xpath_variable(xpath_type_string), value(0) + { + } + + ~xpath_variable_string() + { + if (value) xml_memory::deallocate(value); + } + + char_t* value; + char_t name[1]; + }; + + struct xpath_variable_node_set: xpath_variable + { + xpath_variable_node_set(): xpath_variable(xpath_type_node_set) + { + } + + xpath_node_set value; + char_t name[1]; + }; + + static const xpath_node_set dummy_node_set; + + PUGI__FN PUGI__UNSIGNED_OVERFLOW unsigned int hash_string(const char_t* str) + { + // Jenkins one-at-a-time hash (http://en.wikipedia.org/wiki/Jenkins_hash_function#one-at-a-time) + unsigned int result = 0; + + while (*str) + { + result += static_cast(*str++); + result += result << 10; + result ^= result >> 6; + } + + result += result << 3; + result ^= result >> 11; + result += result << 15; + + return result; + } + + template PUGI__FN T* new_xpath_variable(const char_t* name) + { + size_t length = strlength(name); + if (length == 0) return 0; // empty variable names are invalid + + // $$ we can't use offsetof(T, name) because T is non-POD, so we just allocate additional length characters + void* memory = xml_memory::allocate(sizeof(T) + length * sizeof(char_t)); + if (!memory) return 0; + + T* result = new (memory) T(); + + memcpy(result->name, name, (length + 1) * sizeof(char_t)); + + return result; + } + + PUGI__FN xpath_variable* new_xpath_variable(xpath_value_type type, const char_t* name) + { + switch (type) + { + case xpath_type_node_set: + return new_xpath_variable(name); + + case xpath_type_number: + return new_xpath_variable(name); + + case xpath_type_string: + return new_xpath_variable(name); + + case xpath_type_boolean: + return new_xpath_variable(name); + + default: + return 0; + } + } + + template PUGI__FN void delete_xpath_variable(T* var) + { + var->~T(); + xml_memory::deallocate(var); + } + + PUGI__FN void delete_xpath_variable(xpath_value_type type, xpath_variable* var) + { + switch (type) + { + case xpath_type_node_set: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_number: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_string: + delete_xpath_variable(static_cast(var)); + break; + + case xpath_type_boolean: + delete_xpath_variable(static_cast(var)); + break; + + default: + assert(false && "Invalid variable type"); // unreachable + } + } + + PUGI__FN bool copy_xpath_variable(xpath_variable* lhs, const xpath_variable* rhs) + { + switch (rhs->type()) + { + case xpath_type_node_set: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_number: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_string: + return lhs->set(static_cast(rhs)->value); + + case xpath_type_boolean: + return lhs->set(static_cast(rhs)->value); + + default: + assert(false && "Invalid variable type"); // unreachable + return false; + } + } + + PUGI__FN bool get_variable_scratch(char_t (&buffer)[32], xpath_variable_set* set, const char_t* begin, const char_t* end, xpath_variable** out_result) + { + size_t length = static_cast(end - begin); + char_t* scratch = buffer; + + if (length >= sizeof(buffer) / sizeof(buffer[0])) + { + // need to make dummy on-heap copy + scratch = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); + if (!scratch) return false; + } + + // copy string to zero-terminated buffer and perform lookup + memcpy(scratch, begin, length * sizeof(char_t)); + scratch[length] = 0; + + *out_result = set->get(scratch); + + // free dummy buffer + if (scratch != buffer) xml_memory::deallocate(scratch); + + return true; + } +PUGI__NS_END + +// Internal node set class +PUGI__NS_BEGIN + PUGI__FN xpath_node_set::type_t xpath_get_order(const xpath_node* begin, const xpath_node* end) + { + if (end - begin < 2) + return xpath_node_set::type_sorted; + + document_order_comparator cmp; + + bool first = cmp(begin[0], begin[1]); + + for (const xpath_node* it = begin + 1; it + 1 < end; ++it) + if (cmp(it[0], it[1]) != first) + return xpath_node_set::type_unsorted; + + return first ? xpath_node_set::type_sorted : xpath_node_set::type_sorted_reverse; + } + + PUGI__FN xpath_node_set::type_t xpath_sort(xpath_node* begin, xpath_node* end, xpath_node_set::type_t type, bool rev) + { + xpath_node_set::type_t order = rev ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; + + if (type == xpath_node_set::type_unsorted) + { + xpath_node_set::type_t sorted = xpath_get_order(begin, end); + + if (sorted == xpath_node_set::type_unsorted) + { + sort(begin, end, document_order_comparator()); + + type = xpath_node_set::type_sorted; + } + else + type = sorted; + } + + if (type != order) reverse(begin, end); + + return order; + } + + PUGI__FN xpath_node xpath_first(const xpath_node* begin, const xpath_node* end, xpath_node_set::type_t type) + { + if (begin == end) return xpath_node(); + + switch (type) + { + case xpath_node_set::type_sorted: + return *begin; + + case xpath_node_set::type_sorted_reverse: + return *(end - 1); + + case xpath_node_set::type_unsorted: + return *min_element(begin, end, document_order_comparator()); + + default: + assert(false && "Invalid node set type"); // unreachable + return xpath_node(); + } + } + + class xpath_node_set_raw + { + xpath_node_set::type_t _type; + + xpath_node* _begin; + xpath_node* _end; + xpath_node* _eos; + + public: + xpath_node_set_raw(): _type(xpath_node_set::type_unsorted), _begin(0), _end(0), _eos(0) + { + } + + xpath_node* begin() const + { + return _begin; + } + + xpath_node* end() const + { + return _end; + } + + bool empty() const + { + return _begin == _end; + } + + size_t size() const + { + return static_cast(_end - _begin); + } + + xpath_node first() const + { + return xpath_first(_begin, _end, _type); + } + + void push_back_grow(const xpath_node& node, xpath_allocator* alloc); + + void push_back(const xpath_node& node, xpath_allocator* alloc) + { + if (_end != _eos) + *_end++ = node; + else + push_back_grow(node, alloc); + } + + void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc) + { + if (begin_ == end_) return; + + size_t size_ = static_cast(_end - _begin); + size_t capacity = static_cast(_eos - _begin); + size_t count = static_cast(end_ - begin_); + + if (size_ + count > capacity) + { + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), (size_ + count) * sizeof(xpath_node))); + if (!data) return; + + // finalize + _begin = data; + _end = data + size_; + _eos = data + size_ + count; + } + + memcpy(_end, begin_, count * sizeof(xpath_node)); + _end += count; + } + + void sort_do() + { + _type = xpath_sort(_begin, _end, _type, false); + } + + void truncate(xpath_node* pos) + { + assert(_begin <= pos && pos <= _end); + + _end = pos; + } + + void remove_duplicates(xpath_allocator* alloc) + { + if (_type == xpath_node_set::type_unsorted && _end - _begin > 2) + { + xpath_allocator_capture cr(alloc); + + size_t size_ = static_cast(_end - _begin); + + size_t hash_size = 1; + while (hash_size < size_ + size_ / 2) hash_size *= 2; + + const void** hash_data = static_cast(alloc->allocate(hash_size * sizeof(void**))); + if (!hash_data) return; + + memset(hash_data, 0, hash_size * sizeof(const void**)); + + xpath_node* write = _begin; + + for (xpath_node* it = _begin; it != _end; ++it) + { + const void* attr = it->attribute().internal_object(); + const void* node = it->node().internal_object(); + const void* key = attr ? attr : node; + + if (key && hash_insert(hash_data, hash_size, key)) + { + *write++ = *it; + } + } + + _end = write; + } + else + { + _end = unique(_begin, _end); + } + } + + xpath_node_set::type_t type() const + { + return _type; + } + + void set_type(xpath_node_set::type_t value) + { + _type = value; + } + }; + + PUGI__FN_NO_INLINE void xpath_node_set_raw::push_back_grow(const xpath_node& node, xpath_allocator* alloc) + { + size_t capacity = static_cast(_eos - _begin); + + // get new capacity (1.5x rule) + size_t new_capacity = capacity + capacity / 2 + 1; + + // reallocate the old array or allocate a new one + xpath_node* data = static_cast(alloc->reallocate(_begin, capacity * sizeof(xpath_node), new_capacity * sizeof(xpath_node))); + if (!data) return; + + // finalize + _begin = data; + _end = data + capacity; + _eos = data + new_capacity; + + // push + *_end++ = node; + } +PUGI__NS_END + +PUGI__NS_BEGIN + struct xpath_context + { + xpath_node n; + size_t position, size; + + xpath_context(const xpath_node& n_, size_t position_, size_t size_): n(n_), position(position_), size(size_) + { + } + }; + + enum lexeme_t + { + lex_none = 0, + lex_equal, + lex_not_equal, + lex_less, + lex_greater, + lex_less_or_equal, + lex_greater_or_equal, + lex_plus, + lex_minus, + lex_multiply, + lex_union, + lex_var_ref, + lex_open_brace, + lex_close_brace, + lex_quoted_string, + lex_number, + lex_slash, + lex_double_slash, + lex_open_square_brace, + lex_close_square_brace, + lex_string, + lex_comma, + lex_axis_attribute, + lex_dot, + lex_double_dot, + lex_double_colon, + lex_eof + }; + + struct xpath_lexer_string + { + const char_t* begin; + const char_t* end; + + xpath_lexer_string(): begin(0), end(0) + { + } + + bool operator==(const char_t* other) const + { + size_t length = static_cast(end - begin); + + return strequalrange(other, begin, length); + } + }; + + class xpath_lexer + { + const char_t* _cur; + const char_t* _cur_lexeme_pos; + xpath_lexer_string _cur_lexeme_contents; + + lexeme_t _cur_lexeme; + + public: + explicit xpath_lexer(const char_t* query): _cur(query) + { + next(); + } + + const char_t* state() const + { + return _cur; + } + + void next() + { + const char_t* cur = _cur; + + while (PUGI__IS_CHARTYPE(*cur, ct_space)) ++cur; + + // save lexeme position for error reporting + _cur_lexeme_pos = cur; + + switch (*cur) + { + case 0: + _cur_lexeme = lex_eof; + break; + + case '>': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_greater_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_greater; + } + break; + + case '<': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_less_or_equal; + } + else + { + cur += 1; + _cur_lexeme = lex_less; + } + break; + + case '!': + if (*(cur+1) == '=') + { + cur += 2; + _cur_lexeme = lex_not_equal; + } + else + { + _cur_lexeme = lex_none; + } + break; + + case '=': + cur += 1; + _cur_lexeme = lex_equal; + + break; + + case '+': + cur += 1; + _cur_lexeme = lex_plus; + + break; + + case '-': + cur += 1; + _cur_lexeme = lex_minus; + + break; + + case '*': + cur += 1; + _cur_lexeme = lex_multiply; + + break; + + case '|': + cur += 1; + _cur_lexeme = lex_union; + + break; + + case '$': + cur += 1; + + if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':' && PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // qname + { + cur++; // : + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_var_ref; + } + else + { + _cur_lexeme = lex_none; + } + + break; + + case '(': + cur += 1; + _cur_lexeme = lex_open_brace; + + break; + + case ')': + cur += 1; + _cur_lexeme = lex_close_brace; + + break; + + case '[': + cur += 1; + _cur_lexeme = lex_open_square_brace; + + break; + + case ']': + cur += 1; + _cur_lexeme = lex_close_square_brace; + + break; + + case ',': + cur += 1; + _cur_lexeme = lex_comma; + + break; + + case '/': + if (*(cur+1) == '/') + { + cur += 2; + _cur_lexeme = lex_double_slash; + } + else + { + cur += 1; + _cur_lexeme = lex_slash; + } + break; + + case '.': + if (*(cur+1) == '.') + { + cur += 2; + _cur_lexeme = lex_double_dot; + } + else if (PUGI__IS_CHARTYPEX(*(cur+1), ctx_digit)) + { + _cur_lexeme_contents.begin = cur; // . + + ++cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else + { + cur += 1; + _cur_lexeme = lex_dot; + } + break; + + case '@': + cur += 1; + _cur_lexeme = lex_axis_attribute; + + break; + + case '"': + case '\'': + { + char_t terminator = *cur; + + ++cur; + + _cur_lexeme_contents.begin = cur; + while (*cur && *cur != terminator) cur++; + _cur_lexeme_contents.end = cur; + + if (!*cur) + _cur_lexeme = lex_none; + else + { + cur += 1; + _cur_lexeme = lex_quoted_string; + } + + break; + } + + case ':': + if (*(cur+1) == ':') + { + cur += 2; + _cur_lexeme = lex_double_colon; + } + else + { + _cur_lexeme = lex_none; + } + break; + + default: + if (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + + if (*cur == '.') + { + cur++; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_digit)) cur++; + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_number; + } + else if (PUGI__IS_CHARTYPEX(*cur, ctx_start_symbol)) + { + _cur_lexeme_contents.begin = cur; + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + + if (cur[0] == ':') + { + if (cur[1] == '*') // namespace test ncname:* + { + cur += 2; // :* + } + else if (PUGI__IS_CHARTYPEX(cur[1], ctx_symbol)) // namespace test qname + { + cur++; // : + + while (PUGI__IS_CHARTYPEX(*cur, ctx_symbol)) cur++; + } + } + + _cur_lexeme_contents.end = cur; + + _cur_lexeme = lex_string; + } + else + { + _cur_lexeme = lex_none; + } + } + + _cur = cur; + } + + lexeme_t current() const + { + return _cur_lexeme; + } + + const char_t* current_pos() const + { + return _cur_lexeme_pos; + } + + const xpath_lexer_string& contents() const + { + assert(_cur_lexeme == lex_var_ref || _cur_lexeme == lex_number || _cur_lexeme == lex_string || _cur_lexeme == lex_quoted_string); + + return _cur_lexeme_contents; + } + }; + + enum ast_type_t + { + ast_unknown, + ast_op_or, // left or right + ast_op_and, // left and right + ast_op_equal, // left = right + ast_op_not_equal, // left != right + ast_op_less, // left < right + ast_op_greater, // left > right + ast_op_less_or_equal, // left <= right + ast_op_greater_or_equal, // left >= right + ast_op_add, // left + right + ast_op_subtract, // left - right + ast_op_multiply, // left * right + ast_op_divide, // left / right + ast_op_mod, // left % right + ast_op_negate, // left - right + ast_op_union, // left | right + ast_predicate, // apply predicate to set; next points to next predicate + ast_filter, // select * from left where right + ast_string_constant, // string constant + ast_number_constant, // number constant + ast_variable, // variable + ast_func_last, // last() + ast_func_position, // position() + ast_func_count, // count(left) + ast_func_id, // id(left) + ast_func_local_name_0, // local-name() + ast_func_local_name_1, // local-name(left) + ast_func_namespace_uri_0, // namespace-uri() + ast_func_namespace_uri_1, // namespace-uri(left) + ast_func_name_0, // name() + ast_func_name_1, // name(left) + ast_func_string_0, // string() + ast_func_string_1, // string(left) + ast_func_concat, // concat(left, right, siblings) + ast_func_starts_with, // starts_with(left, right) + ast_func_contains, // contains(left, right) + ast_func_substring_before, // substring-before(left, right) + ast_func_substring_after, // substring-after(left, right) + ast_func_substring_2, // substring(left, right) + ast_func_substring_3, // substring(left, right, third) + ast_func_string_length_0, // string-length() + ast_func_string_length_1, // string-length(left) + ast_func_normalize_space_0, // normalize-space() + ast_func_normalize_space_1, // normalize-space(left) + ast_func_translate, // translate(left, right, third) + ast_func_boolean, // boolean(left) + ast_func_not, // not(left) + ast_func_true, // true() + ast_func_false, // false() + ast_func_lang, // lang(left) + ast_func_number_0, // number() + ast_func_number_1, // number(left) + ast_func_sum, // sum(left) + ast_func_floor, // floor(left) + ast_func_ceiling, // ceiling(left) + ast_func_round, // round(left) + ast_step, // process set left with step + ast_step_root, // select root node + + ast_opt_translate_table, // translate(left, right, third) where right/third are constants + ast_opt_compare_attribute // @name = 'string' + }; + + enum axis_t + { + axis_ancestor, + axis_ancestor_or_self, + axis_attribute, + axis_child, + axis_descendant, + axis_descendant_or_self, + axis_following, + axis_following_sibling, + axis_namespace, + axis_parent, + axis_preceding, + axis_preceding_sibling, + axis_self + }; + + enum nodetest_t + { + nodetest_none, + nodetest_name, + nodetest_type_node, + nodetest_type_comment, + nodetest_type_pi, + nodetest_type_text, + nodetest_pi, + nodetest_all, + nodetest_all_in_namespace + }; + + enum predicate_t + { + predicate_default, + predicate_posinv, + predicate_constant, + predicate_constant_one + }; + + enum nodeset_eval_t + { + nodeset_eval_all, + nodeset_eval_any, + nodeset_eval_first + }; + + template struct axis_to_type + { + static const axis_t axis; + }; + + template const axis_t axis_to_type::axis = N; + + class xpath_ast_node + { + private: + // node type + char _type; + char _rettype; + + // for ast_step + char _axis; + + // for ast_step/ast_predicate/ast_filter + char _test; + + // tree node structure + xpath_ast_node* _left; + xpath_ast_node* _right; + xpath_ast_node* _next; + + union + { + // value for ast_string_constant + const char_t* string; + // value for ast_number_constant + double number; + // variable for ast_variable + xpath_variable* variable; + // node test for ast_step (node name/namespace/node type/pi target) + const char_t* nodetest; + // table for ast_opt_translate_table + const unsigned char* table; + } _data; + + xpath_ast_node(const xpath_ast_node&); + xpath_ast_node& operator=(const xpath_ast_node&); + + template static bool compare_eq(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + { + if (lt == xpath_type_boolean || rt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number || rt == xpath_type_number) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_string || rt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string ls = lhs->eval_string(c, stack); + xpath_string rs = rhs->eval_string(c, stack); + + return comp(ls, rs); + } + } + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(string_value(*li, stack.result), string_value(*ri, stack.result))) + return true; + } + + return false; + } + else + { + if (lt == xpath_type_node_set) + { + swap(lhs, rhs); + swap(lt, rt); + } + + if (lt == xpath_type_boolean) + return comp(lhs->eval_boolean(c, stack), rhs->eval_boolean(c, stack)); + else if (lt == xpath_type_number) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_string) + { + xpath_allocator_capture cr(stack.result); + + xpath_string l = lhs->eval_string(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, string_value(*ri, stack.result))) + return true; + } + + return false; + } + } + + assert(false && "Wrong types"); // unreachable + return false; + } + + static bool eval_once(xpath_node_set::type_t type, nodeset_eval_t eval) + { + return type == xpath_node_set::type_sorted ? eval != nodeset_eval_all : eval == nodeset_eval_any; + } + + template static bool compare_rel(xpath_ast_node* lhs, xpath_ast_node* rhs, const xpath_context& c, const xpath_stack& stack, const Comp& comp) + { + xpath_value_type lt = lhs->rettype(), rt = rhs->rettype(); + + if (lt != xpath_type_node_set && rt != xpath_type_node_set) + return comp(lhs->eval_number(c, stack), rhs->eval_number(c, stack)); + else if (lt == xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + double l = convert_string_to_number(string_value(*li, stack.result).c_str()); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture crii(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + } + + return false; + } + else if (lt != xpath_type_node_set && rt == xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + double l = lhs->eval_number(c, stack); + xpath_node_set_raw rs = rhs->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* ri = rs.begin(); ri != rs.end(); ++ri) + { + xpath_allocator_capture cri(stack.result); + + if (comp(l, convert_string_to_number(string_value(*ri, stack.result).c_str()))) + return true; + } + + return false; + } + else if (lt == xpath_type_node_set && rt != xpath_type_node_set) + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ls = lhs->eval_node_set(c, stack, nodeset_eval_all); + double r = rhs->eval_number(c, stack); + + for (const xpath_node* li = ls.begin(); li != ls.end(); ++li) + { + xpath_allocator_capture cri(stack.result); + + if (comp(convert_string_to_number(string_value(*li, stack.result).c_str()), r)) + return true; + } + + return false; + } + else + { + assert(false && "Wrong types"); // unreachable + return false; + } + } + + static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) + { + assert(ns.size() >= first); + assert(expr->rettype() != xpath_type_number); + + size_t i = 1; + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + // remove_if... or well, sort of + for (xpath_node* it = last; it != ns.end(); ++it, ++i) + { + xpath_context c(*it, i, size); + + if (expr->eval_boolean(c, stack)) + { + *last++ = *it; + + if (once) break; + } + } + + ns.truncate(last); + } + + static void apply_predicate_number(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once) + { + assert(ns.size() >= first); + assert(expr->rettype() == xpath_type_number); + + size_t i = 1; + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + // remove_if... or well, sort of + for (xpath_node* it = last; it != ns.end(); ++it, ++i) + { + xpath_context c(*it, i, size); + + if (expr->eval_number(c, stack) == static_cast(i)) + { + *last++ = *it; + + if (once) break; + } + } + + ns.truncate(last); + } + + static void apply_predicate_number_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) + { + assert(ns.size() >= first); + assert(expr->rettype() == xpath_type_number); + + size_t size = ns.size() - first; + + xpath_node* last = ns.begin() + first; + + xpath_context c(xpath_node(), 1, size); + + double er = expr->eval_number(c, stack); + + if (er >= 1.0 && er <= static_cast(size)) + { + size_t eri = static_cast(er); + + if (er == static_cast(eri)) + { + xpath_node r = last[eri - 1]; + + *last++ = r; + } + } + + ns.truncate(last); + } + + void apply_predicate(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, bool once) + { + if (ns.size() == first) return; + + assert(_type == ast_filter || _type == ast_predicate); + + if (_test == predicate_constant || _test == predicate_constant_one) + apply_predicate_number_const(ns, first, _right, stack); + else if (_right->rettype() == xpath_type_number) + apply_predicate_number(ns, first, _right, stack, once); + else + apply_predicate_boolean(ns, first, _right, stack, once); + } + + void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval) + { + if (ns.size() == first) return; + + bool last_once = eval_once(ns.type(), eval); + + for (xpath_ast_node* pred = _right; pred; pred = pred->_next) + pred->apply_predicate(ns, first, stack, !pred->_next && last_once); + } + + bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc) + { + assert(a); + + const char_t* name = a->name ? a->name + 0 : PUGIXML_TEXT(""); + + switch (_test) + { + case nodetest_name: + if (strequal(name, _data.nodetest) && is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + case nodetest_type_node: + case nodetest_all: + if (is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + case nodetest_all_in_namespace: + if (starts_with(name, _data.nodetest) && is_xpath_attribute(name)) + { + ns.push_back(xpath_node(xml_attribute(a), xml_node(parent)), alloc); + return true; + } + break; + + default: + ; + } + + return false; + } + + bool step_push(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc) + { + assert(n); + + xml_node_type type = PUGI__NODETYPE(n); + + switch (_test) + { + case nodetest_name: + if (type == node_element && n->name && strequal(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_node: + ns.push_back(xml_node(n), alloc); + return true; + + case nodetest_type_comment: + if (type == node_comment) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_text: + if (type == node_pcdata || type == node_cdata) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_type_pi: + if (type == node_pi) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_pi: + if (type == node_pi && n->name && strequal(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_all: + if (type == node_element) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + case nodetest_all_in_namespace: + if (type == node_element && n->name && starts_with(n->name, _data.nodetest)) + { + ns.push_back(xml_node(n), alloc); + return true; + } + break; + + default: + assert(false && "Unknown axis"); // unreachable + } + + return false; + } + + template void step_fill(xpath_node_set_raw& ns, xml_node_struct* n, xpath_allocator* alloc, bool once, T) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_attribute: + { + for (xml_attribute_struct* a = n->first_attribute; a; a = a->next_attribute) + if (step_push(ns, a, n, alloc) & once) + return; + + break; + } + + case axis_child: + { + for (xml_node_struct* c = n->first_child; c; c = c->next_sibling) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_descendant: + case axis_descendant_or_self: + { + if (axis == axis_descendant_or_self) + if (step_push(ns, n, alloc) & once) + return; + + xml_node_struct* cur = n->first_child; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (cur == n) return; + } + + cur = cur->next_sibling; + } + } + + break; + } + + case axis_following_sibling: + { + for (xml_node_struct* c = n->next_sibling; c; c = c->next_sibling) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_preceding_sibling: + { + for (xml_node_struct* c = n->prev_sibling_c; c->next_sibling; c = c->prev_sibling_c) + if (step_push(ns, c, alloc) & once) + return; + + break; + } + + case axis_following: + { + xml_node_struct* cur = n; + + // exit from this node so that we don't include descendants + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + } + } + + break; + } + + case axis_preceding: + { + xml_node_struct* cur = n; + + // exit from this node so that we don't include descendants + while (!cur->prev_sibling_c->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->prev_sibling_c; + + while (cur) + { + if (cur->first_child) + cur = cur->first_child->prev_sibling_c; + else + { + // leaf node, can't be ancestor + if (step_push(ns, cur, alloc) & once) + return; + + while (!cur->prev_sibling_c->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + + if (!node_is_ancestor(cur, n)) + if (step_push(ns, cur, alloc) & once) + return; + } + + cur = cur->prev_sibling_c; + } + } + + break; + } + + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self) + if (step_push(ns, n, alloc) & once) + return; + + xml_node_struct* cur = n->parent; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + cur = cur->parent; + } + + break; + } + + case axis_self: + { + step_push(ns, n, alloc); + + break; + } + + case axis_parent: + { + if (n->parent) + step_push(ns, n->parent, alloc); + + break; + } + + default: + assert(false && "Unimplemented axis"); // unreachable + } + } + + template void step_fill(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* p, xpath_allocator* alloc, bool once, T v) + { + const axis_t axis = T::axis; + + switch (axis) + { + case axis_ancestor: + case axis_ancestor_or_self: + { + if (axis == axis_ancestor_or_self && _test == nodetest_type_node) // reject attributes based on principal node type test + if (step_push(ns, a, p, alloc) & once) + return; + + xml_node_struct* cur = p; + + while (cur) + { + if (step_push(ns, cur, alloc) & once) + return; + + cur = cur->parent; + } + + break; + } + + case axis_descendant_or_self: + case axis_self: + { + if (_test == nodetest_type_node) // reject attributes based on principal node type test + step_push(ns, a, p, alloc); + + break; + } + + case axis_following: + { + xml_node_struct* cur = p; + + while (cur) + { + if (cur->first_child) + cur = cur->first_child; + else + { + while (!cur->next_sibling) + { + cur = cur->parent; + + if (!cur) return; + } + + cur = cur->next_sibling; + } + + if (step_push(ns, cur, alloc) & once) + return; + } + + break; + } + + case axis_parent: + { + step_push(ns, p, alloc); + + break; + } + + case axis_preceding: + { + // preceding:: axis does not include attribute nodes and attribute ancestors (they are the same as parent's ancestors), so we can reuse node preceding + step_fill(ns, p, alloc, once, v); + break; + } + + default: + assert(false && "Unimplemented axis"); // unreachable + } + } + + template void step_fill(xpath_node_set_raw& ns, const xpath_node& xn, xpath_allocator* alloc, bool once, T v) + { + const axis_t axis = T::axis; + const bool axis_has_attributes = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_descendant_or_self || axis == axis_following || axis == axis_parent || axis == axis_preceding || axis == axis_self); + + if (xn.node()) + step_fill(ns, xn.node().internal_object(), alloc, once, v); + else if (axis_has_attributes && xn.attribute() && xn.parent()) + step_fill(ns, xn.attribute().internal_object(), xn.parent().internal_object(), alloc, once, v); + } + + template xpath_node_set_raw step_do(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval, T v) + { + const axis_t axis = T::axis; + const bool axis_reverse = (axis == axis_ancestor || axis == axis_ancestor_or_self || axis == axis_preceding || axis == axis_preceding_sibling); + const xpath_node_set::type_t axis_type = axis_reverse ? xpath_node_set::type_sorted_reverse : xpath_node_set::type_sorted; + + bool once = + (axis == axis_attribute && _test == nodetest_name) || + (!_right && eval_once(axis_type, eval)) || + // coverity[mixed_enums] + (_right && !_right->_next && _right->_test == predicate_constant_one); + + xpath_node_set_raw ns; + ns.set_type(axis_type); + + if (_left) + { + xpath_node_set_raw s = _left->eval_node_set(c, stack, nodeset_eval_all); + + // self axis preserves the original order + if (axis == axis_self) ns.set_type(s.type()); + + for (const xpath_node* it = s.begin(); it != s.end(); ++it) + { + size_t size = ns.size(); + + // in general, all axes generate elements in a particular order, but there is no order guarantee if axis is applied to two nodes + if (axis != axis_self && size != 0) ns.set_type(xpath_node_set::type_unsorted); + + step_fill(ns, *it, stack.result, once, v); + if (_right) apply_predicates(ns, size, stack, eval); + } + } + else + { + step_fill(ns, c.n, stack.result, once, v); + if (_right) apply_predicates(ns, 0, stack, eval); + } + + // child, attribute and self axes always generate unique set of nodes + // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice + if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) + ns.remove_duplicates(stack.temp); + + return ns; + } + + public: + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, const char_t* value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_string_constant); + _data.string = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, double value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_number_constant); + _data.number = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_variable* value): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(0), _right(0), _next(0) + { + assert(type == ast_variable); + _data.variable = value; + } + + xpath_ast_node(ast_type_t type, xpath_value_type rettype_, xpath_ast_node* left = 0, xpath_ast_node* right = 0): + _type(static_cast(type)), _rettype(static_cast(rettype_)), _axis(0), _test(0), _left(left), _right(right), _next(0) + { + } + + xpath_ast_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents): + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(static_cast(axis)), _test(static_cast(test)), _left(left), _right(0), _next(0) + { + assert(type == ast_step); + _data.nodetest = contents; + } + + xpath_ast_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test): + _type(static_cast(type)), _rettype(xpath_type_node_set), _axis(0), _test(static_cast(test)), _left(left), _right(right), _next(0) + { + assert(type == ast_filter || type == ast_predicate); + } + + void set_next(xpath_ast_node* value) + { + _next = value; + } + + void set_right(xpath_ast_node* value) + { + _right = value; + } + + bool eval_boolean(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_or: + return _left->eval_boolean(c, stack) || _right->eval_boolean(c, stack); + + case ast_op_and: + return _left->eval_boolean(c, stack) && _right->eval_boolean(c, stack); + + case ast_op_equal: + return compare_eq(_left, _right, c, stack, equal_to()); + + case ast_op_not_equal: + return compare_eq(_left, _right, c, stack, not_equal_to()); + + case ast_op_less: + return compare_rel(_left, _right, c, stack, less()); + + case ast_op_greater: + return compare_rel(_right, _left, c, stack, less()); + + case ast_op_less_or_equal: + return compare_rel(_left, _right, c, stack, less_equal()); + + case ast_op_greater_or_equal: + return compare_rel(_right, _left, c, stack, less_equal()); + + case ast_func_starts_with: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return starts_with(lr.c_str(), rr.c_str()); + } + + case ast_func_contains: + { + xpath_allocator_capture cr(stack.result); + + xpath_string lr = _left->eval_string(c, stack); + xpath_string rr = _right->eval_string(c, stack); + + return find_substring(lr.c_str(), rr.c_str()) != 0; + } + + case ast_func_boolean: + return _left->eval_boolean(c, stack); + + case ast_func_not: + return !_left->eval_boolean(c, stack); + + case ast_func_true: + return true; + + case ast_func_false: + return false; + + case ast_func_lang: + { + if (c.n.attribute()) return false; + + xpath_allocator_capture cr(stack.result); + + xpath_string lang = _left->eval_string(c, stack); + + for (xml_node n = c.n.node(); n; n = n.parent()) + { + xml_attribute a = n.attribute(PUGIXML_TEXT("xml:lang")); + + if (a) + { + const char_t* value = a.value(); + + // strnicmp / strncasecmp is not portable + for (const char_t* lit = lang.c_str(); *lit; ++lit) + { + if (tolower_ascii(*lit) != tolower_ascii(*value)) return false; + ++value; + } + + return *value == 0 || *value == '-'; + } + } + + return false; + } + + case ast_opt_compare_attribute: + { + const char_t* value = (_right->_type == ast_string_constant) ? _right->_data.string : _right->_data.variable->get_string(); + + xml_attribute attr = c.n.node().attribute(_left->_data.nodetest); + + return attr && strequal(attr.value(), value) && is_xpath_attribute(attr.name()); + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_boolean) + return _data.variable->get_boolean(); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; + } + + default: + ; + } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_number: + return convert_number_to_boolean(eval_number(c, stack)); + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return !eval_string(c, stack).empty(); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return !eval_node_set(c, stack, nodeset_eval_any).empty(); + } + + default: + assert(false && "Wrong expression for return type boolean"); // unreachable + return false; + } + } + + double eval_number(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_op_add: + return _left->eval_number(c, stack) + _right->eval_number(c, stack); + + case ast_op_subtract: + return _left->eval_number(c, stack) - _right->eval_number(c, stack); + + case ast_op_multiply: + return _left->eval_number(c, stack) * _right->eval_number(c, stack); + + case ast_op_divide: + return _left->eval_number(c, stack) / _right->eval_number(c, stack); + + case ast_op_mod: + return fmod(_left->eval_number(c, stack), _right->eval_number(c, stack)); + + case ast_op_negate: + return -_left->eval_number(c, stack); + + case ast_number_constant: + return _data.number; + + case ast_func_last: + return static_cast(c.size); + + case ast_func_position: + return static_cast(c.position); + + case ast_func_count: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(_left->eval_node_set(c, stack, nodeset_eval_all).size()); + } + + case ast_func_string_length_0: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(string_value(c.n, stack.result).length()); + } + + case ast_func_string_length_1: + { + xpath_allocator_capture cr(stack.result); + + return static_cast(_left->eval_string(c, stack).length()); + } + + case ast_func_number_0: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(string_value(c.n, stack.result).c_str()); + } + + case ast_func_number_1: + return _left->eval_number(c, stack); + + case ast_func_sum: + { + xpath_allocator_capture cr(stack.result); + + double r = 0; + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_all); + + for (const xpath_node* it = ns.begin(); it != ns.end(); ++it) + { + xpath_allocator_capture cri(stack.result); + + r += convert_string_to_number(string_value(*it, stack.result).c_str()); + } + + return r; + } + + case ast_func_floor: + { + double r = _left->eval_number(c, stack); + + return r == r ? floor(r) : r; + } + + case ast_func_ceiling: + { + double r = _left->eval_number(c, stack); + + return r == r ? ceil(r) : r; + } + + case ast_func_round: + return round_nearest_nzero(_left->eval_number(c, stack)); + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_number) + return _data.variable->get_number(); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; + } + + default: + ; + } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_boolean: + return eval_boolean(c, stack) ? 1 : 0; + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + default: + assert(false && "Wrong expression for return type number"); // unreachable + return 0; + } + } + + xpath_string eval_string_concat(const xpath_context& c, const xpath_stack& stack) + { + assert(_type == ast_func_concat); + + xpath_allocator_capture ct(stack.temp); + + // count the string number + size_t count = 1; + for (xpath_ast_node* nc = _right; nc; nc = nc->_next) count++; + + // allocate a buffer for temporary string objects + xpath_string* buffer = static_cast(stack.temp->allocate(count * sizeof(xpath_string))); + if (!buffer) return xpath_string(); + + // evaluate all strings to temporary stack + xpath_stack swapped_stack = {stack.temp, stack.result}; + + buffer[0] = _left->eval_string(c, swapped_stack); + + size_t pos = 1; + for (xpath_ast_node* n = _right; n; n = n->_next, ++pos) buffer[pos] = n->eval_string(c, swapped_stack); + assert(pos == count); + + // get total length + size_t length = 0; + for (size_t i = 0; i < count; ++i) length += buffer[i].length(); + + // create final string + char_t* result = static_cast(stack.result->allocate((length + 1) * sizeof(char_t))); + if (!result) return xpath_string(); + + char_t* ri = result; + + for (size_t j = 0; j < count; ++j) + for (const char_t* bi = buffer[j].c_str(); *bi; ++bi) + *ri++ = *bi; + + *ri = 0; + + return xpath_string::from_heap_preallocated(result, ri); + } + + xpath_string eval_string(const xpath_context& c, const xpath_stack& stack) + { + switch (_type) + { + case ast_string_constant: + return xpath_string::from_const(_data.string); + + case ast_func_local_name_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(local_name(na)); + } + + case ast_func_local_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(local_name(na)); + } + + case ast_func_name_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(qualified_name(na)); + } + + case ast_func_name_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(qualified_name(na)); + } + + case ast_func_namespace_uri_0: + { + xpath_node na = c.n; + + return xpath_string::from_const(namespace_uri(na)); + } + + case ast_func_namespace_uri_1: + { + xpath_allocator_capture cr(stack.result); + + xpath_node_set_raw ns = _left->eval_node_set(c, stack, nodeset_eval_first); + xpath_node na = ns.first(); + + return xpath_string::from_const(namespace_uri(na)); + } + + case ast_func_string_0: + return string_value(c.n, stack.result); + + case ast_func_string_1: + return _left->eval_string(c, stack); + + case ast_func_concat: + return eval_string_concat(c, stack); + + case ast_func_substring_before: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + + return pos ? xpath_string::from_heap(s.c_str(), pos, stack.result) : xpath_string(); + } + + case ast_func_substring_after: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + xpath_string p = _right->eval_string(c, swapped_stack); + + const char_t* pos = find_substring(s.c_str(), p.c_str()); + if (!pos) return xpath_string(); + + const char_t* rbegin = pos + p.length(); + const char_t* rend = s.c_str() + s.length(); + + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); + } + + case ast_func_substring_2: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + + if (is_nan(first)) return xpath_string(); // NaN + else if (first >= static_cast(s_length + 1)) return xpath_string(); + + size_t pos = first < 1 ? 1 : static_cast(first); + assert(1 <= pos && pos <= s_length + 1); + + const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + s.length(); + + return s.uses_heap() ? xpath_string::from_heap(rbegin, rend, stack.result) : xpath_string::from_const(rbegin); + } + + case ast_func_substring_3: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, swapped_stack); + size_t s_length = s.length(); + + double first = round_nearest(_right->eval_number(c, stack)); + double last = first + round_nearest(_right->_next->eval_number(c, stack)); + + if (is_nan(first) || is_nan(last)) return xpath_string(); + else if (first >= static_cast(s_length + 1)) return xpath_string(); + else if (first >= last) return xpath_string(); + else if (last < 1) return xpath_string(); + + size_t pos = first < 1 ? 1 : static_cast(first); + size_t end = last >= static_cast(s_length + 1) ? s_length + 1 : static_cast(last); + + assert(1 <= pos && pos <= end && end <= s_length + 1); + const char_t* rbegin = s.c_str() + (pos - 1); + const char_t* rend = s.c_str() + (end - 1); + + return (end == s_length + 1 && !s.uses_heap()) ? xpath_string::from_const(rbegin) : xpath_string::from_heap(rbegin, rend, stack.result); + } + + case ast_func_normalize_space_0: + { + xpath_string s = string_value(c.n, stack.result); + + char_t* begin = s.data(stack.result); + if (!begin) return xpath_string(); + + char_t* end = normalize_space(begin); + + return xpath_string::from_heap_preallocated(begin, end); + } + + case ast_func_normalize_space_1: + { + xpath_string s = _left->eval_string(c, stack); + + char_t* begin = s.data(stack.result); + if (!begin) return xpath_string(); + + char_t* end = normalize_space(begin); + + return xpath_string::from_heap_preallocated(begin, end); + } + + case ast_func_translate: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_string s = _left->eval_string(c, stack); + xpath_string from = _right->eval_string(c, swapped_stack); + xpath_string to = _right->_next->eval_string(c, swapped_stack); + + char_t* begin = s.data(stack.result); + if (!begin) return xpath_string(); + + char_t* end = translate(begin, from.c_str(), to.c_str(), to.length()); + + return xpath_string::from_heap_preallocated(begin, end); + } + + case ast_opt_translate_table: + { + xpath_string s = _left->eval_string(c, stack); + + char_t* begin = s.data(stack.result); + if (!begin) return xpath_string(); + + char_t* end = translate_table(begin, _data.table); + + return xpath_string::from_heap_preallocated(begin, end); + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_string) + return xpath_string::from_const(_data.variable->get_string()); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; + } + + default: + ; + } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_boolean: + return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + + case xpath_type_number: + return convert_number_to_string(eval_number(c, stack), stack.result); + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); + return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); + } + + default: + assert(false && "Wrong expression for return type string"); // unreachable + return xpath_string(); + } + } + + xpath_node_set_raw eval_node_set(const xpath_context& c, const xpath_stack& stack, nodeset_eval_t eval) + { + switch (_type) + { + case ast_op_union: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ls = _left->eval_node_set(c, stack, eval); + xpath_node_set_raw rs = _right->eval_node_set(c, swapped_stack, eval); + + // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother + ls.set_type(xpath_node_set::type_unsorted); + + ls.append(rs.begin(), rs.end(), stack.result); + ls.remove_duplicates(stack.temp); + + return ls; + } + + case ast_filter: + { + xpath_node_set_raw set = _left->eval_node_set(c, stack, _test == predicate_constant_one ? nodeset_eval_first : nodeset_eval_all); + + // either expression is a number or it contains position() call; sort by document order + if (_test != predicate_posinv) set.sort_do(); + + bool once = eval_once(set.type(), eval); + + apply_predicate(set, 0, stack, once); + + return set; + } + + case ast_func_id: + return xpath_node_set_raw(); + + case ast_step: + { + switch (_axis) + { + case axis_ancestor: + return step_do(c, stack, eval, axis_to_type()); + + case axis_ancestor_or_self: + return step_do(c, stack, eval, axis_to_type()); + + case axis_attribute: + return step_do(c, stack, eval, axis_to_type()); + + case axis_child: + return step_do(c, stack, eval, axis_to_type()); + + case axis_descendant: + return step_do(c, stack, eval, axis_to_type()); + + case axis_descendant_or_self: + return step_do(c, stack, eval, axis_to_type()); + + case axis_following: + return step_do(c, stack, eval, axis_to_type()); + + case axis_following_sibling: + return step_do(c, stack, eval, axis_to_type()); + + case axis_namespace: + // namespaced axis is not supported + return xpath_node_set_raw(); + + case axis_parent: + return step_do(c, stack, eval, axis_to_type()); + + case axis_preceding: + return step_do(c, stack, eval, axis_to_type()); + + case axis_preceding_sibling: + return step_do(c, stack, eval, axis_to_type()); + + case axis_self: + return step_do(c, stack, eval, axis_to_type()); + + default: + assert(false && "Unknown axis"); // unreachable + return xpath_node_set_raw(); + } + } + + case ast_step_root: + { + assert(!_right); // root step can't have any predicates + + xpath_node_set_raw ns; + + ns.set_type(xpath_node_set::type_sorted); + + if (c.n.node()) ns.push_back(c.n.node().root(), stack.result); + else if (c.n.attribute()) ns.push_back(c.n.parent().root(), stack.result); + + return ns; + } + + case ast_variable: + { + assert(_rettype == _data.variable->type()); + + if (_rettype == xpath_type_node_set) + { + const xpath_node_set& s = _data.variable->get_node_set(); + + xpath_node_set_raw ns; + + ns.set_type(s.type()); + ns.append(s.begin(), s.end(), stack.result); + + return ns; + } + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; + } + + default: + ; + } + + // none of the ast types that return the value directly matched, but conversions to node set are invalid + assert(false && "Wrong expression for return type node set"); // unreachable + return xpath_node_set_raw(); + } + + void optimize(xpath_allocator* alloc) + { + if (_left) + _left->optimize(alloc); + + if (_right) + _right->optimize(alloc); + + if (_next) + _next->optimize(alloc); + + // coverity[var_deref_model] + optimize_self(alloc); + } + + void optimize_self(xpath_allocator* alloc) + { + // Rewrite [position()=expr] with [expr] + // Note that this step has to go before classification to recognize [position()=1] + if ((_type == ast_filter || _type == ast_predicate) && + _right && // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate) + _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number) + { + _right = _right->_right; + } + + // Classify filter/predicate ops to perform various optimizations during evaluation + if ((_type == ast_filter || _type == ast_predicate) && _right) // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate) + { + assert(_test == predicate_default); + + if (_right->_type == ast_number_constant && _right->_data.number == 1.0) + _test = predicate_constant_one; + else if (_right->_rettype == xpath_type_number && (_right->_type == ast_number_constant || _right->_type == ast_variable || _right->_type == ast_func_last)) + _test = predicate_constant; + else if (_right->_rettype != xpath_type_number && _right->is_posinv_expr()) + _test = predicate_posinv; + } + + // Rewrite descendant-or-self::node()/child::foo with descendant::foo + // The former is a full form of //foo, the latter is much faster since it executes the node test immediately + // Do a similar kind of rewrite for self/descendant/descendant-or-self axes + // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1]) + if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && + _left && _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right && + is_posinv_step()) + { + if (_axis == axis_child || _axis == axis_descendant) + _axis = axis_descendant; + else + _axis = axis_descendant_or_self; + + _left = _left->_left; + } + + // Use optimized lookup table implementation for translate() with constant arguments + if (_type == ast_func_translate && + _right && // workaround for clang static analyzer (_right is never null for ast_func_translate) + _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant) + { + unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string); + + if (table) + { + _type = ast_opt_translate_table; + _data.table = table; + } + } + + // Use optimized path for @attr = 'value' or @attr = $value + if (_type == ast_op_equal && + _left && _right && // workaround for clang static analyzer and Coverity (_left and _right are never null for ast_op_equal) + // coverity[mixed_enums] + _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right && + (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string))) + { + _type = ast_opt_compare_attribute; + } + } + + bool is_posinv_expr() const + { + switch (_type) + { + case ast_func_position: + case ast_func_last: + return false; + + case ast_string_constant: + case ast_number_constant: + case ast_variable: + return true; + + case ast_step: + case ast_step_root: + return true; + + case ast_predicate: + case ast_filter: + return true; + + default: + if (_left && !_left->is_posinv_expr()) return false; + + for (xpath_ast_node* n = _right; n; n = n->_next) + if (!n->is_posinv_expr()) return false; + + return true; + } + } + + bool is_posinv_step() const + { + assert(_type == ast_step); + + for (xpath_ast_node* n = _right; n; n = n->_next) + { + assert(n->_type == ast_predicate); + + if (n->_test != predicate_posinv) + return false; + } + + return true; + } + + xpath_value_type rettype() const + { + return static_cast(_rettype); + } + }; + + static const size_t xpath_ast_depth_limit = + #ifdef PUGIXML_XPATH_DEPTH_LIMIT + PUGIXML_XPATH_DEPTH_LIMIT + #else + 1024 + #endif + ; + + struct xpath_parser + { + xpath_allocator* _alloc; + xpath_lexer _lexer; + + const char_t* _query; + xpath_variable_set* _variables; + + xpath_parse_result* _result; + + char_t _scratch[32]; + + size_t _depth; + + xpath_ast_node* error(const char* message) + { + _result->error = message; + _result->offset = _lexer.current_pos() - _query; + + return 0; + } + + xpath_ast_node* error_oom() + { + assert(_alloc->_error); + *_alloc->_error = true; + + return 0; + } + + xpath_ast_node* error_rec() + { + return error("Exceeded maximum allowed query depth"); + } + + void* alloc_node() + { + return _alloc->allocate(sizeof(xpath_ast_node)); + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, const char_t* value) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, double value) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_variable* value) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, rettype, value) : 0; + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_value_type rettype, xpath_ast_node* left = 0, xpath_ast_node* right = 0) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, rettype, left, right) : 0; + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, axis_t axis, nodetest_t test, const char_t* contents) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, left, axis, test, contents) : 0; + } + + xpath_ast_node* alloc_node(ast_type_t type, xpath_ast_node* left, xpath_ast_node* right, predicate_t test) + { + void* memory = alloc_node(); + return memory ? new (memory) xpath_ast_node(type, left, right, test) : 0; + } + + const char_t* alloc_string(const xpath_lexer_string& value) + { + if (!value.begin) + return PUGIXML_TEXT(""); + + size_t length = static_cast(value.end - value.begin); + + char_t* c = static_cast(_alloc->allocate((length + 1) * sizeof(char_t))); + if (!c) return 0; + + memcpy(c, value.begin, length * sizeof(char_t)); + c[length] = 0; + + return c; + } + + xpath_ast_node* parse_function(const xpath_lexer_string& name, size_t argc, xpath_ast_node* args[2]) + { + switch (name.begin[0]) + { + case 'b': + if (name == PUGIXML_TEXT("boolean") && argc == 1) + return alloc_node(ast_func_boolean, xpath_type_boolean, args[0]); + + break; + + case 'c': + if (name == PUGIXML_TEXT("count") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set"); + return alloc_node(ast_func_count, xpath_type_number, args[0]); + } + else if (name == PUGIXML_TEXT("contains") && argc == 2) + return alloc_node(ast_func_contains, xpath_type_boolean, args[0], args[1]); + else if (name == PUGIXML_TEXT("concat") && argc >= 2) + return alloc_node(ast_func_concat, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("ceiling") && argc == 1) + return alloc_node(ast_func_ceiling, xpath_type_number, args[0]); + + break; + + case 'f': + if (name == PUGIXML_TEXT("false") && argc == 0) + return alloc_node(ast_func_false, xpath_type_boolean); + else if (name == PUGIXML_TEXT("floor") && argc == 1) + return alloc_node(ast_func_floor, xpath_type_number, args[0]); + + break; + + case 'i': + if (name == PUGIXML_TEXT("id") && argc == 1) + return alloc_node(ast_func_id, xpath_type_node_set, args[0]); + + break; + + case 'l': + if (name == PUGIXML_TEXT("last") && argc == 0) + return alloc_node(ast_func_last, xpath_type_number); + else if (name == PUGIXML_TEXT("lang") && argc == 1) + return alloc_node(ast_func_lang, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("local-name") && argc <= 1) + { + if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set"); + return alloc_node(argc == 0 ? ast_func_local_name_0 : ast_func_local_name_1, xpath_type_string, args[0]); + } + + break; + + case 'n': + if (name == PUGIXML_TEXT("name") && argc <= 1) + { + if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set"); + return alloc_node(argc == 0 ? ast_func_name_0 : ast_func_name_1, xpath_type_string, args[0]); + } + else if (name == PUGIXML_TEXT("namespace-uri") && argc <= 1) + { + if (argc == 1 && args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set"); + return alloc_node(argc == 0 ? ast_func_namespace_uri_0 : ast_func_namespace_uri_1, xpath_type_string, args[0]); + } + else if (name == PUGIXML_TEXT("normalize-space") && argc <= 1) + return alloc_node(argc == 0 ? ast_func_normalize_space_0 : ast_func_normalize_space_1, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("not") && argc == 1) + return alloc_node(ast_func_not, xpath_type_boolean, args[0]); + else if (name == PUGIXML_TEXT("number") && argc <= 1) + return alloc_node(argc == 0 ? ast_func_number_0 : ast_func_number_1, xpath_type_number, args[0]); + + break; + + case 'p': + if (name == PUGIXML_TEXT("position") && argc == 0) + return alloc_node(ast_func_position, xpath_type_number); + + break; + + case 'r': + if (name == PUGIXML_TEXT("round") && argc == 1) + return alloc_node(ast_func_round, xpath_type_number, args[0]); + + break; + + case 's': + if (name == PUGIXML_TEXT("string") && argc <= 1) + return alloc_node(argc == 0 ? ast_func_string_0 : ast_func_string_1, xpath_type_string, args[0]); + else if (name == PUGIXML_TEXT("string-length") && argc <= 1) + return alloc_node(argc == 0 ? ast_func_string_length_0 : ast_func_string_length_1, xpath_type_number, args[0]); + else if (name == PUGIXML_TEXT("starts-with") && argc == 2) + return alloc_node(ast_func_starts_with, xpath_type_boolean, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-before") && argc == 2) + return alloc_node(ast_func_substring_before, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring-after") && argc == 2) + return alloc_node(ast_func_substring_after, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("substring") && (argc == 2 || argc == 3)) + return alloc_node(argc == 2 ? ast_func_substring_2 : ast_func_substring_3, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("sum") && argc == 1) + { + if (args[0]->rettype() != xpath_type_node_set) return error("Function has to be applied to node set"); + return alloc_node(ast_func_sum, xpath_type_number, args[0]); + } + + break; + + case 't': + if (name == PUGIXML_TEXT("translate") && argc == 3) + return alloc_node(ast_func_translate, xpath_type_string, args[0], args[1]); + else if (name == PUGIXML_TEXT("true") && argc == 0) + return alloc_node(ast_func_true, xpath_type_boolean); + + break; + + default: + break; + } + + return error("Unrecognized function or wrong parameter count"); + } + + axis_t parse_axis_name(const xpath_lexer_string& name, bool& specified) + { + specified = true; + + switch (name.begin[0]) + { + case 'a': + if (name == PUGIXML_TEXT("ancestor")) + return axis_ancestor; + else if (name == PUGIXML_TEXT("ancestor-or-self")) + return axis_ancestor_or_self; + else if (name == PUGIXML_TEXT("attribute")) + return axis_attribute; + + break; + + case 'c': + if (name == PUGIXML_TEXT("child")) + return axis_child; + + break; + + case 'd': + if (name == PUGIXML_TEXT("descendant")) + return axis_descendant; + else if (name == PUGIXML_TEXT("descendant-or-self")) + return axis_descendant_or_self; + + break; + + case 'f': + if (name == PUGIXML_TEXT("following")) + return axis_following; + else if (name == PUGIXML_TEXT("following-sibling")) + return axis_following_sibling; + + break; + + case 'n': + if (name == PUGIXML_TEXT("namespace")) + return axis_namespace; + + break; + + case 'p': + if (name == PUGIXML_TEXT("parent")) + return axis_parent; + else if (name == PUGIXML_TEXT("preceding")) + return axis_preceding; + else if (name == PUGIXML_TEXT("preceding-sibling")) + return axis_preceding_sibling; + + break; + + case 's': + if (name == PUGIXML_TEXT("self")) + return axis_self; + + break; + + default: + break; + } + + specified = false; + return axis_child; + } + + nodetest_t parse_node_test_type(const xpath_lexer_string& name) + { + switch (name.begin[0]) + { + case 'c': + if (name == PUGIXML_TEXT("comment")) + return nodetest_type_comment; + + break; + + case 'n': + if (name == PUGIXML_TEXT("node")) + return nodetest_type_node; + + break; + + case 'p': + if (name == PUGIXML_TEXT("processing-instruction")) + return nodetest_type_pi; + + break; + + case 't': + if (name == PUGIXML_TEXT("text")) + return nodetest_type_text; + + break; + + default: + break; + } + + return nodetest_none; + } + + // PrimaryExpr ::= VariableReference | '(' Expr ')' | Literal | Number | FunctionCall + xpath_ast_node* parse_primary_expression() + { + switch (_lexer.current()) + { + case lex_var_ref: + { + xpath_lexer_string name = _lexer.contents(); + + if (!_variables) + return error("Unknown variable: variable set is not provided"); + + xpath_variable* var = 0; + if (!get_variable_scratch(_scratch, _variables, name.begin, name.end, &var)) + return error_oom(); + + if (!var) + return error("Unknown variable: variable set does not contain the given name"); + + _lexer.next(); + + return alloc_node(ast_variable, var->type(), var); + } + + case lex_open_brace: + { + _lexer.next(); + + xpath_ast_node* n = parse_expression(); + if (!n) return 0; + + if (_lexer.current() != lex_close_brace) + return error("Expected ')' to match an opening '('"); + + _lexer.next(); + + return n; + } + + case lex_quoted_string: + { + const char_t* value = alloc_string(_lexer.contents()); + if (!value) return 0; + + _lexer.next(); + + return alloc_node(ast_string_constant, xpath_type_string, value); + } + + case lex_number: + { + double value = 0; + + if (!convert_string_to_number_scratch(_scratch, _lexer.contents().begin, _lexer.contents().end, &value)) + return error_oom(); + + _lexer.next(); + + return alloc_node(ast_number_constant, xpath_type_number, value); + } + + case lex_string: + { + xpath_ast_node* args[2] = {0}; + size_t argc = 0; + + xpath_lexer_string function = _lexer.contents(); + _lexer.next(); + + xpath_ast_node* last_arg = 0; + + if (_lexer.current() != lex_open_brace) + return error("Unrecognized function call"); + _lexer.next(); + + size_t old_depth = _depth; + + while (_lexer.current() != lex_close_brace) + { + if (argc > 0) + { + if (_lexer.current() != lex_comma) + return error("No comma between function arguments"); + _lexer.next(); + } + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + xpath_ast_node* n = parse_expression(); + if (!n) return 0; + + if (argc < 2) args[argc] = n; + else last_arg->set_next(n); + + argc++; + last_arg = n; + } + + _lexer.next(); + + _depth = old_depth; + + return parse_function(function, argc, args); + } + + default: + return error("Unrecognizable primary expression"); + } + } + + // FilterExpr ::= PrimaryExpr | FilterExpr Predicate + // Predicate ::= '[' PredicateExpr ']' + // PredicateExpr ::= Expr + xpath_ast_node* parse_filter_expression() + { + xpath_ast_node* n = parse_primary_expression(); + if (!n) return 0; + + size_t old_depth = _depth; + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + if (n->rettype() != xpath_type_node_set) + return error("Predicate has to be applied to node set"); + + xpath_ast_node* expr = parse_expression(); + if (!expr) return 0; + + n = alloc_node(ast_filter, n, expr, predicate_default); + if (!n) return 0; + + if (_lexer.current() != lex_close_square_brace) + return error("Expected ']' to match an opening '['"); + + _lexer.next(); + } + + _depth = old_depth; + + return n; + } + + // Step ::= AxisSpecifier NodeTest Predicate* | AbbreviatedStep + // AxisSpecifier ::= AxisName '::' | '@'? + // NodeTest ::= NameTest | NodeType '(' ')' | 'processing-instruction' '(' Literal ')' + // NameTest ::= '*' | NCName ':' '*' | QName + // AbbreviatedStep ::= '.' | '..' + xpath_ast_node* parse_step(xpath_ast_node* set) + { + if (set && set->rettype() != xpath_type_node_set) + return error("Step has to be applied to node set"); + + bool axis_specified = false; + axis_t axis = axis_child; // implied child axis + + if (_lexer.current() == lex_axis_attribute) + { + axis = axis_attribute; + axis_specified = true; + + _lexer.next(); + } + else if (_lexer.current() == lex_dot) + { + _lexer.next(); + + if (_lexer.current() == lex_open_square_brace) + return error("Predicates are not allowed after an abbreviated step"); + + return alloc_node(ast_step, set, axis_self, nodetest_type_node, 0); + } + else if (_lexer.current() == lex_double_dot) + { + _lexer.next(); + + if (_lexer.current() == lex_open_square_brace) + return error("Predicates are not allowed after an abbreviated step"); + + return alloc_node(ast_step, set, axis_parent, nodetest_type_node, 0); + } + + nodetest_t nt_type = nodetest_none; + xpath_lexer_string nt_name; + + if (_lexer.current() == lex_string) + { + // node name test + nt_name = _lexer.contents(); + _lexer.next(); + + // was it an axis name? + if (_lexer.current() == lex_double_colon) + { + // parse axis name + if (axis_specified) + return error("Two axis specifiers in one step"); + + axis = parse_axis_name(nt_name, axis_specified); + + if (!axis_specified) + return error("Unknown axis"); + + // read actual node test + _lexer.next(); + + if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + nt_name = xpath_lexer_string(); + _lexer.next(); + } + else if (_lexer.current() == lex_string) + { + nt_name = _lexer.contents(); + _lexer.next(); + } + else + { + return error("Unrecognized node test"); + } + } + + if (nt_type == nodetest_none) + { + // node type test or processing-instruction + if (_lexer.current() == lex_open_brace) + { + _lexer.next(); + + if (_lexer.current() == lex_close_brace) + { + _lexer.next(); + + nt_type = parse_node_test_type(nt_name); + + if (nt_type == nodetest_none) + return error("Unrecognized node type"); + + nt_name = xpath_lexer_string(); + } + else if (nt_name == PUGIXML_TEXT("processing-instruction")) + { + if (_lexer.current() != lex_quoted_string) + return error("Only literals are allowed as arguments to processing-instruction()"); + + nt_type = nodetest_pi; + nt_name = _lexer.contents(); + _lexer.next(); + + if (_lexer.current() != lex_close_brace) + return error("Unmatched brace near processing-instruction()"); + _lexer.next(); + } + else + { + return error("Unmatched brace near node type test"); + } + } + // QName or NCName:* + else + { + if (nt_name.end - nt_name.begin > 2 && nt_name.end[-2] == ':' && nt_name.end[-1] == '*') // NCName:* + { + nt_name.end--; // erase * + + nt_type = nodetest_all_in_namespace; + } + else + { + nt_type = nodetest_name; + } + } + } + } + else if (_lexer.current() == lex_multiply) + { + nt_type = nodetest_all; + _lexer.next(); + } + else + { + return error("Unrecognized node test"); + } + + const char_t* nt_name_copy = alloc_string(nt_name); + if (!nt_name_copy) return 0; + + xpath_ast_node* n = alloc_node(ast_step, set, axis, nt_type, nt_name_copy); + if (!n) return 0; + + size_t old_depth = _depth; + + xpath_ast_node* last = 0; + + while (_lexer.current() == lex_open_square_brace) + { + _lexer.next(); + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + xpath_ast_node* expr = parse_expression(); + if (!expr) return 0; + + xpath_ast_node* pred = alloc_node(ast_predicate, 0, expr, predicate_default); + if (!pred) return 0; + + if (_lexer.current() != lex_close_square_brace) + return error("Expected ']' to match an opening '['"); + _lexer.next(); + + if (last) last->set_next(pred); + else n->set_right(pred); + + last = pred; + } + + _depth = old_depth; + + return n; + } + + // RelativeLocationPath ::= Step | RelativeLocationPath '/' Step | RelativeLocationPath '//' Step + xpath_ast_node* parse_relative_location_path(xpath_ast_node* set) + { + xpath_ast_node* n = parse_step(set); + if (!n) return 0; + + size_t old_depth = _depth; + + while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + { + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + if (!n) return 0; + + ++_depth; + } + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + n = parse_step(n); + if (!n) return 0; + } + + _depth = old_depth; + + return n; + } + + // LocationPath ::= RelativeLocationPath | AbsoluteLocationPath + // AbsoluteLocationPath ::= '/' RelativeLocationPath? | '//' RelativeLocationPath + xpath_ast_node* parse_location_path() + { + if (_lexer.current() == lex_slash) + { + _lexer.next(); + + xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set); + if (!n) return 0; + + // relative location path can start from axis_attribute, dot, double_dot, multiply and string lexemes; any other lexeme means standalone root path + lexeme_t l = _lexer.current(); + + if (l == lex_string || l == lex_axis_attribute || l == lex_dot || l == lex_double_dot || l == lex_multiply) + return parse_relative_location_path(n); + else + return n; + } + else if (_lexer.current() == lex_double_slash) + { + _lexer.next(); + + xpath_ast_node* n = alloc_node(ast_step_root, xpath_type_node_set); + if (!n) return 0; + + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + if (!n) return 0; + + return parse_relative_location_path(n); + } + + // else clause moved outside of if because of bogus warning 'control may reach end of non-void function being inlined' in gcc 4.0.1 + return parse_relative_location_path(0); + } + + // PathExpr ::= LocationPath + // | FilterExpr + // | FilterExpr '/' RelativeLocationPath + // | FilterExpr '//' RelativeLocationPath + // UnionExpr ::= PathExpr | UnionExpr '|' PathExpr + // UnaryExpr ::= UnionExpr | '-' UnaryExpr + xpath_ast_node* parse_path_or_unary_expression() + { + // Clarification. + // PathExpr begins with either LocationPath or FilterExpr. + // FilterExpr begins with PrimaryExpr + // PrimaryExpr begins with '$' in case of it being a variable reference, + // '(' in case of it being an expression, string literal, number constant or + // function call. + if (_lexer.current() == lex_var_ref || _lexer.current() == lex_open_brace || + _lexer.current() == lex_quoted_string || _lexer.current() == lex_number || + _lexer.current() == lex_string) + { + if (_lexer.current() == lex_string) + { + // This is either a function call, or not - if not, we shall proceed with location path + const char_t* state = _lexer.state(); + + while (PUGI__IS_CHARTYPE(*state, ct_space)) ++state; + + if (*state != '(') + return parse_location_path(); + + // This looks like a function call; however this still can be a node-test. Check it. + if (parse_node_test_type(_lexer.contents()) != nodetest_none) + return parse_location_path(); + } + + xpath_ast_node* n = parse_filter_expression(); + if (!n) return 0; + + if (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) + { + lexeme_t l = _lexer.current(); + _lexer.next(); + + if (l == lex_double_slash) + { + if (n->rettype() != xpath_type_node_set) + return error("Step has to be applied to node set"); + + n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); + if (!n) return 0; + } + + // select from location path + return parse_relative_location_path(n); + } + + return n; + } + else if (_lexer.current() == lex_minus) + { + _lexer.next(); + + // precedence 7+ - only parses union expressions + xpath_ast_node* n = parse_expression(7); + if (!n) return 0; + + return alloc_node(ast_op_negate, xpath_type_number, n); + } + else + { + return parse_location_path(); + } + } + + struct binary_op_t + { + ast_type_t asttype; + xpath_value_type rettype; + int precedence; + + binary_op_t(): asttype(ast_unknown), rettype(xpath_type_none), precedence(0) + { + } + + binary_op_t(ast_type_t asttype_, xpath_value_type rettype_, int precedence_): asttype(asttype_), rettype(rettype_), precedence(precedence_) + { + } + + static binary_op_t parse(xpath_lexer& lexer) + { + switch (lexer.current()) + { + case lex_string: + if (lexer.contents() == PUGIXML_TEXT("or")) + return binary_op_t(ast_op_or, xpath_type_boolean, 1); + else if (lexer.contents() == PUGIXML_TEXT("and")) + return binary_op_t(ast_op_and, xpath_type_boolean, 2); + else if (lexer.contents() == PUGIXML_TEXT("div")) + return binary_op_t(ast_op_divide, xpath_type_number, 6); + else if (lexer.contents() == PUGIXML_TEXT("mod")) + return binary_op_t(ast_op_mod, xpath_type_number, 6); + else + return binary_op_t(); + + case lex_equal: + return binary_op_t(ast_op_equal, xpath_type_boolean, 3); + + case lex_not_equal: + return binary_op_t(ast_op_not_equal, xpath_type_boolean, 3); + + case lex_less: + return binary_op_t(ast_op_less, xpath_type_boolean, 4); + + case lex_greater: + return binary_op_t(ast_op_greater, xpath_type_boolean, 4); + + case lex_less_or_equal: + return binary_op_t(ast_op_less_or_equal, xpath_type_boolean, 4); + + case lex_greater_or_equal: + return binary_op_t(ast_op_greater_or_equal, xpath_type_boolean, 4); + + case lex_plus: + return binary_op_t(ast_op_add, xpath_type_number, 5); + + case lex_minus: + return binary_op_t(ast_op_subtract, xpath_type_number, 5); + + case lex_multiply: + return binary_op_t(ast_op_multiply, xpath_type_number, 6); + + case lex_union: + return binary_op_t(ast_op_union, xpath_type_node_set, 7); + + default: + return binary_op_t(); + } + } + }; + + xpath_ast_node* parse_expression_rec(xpath_ast_node* lhs, int limit) + { + binary_op_t op = binary_op_t::parse(_lexer); + + while (op.asttype != ast_unknown && op.precedence >= limit) + { + _lexer.next(); + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + xpath_ast_node* rhs = parse_path_or_unary_expression(); + if (!rhs) return 0; + + binary_op_t nextop = binary_op_t::parse(_lexer); + + while (nextop.asttype != ast_unknown && nextop.precedence > op.precedence) + { + rhs = parse_expression_rec(rhs, nextop.precedence); + if (!rhs) return 0; + + nextop = binary_op_t::parse(_lexer); + } + + if (op.asttype == ast_op_union && (lhs->rettype() != xpath_type_node_set || rhs->rettype() != xpath_type_node_set)) + return error("Union operator has to be applied to node sets"); + + lhs = alloc_node(op.asttype, op.rettype, lhs, rhs); + if (!lhs) return 0; + + op = binary_op_t::parse(_lexer); + } + + return lhs; + } + + // Expr ::= OrExpr + // OrExpr ::= AndExpr | OrExpr 'or' AndExpr + // AndExpr ::= EqualityExpr | AndExpr 'and' EqualityExpr + // EqualityExpr ::= RelationalExpr + // | EqualityExpr '=' RelationalExpr + // | EqualityExpr '!=' RelationalExpr + // RelationalExpr ::= AdditiveExpr + // | RelationalExpr '<' AdditiveExpr + // | RelationalExpr '>' AdditiveExpr + // | RelationalExpr '<=' AdditiveExpr + // | RelationalExpr '>=' AdditiveExpr + // AdditiveExpr ::= MultiplicativeExpr + // | AdditiveExpr '+' MultiplicativeExpr + // | AdditiveExpr '-' MultiplicativeExpr + // MultiplicativeExpr ::= UnaryExpr + // | MultiplicativeExpr '*' UnaryExpr + // | MultiplicativeExpr 'div' UnaryExpr + // | MultiplicativeExpr 'mod' UnaryExpr + xpath_ast_node* parse_expression(int limit = 0) + { + size_t old_depth = _depth; + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + + xpath_ast_node* n = parse_path_or_unary_expression(); + if (!n) return 0; + + n = parse_expression_rec(n, limit); + + _depth = old_depth; + + return n; + } + + xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result), _depth(0) + { + } + + xpath_ast_node* parse() + { + xpath_ast_node* n = parse_expression(); + if (!n) return 0; + + assert(_depth == 0); + + // check if there are unparsed tokens left + if (_lexer.current() != lex_eof) + return error("Incorrect query"); + + return n; + } + + static xpath_ast_node* parse(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result) + { + xpath_parser parser(query, variables, alloc, result); + + return parser.parse(); + } + }; + + struct xpath_query_impl + { + static xpath_query_impl* create() + { + void* memory = xml_memory::allocate(sizeof(xpath_query_impl)); + if (!memory) return 0; + + return new (memory) xpath_query_impl(); + } + + static void destroy(xpath_query_impl* impl) + { + // free all allocated pages + impl->alloc.release(); + + // free allocator memory (with the first page) + xml_memory::deallocate(impl); + } + + xpath_query_impl(): root(0), alloc(&block, &oom), oom(false) + { + block.next = 0; + block.capacity = sizeof(block.data); + } + + xpath_ast_node* root; + xpath_allocator alloc; + xpath_memory_block block; + bool oom; + }; + + PUGI__FN impl::xpath_ast_node* evaluate_node_set_prepare(xpath_query_impl* impl) + { + if (!impl) return 0; + + if (impl->root->rettype() != xpath_type_node_set) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return 0; + #else + xpath_parse_result res; + res.error = "Expression does not evaluate to node set"; + + throw xpath_exception(res); + #endif + } + + return impl->root; + } +PUGI__NS_END + +namespace pugi +{ +#ifndef PUGIXML_NO_EXCEPTIONS + PUGI__FN xpath_exception::xpath_exception(const xpath_parse_result& result_): _result(result_) + { + assert(_result.error); + } + + PUGI__FN const char* xpath_exception::what() const throw() + { + return _result.error; + } + + PUGI__FN const xpath_parse_result& xpath_exception::result() const + { + return _result; + } +#endif + + PUGI__FN xpath_node::xpath_node() + { + } + + PUGI__FN xpath_node::xpath_node(const xml_node& node_): _node(node_) + { + } + + PUGI__FN xpath_node::xpath_node(const xml_attribute& attribute_, const xml_node& parent_): _node(attribute_ ? parent_ : xml_node()), _attribute(attribute_) + { + } + + PUGI__FN xml_node xpath_node::node() const + { + return _attribute ? xml_node() : _node; + } + + PUGI__FN xml_attribute xpath_node::attribute() const + { + return _attribute; + } + + PUGI__FN xml_node xpath_node::parent() const + { + return _attribute ? _node : _node.parent(); + } + + PUGI__FN static void unspecified_bool_xpath_node(xpath_node***) + { + } + + PUGI__FN xpath_node::operator xpath_node::unspecified_bool_type() const + { + return (_node || _attribute) ? unspecified_bool_xpath_node : 0; + } + + PUGI__FN bool xpath_node::operator!() const + { + return !(_node || _attribute); + } + + PUGI__FN bool xpath_node::operator==(const xpath_node& n) const + { + return _node == n._node && _attribute == n._attribute; + } + + PUGI__FN bool xpath_node::operator!=(const xpath_node& n) const + { + return _node != n._node || _attribute != n._attribute; + } + +#ifdef __BORLANDC__ + PUGI__FN bool operator&&(const xpath_node& lhs, bool rhs) + { + return (bool)lhs && rhs; + } + + PUGI__FN bool operator||(const xpath_node& lhs, bool rhs) + { + return (bool)lhs || rhs; + } +#endif + + PUGI__FN void xpath_node_set::_assign(const_iterator begin_, const_iterator end_, type_t type_) + { + assert(begin_ <= end_); + + size_t size_ = static_cast(end_ - begin_); + + // use internal buffer for 0 or 1 elements, heap buffer otherwise + xpath_node* storage = (size_ <= 1) ? _storage : static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); + + if (!storage) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif + } + + // deallocate old buffer + if (_begin != _storage) + impl::xml_memory::deallocate(_begin); + + // size check is necessary because for begin_ = end_ = nullptr, memcpy is UB + if (size_) + memcpy(storage, begin_, size_ * sizeof(xpath_node)); + + _begin = storage; + _end = storage + size_; + _type = type_; + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) PUGIXML_NOEXCEPT + { + _type = rhs._type; + _storage[0] = rhs._storage[0]; + _begin = (rhs._begin == rhs._storage) ? _storage : rhs._begin; + _end = _begin + (rhs._end - rhs._begin); + + rhs._type = type_unsorted; + rhs._begin = rhs._storage; + rhs._end = rhs._storage; + } +#endif + + PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage) + { + } + + PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(_storage), _end(_storage) + { + _assign(begin_, end_, type_); + } + + PUGI__FN xpath_node_set::~xpath_node_set() + { + if (_begin != _storage) + impl::xml_memory::deallocate(_begin); + } + + PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(_storage), _end(_storage) + { + _assign(ns._begin, ns._end, ns._type); + } + + PUGI__FN xpath_node_set& xpath_node_set::operator=(const xpath_node_set& ns) + { + if (this == &ns) return *this; + + _assign(ns._begin, ns._end, ns._type); + + return *this; + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(_storage), _end(_storage) + { + _move(rhs); + } + + PUGI__FN xpath_node_set& xpath_node_set::operator=(xpath_node_set&& rhs) PUGIXML_NOEXCEPT + { + if (this == &rhs) return *this; + + if (_begin != _storage) + impl::xml_memory::deallocate(_begin); + + _move(rhs); + + return *this; + } +#endif + + PUGI__FN xpath_node_set::type_t xpath_node_set::type() const + { + return _type; + } + + PUGI__FN size_t xpath_node_set::size() const + { + return _end - _begin; + } + + PUGI__FN bool xpath_node_set::empty() const + { + return _begin == _end; + } + + PUGI__FN const xpath_node& xpath_node_set::operator[](size_t index) const + { + assert(index < size()); + return _begin[index]; + } + + PUGI__FN xpath_node_set::const_iterator xpath_node_set::begin() const + { + return _begin; + } + + PUGI__FN xpath_node_set::const_iterator xpath_node_set::end() const + { + return _end; + } + + PUGI__FN void xpath_node_set::sort(bool reverse) + { + _type = impl::xpath_sort(_begin, _end, _type, reverse); + } + + PUGI__FN xpath_node xpath_node_set::first() const + { + return impl::xpath_first(_begin, _end, _type); + } + + PUGI__FN xpath_parse_result::xpath_parse_result(): error("Internal error"), offset(0) + { + } + + PUGI__FN xpath_parse_result::operator bool() const + { + return error == 0; + } + + PUGI__FN const char* xpath_parse_result::description() const + { + return error ? error : "No error"; + } + + PUGI__FN xpath_variable::xpath_variable(xpath_value_type type_): _type(type_), _next(0) + { + } + + PUGI__FN const char_t* xpath_variable::name() const + { + switch (_type) + { + case xpath_type_node_set: + return static_cast(this)->name; + + case xpath_type_number: + return static_cast(this)->name; + + case xpath_type_string: + return static_cast(this)->name; + + case xpath_type_boolean: + return static_cast(this)->name; + + default: + assert(false && "Invalid variable type"); // unreachable + return 0; + } + } + + PUGI__FN xpath_value_type xpath_variable::type() const + { + return _type; + } + + PUGI__FN bool xpath_variable::get_boolean() const + { + return (_type == xpath_type_boolean) ? static_cast(this)->value : false; + } + + PUGI__FN double xpath_variable::get_number() const + { + return (_type == xpath_type_number) ? static_cast(this)->value : impl::gen_nan(); + } + + PUGI__FN const char_t* xpath_variable::get_string() const + { + const char_t* value = (_type == xpath_type_string) ? static_cast(this)->value : 0; + return value ? value : PUGIXML_TEXT(""); + } + + PUGI__FN const xpath_node_set& xpath_variable::get_node_set() const + { + return (_type == xpath_type_node_set) ? static_cast(this)->value : impl::dummy_node_set; + } + + PUGI__FN bool xpath_variable::set(bool value) + { + if (_type != xpath_type_boolean) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN bool xpath_variable::set(double value) + { + if (_type != xpath_type_number) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN bool xpath_variable::set(const char_t* value) + { + if (_type != xpath_type_string) return false; + + impl::xpath_variable_string* var = static_cast(this); + + // duplicate string + size_t size = (impl::strlength(value) + 1) * sizeof(char_t); + + char_t* copy = static_cast(impl::xml_memory::allocate(size)); + if (!copy) return false; + + memcpy(copy, value, size); + + // replace old string + if (var->value) impl::xml_memory::deallocate(var->value); + var->value = copy; + + return true; + } + + PUGI__FN bool xpath_variable::set(const xpath_node_set& value) + { + if (_type != xpath_type_node_set) return false; + + static_cast(this)->value = value; + return true; + } + + PUGI__FN xpath_variable_set::xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + _data[i] = 0; + } + + PUGI__FN xpath_variable_set::~xpath_variable_set() + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + _destroy(_data[i]); + } + + PUGI__FN xpath_variable_set::xpath_variable_set(const xpath_variable_set& rhs) + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + _data[i] = 0; + + _assign(rhs); + } + + PUGI__FN xpath_variable_set& xpath_variable_set::operator=(const xpath_variable_set& rhs) + { + if (this == &rhs) return *this; + + _assign(rhs); + + return *this; + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN xpath_variable_set::xpath_variable_set(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } + } + + PUGI__FN xpath_variable_set& xpath_variable_set::operator=(xpath_variable_set&& rhs) PUGIXML_NOEXCEPT + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + _destroy(_data[i]); + + _data[i] = rhs._data[i]; + rhs._data[i] = 0; + } + + return *this; + } +#endif + + PUGI__FN void xpath_variable_set::_assign(const xpath_variable_set& rhs) + { + xpath_variable_set temp; + + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + if (rhs._data[i] && !_clone(rhs._data[i], &temp._data[i])) + return; + + _swap(temp); + } + + PUGI__FN void xpath_variable_set::_swap(xpath_variable_set& rhs) + { + for (size_t i = 0; i < sizeof(_data) / sizeof(_data[0]); ++i) + { + xpath_variable* chain = _data[i]; + + _data[i] = rhs._data[i]; + rhs._data[i] = chain; + } + } + + PUGI__FN xpath_variable* xpath_variable_set::_find(const char_t* name) const + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = impl::hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (impl::strequal(var->name(), name)) + return var; + + return 0; + } + + PUGI__FN bool xpath_variable_set::_clone(xpath_variable* var, xpath_variable** out_result) + { + xpath_variable* last = 0; + + while (var) + { + // allocate storage for new variable + xpath_variable* nvar = impl::new_xpath_variable(var->_type, var->name()); + if (!nvar) return false; + + // link the variable to the result immediately to handle failures gracefully + if (last) + last->_next = nvar; + else + *out_result = nvar; + + last = nvar; + + // copy the value; this can fail due to out-of-memory conditions + if (!impl::copy_xpath_variable(nvar, var)) return false; + + var = var->_next; + } + + return true; + } + + PUGI__FN void xpath_variable_set::_destroy(xpath_variable* var) + { + while (var) + { + xpath_variable* next = var->_next; + + impl::delete_xpath_variable(var->_type, var); + + var = next; + } + } + + PUGI__FN xpath_variable* xpath_variable_set::add(const char_t* name, xpath_value_type type) + { + const size_t hash_size = sizeof(_data) / sizeof(_data[0]); + size_t hash = impl::hash_string(name) % hash_size; + + // look for existing variable + for (xpath_variable* var = _data[hash]; var; var = var->_next) + if (impl::strequal(var->name(), name)) + return var->type() == type ? var : 0; + + // add new variable + xpath_variable* result = impl::new_xpath_variable(type, name); + + if (result) + { + result->_next = _data[hash]; + + _data[hash] = result; + } + + return result; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, bool value) + { + xpath_variable* var = add(name, xpath_type_boolean); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, double value) + { + xpath_variable* var = add(name, xpath_type_number); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, const char_t* value) + { + xpath_variable* var = add(name, xpath_type_string); + return var ? var->set(value) : false; + } + + PUGI__FN bool xpath_variable_set::set(const char_t* name, const xpath_node_set& value) + { + xpath_variable* var = add(name, xpath_type_node_set); + return var ? var->set(value) : false; + } + + PUGI__FN xpath_variable* xpath_variable_set::get(const char_t* name) + { + return _find(name); + } + + PUGI__FN const xpath_variable* xpath_variable_set::get(const char_t* name) const + { + return _find(name); + } + + PUGI__FN xpath_query::xpath_query(const char_t* query, xpath_variable_set* variables): _impl(0) + { + impl::xpath_query_impl* qimpl = impl::xpath_query_impl::create(); + + if (!qimpl) + { + #ifdef PUGIXML_NO_EXCEPTIONS + _result.error = "Out of memory"; + #else + throw std::bad_alloc(); + #endif + } + else + { + using impl::auto_deleter; // MSVC7 workaround + auto_deleter impl(qimpl, impl::xpath_query_impl::destroy); + + qimpl->root = impl::xpath_parser::parse(query, variables, &qimpl->alloc, &_result); + + if (qimpl->root) + { + qimpl->root->optimize(&qimpl->alloc); + + _impl = impl.release(); + _result.error = 0; + } + else + { + #ifdef PUGIXML_NO_EXCEPTIONS + if (qimpl->oom) _result.error = "Out of memory"; + #else + if (qimpl->oom) throw std::bad_alloc(); + throw xpath_exception(_result); + #endif + } + } + } + + PUGI__FN xpath_query::xpath_query(): _impl(0) + { + } + + PUGI__FN xpath_query::~xpath_query() + { + if (_impl) + impl::xpath_query_impl::destroy(static_cast(_impl)); + } + +#ifdef PUGIXML_HAS_MOVE + PUGI__FN xpath_query::xpath_query(xpath_query&& rhs) PUGIXML_NOEXCEPT + { + _impl = rhs._impl; + _result = rhs._result; + rhs._impl = 0; + rhs._result = xpath_parse_result(); + } + + PUGI__FN xpath_query& xpath_query::operator=(xpath_query&& rhs) PUGIXML_NOEXCEPT + { + if (this == &rhs) return *this; + + if (_impl) + impl::xpath_query_impl::destroy(static_cast(_impl)); + + _impl = rhs._impl; + _result = rhs._result; + rhs._impl = 0; + rhs._result = xpath_parse_result(); + + return *this; + } +#endif + + PUGI__FN xpath_value_type xpath_query::return_type() const + { + if (!_impl) return xpath_type_none; + + return static_cast(_impl)->root->rettype(); + } + + PUGI__FN bool xpath_query::evaluate_boolean(const xpath_node& n) const + { + if (!_impl) return false; + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + bool r = static_cast(_impl)->root->eval_boolean(c, sd.stack); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return false; + #else + throw std::bad_alloc(); + #endif + } + + return r; + } + + PUGI__FN double xpath_query::evaluate_number(const xpath_node& n) const + { + if (!_impl) return impl::gen_nan(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + double r = static_cast(_impl)->root->eval_number(c, sd.stack); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return impl::gen_nan(); + #else + throw std::bad_alloc(); + #endif + } + + return r; + } + +#ifndef PUGIXML_NO_STL + PUGI__FN string_t xpath_query::evaluate_string(const xpath_node& n) const + { + if (!_impl) return string_t(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + impl::xpath_string r = static_cast(_impl)->root->eval_string(c, sd.stack); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return string_t(); + #else + throw std::bad_alloc(); + #endif + } + + return string_t(r.c_str(), r.length()); + } +#endif + + PUGI__FN size_t xpath_query::evaluate_string(char_t* buffer, size_t capacity, const xpath_node& n) const + { + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + impl::xpath_string r = _impl ? static_cast(_impl)->root->eval_string(c, sd.stack) : impl::xpath_string(); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + r = impl::xpath_string(); + #else + throw std::bad_alloc(); + #endif + } + + size_t full_size = r.length() + 1; + + if (capacity > 0) + { + size_t size = (full_size < capacity) ? full_size : capacity; + assert(size > 0); + + memcpy(buffer, r.c_str(), (size - 1) * sizeof(char_t)); + buffer[size - 1] = 0; + } + + return full_size; + } + + PUGI__FN xpath_node_set xpath_query::evaluate_node_set(const xpath_node& n) const + { + impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); + if (!root) return xpath_node_set(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_all); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return xpath_node_set(); + #else + throw std::bad_alloc(); + #endif + } + + return xpath_node_set(r.begin(), r.end(), r.type()); + } + + PUGI__FN xpath_node xpath_query::evaluate_node(const xpath_node& n) const + { + impl::xpath_ast_node* root = impl::evaluate_node_set_prepare(static_cast(_impl)); + if (!root) return xpath_node(); + + impl::xpath_context c(n, 1, 1); + impl::xpath_stack_data sd; + + impl::xpath_node_set_raw r = root->eval_node_set(c, sd.stack, impl::nodeset_eval_first); + + if (sd.oom) + { + #ifdef PUGIXML_NO_EXCEPTIONS + return xpath_node(); + #else + throw std::bad_alloc(); + #endif + } + + return r.first(); + } + + PUGI__FN const xpath_parse_result& xpath_query::result() const + { + return _result; + } + + PUGI__FN static void unspecified_bool_xpath_query(xpath_query***) + { + } + + PUGI__FN xpath_query::operator xpath_query::unspecified_bool_type() const + { + return _impl ? unspecified_bool_xpath_query : 0; + } + + PUGI__FN bool xpath_query::operator!() const + { + return !_impl; + } + + PUGI__FN xpath_node xml_node::select_node(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return q.evaluate_node(*this); + } + + PUGI__FN xpath_node xml_node::select_node(const xpath_query& query) const + { + return query.evaluate_node(*this); + } + + PUGI__FN xpath_node_set xml_node::select_nodes(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return q.evaluate_node_set(*this); + } + + PUGI__FN xpath_node_set xml_node::select_nodes(const xpath_query& query) const + { + return query.evaluate_node_set(*this); + } + + PUGI__FN xpath_node xml_node::select_single_node(const char_t* query, xpath_variable_set* variables) const + { + xpath_query q(query, variables); + return q.evaluate_node(*this); + } + + PUGI__FN xpath_node xml_node::select_single_node(const xpath_query& query) const + { + return query.evaluate_node(*this); + } +} + +#endif + +#ifdef __BORLANDC__ +# pragma option pop +#endif + +// Intel C++ does not properly keep warning state for function templates, +// so popping warning state at the end of translation unit leads to warnings in the middle. +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) +# pragma warning(pop) +#endif + +#if defined(_MSC_VER) && defined(__c2__) +# pragma clang diagnostic pop +#endif + +// Undefine all local macros (makes sure we're not leaking macros in header-only mode) +#undef PUGI__NO_INLINE +#undef PUGI__UNLIKELY +#undef PUGI__STATIC_ASSERT +#undef PUGI__DMC_VOLATILE +#undef PUGI__UNSIGNED_OVERFLOW +#undef PUGI__MSVC_CRT_VERSION +#undef PUGI__SNPRINTF +#undef PUGI__NS_BEGIN +#undef PUGI__NS_END +#undef PUGI__FN +#undef PUGI__FN_NO_INLINE +#undef PUGI__GETHEADER_IMPL +#undef PUGI__GETPAGE_IMPL +#undef PUGI__GETPAGE +#undef PUGI__NODETYPE +#undef PUGI__IS_CHARTYPE_IMPL +#undef PUGI__IS_CHARTYPE +#undef PUGI__IS_CHARTYPEX +#undef PUGI__ENDSWITH +#undef PUGI__SKIPWS +#undef PUGI__OPTSET +#undef PUGI__PUSHNODE +#undef PUGI__POPNODE +#undef PUGI__SCANFOR +#undef PUGI__SCANWHILE +#undef PUGI__SCANWHILE_UNROLL +#undef PUGI__ENDSEG +#undef PUGI__THROW_ERROR +#undef PUGI__CHECK_ERROR + +#endif + +/** + * Copyright (c) 2006-2020 Arseny Kapoulkine + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ diff --git a/external/libdumper/source/sfo.cpp b/external/libdumper/source/sfo.cpp new file mode 100644 index 0000000..a66b9ce --- /dev/null +++ b/external/libdumper/source/sfo.cpp @@ -0,0 +1,515 @@ +// Copyright (c) 2021 Al Azif +// License: GPLv3 + +#include "sfo.hpp" +#include "common.hpp" + +#include +#include +#include +#include +#include +#include "log.h" +#include + +namespace sfo { +bool is_sfo(const std::string &path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path)) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream sfo_input(path, std::ios::in | std::ios::binary); + if (!sfo_input || !sfo_input.good()) { + sfo_input.close(); + log_error("Cannot open file: %s" ,path.c_str()); + } + + // Read SFO header + SfoHeader header; + sfo_input.read((char *)&header, sizeof(header)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + return false; + } + sfo_input.close(); + + // Compare magic + if (__builtin_bswap32(header.magic) == SFO_MAGIC) { + return true; + } + + return false; +} + +std::vector read(const std::string &path) { // Flawfinder: ignore + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + // Check if file exists and is file + if (!std::filesystem::is_regular_file(path)) { + log_error("Input path does not exist or is not a file!"); + } + + // Open path + std::ifstream sfo_input(path, std::ios::in | std::ios::binary); + if (!sfo_input || !sfo_input.good()) { + sfo_input.close(); + log_error("Cannot open file: %s",path.c_str()); + } + + // Check to make sure file is a SFO + if (!is_sfo(path)) { + sfo_input.close(); + log_error("Input path is not a SFO!"); + } + + // Read SFO header + SfoHeader header; + sfo_input.read((char *)&header, sizeof(header)); // Flawfinder: ignore + if (!sfo_input.good()) { + // Should never reach here... will affect coverage % + sfo_input.close(); + log_error("Error reading SFO header!"); + } + + std::vector data; + + // Read data + for (size_t i = 0; i < header.num_entries; i++) { + // Cannot just read sizeof(SfoData) as it includes a std::string value for key_name which is added in the next loop along with the actual data + SfoData temp_data; + sfo_input.read((char *)&temp_data.key_offset, sizeof(temp_data.key_offset)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading entry key offset!"); + } + sfo_input.read((char *)&temp_data.format, sizeof(temp_data.format)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading entry format!"); + } + sfo_input.read((char *)&temp_data.length, sizeof(temp_data.length)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading entry length!"); + } + sfo_input.read((char *)&temp_data.max_length, sizeof(temp_data.max_length)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading entry max length!"); + } + sfo_input.read((char *)&temp_data.data_offset, sizeof(temp_data.data_offset)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading entry data offset!"); + } + data.push_back(temp_data); + } + + // Read key names and data + for (auto &&entry : data) { + sfo_input.seekg(header.key_table_offset + entry.key_offset, sfo_input.beg); + std::getline(sfo_input, entry.key_name, '\0'); + + unsigned char buffer[entry.length]; + sfo_input.seekg(header.data_table_offset + entry.data_offset, sfo_input.beg); + sfo_input.read((char *)&buffer, sizeof(buffer)); // Flawfinder: ignore + if (!sfo_input.good()) { + sfo_input.close(); + log_error("Error reading data table!"); + } + + for (size_t i = 0; i < sizeof(buffer); i++) { + entry.data.push_back(buffer[i]); + } + } + sfo_input.close(); + + return data; +} + +std::vector get_keys(const std::vector &data) { + std::vector temp_key_list; + for (auto &&entry : data) { + temp_key_list.push_back(entry.key_name); + } + return temp_key_list; +} + +uint16_t get_format(const std::string &key, const std::vector &data) { + for (auto &&entry : data) { + if (entry.key_name == key) { + return entry.format; + } + } + log_error("Could not find key"); + return (uint16_t)NULL; +} + +uint32_t get_length(const std::string &key, const std::vector &data) { + for (auto &&entry : data) { + if (entry.key_name == key) { + return entry.length; + } + } + log_error("Could not find key"); + return (uint32_t)NULL; +} + + +uint32_t get_max_length(const std::string &key, const std::vector &data) { + for (auto &&entry : data) { + if (entry.key_name == key) { + return entry.max_length; + } + } + log_error("Could not find key"); + return (uint32_t)NULL; +} + +std::vector get_value(const std::string &key, const std::vector &data) { + std::vector buffer; + for (auto &&entry : data) { + if (entry.key_name == key) { + for (uint32_t i = 0; i < entry.length; i++) { + buffer.push_back(entry.data[i]); + } + } + } + log_error("Could not find key"); + return buffer; +} + +std::vector read_pubtool_data(const std::vector &data) { + std::vector sfo_keys = get_keys(data); + std::vector pubtool_data; + + if (std::count(sfo_keys.begin(), sfo_keys.end(), std::string("PUBTOOLINFO"))) { + std::vector pubtoolinfo_buffer = get_value("PUBTOOLINFO", data); + std::stringstream ss(std::string(pubtoolinfo_buffer.begin(), pubtoolinfo_buffer.end())); + + std::vector csv; + while (ss.good()) { + std::string substr; + getline(ss, substr, ','); + csv.push_back(substr); + } + + for (auto &&value : csv) { + SfoPubtoolinfoIndex temp_index; + temp_index.key_name = value.substr(0, value.find('=')); + temp_index.value = value.substr(value.find('=') + 1, value.size()); + pubtool_data.push_back(temp_index); + } + } + + return pubtool_data; +} + +std::vector get_pubtool_keys(const std::vector &data) { + std::vector temp_key_list; + for (auto &&entry : data) { + temp_key_list.push_back(entry.key_name); + } + return temp_key_list; +} + +std::string get_pubtool_value(const std::string &key, const std::vector &data) { + for (auto &&entry : data) { + if (entry.key_name == key) { + return entry.value; + } + } + log_error("Could not find key"); + return ""; +} + +SfoData build_data(const std::string &key_name, const std::string &format, uint32_t length, uint32_t max_length, const std::vector &data) { + SfoData new_data; + + new_data.key_name = key_name; + new_data.key_offset = 0; + new_data.data_offset = 0; + + // Calculate format value + if (format == "special") { + // Used in contents generated by the system (e.g.: save data) + new_data.format = 0x0004; + } else if (format == "utf-8") { + // Character string, NULL finished (0x00) + new_data.format = 0x0204; + } else if (format == "integer") { + // 32 bits unsigned + new_data.format = 0x0404; + } else { + log_error("Unknown SFO format type!"); + } + + if (length > max_length) { + log_error("Input `length` of SFO entry must be <= input `max_length`!"); + } + new_data.length = length; + new_data.max_length = max_length; + + if (data.size() > length) { + log_error("Input SFO data is larger than the `length`"); + } + new_data.data = data; + + return new_data; +} + +SfoPubtoolinfoIndex build_pubtool_data(const std::string &key, const std::string &value) { + SfoPubtoolinfoIndex new_data; + new_data.key_name = key; + new_data.value = value; + + return new_data; +} + +std::vector add_data(const SfoData &data_to_add, const std::vector ¤t_data) { + // Validate data_to_add + if (data_to_add.format != 0x0004 && data_to_add.format != 0x0204 && data_to_add.format != 0x0404) { + log_error("Unknown SFO format type!"); + } + if (data_to_add.length > data_to_add.max_length) { + log_error("Input `length` of SFO entry must be <= input `max_length`!"); + } + if (data_to_add.data.size() > data_to_add.length) { + log_error("Input SFO data is larger than the `length`"); + } + + // Remove existing key from current data and add new data + std::vector new_data = remove_key(data_to_add.key_name, current_data); + new_data.push_back(data_to_add); + + return new_data; +} + +std::vector add_pubtool_data(const SfoPubtoolinfoIndex &data_to_add, const std::vector ¤t_data) { + std::vector new_data = remove_pubtool_key(data_to_add.key_name, current_data); + std::vector pubtool_data = read_pubtool_data(new_data); + + std::vector new_value; + for (auto &&entry : pubtool_data) { + for (auto &&character : entry.key_name) { + new_value.push_back(character); + } + new_value.push_back('='); + for (auto &&character : entry.value) { + new_value.push_back(character); + } + new_value.push_back(','); + } + new_value.pop_back(); // Remove trailing comma + if (new_value.size() > 0x200) { + log_error("New PUBTOOLINFO key is too large (> 0x200)!"); + } + + SfoData new_entry = build_data("PUBTOOLINFO", "utf-8", new_value.size(), 0x200, new_value); + new_data = add_data(new_entry, new_data); + + return new_data; +} + +std::vector remove_key(const std::string &remove_key, const std::vector ¤t_data) { + std::vector new_data; + for (auto &&entry : current_data) { + if (entry.key_name != remove_key) { + new_data.push_back(entry); + } + } + + return new_data; +} + +std::vector remove_pubtool_key(const std::string &remove_key, const std::vector ¤t_data) { + std::vector sfo_keys = sfo::get_keys(current_data); + if (!std::count(sfo_keys.begin(), sfo_keys.end(), std::string("PUBTOOLINFO"))) { + return current_data; + } + + std::vector pubtool_data = read_pubtool_data(current_data); + std::vector new_pubtool_data; + + for (auto &&index : pubtool_data) { + if (index.key_name != remove_key) { + new_pubtool_data.push_back(index); + } + } + + std::vector new_value; + for (auto &&entry : new_pubtool_data) { + for (auto &&character : entry.key_name) { + new_value.push_back(character); + } + new_value.push_back('='); + for (auto &&character : entry.value) { + new_value.push_back(character); + } + new_value.push_back(','); + } + new_value.pop_back(); // Remove trailing comma + if (new_value.size() > 0x200) { + log_error("New PUBTOOLINFO key is too large (> 0x200)!"); + } + + SfoData new_entry = build_data("PUBTOOLINFO", "utf-8", new_value.size(), 0x200, new_value); + std::vector new_data = add_data(new_entry, current_data); + + return new_data; +} + +bool compare_sfo_date(SfoData data_1, SfoData data_2) { + return (data_1.key_name.compare(data_2.key_name) < 0); +} + +void write(const std::vector &data, const std::string &path) { + // Check for empty or pure whitespace path + if (path.empty() || std::all_of(path.begin(), path.end(), [](char c) { return std::isspace(c); })) { + log_error("Empty path argument!"); + } + + std::filesystem::path output_path(path); + + // Exists, but is not a file + if (std::filesystem::exists(output_path) && !std::filesystem::is_regular_file(output_path)) { + log_error("Output path exists, but is not a file!"); + } + + // Open path + std::ofstream output_file(output_path, std::ios::out | std::ios::trunc | std::ios::binary); + if (!output_file || !output_file.good()) { + output_file.close(); + log_error("Cannot open output file: %s",path.c_str()); + } + + // Check for duplicate key_name + for (size_t i = 0; i < data.size(); i++) { + for (size_t j = 0; j < data.size(); j++) { + if (i != j && data[i].key_name == data[j].key_name) { + log_error("Duplicate key name found in SFO!"); + } + } + } + + // Validate/Standardize data + std::vector new_data; + for (auto &&entry : data) { + if (entry.format != 0x0004 && entry.format != 0x0204 && entry.format != 0x0404) { + output_file.close(); + log_error("Unknown SFO format type!"); + } + if (entry.length > entry.max_length) { + output_file.close(); + log_error("Input `length` of SFO entry must be <= input `max_length`!"); + } + if (entry.data.size() > entry.length) { + output_file.close(); + log_error("Input SFO data is larger than the `length`"); + } + + SfoData temp_data = entry; + temp_data.key_offset = 0; + temp_data.data_offset = 0; + + new_data.push_back(temp_data); + } + + // Alphabetize new_data by key_name + std::sort(new_data.begin(), new_data.end(), compare_sfo_date); + + // Calculate file offsets + uint16_t total_key_offset = 0; + uint32_t total_data_offset = 0; + + // Calculate key and data table offsets + for (auto &&entry : new_data) { + entry.key_offset = total_key_offset; + total_key_offset += entry.key_name.size(); + total_key_offset++; // Null terminator + + entry.data_offset = total_data_offset; + total_data_offset += entry.max_length; + } + + // Add alignment bytes + while (total_key_offset % 0x4 != 0) { + total_key_offset++; + } + + // Build header + SfoHeader header; + header.magic = __builtin_bswap32(SFO_MAGIC); + header.version = 0x00000101; + header.key_table_offset = new_data.size() * 0x10 + sizeof(header); + header.data_table_offset = header.key_table_offset + total_key_offset; + header.num_entries = new_data.size(); + + // Create stringstream + std::stringstream ss; + + // Write header to stringstream + ss.write(reinterpret_cast(&header), sizeof(header)); + + // Write index to stringstream + for (auto &&entry : new_data) { + ss.write(reinterpret_cast(&entry.key_offset), sizeof(entry.key_offset)); + ss.write(reinterpret_cast(&entry.format), sizeof(entry.format)); + ss.write(reinterpret_cast(&entry.length), sizeof(entry.length)); + ss.write(reinterpret_cast(&entry.max_length), sizeof(entry.max_length)); + ss.write(reinterpret_cast(&entry.data_offset), sizeof(entry.data_offset)); + } + + // Build key table + std::vector key_table; + for (auto &&entry : new_data) { + for (size_t i = 0; i < entry.key_name.size(); i++) { + key_table.insert(key_table.begin() + entry.key_offset + i, entry.key_name[i]); + if (i == entry.key_name.size() - 1) { + key_table.insert(key_table.begin() + entry.key_offset + i + 1, '\0'); + } + } + } + + // Add alignment bytes to key table + while (key_table.size() % 0x4 != 0) { + key_table.push_back('\0'); + } + + // Write key table to stringstream + for (auto &&entry : key_table) { + ss.write(reinterpret_cast(&entry), sizeof(entry)); + } + + // Build data table + std::vector data_table; + for (auto &&entry : new_data) { + for (size_t i = 0; i < entry.max_length; i++) { + if (i < entry.length) { + data_table.insert(data_table.begin() + entry.data_offset + i, entry.data[i]); + } else { + data_table.insert(data_table.begin() + entry.data_offset + i, '\0'); + } + } + } + + // Write data table to stringstream + for (auto &&entry : data_table) { + ss.write(reinterpret_cast(&entry), sizeof(entry)); + } + + // Write streamstream to output file + output_file << ss.rdbuf(); + output_file.close(); +} +} // namespace sfo diff --git a/external/libfuse/Makefile b/external/libfuse/Makefile new file mode 100644 index 0000000..d843efb --- /dev/null +++ b/external/libfuse/Makefile @@ -0,0 +1,22 @@ +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target := ps4_lib +OutPath := lib +TargetFile := libfuse +AllTarget = $(OutPath)/$(TargetFile).a + +include $(ORBISDEV)/make/ps4sdklib.mk +CompilerFlags += -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -D__ORBIS__=1 -D_ORBIS_ -D__FreeBSD__=9 -DNDEBUG -D_BSD_SOURCE -fexceptions -frtti +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -Iinclude + + +$(OutPath)/$(TargetFile).a: $(ObjectFiles) + $(dirp) + $(archive) + +install: + @cp $(OutPath)/$(TargetFile).a $(DESTDIR)$(ORBISDEV)/usr/lib + @echo "$(TargetFile) Installed!" + diff --git a/external/libfuse/include/Makefile.am b/external/libfuse/include/Makefile.am new file mode 100644 index 0000000..663e164 --- /dev/null +++ b/external/libfuse/include/Makefile.am @@ -0,0 +1,17 @@ +## Process this file with automake to produce Makefile.in + +fuseincludedir=$(includedir)/fuse + +fuseinclude_HEADERS = \ + fuse.h \ + fuse_compat.h \ + fuse_common.h \ + fuse_common_compat.h \ + fuse_lowlevel.h \ + fuse_lowlevel_compat.h \ + fuse_opt.h \ + cuse_lowlevel.h + +include_HEADERS = old/fuse.h ulockmgr.h + +noinst_HEADERS = fuse_kernel.h diff --git a/external/libfuse/include/Makefile.in b/external/libfuse/include/Makefile.in new file mode 100644 index 0000000..7cbd333 --- /dev/null +++ b/external/libfuse/include/Makefile.in @@ -0,0 +1,516 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = include +DIST_COMMON = $(fuseinclude_HEADERS) $(include_HEADERS) \ + $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(fuseincludedir)" \ + "$(DESTDIR)$(includedir)" +HEADERS = $(fuseinclude_HEADERS) $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INIT_D_PATH = @INIT_D_PATH@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MOUNT_FUSE_PATH = @MOUNT_FUSE_PATH@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UDEV_RULES_PATH = @UDEV_RULES_PATH@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libfuse_libs = @libfuse_libs@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs2 = @subdirs2@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +fuseincludedir = $(includedir)/fuse +fuseinclude_HEADERS = \ + fuse.h \ + fuse_compat.h \ + fuse_common.h \ + fuse_common_compat.h \ + fuse_lowlevel.h \ + fuse_lowlevel_compat.h \ + fuse_opt.h \ + cuse_lowlevel.h + +include_HEADERS = old/fuse.h ulockmgr.h +noinst_HEADERS = fuse_kernel.h +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status include/config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-fuseincludeHEADERS: $(fuseinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(fuseincludedir)" || $(MKDIR_P) "$(DESTDIR)$(fuseincludedir)" + @list='$(fuseinclude_HEADERS)'; test -n "$(fuseincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(fuseincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(fuseincludedir)" || exit $$?; \ + done + +uninstall-fuseincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(fuseinclude_HEADERS)'; test -n "$(fuseincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(fuseincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(fuseincludedir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) config.h +installdirs: + for dir in "$(DESTDIR)$(fuseincludedir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-fuseincludeHEADERS install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-fuseincludeHEADERS uninstall-includeHEADERS + +.MAKE: all install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-fuseincludeHEADERS install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-fuseincludeHEADERS \ + uninstall-includeHEADERS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/external/libfuse/include/config.h b/external/libfuse/include/config.h new file mode 100644 index 0000000..b914b0e --- /dev/null +++ b/external/libfuse/include/config.h @@ -0,0 +1,90 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `setxattr' function. */ +/* #undef HAVE_SETXATTR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `st_atim' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_ATIM */ + +/* Define to 1 if `st_atimespec' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_ATIMESPEC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST const + +/* Don't update /etc/mtab */ +/* #undef IGNORE_MTAB */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "fuse" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "fuse" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "fuse 2.8.6" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "fuse" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.8.6" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "2.8.6" diff --git a/external/libfuse/include/config.h.in b/external/libfuse/include/config.h.in new file mode 100644 index 0000000..4181f89 --- /dev/null +++ b/external/libfuse/include/config.h.in @@ -0,0 +1,89 @@ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `fdatasync' function. */ +#undef HAVE_FDATASYNC + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `setxattr' function. */ +#undef HAVE_SETXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if `st_atim' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_ATIM + +/* Define to 1 if `st_atimespec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_ATIMESPEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Don't update /etc/mtab */ +#undef IGNORE_MTAB + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/external/libfuse/include/cuse_lowlevel.h b/external/libfuse/include/cuse_lowlevel.h new file mode 100644 index 0000000..e147fa2 --- /dev/null +++ b/external/libfuse/include/cuse_lowlevel.h @@ -0,0 +1,87 @@ +/* + CUSE: Character device in Userspace + Copyright (C) 2008-2009 SUSE Linux Products GmbH + Copyright (C) 2008-2009 Tejun Heo + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. + + Read example/cusexmp.c for usages. +*/ + +#ifndef _CUSE_LOWLEVEL_H_ +#define _CUSE_LOWLEVEL_H_ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 29 +#endif + +#include "fuse_lowlevel.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) /* use unrestricted ioctl */ + +struct fuse_session; + +struct cuse_info { + unsigned dev_major; + unsigned dev_minor; + unsigned dev_info_argc; + const char **dev_info_argv; + unsigned flags; +}; + +/* + * Most ops behave almost identically to the matching fuse_lowlevel + * ops except that they don't take @ino. + * + * init_done : called after initialization is complete + * read/write : always direct IO, simultaneous operations allowed + * ioctl : might be in unrestricted mode depending on ci->flags + */ +struct cuse_lowlevel_ops { + void (*init) (void *userdata, struct fuse_conn_info *conn); + void (*init_done) (void *userdata); + void (*destroy) (void *userdata); + void (*open) (fuse_req_t req, struct fuse_file_info *fi); + void (*read) (fuse_req_t req, size_t size, off_t off, + struct fuse_file_info *fi); + void (*write) (fuse_req_t req, const char *buf, size_t size, off_t off, + struct fuse_file_info *fi); + void (*flush) (fuse_req_t req, struct fuse_file_info *fi); + void (*release) (fuse_req_t req, struct fuse_file_info *fi); + void (*fsync) (fuse_req_t req, int datasync, struct fuse_file_info *fi); + void (*ioctl) (fuse_req_t req, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz); + void (*poll) (fuse_req_t req, struct fuse_file_info *fi, + struct fuse_pollhandle *ph); +}; + +struct fuse_session *cuse_lowlevel_new(struct fuse_args *args, + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + void *userdata); + +struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + int *multithreaded, void *userdata); + +void cuse_lowlevel_teardown(struct fuse_session *se); + +int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif /* _CUSE_LOWLEVEL_H_ */ diff --git a/external/libfuse/include/fuse.h b/external/libfuse/include/fuse.h new file mode 100644 index 0000000..d60d0d2 --- /dev/null +++ b/external/libfuse/include/fuse.h @@ -0,0 +1,951 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_H_ +#define _FUSE_H_ + +/** @file + * + * This file defines the library interface of FUSE + * + * IMPORTANT: you should define FUSE_USE_VERSION before including this + * header. To use the newest API define it to 26 (recommended for any + * new application), to use the old API define it to 21 (default) 22 + * or 25, to use the even older 1.X API define it to 11. + */ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 21 +#endif + +#include "fuse_common.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------- * + * Basic FUSE API * + * ----------------------------------------------------------- */ + +/** Handle for a FUSE filesystem */ +struct fuse; + +/** Structure containing a raw command */ +struct fuse_cmd; + +/** Function to add an entry in a readdir() operation + * + * @param buf the buffer passed to the readdir() operation + * @param name the file name of the directory entry + * @param stat file attributes, can be NULL + * @param off offset of the next entry or zero + * @return 1 if buffer is full, zero otherwise + */ +typedef int (*fuse_fill_dir_t) (void *buf, const char *name, + const struct stat *stbuf, off_t off); + +/* Used by deprecated getdir() method */ +typedef struct fuse_dirhandle *fuse_dirh_t; +typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type, + ino_t ino); + +/** + * The file system operations: + * + * Most of these should work very similarly to the well known UNIX + * file system operations. A major exception is that instead of + * returning an error in 'errno', the operation should return the + * negated error value (-errno) directly. + * + * All methods are optional, but some are essential for a useful + * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, + * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, + * init and destroy are special purpose methods, without which a full + * featured filesystem can still be implemented. + * + * Almost all operations take a path which can be of any length. + * + * Changed in fuse 2.8.0 (regardless of API version) + * Previously, paths were limited to a length of PATH_MAX. + * + * See http://fuse.sourceforge.net/wiki/ for more information. There + * is also a snapshot of the relevant wiki pages in the doc/ folder. + */ +struct fuse_operations { + /** Get file attributes. + * + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are + * ignored. The 'st_ino' field is ignored except if the 'use_ino' + * mount option is given. + */ + int (*getattr) (const char *, struct stat *); + + /** Read the target of a symbolic link + * + * The buffer should be filled with a null terminated string. The + * buffer size argument includes the space for the terminating + * null character. If the linkname is too long to fit in the + * buffer, it should be truncated. The return value should be 0 + * for success. + */ + int (*readlink) (const char *, char *, size_t); + + /* Deprecated, use readdir() instead */ + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + + /** Create a file node + * + * This is called for creation of all non-directory, non-symlink + * nodes. If the filesystem defines a create() method, then for + * regular files that will be called instead. + */ + int (*mknod) (const char *, mode_t, dev_t); + + /** Create a directory + * + * Note that the mode argument may not have the type specification + * bits set, i.e. S_ISDIR(mode) can be false. To obtain the + * correct directory type bits use mode|S_IFDIR + * */ + int (*mkdir) (const char *, mode_t); + + /** Remove a file */ + int (*unlink) (const char *); + + /** Remove a directory */ + int (*rmdir) (const char *); + + /** Create a symbolic link */ + int (*symlink) (const char *, const char *); + + /** Rename a file */ + int (*rename) (const char *, const char *); + + /** Create a hard link to a file */ + int (*link) (const char *, const char *); + + /** Change the permission bits of a file */ + int (*chmod) (const char *, mode_t); + + /** Change the owner and group of a file */ + int (*chown) (const char *, uid_t, gid_t); + + /** Change the size of a file */ + int (*truncate) (const char *, off_t); + + /** Change the access and/or modification times of a file + * + * Deprecated, use utimens() instead. + */ + int (*utime) (const char *, struct utimbuf *); + + /** File open operation + * + * No creation (O_CREAT, O_EXCL) and by default also no + * truncation (O_TRUNC) flags will be passed to open(). If an + * application specifies O_TRUNC, fuse first calls truncate() + * and then open(). Only if 'atomic_o_trunc' has been + * specified and kernel version is 2.6.24 or later, O_TRUNC is + * passed on to open. + * + * Unless the 'default_permissions' mount option is given, + * open should check if the operation is permitted for the + * given flags. Optionally open may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to all file operations. + * + * Changed in version 2.2 + */ + int (*open) (const char *, struct fuse_file_info *); + + /** Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 + */ + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info *); + + /** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info *); + + /** Get file system statistics + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + * + * Replaced 'struct statfs' parameter with 'struct statvfs' in + * version 2.5 + */ + int (*statfs) (const char *, struct statvfs *); + + /** Possibly flush cached data + * + * BIG NOTE: This is not equivalent to fsync(). It's not a + * request to sync dirty data. + * + * Flush is called on each close() of a file descriptor. So if a + * filesystem wants to return write errors in close() and the file + * has cached dirty data, this is a good place to write back data + * and return any errors. Since many applications ignore close() + * errors this is not always useful. + * + * NOTE: The flush() method may be called more than once for each + * open(). This happens if more than one file descriptor refers + * to an opened file due to dup(), dup2() or fork() calls. It is + * not possible to determine if a flush is final, so each flush + * should be treated equally. Multiple write-flush sequences are + * relatively rare, so this shouldn't be a problem. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * Changed in version 2.2 + */ + int (*flush) (const char *, struct fuse_file_info *); + + /** Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + * + * Changed in version 2.2 + */ + int (*release) (const char *, struct fuse_file_info *); + + /** Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Changed in version 2.2 + */ + int (*fsync) (const char *, int, struct fuse_file_info *); + + /** Set extended attributes */ + int (*setxattr) (const char *, const char *, const char *, size_t, int); + + /** Get extended attributes */ + int (*getxattr) (const char *, const char *, char *, size_t); + + /** List extended attributes */ + int (*listxattr) (const char *, char *, size_t); + + /** Remove extended attributes */ + int (*removexattr) (const char *, const char *); + + /** Open directory + * + * Unless the 'default_permissions' mount option is given, + * this method should check if opendir is permitted for this + * directory. Optionally opendir may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to readdir, closedir and fsyncdir. + * + * Introduced in version 2.3 + */ + int (*opendir) (const char *, struct fuse_file_info *); + + /** Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. + * + * The filesystem may choose between two modes of operation: + * + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. + * + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + * + * Introduced in version 2.3 + */ + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info *); + + /** Release directory + * + * Introduced in version 2.3 + */ + int (*releasedir) (const char *, struct fuse_file_info *); + + /** Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data + * + * Introduced in version 2.3 + */ + int (*fsyncdir) (const char *, int, struct fuse_file_info *); + + /** + * Initialize filesystem + * + * The return value will passed in the private_data field of + * fuse_context to all file operations and as a parameter to the + * destroy() method. + * + * Introduced in version 2.3 + * Changed in version 2.6 + */ + void *(*init) (struct fuse_conn_info *conn); + + /** + * Clean up filesystem + * + * Called on filesystem exit. + * + * Introduced in version 2.3 + */ + void (*destroy) (void *); + + /** + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 + */ + int (*access) (const char *, int); + + /** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + */ + int (*create) (const char *, mode_t, struct fuse_file_info *); + + /** + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the truncate() method will be + * called instead. + * + * Introduced in version 2.5 + */ + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); + + /** + * Get attributes from an open file + * + * This method is called instead of the getattr() method if the + * file information is available. + * + * Currently this is only called after the create() method if that + * is implemented (see above). Later it may be called for + * invocations of fstat() too. + * + * Introduced in version 2.5 + */ + int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); + + /** + * Perform POSIX file locking operation + * + * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. + * + * For the meaning of fields in 'struct flock' see the man page + * for fcntl(2). The l_whence field will always be set to + * SEEK_SET. + * + * For checking lock ownership, the 'fuse_file_info->owner' + * argument must be used. + * + * For F_GETLK operation, the library will first check currently + * held locks, and if a conflicting lock is found it will return + * information without calling this method. This ensures, that + * for local locks the l_pid field is correctly filled in. The + * results may not be accurate in case of race conditions and in + * the presence of hard links, but it's unlikly that an + * application would rely on accurate GETLK results in these + * cases. If a conflicting lock is not found, this method will be + * called, and the filesystem may fill out l_pid by a meaningful + * value, or it may leave this field zero. + * + * For F_SETLK and F_SETLKW the l_pid field will be set to the pid + * of the process performing the locking operation. + * + * Note: if this method is not implemented, the kernel will still + * allow file locking to work locally. Hence it is only + * interesting for network filesystems and similar. + * + * Introduced in version 2.6 + */ + int (*lock) (const char *, struct fuse_file_info *, int cmd, + struct flock *); + + /** + * Change the access and modification times of a file with + * nanosecond resolution + * + * Introduced in version 2.6 + */ + int (*utimens) (const char *, const struct timespec tv[2]); + + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 + */ + int (*bmap) (const char *, size_t blocksize, uint64_t *idx); + + /** + * Flag indicating, that the filesystem can accept a NULL path + * as the first argument for the following operations: + * + * read, write, flush, release, fsync, readdir, releasedir, + * fsyncdir, ftruncate, fgetattr and lock + */ + unsigned int flag_nullpath_ok : 1; + + /** + * Reserved flags, don't set + */ + unsigned int flag_reserved : 31; + + /** + * Ioctl + * + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in + * 64bit environment. The size and direction of data is + * determined by _IOC_*() decoding of cmd. For _IOC_NONE, + * data will be NULL, for _IOC_WRITE data is out area, for + * _IOC_READ in area and if both are set in/out area. In all + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. + * + * Introduced in version 2.8 + */ + int (*ioctl) (const char *, int cmd, void *arg, + struct fuse_file_info *, unsigned int flags, void *data); + + /** + * Poll for IO readiness events + * + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Introduced in version 2.8 + */ + int (*poll) (const char *, struct fuse_file_info *, + struct fuse_pollhandle *ph, unsigned *reventsp); +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + void (*mount_done) (int); +}; + +/** Extra context that may be needed by some filesystems + * + * The uid, gid and pid fields are not filled in case of a writepage + * operation. + */ +struct fuse_context { + /** Pointer to the fuse object */ + struct fuse *fuse; + + /** User ID of the calling process */ + uid_t uid; + + /** Group ID of the calling process */ + gid_t gid; + + /** Thread ID of the calling process */ + pid_t pid; + + /** Private filesystem data */ + void *private_data; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +}; + +/** + * Main function of FUSE. + * + * This is for the lazy. This is all that has to be called from the + * main() function. + * + * This function does the following: + * - parses command line options (-d -s and -h) + * - passes relevant mount options to the fuse_mount() + * - installs signal handlers for INT, HUP, TERM and PIPE + * - registers an exit handler to unmount the filesystem on program exit + * - creates a fuse handle + * - registers the operations + * - calls either the single-threaded or the multi-threaded event loop + * + * Note: this is currently implemented as a macro. + * + * @param argc the argument counter passed to the main() function + * @param argv the argument vector passed to the main() function + * @param op the file system operation + * @param user_data user data supplied in the context during the init() method + * @return 0 on success, nonzero on failure + */ +/* + int fuse_main(int argc, char *argv[], const struct fuse_operations *op, + void *user_data); +*/ +#define fuse_main(argc, argv, op, user_data) \ + fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) + +/* ----------------------------------------------------------- * + * More detailed API * + * ----------------------------------------------------------- */ + +/** + * Create a new FUSE filesystem. + * + * @param ch the communication channel + * @param args argument vector + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return the created FUSE handle + */ +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, size_t op_size, + void *user_data); + +/** + * Destroy the FUSE handle. + * + * The communication channel attached to the handle is also destroyed. + * + * NOTE: This function does not unmount the filesystem. If this is + * needed, call fuse_unmount() before calling this function. + * + * @param f the FUSE handle + */ +void fuse_destroy(struct fuse *f); + +/** + * FUSE event loop. + * + * Requests from the kernel are processed, and the appropriate + * operations are called. + * + * @param f the FUSE handle + * @return 0 if no error occurred, -1 otherwise + */ +int fuse_loop(struct fuse *f); + +/** + * Exit from event loop + * + * @param f the FUSE handle + */ +void fuse_exit(struct fuse *f); + +/** + * FUSE event loop with multiple threads + * + * Requests from the kernel are processed, and the appropriate + * operations are called. Request are processed in parallel by + * distributing them between multiple threads. + * + * Calling this function requires the pthreads library to be linked to + * the application. + * + * @param f the FUSE handle + * @return 0 if no error occurred, -1 otherwise + */ +int fuse_loop_mt(struct fuse *f); +void libfuse_print(char* format, ...); + +/** + * Get the current context + * + * The context is only valid for the duration of a filesystem + * operation, and thus must not be stored and used later. + * + * @return the context + */ +struct fuse_context *fuse_get_context(void); + +/** + * Get the current supplementary group IDs for the current request + * + * Similar to the getgroups(2) system call, except the return value is + * always the total number of group IDs, even if it is larger than the + * specified size. + * + * The current fuse kernel module in linux (as of 2.6.30) doesn't pass + * the group list to userspace, hence this function needs to parse + * "/proc/$TID/task/$TID/status" to get the group IDs. + * + * This feature may not be supported on all operating systems. In + * such a case this function will return -ENOSYS. + * + * @param size size of given array + * @param list array of group IDs to be filled in + * @return the total number of supplementary group IDs or -errno on failure + */ +int fuse_getgroups(int size, gid_t list[]); + +/** + * Check if the current request has already been interrupted + * + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_interrupted(void); + +/** + * Obsolete, doesn't do anything + * + * @return -EINVAL + */ +int fuse_invalidate(struct fuse *f, const char *path); + +/* Deprecated, don't use */ +int fuse_is_lib_option(const char *opt); + +/** + * The real main function + * + * Do not call this directly, use fuse_main() + */ +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, + size_t op_size, void *user_data); + +/* + * Stacking API + */ + +/** + * Fuse filesystem object + * + * This is opaque object represents a filesystem layer + */ +struct fuse_fs; + +/* + * These functions call the relevant filesystem operation, and return + * the result. + * + * If the operation is not defined, they return -ENOSYS, with the + * exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir, + * fuse_fs_releasedir and fuse_fs_statfs, which return 0. + */ + +int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf); +int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf, + struct fuse_file_info *fi); +int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, + const char *newpath); +int fuse_fs_unlink(struct fuse_fs *fs, const char *path); +int fuse_fs_rmdir(struct fuse_fs *fs, const char *path); +int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, + const char *path); +int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath); +int fuse_fs_release(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_open(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size, + off_t off, struct fuse_file_info *fi); +int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); +int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi); +int fuse_fs_flush(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf); +int fuse_fs_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, + fuse_fill_dir_t filler, off_t off, + struct fuse_file_info *fi); +int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi); +int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, + struct fuse_file_info *fi); +int fuse_fs_lock(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, int cmd, struct flock *lock); +int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid); +int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size); +int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size, + struct fuse_file_info *fi); +int fuse_fs_utimens(struct fuse_fs *fs, const char *path, + const struct timespec tv[2]); +int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask); +int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, + size_t len); +int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, + dev_t rdev); +int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, + const char *value, size_t size, int flags); +int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, + char *value, size_t size); +int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, + size_t size); +int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, + const char *name); +int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, + uint64_t *idx); +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, void *data); +int fuse_fs_poll(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, struct fuse_pollhandle *ph, + unsigned *reventsp); +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); +void fuse_fs_destroy(struct fuse_fs *fs); + +int fuse_notify_poll(struct fuse_pollhandle *ph); + +/** + * Create a new fuse filesystem object + * + * This is usually called from the factory of a fuse module to create + * a new instance of a filesystem. + * + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return a new filesystem object + */ +struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, + void *user_data); + +/** + * Filesystem module + * + * Filesystem modules are registered with the FUSE_REGISTER_MODULE() + * macro. + * + * If the "-omodules=modname:..." option is present, filesystem + * objects are created and pushed onto the stack with the 'factory' + * function. + */ +struct fuse_module { + /** + * Name of filesystem + */ + const char *name; + + /** + * Factory for creating filesystem objects + * + * The function may use and remove options from 'args' that belong + * to this module. + * + * For now the 'fs' vector always contains exactly one filesystem. + * This is the filesystem which will be below the newly created + * filesystem in the stack. + * + * @param args the command line arguments + * @param fs NULL terminated filesystem object vector + * @return the new filesystem object + */ + struct fuse_fs *(*factory)(struct fuse_args *args, + struct fuse_fs *fs[]); + + struct fuse_module *next; + struct fusemod_so *so; + int ctr; +}; + +/** + * Register a filesystem module + * + * This function is used by FUSE_REGISTER_MODULE and there's usually + * no need to call it directly + */ +void fuse_register_module(struct fuse_module *mod); + +/** + * Register filesystem module + * + * For the parameters, see description of the fields in 'struct + * fuse_module' + */ +#define FUSE_REGISTER_MODULE(name_, factory_) \ + static __attribute__((constructor)) void name_ ## _register(void) \ + { \ + static struct fuse_module mod = \ + { #name_, factory_, NULL, NULL, 0 }; \ + fuse_register_module(&mod); \ + } + + +/* ----------------------------------------------------------- * + * Advanced API for event handling, don't worry about this... * + * ----------------------------------------------------------- */ + +/* NOTE: the following functions are deprecated, and will be removed + from the 3.0 API. Use the lowlevel session functions instead */ + +/** Function type used to process commands */ +typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *); + +/** This is the part of fuse_main() before the event loop */ +struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + char **mountpoint, int *multithreaded, + void *user_data); + +/** This is the part of fuse_main() after the event loop */ +void fuse_teardown(struct fuse *fuse, char *mountpoint); + +/** Read a single command. If none are read, return NULL */ +struct fuse_cmd *fuse_read_cmd(struct fuse *f); + +/** Process a single command */ +void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd); + +/** Multi threaded event loop, which calls the custom command + processor function */ +int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); + +/** Return the exited flag, which indicates if fuse_exit() has been + called */ +int fuse_exited(struct fuse *f); + +/** This function is obsolete and implemented as a no-op */ +void fuse_set_getcontext_func(struct fuse_context *(*func)(void)); + +/** Get session from fuse object */ +struct fuse_session *fuse_get_session(struct fuse *f); + +/* ----------------------------------------------------------- * + * Compatibility stuff * + * ----------------------------------------------------------- */ + +#if FUSE_USE_VERSION < 26 +# include "fuse_compat.h" +# undef fuse_main +# if FUSE_USE_VERSION == 25 +# define fuse_main(argc, argv, op) \ + fuse_main_real_compat25(argc, argv, op, sizeof(*(op))) +# define fuse_new fuse_new_compat25 +# define fuse_setup fuse_setup_compat25 +# define fuse_teardown fuse_teardown_compat22 +# define fuse_operations fuse_operations_compat25 +# elif FUSE_USE_VERSION == 22 +# define fuse_main(argc, argv, op) \ + fuse_main_real_compat22(argc, argv, op, sizeof(*(op))) +# define fuse_new fuse_new_compat22 +# define fuse_setup fuse_setup_compat22 +# define fuse_teardown fuse_teardown_compat22 +# define fuse_operations fuse_operations_compat22 +# define fuse_file_info fuse_file_info_compat +# elif FUSE_USE_VERSION == 24 +# error Compatibility with high-level API version 24 not supported +# else +# define fuse_dirfil_t fuse_dirfil_t_compat +# define __fuse_read_cmd fuse_read_cmd +# define __fuse_process_cmd fuse_process_cmd +# define __fuse_loop_mt fuse_loop_mt_proc +# if FUSE_USE_VERSION == 21 +# define fuse_operations fuse_operations_compat2 +# define fuse_main fuse_main_compat2 +# define fuse_new fuse_new_compat2 +# define __fuse_setup fuse_setup_compat2 +# define __fuse_teardown fuse_teardown_compat22 +# define __fuse_exited fuse_exited +# define __fuse_set_getcontext_func fuse_set_getcontext_func +# else +# define fuse_statfs fuse_statfs_compat1 +# define fuse_operations fuse_operations_compat1 +# define fuse_main fuse_main_compat1 +# define fuse_new fuse_new_compat1 +# define FUSE_DEBUG FUSE_DEBUG_COMPAT1 +# endif +# endif +#endif +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +/* ----------------------------------------------------------- * + * For DRFP * + * ------------------------------------------------------------*/ +#define DRFP_MNTDONE_RELATIVE (1) +#define DRFP_MNTDONE_ABSOLUTE (2) + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_H_ */ diff --git a/external/libfuse/include/fuse_common.h b/external/libfuse/include/fuse_common.h new file mode 100644 index 0000000..f7bf2e4 --- /dev/null +++ b/external/libfuse/include/fuse_common.h @@ -0,0 +1,311 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/** @file */ + +#if !defined(_FUSE_H_) && !defined(_FUSE_LOWLEVEL_H_) +#error "Never include directly; use or instead." +#endif + +#ifndef _FUSE_COMMON_H_ +#define _FUSE_COMMON_H_ + +#include "fuse_opt.h" +#include + +/** Major version of FUSE library interface */ +#define FUSE_MAJOR_VERSION 2 + +/** Minor version of FUSE library interface */ +#define FUSE_MINOR_VERSION 8 + +#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) +#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) + +/* This interface uses 64 bit off_t */ +#if _FILE_OFFSET_BITS != 64 +#error Please add -D_FILE_OFFSET_BITS=64 to your compile flags! +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Information about open files + * + * Changed in version 2.5 + */ +struct fuse_file_info { + /** Open flags. Available in open() and release() */ + int flags; + + /** Old file handle, don't use */ + unsigned long fh_old; + + /** In case of a write operation indicates if this was caused by a + writepage */ + int writepage; + + /** Can be filled in by open, to use direct I/O on this file. + Introduced in version 2.4 */ + unsigned int direct_io : 1; + + /** Can be filled in by open, to indicate, that cached file data + need not be invalidated. Introduced in version 2.4 */ + unsigned int keep_cache : 1; + + /** Indicates a flush operation. Set in flush operation, also + maybe set in highlevel lock operation and lowlevel release + operation. Introduced in version 2.6 */ + unsigned int flush : 1; + + /** Can be filled in by open, to indicate that the file is not + seekable. Introduced in version 2.8 */ + unsigned int nonseekable : 1; + +/* +Modified by Y.ITO, 07/27/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /** Padding. Do not use*/ + unsigned int padding : 12; + + /** Known count to be issued with the same read size */ + unsigned int ra_hint : 8; + + /** heuristic from vfs */ + unsigned int seq_count : 8; + + /** File handle. May be filled in by filesystem in open(). + Available in all other file operations */ + uint64_t fh; + + /** Lock owner id. Available in locking operations and flush */ + uint64_t lock_owner; +}; + +/** + * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' + * + * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests + * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking + * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag + * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB + * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations + */ +#define FUSE_CAP_ASYNC_READ (1 << 0) +#define FUSE_CAP_POSIX_LOCKS (1 << 1) +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) +#define FUSE_CAP_BIG_WRITES (1 << 5) +#define FUSE_CAP_DONT_MASK (1 << 6) + +/** + * Ioctl flags + * + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed + * FUSE_IOCTL_RETRY: retry with new iovecs + * + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs + */ +#define FUSE_IOCTL_COMPAT (1 << 0) +#define FUSE_IOCTL_UNRESTRICTED (1 << 1) +#define FUSE_IOCTL_RETRY (1 << 2) + +#define FUSE_IOCTL_MAX_IOV 256 + +/** + * Connection information, passed to the ->init() method + * + * Some of the elements are read-write, these can be changed to + * indicate the value requested by the filesystem. The requested + * value must usually be smaller than the indicated value. + */ +struct fuse_conn_info { + /** + * Major version of the protocol (read-only) + */ + unsigned proto_major; + + /** + * Minor version of the protocol (read-only) + */ + unsigned proto_minor; + + /** + * Is asynchronous read supported (read-write) + */ + unsigned async_read; + + /** + * Maximum size of the write buffer + */ + unsigned max_write; + + /** + * Maximum readahead + */ + unsigned max_readahead; + + /** + * Capability flags, that the kernel supports + */ + unsigned capable; + + /** + * Capability flags, that the filesystem wants to enable + */ + unsigned want; + + /** + * For future use. + */ + unsigned reserved[25]; +}; + +struct fuse_session; +struct fuse_chan; +struct fuse_pollhandle; + +/** + * Create a FUSE mountpoint + * + * Returns a control file descriptor suitable for passing to + * fuse_new() + * + * @param mountpoint the mount point path + * @param args argument vector + * @return the communication channel on success, NULL on failure + */ +struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args); + +/** + * Umount a FUSE mountpoint + * + * @param mountpoint the mount point path + * @param ch the communication channel + */ +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); + +/** + * Parse common options + * + * The following options are parsed: + * + * '-f' foreground + * '-d' '-odebug' foreground, but keep the debug option + * '-s' single threaded + * '-h' '--help' help + * '-ho' help without header + * '-ofsname=..' file system name, if not present, then set to the program + * name + * + * All parameters may be NULL + * + * @param args argument vector + * @param mountpoint the returned mountpoint, should be freed after use + * @param multithreaded set to 1 unless the '-s' option is present + * @param foreground set to 1 if one of the relevant options is present + * @return 0 on success, -1 on failure + */ +int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, + int *multithreaded, int *foreground); + +/** + * Go into the background + * + * @param foreground if true, stay in the foreground + * @return 0 on success, -1 on failure + */ +int fuse_daemonize(int foreground); + +/** + * Get the version of the library + * + * @return the version + */ +int fuse_version(void); + +/** + * Destroy poll handle + * + * @param ph the poll handle + */ +void fuse_pollhandle_destroy(struct fuse_pollhandle *ph); + +/* ----------------------------------------------------------- * + * Signal handling * + * ----------------------------------------------------------- */ + +/** + * Exit session on HUP, TERM and INT signals and ignore PIPE signal + * + * Stores session in a global variable. May only be called once per + * process until fuse_remove_signal_handlers() is called. + * + * @param se the session to exit + * @return 0 on success, -1 on failure + */ +int fuse_set_signal_handlers(struct fuse_session *se); + +/** + * Restore default signal handlers + * + * Resets global session. After this fuse_set_signal_handlers() may + * be called again. + * + * @param se the same session as given in fuse_set_signal_handlers() + */ +void fuse_remove_signal_handlers(struct fuse_session *se); + +/* ----------------------------------------------------------- * + * Compatibility stuff * + * ----------------------------------------------------------- */ + +#if FUSE_USE_VERSION < 26 +# ifdef __FreeBSD__ +# if FUSE_USE_VERSION < 25 +# error On FreeBSD API version 25 or greater must be used +# endif +# endif +# include "fuse_common_compat.h" +# undef FUSE_MINOR_VERSION +# undef fuse_main +# define fuse_unmount fuse_unmount_compat22 +# if FUSE_USE_VERSION == 25 +# define FUSE_MINOR_VERSION 5 +# define fuse_mount fuse_mount_compat25 +# elif FUSE_USE_VERSION == 24 || FUSE_USE_VERSION == 22 +# define FUSE_MINOR_VERSION 4 +# define fuse_mount fuse_mount_compat22 +# elif FUSE_USE_VERSION == 21 +# define FUSE_MINOR_VERSION 1 +# define fuse_mount fuse_mount_compat22 +# elif FUSE_USE_VERSION == 11 +# warning Compatibility with API version 11 is deprecated +# undef FUSE_MAJOR_VERSION +# define FUSE_MAJOR_VERSION 1 +# define FUSE_MINOR_VERSION 1 +# define fuse_mount fuse_mount_compat1 +# else +# error Compatibility with API version other than 21, 22, 24, 25 and 11 not supported +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_COMMON_H_ */ diff --git a/external/libfuse/include/fuse_common_compat.h b/external/libfuse/include/fuse_common_compat.h new file mode 100644 index 0000000..a3edfde --- /dev/null +++ b/external/libfuse/include/fuse_common_compat.h @@ -0,0 +1,33 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_file_info_compat { + int flags; + unsigned long fh; + int writepage; + unsigned int direct_io : 1; + unsigned int keep_cache : 1; +}; +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args, const struct fuse_operations *op); + +int fuse_mount_compat22(const char *mountpoint, const char *opts); + +int fuse_mount_compat1(const char *mountpoint, const char *args[]); + +void fuse_unmount_compat22(const char *mountpoint); diff --git a/external/libfuse/include/fuse_compat.h b/external/libfuse/include/fuse_compat.h new file mode 100644 index 0000000..225276f --- /dev/null +++ b/external/libfuse/include/fuse_compat.h @@ -0,0 +1,201 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_operations_compat25 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, struct fuse_file_info *); + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info *); + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info *); + int (*statfs) (const char *, struct statvfs *); + int (*flush) (const char *, struct fuse_file_info *); + int (*release) (const char *, struct fuse_file_info *); + int (*fsync) (const char *, int, struct fuse_file_info *); + int (*setxattr) (const char *, const char *, const char *, size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); + int (*opendir) (const char *, struct fuse_file_info *); + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info *); + int (*releasedir) (const char *, struct fuse_file_info *); + int (*fsyncdir) (const char *, int, struct fuse_file_info *); + void *(*init) (void); + void (*destroy) (void *); + int (*access) (const char *, int); + int (*create) (const char *, mode_t, struct fuse_file_info *); + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); + int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); +}; + +struct fuse *fuse_new_compat25(int fd, struct fuse_args *args, + const struct fuse_operations_compat25 *op, + size_t op_size); + +int fuse_main_real_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size); + +struct fuse *fuse_setup_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd); + +void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint); + +#ifndef __FreeBSD__ +#include + +struct fuse_operations_compat22 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, struct fuse_file_info_compat *); + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info_compat *); + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info_compat *); + int (*statfs) (const char *, struct statfs *); + int (*flush) (const char *, struct fuse_file_info_compat *); + int (*release) (const char *, struct fuse_file_info_compat *); + int (*fsync) (const char *, int, struct fuse_file_info_compat *); + int (*setxattr) (const char *, const char *, const char *, size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); + int (*opendir) (const char *, struct fuse_file_info_compat *); + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info_compat *); + int (*releasedir) (const char *, struct fuse_file_info_compat *); + int (*fsyncdir) (const char *, int, struct fuse_file_info_compat *); + void *(*init) (void); + void (*destroy) (void *); +}; + +struct fuse *fuse_new_compat22(int fd, const char *opts, + const struct fuse_operations_compat22 *op, + size_t op_size); + +struct fuse *fuse_setup_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd); + +int fuse_main_real_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size); + +typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type); +struct fuse_operations_compat2 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, int); + int (*read) (const char *, char *, size_t, off_t); + int (*write) (const char *, const char *, size_t, off_t); + int (*statfs) (const char *, struct statfs *); + int (*flush) (const char *); + int (*release) (const char *, int); + int (*fsync) (const char *, int); + int (*setxattr) (const char *, const char *, const char *, + size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); +}; + +int fuse_main_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op); + +struct fuse *fuse_new_compat2(int fd, const char *opts, + const struct fuse_operations_compat2 *op); + +struct fuse *fuse_setup_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op, + char **mountpoint, int *multithreaded, int *fd); + +struct fuse_statfs_compat1 { + long block_size; + long blocks; + long blocks_free; + long files; + long files_free; + long namelen; +}; + +struct fuse_operations_compat1 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, int); + int (*read) (const char *, char *, size_t, off_t); + int (*write) (const char *, const char *, size_t, off_t); + int (*statfs) (struct fuse_statfs_compat1 *); + int (*release) (const char *, int); + int (*fsync) (const char *, int); +}; + +#define FUSE_DEBUG_COMPAT1 (1 << 1) + +struct fuse *fuse_new_compat1(int fd, int flags, + const struct fuse_operations_compat1 *op); + +void fuse_main_compat1(int argc, char *argv[], + const struct fuse_operations_compat1 *op); + +#endif /* __FreeBSD__ */ diff --git a/external/libfuse/include/fuse_kernel.h b/external/libfuse/include/fuse_kernel.h new file mode 100644 index 0000000..bd73630 --- /dev/null +++ b/external/libfuse/include/fuse_kernel.h @@ -0,0 +1,593 @@ +/* + This file defines the kernel interface of FUSE + Copyright (C) 2001-2008 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + This -- and only this -- header file may also be distributed under + the terms of the BSD Licence as follows: + + Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * This file defines the kernel interface of FUSE + * + * Protocol changelog: + * + * 7.9: + * - new fuse_getattr_in input argument of GETATTR + * - add lk_flags in fuse_lk_in + * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in + * - add blksize field to fuse_attr + * - add file flags field to fuse_read_in and fuse_write_in + * + * 7.10 + * - add nonseekable open flag + * + * 7.11 + * - add IOCTL message + * - add unsolicited notification support + * - add POLL message and NOTIFY_POLL notification + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir + * - add notification messages for invalidation of inodes and + * directory entries + */ + +#ifndef _LINUX_FUSE_H +#define _LINUX_FUSE_H + +#include +#define __u64 uint64_t +#define __s64 int64_t +#define __u32 uint32_t +#define __s32 int32_t + +/* + * Version negotiation: + * + * Both the kernel and userspace send the version they support in the + * INIT request and reply respectively. + * + * If the major versions match then both shall use the smallest + * of the two minor versions for communication. + * + * If the kernel supports a larger major version, then userspace shall + * reply with the major version it supports, ignore the rest of the + * INIT message and expect a new INIT message from the kernel with a + * matching major version. + * + * If the library supports a larger major version, then it shall fall + * back to the major protocol version sent by the kernel for + * communication and reply with that major version (and an arbitrary + * supported minor version). + */ + +/** Version number of this interface */ +#define FUSE_KERNEL_VERSION 7 + +/** Minor version number of this interface */ +#define FUSE_KERNEL_MINOR_VERSION 12 + +/** The node ID of the root inode */ +#define FUSE_ROOT_ID 1 + +/* Make sure all structures are padded to 64bit boundary, so 32bit + userspace works under 64bit kernels */ + +struct fuse_attr { + __u64 ino; + __u64 size; + __u64 blocks; + __u64 atime; + __u64 mtime; + __u64 ctime; + __u32 atimensec; + __u32 mtimensec; + __u32 ctimensec; + __u32 mode; + __u32 nlink; + __u32 uid; + __u32 gid; + __u32 rdev; + __u32 blksize; + __u32 padding; +}; + +struct fuse_kstatfs { + __u64 blocks; + __u64 bfree; + __u64 bavail; + __u64 files; + __u64 ffree; + __u32 bsize; + __u32 namelen; + __u32 frsize; + __u32 padding; + __u32 spare[6]; +}; + +struct fuse_file_lock { + __u64 start; + __u64 end; + __u32 type; + __u32 pid; /* tgid */ +}; + +/** + * Bitmasks for fuse_setattr_in.valid + */ +#define FATTR_MODE (1 << 0) +#define FATTR_UID (1 << 1) +#define FATTR_GID (1 << 2) +#define FATTR_SIZE (1 << 3) +#define FATTR_ATIME (1 << 4) +#define FATTR_MTIME (1 << 5) +#define FATTR_FH (1 << 6) +#define FATTR_ATIME_NOW (1 << 7) +#define FATTR_MTIME_NOW (1 << 8) +#define FATTR_LOCKOWNER (1 << 9) + +/** + * Flags returned by the OPEN request + * + * FOPEN_DIRECT_IO: bypass page cache for this open file + * FOPEN_KEEP_CACHE: don't invalidate the data cache on open + * FOPEN_NONSEEKABLE: the file is not seekable + */ +#define FOPEN_DIRECT_IO (1 << 0) +#define FOPEN_KEEP_CACHE (1 << 1) +#define FOPEN_NONSEEKABLE (1 << 2) + +/** + * INIT request/reply flags + * + * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_DONT_MASK: don't apply umask to file mode on create operations + */ +#define FUSE_ASYNC_READ (1 << 0) +#define FUSE_POSIX_LOCKS (1 << 1) +#define FUSE_FILE_OPS (1 << 2) +#define FUSE_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_EXPORT_SUPPORT (1 << 4) +#define FUSE_BIG_WRITES (1 << 5) +#define FUSE_DONT_MASK (1 << 6) + +/** + * CUSE INIT request/reply flags + * + * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl + */ +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) + +/** + * Release flags + */ +#define FUSE_RELEASE_FLUSH (1 << 0) + +/** + * Getattr flags + */ +#define FUSE_GETATTR_FH (1 << 0) + +/** + * Lock flags + */ +#define FUSE_LK_FLOCK (1 << 0) + +/** + * WRITE flags + * + * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed + * FUSE_WRITE_LOCKOWNER: lock_owner field is valid + */ +#define FUSE_WRITE_CACHE (1 << 0) +#define FUSE_WRITE_LOCKOWNER (1 << 1) + +/** + * Read flags + */ +#define FUSE_READ_LOCKOWNER (1 << 1) + +/** + * Ioctl flags + * + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed + * FUSE_IOCTL_RETRY: retry with new iovecs + * + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs + */ +#define FUSE_IOCTL_COMPAT (1 << 0) +#define FUSE_IOCTL_UNRESTRICTED (1 << 1) +#define FUSE_IOCTL_RETRY (1 << 2) + +#define FUSE_IOCTL_MAX_IOV 256 + +/** + * Poll flags + * + * FUSE_POLL_SCHEDULE_NOTIFY: request poll notify + */ +#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0) + +enum fuse_opcode { + FUSE_LOOKUP = 1, + FUSE_FORGET = 2, /* no reply */ + FUSE_GETATTR = 3, + FUSE_SETATTR = 4, + FUSE_READLINK = 5, + FUSE_SYMLINK = 6, + FUSE_MKNOD = 8, + FUSE_MKDIR = 9, + FUSE_UNLINK = 10, + FUSE_RMDIR = 11, + FUSE_RENAME = 12, + FUSE_LINK = 13, + FUSE_OPEN = 14, + FUSE_READ = 15, + FUSE_WRITE = 16, + FUSE_STATFS = 17, + FUSE_RELEASE = 18, + FUSE_FSYNC = 20, + FUSE_SETXATTR = 21, + FUSE_GETXATTR = 22, + FUSE_LISTXATTR = 23, + FUSE_REMOVEXATTR = 24, + FUSE_FLUSH = 25, + FUSE_INIT = 26, + FUSE_OPENDIR = 27, + FUSE_READDIR = 28, + FUSE_RELEASEDIR = 29, + FUSE_FSYNCDIR = 30, + FUSE_GETLK = 31, + FUSE_SETLK = 32, + FUSE_SETLKW = 33, + FUSE_ACCESS = 34, + FUSE_CREATE = 35, + FUSE_INTERRUPT = 36, + FUSE_BMAP = 37, + FUSE_DESTROY = 38, + FUSE_IOCTL = 39, + FUSE_POLL = 40, + + /* CUSE specific operations */ + CUSE_INIT = 4096, +}; + +enum fuse_notify_code { + FUSE_NOTIFY_POLL = 1, + FUSE_NOTIFY_INVAL_INODE = 2, + FUSE_NOTIFY_INVAL_ENTRY = 3, + FUSE_NOTIFY_CODE_MAX, +}; + +/* The read buffer is required to be at least 8k, but may be much larger */ +#define FUSE_MIN_READ_BUFFER 8192 + +#define FUSE_COMPAT_ENTRY_OUT_SIZE 120 + +struct fuse_entry_out { + __u64 nodeid; /* Inode ID */ + __u64 generation; /* Inode generation: nodeid:gen must + be unique for the fs's lifetime */ + __u64 entry_valid; /* Cache timeout for the name */ + __u64 attr_valid; /* Cache timeout for the attributes */ + __u32 entry_valid_nsec; + __u32 attr_valid_nsec; + struct fuse_attr attr; +}; + +struct fuse_forget_in { + __u64 nlookup; +}; + +struct fuse_getattr_in { + __u32 getattr_flags; + __u32 dummy; + __u64 fh; +}; + +#define FUSE_COMPAT_ATTR_OUT_SIZE 96 + +struct fuse_attr_out { + __u64 attr_valid; /* Cache timeout for the attributes */ + __u32 attr_valid_nsec; + __u32 dummy; + struct fuse_attr attr; +}; + +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + +struct fuse_mknod_in { + __u32 mode; + __u32 rdev; + __u32 umask; + __u32 padding; +}; + +struct fuse_mkdir_in { + __u32 mode; + __u32 umask; +}; + +struct fuse_rename_in { + __u64 newdir; +}; + +struct fuse_link_in { + __u64 oldnodeid; +}; + +struct fuse_setattr_in { + __u32 valid; + __u32 padding; + __u64 fh; + __u64 size; + __u64 lock_owner; + __u64 atime; + __u64 mtime; + __u64 unused2; + __u32 atimensec; + __u32 mtimensec; + __u32 unused3; + __u32 mode; + __u32 unused4; + __u32 uid; + __u32 gid; + __u32 unused5; +}; + +struct fuse_open_in { + __u32 flags; + __u32 unused; +}; + +struct fuse_create_in { + __u32 flags; + __u32 mode; + __u32 umask; + __u32 padding; +}; + +struct fuse_open_out { + __u64 fh; + __u32 open_flags; + __u32 padding; +}; + +struct fuse_release_in { + __u64 fh; + __u32 flags; + __u32 release_flags; + __u64 lock_owner; +}; + +struct fuse_flush_in { + __u64 fh; + __u32 unused; + __u32 padding; + __u64 lock_owner; +}; + +struct fuse_read_in { + __u64 fh; + __u64 offset; + __u32 size; + __u32 read_flags; + __u64 lock_owner; + __u32 flags; + __u32 padding; +}; + +#define FUSE_COMPAT_WRITE_IN_SIZE 24 + +struct fuse_write_in { + __u64 fh; + __u64 offset; + __u32 size; + __u32 write_flags; + __u64 lock_owner; + __u32 flags; + __u32 padding; +}; + +struct fuse_write_out { + __u32 size; + __u32 padding; +}; + +#define FUSE_COMPAT_STATFS_SIZE 48 + +struct fuse_statfs_out { + struct fuse_kstatfs st; +}; + +struct fuse_fsync_in { + __u64 fh; + __u32 fsync_flags; + __u32 padding; +}; + +struct fuse_setxattr_in { + __u32 size; + __u32 flags; +}; + +struct fuse_getxattr_in { + __u32 size; + __u32 padding; +}; + +struct fuse_getxattr_out { + __u32 size; + __u32 padding; +}; + +struct fuse_lk_in { + __u64 fh; + __u64 owner; + struct fuse_file_lock lk; + __u32 lk_flags; + __u32 padding; +}; + +struct fuse_lk_out { + struct fuse_file_lock lk; +}; + +struct fuse_access_in { + __u32 mask; + __u32 padding; +}; + +struct fuse_init_in { + __u32 major; + __u32 minor; + __u32 max_readahead; + __u32 flags; +}; + +struct fuse_init_out { + __u32 major; + __u32 minor; + __u32 max_readahead; + __u32 flags; + __u32 unused; + __u32 max_write; +}; + +#define CUSE_INIT_INFO_MAX 4096 + +struct cuse_init_in { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; +}; + +struct cuse_init_out { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; + __u32 max_read; + __u32 max_write; + __u32 dev_major; /* chardev major */ + __u32 dev_minor; /* chardev minor */ + __u32 spare[10]; +}; + +struct fuse_interrupt_in { + __u64 unique; +}; + +struct fuse_bmap_in { + __u64 block; + __u32 blocksize; + __u32 padding; +}; + +struct fuse_bmap_out { + __u64 block; +}; + +struct fuse_ioctl_in { + __u64 fh; + __u32 flags; + __u32 cmd; + __u64 arg; + __u32 in_size; + __u32 out_size; +}; + +struct fuse_ioctl_out { + __s32 result; + __u32 flags; + __u32 in_iovs; + __u32 out_iovs; +}; + +struct fuse_poll_in { + __u64 fh; + __u64 kh; + __u32 flags; + __u32 padding; +}; + +struct fuse_poll_out { + __u32 revents; + __u32 padding; +}; + +struct fuse_notify_poll_wakeup_out { + __u64 kh; +}; + +struct fuse_in_header { + __u32 len; + __u32 opcode; + __u64 unique; + __u64 nodeid; + __u32 uid; + __u32 gid; + __u32 pid; + __u32 padding; +}; + +struct fuse_out_header { + __u32 len; + __s32 error; + __u64 unique; +}; + +struct fuse_dirent { + __u64 ino; + __u64 off; + __u32 namelen; + __u32 type; + char name[0]; +}; + +#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) +#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1)) +#define FUSE_DIRENT_SIZE(d) \ + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) + +struct fuse_notify_inval_inode_out { + __u64 ino; + __s64 off; + __s64 len; +}; + +struct fuse_notify_inval_entry_out { + __u64 parent; + __u32 namelen; + __u32 padding; +}; + +#endif /* _LINUX_FUSE_H */ diff --git a/external/libfuse/include/fuse_lowlevel.h b/external/libfuse/include/fuse_lowlevel.h new file mode 100644 index 0000000..2855e51 --- /dev/null +++ b/external/libfuse/include/fuse_lowlevel.h @@ -0,0 +1,1577 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_LOWLEVEL_H_ +#define _FUSE_LOWLEVEL_H_ + +/** @file + * + * Low level API + * + * IMPORTANT: you should define FUSE_USE_VERSION before including this + * header. To use the newest API define it to 26 (recommended for any + * new application), to use the old API define it to 24 (default) or + * 25 + */ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 24 +#endif + +#include "fuse_common.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------- * + * Miscellaneous definitions * + * ----------------------------------------------------------- */ + +/** The node ID of the root inode */ +#define FUSE_ROOT_ID 1 + +/** Inode number type */ +typedef unsigned long fuse_ino_t; + +/** Request pointer type */ +typedef struct fuse_req *fuse_req_t; + +/** + * Session + * + * This provides hooks for processing requests, and exiting + */ +struct fuse_session; + +/** + * Channel + * + * A communication channel, providing hooks for sending and receiving + * messages + */ +struct fuse_chan; + +/** Directory entry parameters supplied to fuse_reply_entry() */ +struct fuse_entry_param { + /** Unique inode number + * + * In lookup, zero means negative entry (from version 2.5) + * Returning ENOENT also means negative entry, but by setting zero + * ino the kernel may cache negative entries for entry_timeout + * seconds. + */ + fuse_ino_t ino; + + /** Generation number for this entry. + * + * The ino/generation pair should be unique for the filesystem's + * lifetime. It must be non-zero, otherwise FUSE will treat it as an + * error. + */ + unsigned long generation; + + /** Inode attributes. + * + * Even if attr_timeout == 0, attr must be correct. For example, + * for open(), FUSE uses attr.st_size from lookup() to determine + * how many bytes to request. If this value is not correct, + * incorrect data will be returned. + */ + struct stat attr; + + /** Validity timeout (in seconds) for the attributes */ + double attr_timeout; + + /** Validity timeout (in seconds) for the name */ + double entry_timeout; +}; + +/** Additional context associated with requests */ +struct fuse_ctx { + /** User ID of the calling process */ + uid_t uid; + + /** Group ID of the calling process */ + gid_t gid; + + /** Thread ID of the calling process */ + pid_t pid; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +}; + +/* 'to_set' flags in setattr */ +#define FUSE_SET_ATTR_MODE (1 << 0) +#define FUSE_SET_ATTR_UID (1 << 1) +#define FUSE_SET_ATTR_GID (1 << 2) +#define FUSE_SET_ATTR_SIZE (1 << 3) +#define FUSE_SET_ATTR_ATIME (1 << 4) +#define FUSE_SET_ATTR_MTIME (1 << 5) +#define FUSE_SET_ATTR_ATIME_NOW (1 << 7) +#define FUSE_SET_ATTR_MTIME_NOW (1 << 8) + +/* ----------------------------------------------------------- * + * Request methods and replies * + * ----------------------------------------------------------- */ + +/** + * Low level filesystem operations + * + * Most of the methods (with the exception of init and destroy) + * receive a request handle (fuse_req_t) as their first argument. + * This handle must be passed to one of the specified reply functions. + * + * This may be done inside the method invocation, or after the call + * has returned. The request handle is valid until one of the reply + * functions is called. + * + * Other pointer arguments (name, fuse_file_info, etc) are not valid + * after the call has returned, so if they are needed later, their + * contents have to be copied. + * + * The filesystem sometimes needs to handle a return value of -ENOENT + * from the reply function, which means, that the request was + * interrupted, and the reply discarded. For example if + * fuse_reply_open() return -ENOENT means, that the release method for + * this file will not be called. + */ +struct fuse_lowlevel_ops { + /** + * Initialize filesystem + * + * Called before any other filesystem method + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ + void (*init) (void *userdata, struct fuse_conn_info *conn); + + /** + * Clean up filesystem + * + * Called on filesystem exit + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ + void (*destroy) (void *userdata); + + /** + * Look up a directory entry by name and get its attributes. + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name the name to look up + */ + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Forget about an inode + * + * The nlookup parameter indicates the number of lookups + * previously performed on this inode. + * + * If the filesystem implements inode lifetimes, it is recommended + * that inodes acquire a single reference on each lookup, and lose + * nlookup references on each forget. + * + * The filesystem may ignore forget calls, if the inodes don't + * need to have a limited lifetime. + * + * On unmount it is not guaranteed, that all referenced inodes + * will receive a forget message. + * + * Valid replies: + * fuse_reply_none + * + * @param req request handle + * @param ino the inode number + * @param nlookup the number of lookups to forget + */ + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + + /** + * Get file attributes + * + * Valid replies: + * fuse_reply_attr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi for future use, currently always NULL + */ + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Set file attributes + * + * In the 'attr' argument only members indicated by the 'to_set' + * bitmask contain valid values. Other members contain undefined + * values. + * + * If the setattr was invoked from the ftruncate() system call + * under Linux kernel versions 2.6.15 or later, the fi->fh will + * contain the value set by the open method or will be undefined + * if the open method didn't set any value. Otherwise (not + * ftruncate call, or kernel version earlier than 2.6.15) the fi + * parameter will be NULL. + * + * Valid replies: + * fuse_reply_attr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param attr the attributes + * @param to_set bit mask of attributes which should be set + * @param fi file information, or NULL + * + * Changed in version 2.5: + * file information filled in for ftruncate + */ + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi); + + /** + * Read symbolic link + * + * Valid replies: + * fuse_reply_readlink + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + */ + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + + /** + * Create file node + * + * Create a regular file, character device, block device, fifo or + * socket node. + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param rdev the device number (only valid if created file is a device) + */ + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + + /** + * Create a directory + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode with which to create the new file + */ + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + + /** + * Remove a file + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to remove + */ + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Remove a directory + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to remove + */ + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Create a symbolic link + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param link the contents of the symbolic link + * @param parent inode number of the parent directory + * @param name to create + */ + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + + /** Rename a file + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the old parent directory + * @param name old name + * @param newparent inode number of the new parent directory + * @param newname new name + */ + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + + /** + * Create a hard link + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param ino the old inode number + * @param newparent inode number of the new parent directory + * @param newname new name to create + */ + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + + /** + * Open a file + * + * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and + * O_TRUNC) are available in fi->flags. + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). + * + * Filesystem may also implement stateless file I/O and not store + * anything in fi->fh. + * + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. + * + * Valid replies: + * fuse_reply_open + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Read data + * + * Read should send exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the file + * has been opened in 'direct_io' mode, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_iov + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size number of bytes to read + * @param off offset to read from + * @param fi file information + */ + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + + /** + * Write data + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the file has + * been opened in 'direct_io' mode, in which case the return value + * of the write system call will reflect the return value of this + * operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * Valid replies: + * fuse_reply_write + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param buf data to write + * @param size number of bytes to write + * @param off offset to write to + * @param fi file information + */ + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); + + /** + * Flush method + * + * This is called on each close() of the opened file. + * + * Since file descriptors can be duplicated (dup, dup2, fork), for + * one open call there may be many flush calls. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * NOTE: the name of the method is misleading, since (unlike + * fsync) the filesystem is not forced to flush pending writes. + * One reason to flush data, is if the filesystem wants to return + * write errors. + * + * If the filesystem supports file locking operations (setlk, + * getlk) it should remove all locks belonging to 'fi->owner'. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open call there will be exactly one release call. + * + * The filesystem may reply with an error, but error values are + * not returned to close() or munmap() which triggered the + * release. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * fi->flags will contain the same flags as for open. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param datasync flag indicating if only data should be flushed + * @param fi file information + */ + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + + /** + * Open a directory + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other directory + * stream operations (readdir, releasedir, fsyncdir). + * + * Filesystem may also implement stateless directory I/O and not + * store anything in fi->fh, though that makes it impossible to + * implement standard conforming directory stream operations in + * case the contents of the directory can change between opendir + * and releasedir. + * + * Valid replies: + * fuse_reply_open + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Read directory + * + * Send a buffer filled using fuse_add_direntry(), with size not + * exceeding the requested size. Send an empty buffer on end of + * stream. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum number of bytes to send + * @param off offset to continue reading the directory stream + * @param fi file information + */ + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + + /** + * Release an open directory + * + * For every opendir call there will be exactly one releasedir + * call. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the directory + * contents should be flushed, not the meta data. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param datasync flag indicating if only data should be flushed + * @param fi file information + */ + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + + /** + * Get file system statistics + * + * Valid replies: + * fuse_reply_statfs + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number, zero means "undefined" + */ + void (*statfs) (fuse_req_t req, fuse_ino_t ino); + + /** + * Set an extended attribute + * + * Valid replies: + * fuse_reply_err + */ + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + + /** + * Get an extended attribute + * + * If size is zero, the size of the value should be sent with + * fuse_reply_xattr. + * + * If the size is non-zero, and the value fits in the buffer, the + * value should be sent with fuse_reply_buf. + * + * If the size is too small for the value, the ERANGE error should + * be sent. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_xattr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param name of the extended attribute + * @param size maximum size of the value to send + */ + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + + /** + * List extended attribute names + * + * If size is zero, the total size of the attribute list should be + * sent with fuse_reply_xattr. + * + * If the size is non-zero, and the null character separated + * attribute list fits in the buffer, the list should be sent with + * fuse_reply_buf. + * + * If the size is too small for the list, the ERANGE error should + * be sent. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_xattr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum size of the list to send + */ + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + + /** + * Remove an extended attribute + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param name of the extended attribute + */ + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + + /** + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param mask requested access mode + */ + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + + /** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * Open flags (with the exception of O_NOCTTY) are available in + * fi->flags. + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). + * + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_create + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param fi file information + */ + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi); + + /** + * Test for a POSIX file lock + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_lock + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param lock the region/type to test + */ + void (*getlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock); + + /** + * Acquire, modify or release a POSIX file lock + * + * For POSIX threads (NPTL) there's a 1-1 relation between pid and + * owner, but otherwise this is not always the case. For checking + * lock ownership, 'fi->owner' must be used. The l_pid field in + * 'struct flock' should only be used to fill in this field in + * getlk(). + * + * Note: if the locking methods are not implemented, the kernel + * will still allow file locking to work locally. Hence these are + * only interesting for network filesystems and similar. + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param lock the region/type to test + * @param sleep locking operation may sleep + */ + void (*setlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, + struct flock *lock, int sleep); + + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_bmap + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param blocksize unit of block index + * @param idx block index within file + */ + void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t idx); + + /** + * Ioctl + * + * Note: For unrestricted ioctls (not allowed for FUSE + * servers), data in and out areas can be discovered by giving + * iovs and setting FUSE_IOCTL_RETRY in @flags. For + * restricted ioctls, kernel prepares in/out data area + * according to the information encoded in cmd. + * + * Introduced in version 2.8 + * + * Valid replies: + * fuse_reply_ioctl_retry + * fuse_reply_ioctl + * fuse_reply_ioctl_iov + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param cmd ioctl command + * @param arg ioctl argument + * @param fi file information + * @param flags for FUSE_IOCTL_* flags + * @param in_buf data fetched from the caller + * @param in_bufsz number of fetched bytes + * @param out_bufsz maximum size of output data + */ + void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, + struct fuse_file_info *fi, unsigned flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz); + + /** + * Poll for IO readiness + * + * Introduced in version 2.8 + * + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_lowelevel_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Valid replies: + * fuse_reply_poll + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param ph poll handle to be used for notification + */ + void (*poll) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, + struct fuse_pollhandle *ph); +}; + +/** + * Reply with an error code or success + * + * Possible requests: + * all except forget + * + * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr, + * removexattr and setlk may send a zero code + * + * @param req request handle + * @param err the positive error value, or zero for success + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_err(fuse_req_t req, int err); + +/** + * Don't send reply + * + * Possible requests: + * forget + * + * @param req request handle + */ +void fuse_reply_none(fuse_req_t req); + +/** + * Reply with a directory entry + * + * Possible requests: + * lookup, mknod, mkdir, symlink, link + * + * @param req request handle + * @param e the entry parameters + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e); + +/** + * Reply with a directory entry and open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * create + * + * @param req request handle + * @param e the entry parameters + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, + const struct fuse_file_info *fi); + +/** + * Reply with attributes + * + * Possible requests: + * getattr, setattr + * + * @param req request handle + * @param attr the attributes + * @param attr_timeout validity timeout (in seconds) for the attributes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_attr(fuse_req_t req, const struct stat *attr, + double attr_timeout); + +/** + * Reply with the contents of a symbolic link + * + * Possible requests: + * readlink + * + * @param req request handle + * @param link symbolic link contents + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_readlink(fuse_req_t req, const char *link); + +/** + * Reply with open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * open, opendir + * + * @param req request handle + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi); + +/** + * Reply with number of bytes written + * + * Possible requests: + * write + * + * @param req request handle + * @param count the number of bytes written + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_write(fuse_req_t req, size_t count); + +/** + * Reply with data + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param buf buffer containing data + * @param size the size of data in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); + +/** + * Reply with data vector + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param iov the vector containing the data + * @param count the size of vector + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count); + +/** + * Reply with filesystem statistics + * + * Possible requests: + * statfs + * + * @param req request handle + * @param stbuf filesystem statistics + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf); + +/** + * Reply with needed buffer size + * + * Possible requests: + * getxattr, listxattr + * + * @param req request handle + * @param count the buffer size needed in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_xattr(fuse_req_t req, size_t count); + +/** + * Reply with file lock information + * + * Possible requests: + * getlk + * + * @param req request handle + * @param lock the lock information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_lock(fuse_req_t req, struct flock *lock); + +/** + * Reply with block index + * + * Possible requests: + * bmap + * + * @param req request handle + * @param idx block index within device + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_bmap(fuse_req_t req, uint64_t idx); + +/* ----------------------------------------------------------- * + * Filling a buffer in readdir * + * ----------------------------------------------------------- */ + +/** + * Add a directory entry to the buffer + * + * Buffer needs to be large enough to hold the entry. If it's not, + * then the entry is not filled in but the size of the entry is still + * returned. The caller can check this by comparing the bufsize + * parameter with the returned entry size. If the entry size is + * larger than the buffer size, the operation failed. + * + * From the 'stbuf' argument the st_ino field and bits 12-15 of the + * st_mode field are used. The other fields are ignored. + * + * Note: offsets do not necessarily represent physical offsets, and + * could be any marker, that enables the implementation to find a + * specific point in the directory stream. + * + * @param req request handle + * @param buf the point where the new entry will be added to the buffer + * @param bufsize remaining size of the buffer + * @param name the name of the entry + * @param stbuf the file attributes + * @param off the offset of the next entry + * @return the space needed for the entry + */ +size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, + const char *name, const struct stat *stbuf, + off_t off); + +/** + * Reply to ask for data fetch and output buffer preparation. ioctl + * will be retried with the specified input data fetched and output + * buffer prepared. + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param in_iov iovec specifying data to fetch from the caller + * @param in_count number of entries in in_iov + * @param out_iov iovec specifying addresses to write output to + * @param out_count number of entries in out_iov + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_ioctl_retry(fuse_req_t req, + const struct iovec *in_iov, size_t in_count, + const struct iovec *out_iov, size_t out_count); + +/** + * Reply to finish ioctl + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param buf buffer containing output data + * @param size length of output data + */ +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size); + +/** + * Reply to finish ioctl with iov buffer + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param iov the vector containing the data + * @param count the size of vector + */ +int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, + int count); + +/** + * Reply with poll result event mask + * + * @param req request handle + * @param revents poll result event mask + */ +int fuse_reply_poll(fuse_req_t req, unsigned revents); + +/* ----------------------------------------------------------- * + * Notification * + * ----------------------------------------------------------- */ + +/** + * Notify IO readiness event + * + * For more information, please read comment for poll operation. + * + * @param ph poll handle to notify IO readiness event for + */ +int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph); + +/** + * Notify to invalidate cache for an inode + * + * @param ch the channel through which to send the invalidation + * @param ino the inode number + * @param off the offset in the inode where to start invalidating + * or negative to invalidate attributes only + * @param len the amount of cache to invalidate or 0 for all + * @return zero for success, -errno for failure + */ +int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, + off_t off, off_t len); + +/** + * Notify to invalidate parent attributes and the dentry matching + * parent/name + * + * @param ch the channel through which to send the invalidation + * @param parent inode number + * @param name file name + * @param namelen strlen() of file name + * @return zero for success, -errno for failure + */ +int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, + const char *name, size_t namelen); + +/* ----------------------------------------------------------- * + * Utility functions * + * ----------------------------------------------------------- */ + +/** + * Get the userdata from the request + * + * @param req request handle + * @return the user data passed to fuse_lowlevel_new() + */ +void *fuse_req_userdata(fuse_req_t req); + +/** + * Get the context from the request + * + * The pointer returned by this function will only be valid for the + * request's lifetime + * + * @param req request handle + * @return the context structure + */ +const struct fuse_ctx *fuse_req_ctx(fuse_req_t req); + +/** + * Get the current supplementary group IDs for the specified request + * + * Similar to the getgroups(2) system call, except the return value is + * always the total number of group IDs, even if it is larger than the + * specified size. + * + * The current fuse kernel module in linux (as of 2.6.30) doesn't pass + * the group list to userspace, hence this function needs to parse + * "/proc/$TID/task/$TID/status" to get the group IDs. + * + * This feature may not be supported on all operating systems. In + * such a case this function will return -ENOSYS. + * + * @param req request handle + * @param size size of given array + * @param list array of group IDs to be filled in + * @return the total number of supplementary group IDs or -errno on failure + */ +int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]); + +/** + * Callback function for an interrupt + * + * @param req interrupted request + * @param data user data + */ +typedef void (*fuse_interrupt_func_t)(fuse_req_t req, void *data); + +/** + * Register/unregister callback for an interrupt + * + * If an interrupt has already happened, then the callback function is + * called from within this function, hence it's not possible for + * interrupts to be lost. + * + * @param req request handle + * @param func the callback function or NULL for unregister + * @param data user data passed to the callback function + */ +void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, + void *data); + +/** + * Check if a request has already been interrupted + * + * @param req request handle + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_req_interrupted(fuse_req_t req); + +/* ----------------------------------------------------------- * + * Filesystem setup * + * ----------------------------------------------------------- */ + +/* Deprecated, don't use */ +int fuse_lowlevel_is_lib_option(const char *opt); + +/** + * Create a low level session + * + * @param args argument vector + * @param op the low level filesystem operations + * @param op_size sizeof(struct fuse_lowlevel_ops) + * @param userdata user data + * @return the created session object, or NULL on failure + */ +struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata); + +/* ----------------------------------------------------------- * + * Session interface * + * ----------------------------------------------------------- */ + +/** + * Session operations + * + * This is used in session creation + */ +struct fuse_session_ops { + /** + * Hook to process a request (mandatory) + * + * @param data user data passed to fuse_session_new() + * @param buf buffer containing the raw request + * @param len request length + * @param ch channel on which the request was received + */ + void (*process) (void *data, const char *buf, size_t len, + struct fuse_chan *ch); + + /** + * Hook for session exit and reset (optional) + * + * @param data user data passed to fuse_session_new() + * @param val exited status (1 - exited, 0 - not exited) + */ + void (*exit) (void *data, int val); + + /** + * Hook for querying the current exited status (optional) + * + * @param data user data passed to fuse_session_new() + * @return 1 if exited, 0 if not exited + */ + int (*exited) (void *data); + + /** + * Hook for cleaning up the channel on destroy (optional) + * + * @param data user data passed to fuse_session_new() + */ + void (*destroy) (void *data); +}; + +/** + * Create a new session + * + * @param op session operations + * @param data user data + * @return new session object, or NULL on failure + */ +struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data); + +/** + * Assign a channel to a session + * + * Note: currently only a single channel may be assigned. This may + * change in the future + * + * If a session is destroyed, the assigned channel is also destroyed + * + * @param se the session + * @param ch the channel + */ +void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch); + +/** + * Remove a channel from a session + * + * If the channel is not assigned to a session, then this is a no-op + * + * @param ch the channel to remove + */ +void fuse_session_remove_chan(struct fuse_chan *ch); + +/** + * Iterate over the channels assigned to a session + * + * The iterating function needs to start with a NULL channel, and + * after that needs to pass the previously returned channel to the + * function. + * + * @param se the session + * @param ch the previous channel, or NULL + * @return the next channel, or NULL if no more channels exist + */ +struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, + struct fuse_chan *ch); + +/** + * Process a raw request + * + * @param se the session + * @param buf buffer containing the raw request + * @param len request length + * @param ch channel on which the request was received + */ +void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, + struct fuse_chan *ch); + +/** + * Destroy a session + * + * @param se the session + */ +void fuse_session_destroy(struct fuse_session *se); + +/** + * Exit a session + * + * @param se the session + */ +void fuse_session_exit(struct fuse_session *se); + +/** + * Reset the exited status of a session + * + * @param se the session + */ +void fuse_session_reset(struct fuse_session *se); + +/** + * Query the exited status of a session + * + * @param se the session + * @return 1 if exited, 0 if not exited + */ +int fuse_session_exited(struct fuse_session *se); + +/** + * Get the user data provided to the session + * + * @param se the session + * @return the user data + */ +void *fuse_session_data(struct fuse_session *se); + +/** + * Enter a single threaded event loop + * + * @param se the session + * @return 0 on success, -1 on error + */ +int fuse_session_loop(struct fuse_session *se); + +/** + * Enter a multi-threaded event loop + * + * @param se the session + * @return 0 on success, -1 on error + */ +int fuse_session_loop_mt(struct fuse_session *se); + +/* ----------------------------------------------------------- * + * Channel interface * + * ----------------------------------------------------------- */ + +/** + * Channel operations + * + * This is used in channel creation + */ +struct fuse_chan_ops { + /** + * Hook for receiving a raw request + * + * @param ch pointer to the channel + * @param buf the buffer to store the request in + * @param size the size of the buffer + * @return the actual size of the raw request, or -1 on error + */ + int (*receive)(struct fuse_chan **chp, char *buf, size_t size); + + /** + * Hook for sending a raw reply + * + * A return value of -ENOENT means, that the request was + * interrupted, and the reply was discarded + * + * @param ch the channel + * @param iov vector of blocks + * @param count the number of blocks in vector + * @return zero on success, -errno on failure + */ + int (*send)(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + + /** + * Destroy the channel + * + * @param ch the channel + */ + void (*destroy)(struct fuse_chan *ch); +}; + +/** + * Create a new channel + * + * @param op channel operations + * @param fd file descriptor of the channel + * @param bufsize the minimal receive buffer size + * @param data user data + * @return the new channel object, or NULL on failure + */ +struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data); + +/** + * Query the file descriptor of the channel + * + * @param ch the channel + * @return the file descriptor passed to fuse_chan_new() + */ +int fuse_chan_fd(struct fuse_chan *ch); + +/** + * Query the minimal receive buffer size + * + * @param ch the channel + * @return the buffer size passed to fuse_chan_new() + */ +size_t fuse_chan_bufsize(struct fuse_chan *ch); + +/** + * Query the user data + * + * @param ch the channel + * @return the user data passed to fuse_chan_new() + */ +void *fuse_chan_data(struct fuse_chan *ch); + +/** + * Query the session to which this channel is assigned + * + * @param ch the channel + * @return the session, or NULL if the channel is not assigned + */ +struct fuse_session *fuse_chan_session(struct fuse_chan *ch); + +/** + * Receive a raw request + * + * A return value of -ENODEV means, that the filesystem was unmounted + * + * @param ch pointer to the channel + * @param buf the buffer to store the request in + * @param size the size of the buffer + * @return the actual size of the raw request, or -errno on error + */ +int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size); + +/** + * Send a raw reply + * + * A return value of -ENOENT means, that the request was + * interrupted, and the reply was discarded + * + * @param ch the channel + * @param iov vector of blocks + * @param count the number of blocks in vector + * @return zero on success, -errno on failure + */ +int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + +/** + * Destroy a channel + * + * @param ch the channel + */ +void fuse_chan_destroy(struct fuse_chan *ch); + +/* ----------------------------------------------------------- * + * Compatibility stuff * + * ----------------------------------------------------------- */ + +#if FUSE_USE_VERSION < 26 +# include "fuse_lowlevel_compat.h" +# define fuse_chan_ops fuse_chan_ops_compat24 +# define fuse_chan_new fuse_chan_new_compat24 +# if FUSE_USE_VERSION == 25 +# define fuse_lowlevel_ops fuse_lowlevel_ops_compat25 +# define fuse_lowlevel_new fuse_lowlevel_new_compat25 +# elif FUSE_USE_VERSION == 24 +# define fuse_lowlevel_ops fuse_lowlevel_ops_compat +# define fuse_lowlevel_new fuse_lowlevel_new_compat +# define fuse_file_info fuse_file_info_compat +# define fuse_reply_statfs fuse_reply_statfs_compat +# define fuse_reply_open fuse_reply_open_compat +# else +# error Compatibility with low-level API version < 24 not supported +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_LOWLEVEL_H_ */ diff --git a/external/libfuse/include/fuse_lowlevel_compat.h b/external/libfuse/include/fuse_lowlevel_compat.h new file mode 100644 index 0000000..aba45e6 --- /dev/null +++ b/external/libfuse/include/fuse_lowlevel_compat.h @@ -0,0 +1,155 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_lowlevel_ops_compat25 { + void (*init) (void *userdata); + void (*destroy) (void *userdata); + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi); + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + void (*statfs) (fuse_req_t req); + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi); +}; + +struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args, + const struct fuse_lowlevel_ops_compat25 *op, + size_t op_size, void *userdata); + +size_t fuse_dirent_size(size_t namelen); + +char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf, + off_t off); + +#ifndef __FreeBSD__ + +#include + +struct fuse_lowlevel_ops_compat { + void (*init) (void *userdata); + void (*destroy) (void *userdata); + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info_compat *fi); + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info_compat *fi); + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info_compat *fi); + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info_compat *fi); + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info_compat *fi); + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info_compat *fi); + void (*statfs) (fuse_req_t req); + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info_compat *fi); +}; + +int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf); + +int fuse_reply_open_compat(fuse_req_t req, + const struct fuse_file_info_compat *fi); + +struct fuse_session *fuse_lowlevel_new_compat(const char *opts, + const struct fuse_lowlevel_ops_compat *op, + size_t op_size, void *userdata); + +#endif /* __FreeBSD__ */ + +struct fuse_chan_ops_compat24 { + int (*receive)(struct fuse_chan *ch, char *buf, size_t size); + int (*send)(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + void (*destroy)(struct fuse_chan *ch); +}; + +struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, + int fd, size_t bufsize, void *data); + +int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size); +struct fuse_chan *fuse_kern_chan_new(int fd); diff --git a/external/libfuse/include/fuse_opt.h b/external/libfuse/include/fuse_opt.h new file mode 100644 index 0000000..8c08d77 --- /dev/null +++ b/external/libfuse/include/fuse_opt.h @@ -0,0 +1,270 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_OPT_H_ +#define _FUSE_OPT_H_ + +/** @file + * + * This file defines the option parsing interface of FUSE + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Option description + * + * This structure describes a single option, and and action associated + * with it, in case it matches. + * + * More than one such match may occur, in which case the action for + * each match is executed. + * + * There are three possible actions in case of a match: + * + * i) An integer (int or unsigned) variable determined by 'offset' is + * set to 'value' + * + * ii) The processing function is called, with 'value' as the key + * + * iii) An integer (any) or string (char *) variable determined by + * 'offset' is set to the value of an option parameter + * + * 'offset' should normally be either set to + * + * - 'offsetof(struct foo, member)' actions i) and iii) + * + * - -1 action ii) + * + * The 'offsetof()' macro is defined in the header. + * + * The template determines which options match, and also have an + * effect on the action. Normally the action is either i) or ii), but + * if a format is present in the template, then action iii) is + * performed. + * + * The types of templates are: + * + * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only + * themselves. Invalid values are "--" and anything beginning + * with "-o" + * + * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or + * the relevant option in a comma separated option list + * + * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) + * which have a parameter + * + * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform + * action iii). + * + * 5) "-x ", etc. Matches either "-xparam" or "-x param" as + * two separate arguments + * + * 6) "-x %s", etc. Combination of 4) and 5) + * + * If the format is "%s", memory is allocated for the string unlike + * with scanf(). + */ +struct fuse_opt { + /** Matching template and optional parameter formatting */ + const char *templ; + + /** + * Offset of variable within 'data' parameter of fuse_opt_parse() + * or -1 + */ + unsigned long offset; + + /** + * Value to set the variable to, or to be passed as 'key' to the + * processing function. Ignored if template has a format + */ + int value; +}; + +/** + * Key option. In case of a match, the processing function will be + * called with the specified key. + */ +#define FUSE_OPT_KEY(templ, key) { templ, -1U, key } + +/** + * Last option. An array of 'struct fuse_opt' must end with a NULL + * template value + */ +#define FUSE_OPT_END { NULL, 0, 0 } + +/** + * Argument list + */ +struct fuse_args { + /** Argument count */ + int argc; + + /** Argument vector. NULL terminated */ + char **argv; + + /** Is 'argv' allocated? */ + int allocated; +}; + +/** + * Initializer for 'struct fuse_args' + */ +#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } + +/** + * Key value passed to the processing function if an option did not + * match any template + */ +#define FUSE_OPT_KEY_OPT -1 + +/** + * Key value passed to the processing function for all non-options + * + * Non-options are the arguments beginning with a charater other than + * '-' or all arguments after the special '--' option + */ +#define FUSE_OPT_KEY_NONOPT -2 + +/** + * Special key value for options to keep + * + * Argument is not passed to processing function, but behave as if the + * processing function returned 1 + */ +#define FUSE_OPT_KEY_KEEP -3 + +/** + * Special key value for options to discard + * + * Argument is not passed to processing function, but behave as if the + * processing function returned zero + */ +#define FUSE_OPT_KEY_DISCARD -4 + +/** + * Processing function + * + * This function is called if + * - option did not match any 'struct fuse_opt' + * - argument is a non-option + * - option did match and offset was set to -1 + * + * The 'arg' parameter will always contain the whole argument or + * option including the parameter if exists. A two-argument option + * ("-x foo") is always converted to single arguemnt option of the + * form "-xfoo" before this function is called. + * + * Options of the form '-ofoo' are passed to this function without the + * '-o' prefix. + * + * The return value of this function determines whether this argument + * is to be inserted into the output argument vector, or discarded. + * + * @param data is the user data passed to the fuse_opt_parse() function + * @param arg is the whole argument or option + * @param key determines why the processing function was called + * @param outargs the current output argument list + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept + */ +typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, + struct fuse_args *outargs); + +/** + * Option parsing function + * + * If 'args' was returned from a previous call to fuse_opt_parse() or + * it was constructed from + * + * A NULL 'args' is equivalent to an empty argument vector + * + * A NULL 'opts' is equivalent to an 'opts' array containing a single + * end marker + * + * A NULL 'proc' is equivalent to a processing function always + * returning '1' + * + * @param args is the input and output argument list + * @param data is the user data + * @param opts is the option description array + * @param proc is the processing function + * @return -1 on error, 0 on success + */ +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc); + +/** + * Add an option to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt(char **opts, const char *opt); + +/** + * Add an option, escaping commas, to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt_escaped(char **opts, const char *opt); + +/** + * Add an argument to a NULL terminated argument vector + * + * @param args is the structure containing the current argument list + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_arg(struct fuse_args *args, const char *arg); + +/** + * Add an argument at the specified position in a NULL terminated + * argument vector + * + * Adds the argument to the N-th position. This is useful for adding + * options at the beggining of the array which must not come after the + * special '--' option. + * + * @param args is the structure containing the current argument list + * @param pos is the position at which to add the argument + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); + +/** + * Free the contents of argument list + * + * The structure itself is not freed + * + * @param args is the structure containing the argument list + */ +void fuse_opt_free_args(struct fuse_args *args); + + +/** + * Check if an option matches + * + * @param opts is the option description array + * @param opt is the option to match + * @return 1 if a match is found, 0 if not + */ +int fuse_opt_match(const struct fuse_opt opts[], const char *opt); + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_OPT_H_ */ diff --git a/external/libfuse/include/old/fuse.h b/external/libfuse/include/old/fuse.h new file mode 100644 index 0000000..3db0945 --- /dev/null +++ b/external/libfuse/include/old/fuse.h @@ -0,0 +1,9 @@ +/* + This header is for compatibility with older software using FUSE. + + Please use 'pkg-config --cflags fuse' to set include path. The + correct usage is still '#include ', not '#include + '. +*/ + +#include "fuse/fuse.h" diff --git a/external/libfuse/include/ulockmgr.h b/external/libfuse/include/ulockmgr.h new file mode 100644 index 0000000..ad55579 --- /dev/null +++ b/external/libfuse/include/ulockmgr.h @@ -0,0 +1,24 @@ +/* + libulockmgr: Userspace Lock Manager Library + Copyright (C) 2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include +#include +#include + +/** + * Perform POSIX locking operation + * + * @param fd the file descriptor + * @param cmd the locking command (F_GETFL, F_SETLK or F_SETLKW) + * @param lock the lock parameters + * @param owner the lock owner ID cookie + * @param owner_len length of the lock owner ID cookie + * @return 0 on success -errno on error + */ +int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner, + size_t owner_len); diff --git a/external/libfuse/source/Makefile.am b/external/libfuse/source/Makefile.am new file mode 100644 index 0000000..c51da5b --- /dev/null +++ b/external/libfuse/source/Makefile.am @@ -0,0 +1,44 @@ +## Process this file with automake to produce Makefile.in + +AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \ + -D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=26 + +lib_LTLIBRARIES = libfuse.la libulockmgr.la + +if BSD +mount_source = mount_bsd.c +else +mount_source = mount.c mount_util.c mount_util.h +endif + +if ICONV +iconv_source = modules/iconv.c +else +iconv_source = +endif + +libfuse_la_SOURCES = \ + fuse.c \ + fuse_i.h \ + fuse_kern_chan.c \ + fuse_loop.c \ + fuse_loop_mt.c \ + fuse_lowlevel.c \ + fuse_misc.h \ + fuse_mt.c \ + fuse_opt.c \ + fuse_session.c \ + fuse_signals.c \ + cuse_lowlevel.c \ + helper.c \ + modules/subdir.c \ + $(iconv_source) \ + $(mount_source) + +libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:8:6 \ + -Wl,--version-script,$(srcdir)/fuse_versionscript + +libulockmgr_la_SOURCES = ulockmgr.c +libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1 + +EXTRA_DIST = fuse_versionscript diff --git a/external/libfuse/source/Makefile.in b/external/libfuse/source/Makefile.in new file mode 100644 index 0000000..e4d02df --- /dev/null +++ b/external/libfuse/source/Makefile.in @@ -0,0 +1,610 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = lib +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libfuse_la_LIBADD = +am__libfuse_la_SOURCES_DIST = fuse.c fuse_i.h fuse_kern_chan.c \ + fuse_loop.c fuse_loop_mt.c fuse_lowlevel.c fuse_misc.h \ + fuse_mt.c fuse_opt.c fuse_session.c fuse_signals.c \ + cuse_lowlevel.c helper.c modules/subdir.c modules/iconv.c \ + mount.c mount_util.c mount_util.h mount_bsd.c +@ICONV_TRUE@am__objects_1 = iconv.lo +@BSD_FALSE@am__objects_2 = mount.lo mount_util.lo +@BSD_TRUE@am__objects_2 = mount_bsd.lo +am_libfuse_la_OBJECTS = fuse.lo fuse_kern_chan.lo fuse_loop.lo \ + fuse_loop_mt.lo fuse_lowlevel.lo fuse_mt.lo fuse_opt.lo \ + fuse_session.lo fuse_signals.lo cuse_lowlevel.lo helper.lo \ + subdir.lo $(am__objects_1) $(am__objects_2) +libfuse_la_OBJECTS = $(am_libfuse_la_OBJECTS) +libfuse_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libfuse_la_LDFLAGS) $(LDFLAGS) -o $@ +libulockmgr_la_LIBADD = +am_libulockmgr_la_OBJECTS = ulockmgr.lo +libulockmgr_la_OBJECTS = $(am_libulockmgr_la_OBJECTS) +libulockmgr_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libulockmgr_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libfuse_la_SOURCES) $(libulockmgr_la_SOURCES) +DIST_SOURCES = $(am__libfuse_la_SOURCES_DIST) \ + $(libulockmgr_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INIT_D_PATH = @INIT_D_PATH@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MOUNT_FUSE_PATH = @MOUNT_FUSE_PATH@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UDEV_RULES_PATH = @UDEV_RULES_PATH@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libfuse_libs = @libfuse_libs@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs2 = @subdirs2@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \ + -D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=26 + +lib_LTLIBRARIES = libfuse.la libulockmgr.la +@BSD_FALSE@mount_source = mount.c mount_util.c mount_util.h +@BSD_TRUE@mount_source = mount_bsd.c +@ICONV_FALSE@iconv_source = +@ICONV_TRUE@iconv_source = modules/iconv.c +libfuse_la_SOURCES = \ + fuse.c \ + fuse_i.h \ + fuse_kern_chan.c \ + fuse_loop.c \ + fuse_loop_mt.c \ + fuse_lowlevel.c \ + fuse_misc.h \ + fuse_mt.c \ + fuse_opt.c \ + fuse_session.c \ + fuse_signals.c \ + cuse_lowlevel.c \ + helper.c \ + modules/subdir.c \ + $(iconv_source) \ + $(mount_source) + +libfuse_la_LDFLAGS = @libfuse_libs@ -version-number 2:8:6 \ + -Wl,--version-script,$(srcdir)/fuse_versionscript + +libulockmgr_la_SOURCES = ulockmgr.c +libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1 +EXTRA_DIST = fuse_versionscript +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lib/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu lib/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libfuse.la: $(libfuse_la_OBJECTS) $(libfuse_la_DEPENDENCIES) + $(libfuse_la_LINK) -rpath $(libdir) $(libfuse_la_OBJECTS) $(libfuse_la_LIBADD) $(LIBS) +libulockmgr.la: $(libulockmgr_la_OBJECTS) $(libulockmgr_la_DEPENDENCIES) + $(libulockmgr_la_LINK) -rpath $(libdir) $(libulockmgr_la_OBJECTS) $(libulockmgr_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cuse_lowlevel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_kern_chan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_loop.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_loop_mt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_lowlevel.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_mt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_opt.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_session.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fuse_signals.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iconv.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount_bsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount_util.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/subdir.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ulockmgr.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +subdir.lo: modules/subdir.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT subdir.lo -MD -MP -MF $(DEPDIR)/subdir.Tpo -c -o subdir.lo `test -f 'modules/subdir.c' || echo '$(srcdir)/'`modules/subdir.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/subdir.Tpo $(DEPDIR)/subdir.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modules/subdir.c' object='subdir.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o subdir.lo `test -f 'modules/subdir.c' || echo '$(srcdir)/'`modules/subdir.c + +iconv.lo: modules/iconv.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT iconv.lo -MD -MP -MF $(DEPDIR)/iconv.Tpo -c -o iconv.lo `test -f 'modules/iconv.c' || echo '$(srcdir)/'`modules/iconv.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/iconv.Tpo $(DEPDIR)/iconv.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modules/iconv.c' object='iconv.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o iconv.lo `test -f 'modules/iconv.c' || echo '$(srcdir)/'`modules/iconv.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-libLTLIBRARIES + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/external/libfuse/source/cuse_lowlevel.c b/external/libfuse/source/cuse_lowlevel.c new file mode 100644 index 0000000..bc28266 --- /dev/null +++ b/external/libfuse/source/cuse_lowlevel.c @@ -0,0 +1,371 @@ +/* + CUSE: Character device in Userspace + Copyright (C) 2008 SUSE Linux Products GmbH + Copyright (C) 2008 Tejun Heo + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include "cuse_lowlevel.h" +#include "fuse_kernel.h" +#include "fuse_i.h" +#include "fuse_opt.h" +#include "fuse_misc.h" + +#include +#include +#include +#include +#include +#include + +struct cuse_data { + struct cuse_lowlevel_ops clop; + unsigned max_read; + unsigned dev_major; + unsigned dev_minor; + unsigned flags; + unsigned dev_info_len; + char dev_info[]; +}; + +static struct cuse_lowlevel_ops *req_clop(fuse_req_t req) +{ + return &req->f->cuse_data->clop; +} + +static void cuse_fll_open(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->open(req, fi); +} + +static void cuse_fll_read(fuse_req_t req, fuse_ino_t ino, size_t size, + off_t off, struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->read(req, size, off, fi); +} + +static void cuse_fll_write(fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->write(req, buf, size, off, fi); +} + +static void cuse_fll_flush(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->flush(req, fi); +} + +static void cuse_fll_release(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->release(req, fi); +} + +static void cuse_fll_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi) +{ + (void)ino; + req_clop(req)->fsync(req, datasync, fi); +} + +static void cuse_fll_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz) +{ + (void)ino; + req_clop(req)->ioctl(req, cmd, arg, fi, flags, in_buf, in_bufsz, + out_bufsz); +} + +static void cuse_fll_poll(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct fuse_pollhandle *ph) +{ + (void)ino; + req_clop(req)->poll(req, fi, ph); +} + +static size_t cuse_pack_info(int argc, const char **argv, char *buf) +{ + size_t size = 0; + int i; + + for (i = 0; i < argc; i++) { + size_t len; + + len = strlen(argv[i]) + 1; + size += len; + if (buf) { + memcpy(buf, argv[i], len); + buf += len; + } + } + + return size; +} + +static struct cuse_data *cuse_prep_data(const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop) +{ + struct cuse_data *cd; + size_t dev_info_len; + + dev_info_len = cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv, + NULL); + + if (dev_info_len > CUSE_INIT_INFO_MAX) { + libfuse_print("cuse: dev_info (%zu) too large, limit=%u", + dev_info_len, CUSE_INIT_INFO_MAX); + return NULL; + } + + cd = calloc(1, sizeof(*cd) + dev_info_len); + if (!cd) { + libfuse_print("cuse: failed to allocate cuse_data"); + return NULL; + } + + memcpy(&cd->clop, clop, sizeof(cd->clop)); + cd->max_read = 131072; + cd->dev_major = ci->dev_major; + cd->dev_minor = ci->dev_minor; + cd->dev_info_len = dev_info_len; + cd->flags = ci->flags; + cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv, cd->dev_info); + + return cd; +} + +struct fuse_session *cuse_lowlevel_new(struct fuse_args *args, + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + void *userdata) +{ + struct fuse_lowlevel_ops lop; + struct cuse_data *cd; + struct fuse_session *se; + struct fuse_ll *ll; + + cd = cuse_prep_data(ci, clop); + if (!cd) + return NULL; + + memset(&lop, 0, sizeof(lop)); + lop.init = clop->init; + lop.destroy = clop->destroy; + lop.open = clop->open ? cuse_fll_open : NULL; + lop.read = clop->read ? cuse_fll_read : NULL; + lop.write = clop->write ? cuse_fll_write : NULL; + lop.flush = clop->flush ? cuse_fll_flush : NULL; + lop.release = clop->release ? cuse_fll_release : NULL; + lop.fsync = clop->fsync ? cuse_fll_fsync : NULL; + lop.ioctl = clop->ioctl ? cuse_fll_ioctl : NULL; + lop.poll = clop->poll ? cuse_fll_poll : NULL; + + se = fuse_lowlevel_new_common(args, &lop, sizeof(lop), userdata); + if (!se) { + free(cd); + return NULL; + } + ll = se->data; + ll->cuse_data = cd; + + return se; +} + +static int cuse_reply_init(fuse_req_t req, struct cuse_init_out *arg, + char *dev_info, unsigned dev_info_len) +{ + struct iovec iov[3]; + + iov[1].iov_base = arg; + iov[1].iov_len = sizeof(struct cuse_init_out); + iov[2].iov_base = dev_info; + iov[2].iov_len = dev_info_len; + + return fuse_send_reply_iov_nofree(req, 0, iov, 3); +} + +void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_init_in *arg = (struct fuse_init_in *) inarg; + struct cuse_init_out outarg; + struct fuse_ll *f = req->f; + struct cuse_data *cd = f->cuse_data; + size_t bufsize = fuse_chan_bufsize(req->ch); + struct cuse_lowlevel_ops *clop = req_clop(req); + + (void) nodeid; + if (f->debug) { + libfuse_print("CUSE_INIT: %u.%u", arg->major, arg->minor); + libfuse_print("flags=0x%08x", arg->flags); + } + f->conn.proto_major = arg->major; + f->conn.proto_minor = arg->minor; + f->conn.capable = 0; + f->conn.want = 0; + + if (arg->major < 7) { + libfuse_print("fuse: unsupported protocol version: %u.%u", + arg->major, arg->minor); + fuse_reply_err(req, EPROTO); + return; + } + + if (bufsize < FUSE_MIN_READ_BUFFER) { + libfuse_print("fuse: warning: buffer size too small: %zu", + bufsize); + bufsize = FUSE_MIN_READ_BUFFER; + } + + bufsize -= 4096; + if (bufsize < f->conn.max_write) + f->conn.max_write = bufsize; + + f->got_init = 1; + if (f->op.init) + f->op.init(f->userdata, &f->conn); + + memset(&outarg, 0, sizeof(outarg)); + outarg.major = FUSE_KERNEL_VERSION; + outarg.minor = FUSE_KERNEL_MINOR_VERSION; + outarg.flags = cd->flags; + outarg.max_read = cd->max_read; + outarg.max_write = f->conn.max_write; + outarg.dev_major = cd->dev_major; + outarg.dev_minor = cd->dev_minor; + + if (f->debug) { + libfuse_print(" CUSE_INIT: %u.%u", + outarg.major, outarg.minor); + libfuse_print(" flags=0x%08x", outarg.flags); + libfuse_print(" max_read=0x%08x", outarg.max_read); + libfuse_print(" max_write=0x%08x", outarg.max_write); + libfuse_print(" dev_major=%u", outarg.dev_major); + libfuse_print(" dev_minor=%u", outarg.dev_minor); + libfuse_print(" dev_info: %.*s", cd->dev_info_len, + cd->dev_info); + } + + cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len); + + if (clop->init_done) + clop->init_done(f->userdata); + + fuse_free_req(req); +} + +struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + int *multithreaded, void *userdata) +{ + const char *devname = "/dev/cuse"; + static const struct fuse_opt kill_subtype_opts[] = { + FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_END + }; + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_session *se; + struct fuse_chan *ch; + int fd; + int foreground; + int res; + + res = fuse_parse_cmdline(&args, NULL, multithreaded, &foreground); + if (res == -1) + goto err_args; + + res = fuse_opt_parse(&args, NULL, kill_subtype_opts, NULL); + if (res == -1) + goto err_args; + + /* + * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos + * would ensue. + */ + do { + fd = open("/dev/null", O_RDWR); + if (fd > 2) + close(fd); + } while (fd >= 0 && fd <= 2); + + se = cuse_lowlevel_new(&args, ci, clop, userdata); + fuse_opt_free_args(&args); + if (se == NULL) + goto err_args; + + fd = open(devname, O_RDWR); + if (fd == -1) { + if (errno == ENODEV || errno == ENOENT) + libfuse_print("fuse: device not found, try 'modprobe cuse' first"); + else + libfuse_print("fuse: failed to open %s: %s", + devname, strerror(errno)); + goto err_se; + } + + ch = fuse_kern_chan_new(fd); + if (!ch) { + close(fd); + goto err_se; + } + + fuse_session_add_chan(se, ch); + + res = fuse_set_signal_handlers(se); + if (res == -1) + goto err_se; + + res = fuse_daemonize(foreground); + if (res == -1) + goto err_sig; + + return se; + +err_sig: + fuse_remove_signal_handlers(se); +err_se: + fuse_session_destroy(se); +err_args: + fuse_opt_free_args(&args); + return NULL; +} + +void cuse_lowlevel_teardown(struct fuse_session *se) +{ + fuse_remove_signal_handlers(se); + fuse_session_destroy(se); +} + +int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, void *userdata) +{ + struct fuse_session *se; + int multithreaded; + int res; + + se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded, + userdata); + if (se == NULL) + return 1; + + if (multithreaded) + res = fuse_session_loop_mt(se); + else + res = fuse_session_loop(se); + + cuse_lowlevel_teardown(se); + if (res == -1) + return 1; + + return 0; +} diff --git a/external/libfuse/source/fuse.c b/external/libfuse/source/fuse.c new file mode 100644 index 0000000..a408278 --- /dev/null +++ b/external/libfuse/source/fuse.c @@ -0,0 +1,4194 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + + +/* For pthread_rwlock_t */ +#define _GNU_SOURCE + +#include "fuse_i.h" +#include "fuse_lowlevel.h" +#include "fuse_opt.h" +#include "fuse_misc.h" +#include "fuse_common_compat.h" +#include "fuse_compat.h" +#include "fuse_kernel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + +#define FUSE_DEFAULT_INTR_SIGNAL SIGUSR1 + +#define FUSE_UNKNOWN_INO 0xffffffff +#define OFFSET_MAX 0x7fffffffffffffffLL + +struct fuse_config { + unsigned int uid; + unsigned int gid; + unsigned int umask; + double entry_timeout; + double negative_timeout; + double attr_timeout; + double ac_attr_timeout; + int ac_attr_timeout_set; + int noforget; + int debug; + int hard_remove; + int use_ino; + int readdir_ino; + int set_mode; + int set_uid; + int set_gid; + int direct_io; + int kernel_cache; + int auto_cache; + int intr; + int intr_signal; + int help; + char *modules; +}; + +struct fuse_fs { + struct fuse_operations op; + struct fuse_module *m; + void *user_data; + int compat; + int debug; +}; + +struct fusemod_so { +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +// void *handle; + void* handle; + int ctr; +}; + +struct lock_queue_element { + struct lock_queue_element *next; + pthread_cond_t cond; +}; + +struct fuse { + struct fuse_session *se; + struct node **name_table; + size_t name_table_size; + struct node **id_table; + size_t id_table_size; + fuse_ino_t ctr; + unsigned int generation; + unsigned int hidectr; + pthread_mutex_t lock; + struct fuse_config conf; + int intr_installed; + struct fuse_fs *fs; + int nullpath_ok; + int curr_ticket; + struct lock_queue_element *lockq; +}; + +struct lock { + int type; + off_t start; + off_t end; + pid_t pid; + uint64_t owner; + struct lock *next; +}; + +struct node { + struct node *name_next; + struct node *id_next; + fuse_ino_t nodeid; + unsigned int generation; + int refctr; + struct node *parent; + char *name; + uint64_t nlookup; + int open_count; + struct timespec stat_updated; + struct timespec mtime; + off_t size; + struct lock *locks; + unsigned int is_hidden : 1; + unsigned int cache_valid : 1; + int treelock; + int ticket; +}; + +struct fuse_dh { + pthread_mutex_t lock; + struct fuse *fuse; + fuse_req_t req; + char *contents; + int allocated; + unsigned len; + unsigned size; + unsigned needlen; + int filled; + uint64_t fh; + int error; + fuse_ino_t nodeid; +}; + +/* old dir handle */ +struct fuse_dirhandle { + fuse_fill_dir_t filler; + void *buf; +}; + +struct fuse_context_i { + struct fuse_context ctx; + fuse_req_t req; +}; + +static pthread_key_t fuse_context_key; +static pthread_mutex_t fuse_context_lock = PTHREAD_MUTEX_INITIALIZER; +static int fuse_context_ref; +static struct fusemod_so *fuse_current_so; +static struct fuse_module *fuse_modules; + +static int fuse_load_so_name(const char *soname) +{ + struct fusemod_so *so; + + so = calloc(1, sizeof(struct fusemod_so)); + if (!so) { + libfuse_print("fuse: memory allocation failed"); + return -1; + } + + fuse_current_so = so; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + so->handle = sceKernelLoadStartModule(soname, 0, NULL, 0, NULL, NULL); + fuse_current_so = NULL; + if (so->handle < 0) { + libfuse_print("fuse: %s", dlerror()); + goto err; + } + if (!so->ctr) { + libfuse_print("fuse: %s did not register any modules", + soname); + goto err; + } + return 0; + +err: + if (so->handle > 0) + sceKernelStopUnloadModule(so->handle, 0, NULL, 0, NULL, NULL); + free(so); + return -1; +} + +static int fuse_load_so_module(const char *module) +{ + int res; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + size_t soname_size = strlen(module) + 64; + char *soname = malloc(soname_size); + if (!soname) { + libfuse_print("fuse: memory allocation failed"); + return -1; + } + snprintf(soname, soname_size, "libfusemod_%s.so", module); + res = fuse_load_so_name(soname); + free(soname); + return res; +} + +static struct fuse_module *fuse_find_module(const char *module) +{ + struct fuse_module *m; + for (m = fuse_modules; m; m = m->next) { + if (strcmp(module, m->name) == 0) { + m->ctr++; + break; + } + } + return m; +} + +static struct fuse_module *fuse_get_module(const char *module) +{ + struct fuse_module *m; + + pthread_mutex_lock(&fuse_context_lock); + m = fuse_find_module(module); + if (!m) { + int err = fuse_load_so_module(module); + if (!err) + m = fuse_find_module(module); + } + pthread_mutex_unlock(&fuse_context_lock); + return m; +} + +static void fuse_put_module(struct fuse_module *m) +{ + pthread_mutex_lock(&fuse_context_lock); + assert(m->ctr > 0); + m->ctr--; + if (!m->ctr && m->so) { + struct fusemod_so *so = m->so; + assert(so->ctr > 0); + so->ctr--; + if (!so->ctr) { + struct fuse_module **mp; + for (mp = &fuse_modules; *mp;) { + if ((*mp)->so == so) + *mp = (*mp)->next; + else + mp = &(*mp)->next; + } +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + sceKernelStopUnloadModule(so->handle, 0, NULL, 0, NULL, NULL); + free(so); + } + } + pthread_mutex_unlock(&fuse_context_lock); +} + +static struct node *get_node_nocheck(struct fuse *f, fuse_ino_t nodeid) +{ + size_t hash = nodeid % f->id_table_size; + struct node *node; + + for (node = f->id_table[hash]; node != NULL; node = node->id_next) + if (node->nodeid == nodeid) + return node; + + return NULL; +} + +static struct node *get_node(struct fuse *f, fuse_ino_t nodeid) +{ + struct node *node = get_node_nocheck(f, nodeid); + if (!node) { + libfuse_print("fuse internal error: node %llu not found", + (unsigned long long) nodeid); + abort(); + } + return node; +} + +static void free_node(struct node *node) +{ + free(node->name); + free(node); +} + +static void unhash_id(struct fuse *f, struct node *node) +{ + size_t hash = node->nodeid % f->id_table_size; + struct node **nodep = &f->id_table[hash]; + + for (; *nodep != NULL; nodep = &(*nodep)->id_next) + if (*nodep == node) { + *nodep = node->id_next; + return; + } +} + +static void hash_id(struct fuse *f, struct node *node) +{ + size_t hash = node->nodeid % f->id_table_size; + node->id_next = f->id_table[hash]; + f->id_table[hash] = node; +} + +static unsigned int name_hash(struct fuse *f, fuse_ino_t parent, + const char *name) +{ + unsigned int hash = *name; + + if (hash) + for (name += 1; *name != '\0'; name++) + hash = (hash << 5) - hash + *name; + + return (hash + parent) % f->name_table_size; +} + +static void unref_node(struct fuse *f, struct node *node); + +static void unhash_name(struct fuse *f, struct node *node) +{ + if (node->name) { + size_t hash = name_hash(f, node->parent->nodeid, node->name); + struct node **nodep = &f->name_table[hash]; + + for (; *nodep != NULL; nodep = &(*nodep)->name_next) + if (*nodep == node) { + *nodep = node->name_next; + node->name_next = NULL; + unref_node(f, node->parent); + free(node->name); + node->name = NULL; + node->parent = NULL; + return; + } + fprintf(stderr, + "fuse internal error: unable to unhash node: %llu", + (unsigned long long) node->nodeid); + abort(); + } +} + +static int hash_name(struct fuse *f, struct node *node, fuse_ino_t parentid, + const char *name) +{ + size_t hash = name_hash(f, parentid, name); + struct node *parent = get_node(f, parentid); + node->name = strdup(name); + if (node->name == NULL) + return -1; + + parent->refctr ++; + node->parent = parent; + node->name_next = f->name_table[hash]; + f->name_table[hash] = node; + return 0; +} + +static void delete_node(struct fuse *f, struct node *node) +{ + if (f->conf.debug) + libfuse_print("DELETE: %llu", + (unsigned long long) node->nodeid); + + assert(node->treelock == 0); + unhash_name(f, node); + unhash_id(f, node); + free_node(node); +} + +static void unref_node(struct fuse *f, struct node *node) +{ + assert(node->refctr > 0); + node->refctr --; + if (!node->refctr) + delete_node(f, node); +} + +static fuse_ino_t next_id(struct fuse *f) +{ + do { + f->ctr = (f->ctr + 1) & 0xffffffff; + if (!f->ctr) + f->generation ++; + } while (f->ctr == 0 || f->ctr == FUSE_UNKNOWN_INO || + get_node_nocheck(f, f->ctr) != NULL); + return f->ctr; +} + +static struct node *lookup_node(struct fuse *f, fuse_ino_t parent, + const char *name) +{ + size_t hash = name_hash(f, parent, name); + struct node *node; + + for (node = f->name_table[hash]; node != NULL; node = node->name_next) + if (node->parent->nodeid == parent && + strcmp(node->name, name) == 0) + return node; + + return NULL; +} + +static void inc_nlookup(struct node *node) +{ + if (!node->nlookup) + node->refctr++; + node->nlookup++; +} + +static struct node *find_node(struct fuse *f, fuse_ino_t parent, + const char *name, unsigned int mode) +{ + struct node *node = NULL; + + pthread_mutex_lock(&f->lock); +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +/* + if (!name) + node = get_node(f, parent); + else +*/ + if (S_ISDIR(mode)) { + node = lookup_node(f, parent, name); + } + if (node == NULL) { + node = (struct node *) calloc(1, sizeof(struct node)); + if (node == NULL) + goto out_err; + + node->refctr = 0; + node->nodeid = next_id(f); + node->generation = f->generation; + node->open_count = 0; + node->is_hidden = 0; + node->treelock = 0; + node->ticket = 0; + if (f->conf.noforget) + inc_nlookup(node); + if (hash_name(f, node, parent, name) == -1) { + free(node); + node = NULL; + goto out_err; + } + hash_id(f, node); + } + inc_nlookup(node); +out_err: + pthread_mutex_unlock(&f->lock); + return node; +} + +static char *add_name(char **buf, unsigned *bufsize, char *s, const char *name) +{ + size_t len = strlen(name); + + if (s - len <= *buf) { + unsigned pathlen = *bufsize - (s - *buf); + unsigned newbufsize = *bufsize; + char *newbuf; + + while (newbufsize < pathlen + len + 1) { + if (newbufsize >= 0x80000000) + newbufsize = 0xffffffff; + else + newbufsize *= 2; + } + + newbuf = realloc(*buf, newbufsize); + if (newbuf == NULL) + return NULL; + + *buf = newbuf; + s = newbuf + newbufsize - pathlen; + memmove(s, newbuf + *bufsize - pathlen, pathlen); + *bufsize = newbufsize; + } + s -= len; + strncpy(s, name, len); + s--; + *s = '/'; + + return s; +} + +static void unlock_path(struct fuse *f, fuse_ino_t nodeid, struct node *wnode, + struct node *end, int ticket) +{ + struct node *node; + + if (wnode) { + assert(wnode->treelock == -1); + wnode->treelock = 0; + if (!wnode->ticket) + wnode->ticket = ticket; + } + + for (node = get_node(f, nodeid); + node != end && node->nodeid != FUSE_ROOT_ID; node = node->parent) { + assert(node->treelock > 0); + node->treelock--; + if (!node->ticket) + node->ticket = ticket; + } +} + +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +static void release_tickets(struct fuse *f, fuse_ino_t nodeid, + struct node *wnode, int ticket) +{ + struct node *node; + + if (wnode) { + if (wnode->ticket != ticket) + return; + + wnode->ticket = 0; + } + + for (node = get_node(f, nodeid); + node->nodeid != FUSE_ROOT_ID; node = node->parent) { + if (node->ticket != ticket) + return; + node->ticket = 0; + } +} + +static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path, struct node **wnodep, int ticket) +{ + unsigned bufsize = 256; + char *buf; + char *s; + struct node *node; + struct node *wnode = NULL; + int err; + + *path = NULL; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + err = -ENOMEM; + buf = malloc(bufsize); + if (buf == NULL) + goto out_err; + + s = buf + bufsize - 1; + *s = '\0'; + + if (name != NULL) { + s = add_name(&buf, &bufsize, s, name); + err = -ENOMEM; + if (s == NULL) + goto out_free; + } + + if (wnodep) { + assert(ticket); + wnode = lookup_node(f, nodeid, name); + if (wnode) { + if (wnode->treelock != 0 || + (wnode->ticket && wnode->ticket != ticket)) { + if (!wnode->ticket) + wnode->ticket = ticket; + err = -EAGAIN; + goto out_free; + } + wnode->treelock = -1; + wnode->ticket = 0; + } + } + + err = 0; + for (node = get_node(f, nodeid); node->nodeid != FUSE_ROOT_ID; + node = node->parent) { + err = -ENOENT; + if (node->name == NULL || node->parent == NULL) + goto out_unlock; + + err = -ENOMEM; + s = add_name(&buf, &bufsize, s, node->name); + if (s == NULL) + goto out_unlock; + + if (ticket) { + err = -EAGAIN; + if (node->treelock == -1 || + (node->ticket && node->ticket != ticket)) + goto out_unlock; + + node->treelock++; + node->ticket = 0; + } + } + + if (s[0]) + memmove(buf, s, bufsize - (s - buf)); + else + strncpy(buf, "/", bufsize); + + *path = buf; + if (wnodep) + *wnodep = wnode; + + return 0; + + out_unlock: + if (ticket) + unlock_path(f, nodeid, wnode, node, ticket); + out_free: + free(buf); + + out_err: + if (ticket && err != -EAGAIN) + release_tickets(f, nodeid, wnode, ticket); + + return err; +} + +static void wake_up_first(struct fuse *f) +{ + if (f->lockq) + pthread_cond_signal(&f->lockq->cond); +} + +static void wake_up_next(struct lock_queue_element *qe) +{ + if (qe->next) + pthread_cond_signal(&qe->next->cond); +} + +static int get_ticket(struct fuse *f) +{ + do f->curr_ticket++; + while (f->curr_ticket == 0); + + return f->curr_ticket; +} + +static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid, + const char *name, int wr) +{ + if (f->conf.debug) { + struct node *wnode = NULL; + + if (wr) + wnode = lookup_node(f, nodeid, name); + + if (wnode) + libfuse_print("%s %li (w)", msg, wnode->nodeid); + else + libfuse_print("%s %li", msg, nodeid); + } +} + +static void queue_path(struct fuse *f, struct lock_queue_element *qe, + fuse_ino_t nodeid, const char *name, int wr) +{ + struct lock_queue_element **qp; + + debug_path(f, "QUEUE PATH", nodeid, name, wr); + pthread_cond_init(&qe->cond, NULL); + qe->next = NULL; + for (qp = &f->lockq; *qp != NULL; qp = &(*qp)->next); + *qp = qe; +} + +static void dequeue_path(struct fuse *f, struct lock_queue_element *qe, + fuse_ino_t nodeid, const char *name, int wr) +{ + struct lock_queue_element **qp; + + debug_path(f, "DEQUEUE PATH", nodeid, name, wr); + pthread_cond_destroy(&qe->cond); + for (qp = &f->lockq; *qp != qe; qp = &(*qp)->next); + *qp = qe->next; +} + +static void wait_on_path(struct fuse *f, struct lock_queue_element *qe, + fuse_ino_t nodeid, const char *name, int wr) +{ + debug_path(f, "WAIT ON PATH", nodeid, name, wr); + pthread_cond_wait(&qe->cond, &f->lock); +} + +static int get_path_common(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path, struct node **wnode) +{ + int err; + int ticket; + + pthread_mutex_lock(&f->lock); + ticket = get_ticket(f); + err = try_get_path(f, nodeid, name, path, wnode, ticket); + if (err == -EAGAIN) { + struct lock_queue_element qe; + + queue_path(f, &qe, nodeid, name, !!wnode); + do { + wait_on_path(f, &qe, nodeid, name, !!wnode); + err = try_get_path(f, nodeid, name, path, wnode, + ticket); + wake_up_next(&qe); + } while (err == -EAGAIN); + dequeue_path(f, &qe, nodeid, name, !!wnode); + } + pthread_mutex_unlock(&f->lock); + + return err; +} + +static int get_path(struct fuse *f, fuse_ino_t nodeid, char **path) +{ + return get_path_common(f, nodeid, NULL, path, NULL); +} + +static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path) +{ + int err = get_path_common(f, nodeid, NULL, path, NULL); + + if (err == -ENOENT && f->nullpath_ok) + err = 0; + + return err; +} + +static int get_path_name(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path) +{ + return get_path_common(f, nodeid, name, path, NULL); +} + +static int get_path_wrlock(struct fuse *f, fuse_ino_t nodeid, const char *name, + char **path, struct node **wnode) +{ + return get_path_common(f, nodeid, name, path, wnode); +} + +static int try_get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, + fuse_ino_t nodeid2, const char *name2, + char **path1, char **path2, + struct node **wnode1, struct node **wnode2, + int ticket) +{ + int err; + + /* FIXME: locking two paths needs deadlock checking */ + err = try_get_path(f, nodeid1, name1, path1, wnode1, ticket); + if (!err) { + err = try_get_path(f, nodeid2, name2, path2, wnode2, ticket); +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +/* +Modified by Y.ITO, 02/16/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + if (err) { + struct node *wn1 = wnode1 ? *wnode1 : NULL; + + unlock_path(f, nodeid1, wn1, NULL, ticket); + free(*path1); + if (ticket && err != -EAGAIN) + release_tickets(f, nodeid1, wn1, ticket); + } + } + return err; +} + +static int get_path2(struct fuse *f, fuse_ino_t nodeid1, const char *name1, + fuse_ino_t nodeid2, const char *name2, + char **path1, char **path2, + struct node **wnode1, struct node **wnode2) +{ + int err; + int ticket; + + pthread_mutex_lock(&f->lock); + ticket = get_ticket(f); + err = try_get_path2(f, nodeid1, name1, nodeid2, name2, + path1, path2, wnode1, wnode2, ticket); + if (err == -EAGAIN) { + struct lock_queue_element qe; + + queue_path(f, &qe, nodeid1, name1, !!wnode1); + debug_path(f, " path2", nodeid2, name2, !!wnode2); + do { + wait_on_path(f, &qe, nodeid1, name1, !!wnode1); + debug_path(f, " path2", nodeid2, name2, !!wnode2); + err = try_get_path2(f, nodeid1, name1, nodeid2, name2, + path1, path2, wnode1, wnode2, + ticket); + wake_up_next(&qe); + } while (err == -EAGAIN); + dequeue_path(f, &qe, nodeid1, name1, !!wnode1); + debug_path(f, " path2", nodeid2, name2, !!wnode2); + } + pthread_mutex_unlock(&f->lock); + + return err; +} + +static void free_path_wrlock(struct fuse *f, fuse_ino_t nodeid, + struct node *wnode, char *path) +{ + pthread_mutex_lock(&f->lock); + unlock_path(f, nodeid, wnode, NULL, 0); + wake_up_first(f); + pthread_mutex_unlock(&f->lock); + free(path); +} + +static void free_path(struct fuse *f, fuse_ino_t nodeid, char *path) +{ + if (path) + free_path_wrlock(f, nodeid, NULL, path); +} + +static void free_path2(struct fuse *f, fuse_ino_t nodeid1, fuse_ino_t nodeid2, + struct node *wnode1, struct node *wnode2, + char *path1, char *path2) +{ + pthread_mutex_lock(&f->lock); + unlock_path(f, nodeid1, wnode1, NULL, 0); + unlock_path(f, nodeid2, wnode2, NULL, 0); + wake_up_first(f); + pthread_mutex_unlock(&f->lock); + free(path1); + free(path2); +} + +static void forget_node(struct fuse *f, fuse_ino_t nodeid, uint64_t nlookup) +{ + struct node *node; + if (nodeid == FUSE_ROOT_ID) + return; + pthread_mutex_lock(&f->lock); + node = get_node(f, nodeid); + + /* + * Node may still be locked due to interrupt idiocy in open, + * create and opendir + */ + while (node->nlookup == nlookup && node->treelock) { + struct lock_queue_element qe; + + queue_path(f, &qe, node->nodeid, NULL, 0); + do { + wait_on_path(f, &qe, node->nodeid, NULL, 0); + wake_up_next(&qe); + + } while (node->nlookup == nlookup && node->treelock); + dequeue_path(f, &qe, node->nodeid, NULL, 0); + } + + assert(node->nlookup >= nlookup); + node->nlookup -= nlookup; + if (!node->nlookup) { + unref_node(f, node); + } + pthread_mutex_unlock(&f->lock); +} + +static void unlink_node(struct fuse *f, struct node *node) +{ + if (f->conf.noforget) { + assert(node->nlookup > 1); + node->nlookup--; + } + unhash_name(f, node); +} + +static void remove_node(struct fuse *f, fuse_ino_t dir, const char *name) +{ + struct node *node; + + pthread_mutex_lock(&f->lock); + node = lookup_node(f, dir, name); + if (node != NULL) + unlink_node(f, node); + pthread_mutex_unlock(&f->lock); +} + +static int rename_node(struct fuse *f, fuse_ino_t olddir, const char *oldname, + fuse_ino_t newdir, const char *newname, int hide) +{ + struct node *node; + struct node *newnode; + int err = 0; + + pthread_mutex_lock(&f->lock); + node = lookup_node(f, olddir, oldname); + newnode = lookup_node(f, newdir, newname); + if (node == NULL) + goto out; + + if (newnode != NULL) { + if (hide) { + libfuse_print("fuse: hidden file got created during hiding"); + err = -EBUSY; + goto out; + } + unlink_node(f, newnode); + } + + unhash_name(f, node); + if (hash_name(f, node, newdir, newname) == -1) { + err = -ENOMEM; + goto out; + } + + if (hide) + node->is_hidden = 1; + +out: + pthread_mutex_unlock(&f->lock); + return err; +} + +static void set_stat(struct fuse *f, fuse_ino_t nodeid, struct stat *stbuf) +{ + if (!f->conf.use_ino) + stbuf->st_ino = nodeid; + if (f->conf.set_mode) + stbuf->st_mode = (stbuf->st_mode & S_IFMT) | + (0777 & ~f->conf.umask); + if (f->conf.set_uid) + stbuf->st_uid = f->conf.uid; + if (f->conf.set_gid) + stbuf->st_gid = f->conf.gid; +} + +static struct fuse *req_fuse(fuse_req_t req) +{ + return (struct fuse *) fuse_req_userdata(req); +} + +static void fuse_intr_sighandler(int sig) +{ + (void) sig; + /* Nothing to do */ +} + +struct fuse_intr_data { + pthread_t id; + pthread_cond_t cond; + int finished; +}; + +static void fuse_interrupt(fuse_req_t req, void *d_) +{ + struct fuse_intr_data *d = d_; + struct fuse *f = req_fuse(req); + + if (d->id == pthread_self()) + return; + + pthread_mutex_lock(&f->lock); + while (!d->finished) { + struct timeval now; + struct timespec timeout; + + pthread_kill(d->id, f->conf.intr_signal); + gettimeofday(&now, NULL); + timeout.tv_sec = now.tv_sec + 1; + timeout.tv_nsec = now.tv_usec * 1000; + pthread_cond_timedwait(&d->cond, &f->lock, &timeout); + } + pthread_mutex_unlock(&f->lock); +} + +static void fuse_do_finish_interrupt(struct fuse *f, fuse_req_t req, + struct fuse_intr_data *d) +{ + pthread_mutex_lock(&f->lock); + d->finished = 1; + pthread_cond_broadcast(&d->cond); + pthread_mutex_unlock(&f->lock); + fuse_req_interrupt_func(req, NULL, NULL); + pthread_cond_destroy(&d->cond); +} + +static void fuse_do_prepare_interrupt(fuse_req_t req, struct fuse_intr_data *d) +{ + d->id = pthread_self(); + pthread_cond_init(&d->cond, NULL); + d->finished = 0; + fuse_req_interrupt_func(req, fuse_interrupt, d); +} + +static inline void fuse_finish_interrupt(struct fuse *f, fuse_req_t req, + struct fuse_intr_data *d) +{ + if (f->conf.intr) + fuse_do_finish_interrupt(f, req, d); +} + +static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req, + struct fuse_intr_data *d) +{ + if (f->conf.intr) + fuse_do_prepare_interrupt(req, d); +} + +#ifndef __FreeBSD__ + +static int fuse_compat_open(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + int err; + if (!fs->compat || fs->compat >= 25) + err = fs->op.open(path, fi); + else if (fs->compat == 22) { + struct fuse_file_info_compat tmp; + memcpy(&tmp, fi, sizeof(tmp)); + err = ((struct fuse_operations_compat22 *) &fs->op)->open(path, + &tmp); + memcpy(fi, &tmp, sizeof(tmp)); + fi->fh = tmp.fh; + } else + err = ((struct fuse_operations_compat2 *) &fs->op) + ->open(path, fi->flags); + return err; +} + +static int fuse_compat_release(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + if (!fs->compat || fs->compat >= 22) + return fs->op.release(path, fi); + else + return ((struct fuse_operations_compat2 *) &fs->op) + ->release(path, fi->flags); +} + +static int fuse_compat_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + if (!fs->compat || fs->compat >= 25) + return fs->op.opendir(path, fi); + else { + int err; + struct fuse_file_info_compat tmp; + memcpy(&tmp, fi, sizeof(tmp)); + err = ((struct fuse_operations_compat22 *) &fs->op) + ->opendir(path, &tmp); + memcpy(fi, &tmp, sizeof(tmp)); + fi->fh = tmp.fh; + return err; + } +} + +static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf, + struct statvfs *stbuf) +{ + stbuf->f_bsize = compatbuf->block_size; + stbuf->f_blocks = compatbuf->blocks; + stbuf->f_bfree = compatbuf->blocks_free; + stbuf->f_bavail = compatbuf->blocks_free; + stbuf->f_files = compatbuf->files; + stbuf->f_ffree = compatbuf->files_free; + stbuf->f_namemax = compatbuf->namelen; +} + +static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf) +{ + stbuf->f_bsize = oldbuf->f_bsize; + stbuf->f_blocks = oldbuf->f_blocks; + stbuf->f_bfree = oldbuf->f_bfree; + stbuf->f_bavail = oldbuf->f_bavail; + stbuf->f_files = oldbuf->f_files; + stbuf->f_ffree = oldbuf->f_ffree; + stbuf->f_namemax = oldbuf->f_namelen; +} + +static int fuse_compat_statfs(struct fuse_fs *fs, const char *path, + struct statvfs *buf) +{ + int err; + + if (!fs->compat || fs->compat >= 25) { + err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf); + } else if (fs->compat > 11) { + struct statfs oldbuf; + err = ((struct fuse_operations_compat22 *) &fs->op) + ->statfs("/", &oldbuf); + if (!err) + convert_statfs_old(&oldbuf, buf); + } else { + struct fuse_statfs_compat1 compatbuf; + memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1)); + err = ((struct fuse_operations_compat1 *) &fs->op) + ->statfs(&compatbuf); + if (!err) + convert_statfs_compat(&compatbuf, buf); + } + return err; +} + +#else /* __FreeBSD__ */ + +static inline int fuse_compat_open(struct fuse_fs *fs, char *path, + struct fuse_file_info *fi) +{ + return fs->op.open(path, fi); +} + +static inline int fuse_compat_release(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + return fs->op.release(path, fi); +} + +static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + return fs->op.opendir(path, fi); +} + +static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path, + struct statvfs *buf) +{ + return fs->op.statfs(fs->compat == 25 ? "/" : path, buf); +} + +#endif /* __FreeBSD__ */ + +int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.getattr) { + if (1) + libfuse_print("getattr %s", path); + + return fs->op.getattr(path, buf); + } else { + return -ENOSYS; + } +} + +int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.fgetattr) { + if (1) + libfuse_print("fgetattr[%llu] %s", + (unsigned long long) fi->fh, path); + + return fs->op.fgetattr(path, buf, fi); + } else if (path && fs->op.getattr) { + if (1) + libfuse_print("getattr %s", path); + + return fs->op.getattr(path, buf); + } else { + return -ENOSYS; + } +} + +int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, + const char *newpath) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.rename) { + if (1) + libfuse_print("rename %s %s", oldpath, newpath); + + return fs->op.rename(oldpath, newpath); + } else { + return -ENOSYS; + } +} + +int fuse_fs_unlink(struct fuse_fs *fs, const char *path) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.unlink) { + if (1) + libfuse_print("unlink %s", path); + + return fs->op.unlink(path); + } else { + return -ENOSYS; + } +} + +int fuse_fs_rmdir(struct fuse_fs *fs, const char *path) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.rmdir) { + if (1) + libfuse_print("rmdir %s", path); + + return fs->op.rmdir(path); + } else { + return -ENOSYS; + } +} + +int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, const char *path) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.symlink) { + if (1) + libfuse_print("symlink %s %s", linkname, path); + + return fs->op.symlink(linkname, path); + } else { + return -ENOSYS; + } +} + +int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.link) { + if (1) + libfuse_print("link %s %s", oldpath, newpath); + + return fs->op.link(oldpath, newpath); + } else { + return -ENOSYS; + } +} + +int fuse_fs_release(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.release) { + if (1) + libfuse_print("release%s[%llu] flags: 0x%x", + fi->flush ? "+flush" : "", + (unsigned long long) fi->fh, fi->flags); + + return fuse_compat_release(fs, path, fi); + } else { + return 0; + } +} + +int fuse_fs_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.opendir) { + int err; + + if (1) + libfuse_print("opendir flags: 0x%x %s", fi->flags, + path); + + err = fuse_compat_opendir(fs, path, fi); + + if (1 && !err) + libfuse_print(" opendir[%lli] flags: 0x%x %s", + (unsigned long long) fi->fh, fi->flags, path); + + return err; + } else { + return 0; + } +} + +int fuse_fs_open(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.open) { + int err; + + if (1) + libfuse_print("open flags: 0x%x %s", fi->flags, + path); +/* +Modified by Y.OGATA, 06/05/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + err = fuse_compat_open(fs, (char*)path, fi); + + if (1 && !err) + libfuse_print(" open[%lli] flags: 0x%x %s", + (unsigned long long) fi->fh, fi->flags, path); + + return err; + } else { + return 0; + } +} + +int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size, + off_t off, struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.read) { + int res; + + if (1) + fprintf(stderr, + "read[%llu] %lu bytes from %llu flags: 0x%x", + (unsigned long long) fi->fh, + (unsigned long) size, (unsigned long long) off, + fi->flags); + + res = fs->op.read(path, buf, size, off, fi); + + if (1 && res >= 0) + libfuse_print(" read[%llu] %u bytes from %llu", + (unsigned long long) fi->fh, res, + (unsigned long long) off); + if (res > (int) size) + libfuse_print("fuse: read too many bytes"); + + return res; + } else { + return -ENOSYS; + } +} + +int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.write) { + int res; + + if (1) + fprintf(stderr, + "write%s[%llu] %lu bytes to %llu flags: 0x%x", + fi->writepage ? "page" : "", + (unsigned long long) fi->fh, + (unsigned long) size, (unsigned long long) off, + fi->flags); + + res = fs->op.write(path, buf, size, off, fi); + + if (1 && res >= 0) + libfuse_print(" write%s[%llu] %u bytes to %llu", + fi->writepage ? "page" : "", + (unsigned long long) fi->fh, res, + (unsigned long long) off); + if (res > (int) size) + libfuse_print("fuse: wrote too many bytes"); + + return res; + } else { + return -ENOSYS; + } +} + +int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.fsync) { + if (1) + libfuse_print("fsync[%llu] datasync: %i", + (unsigned long long) fi->fh, datasync); + + return fs->op.fsync(path, datasync, fi); + } else { + return -ENOSYS; + } +} + +int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.fsyncdir) { + if (1) + libfuse_print("fsyncdir[%llu] datasync: %i", + (unsigned long long) fi->fh, datasync); + + return fs->op.fsyncdir(path, datasync, fi); + } else { + return -ENOSYS; + } +} + +int fuse_fs_flush(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.flush) { + if (1) + libfuse_print("flush[%llu]", + (unsigned long long) fi->fh); + + return fs->op.flush(path, fi); + } else { + return -ENOSYS; + } +} + +int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.statfs) { + if (1) + libfuse_print("statfs %s", path); + + return fuse_compat_statfs(fs, path, buf); + } else { + buf->f_namemax = 255; + buf->f_bsize = 512; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + buf->f_frsize = 512; + return 0; + } +} + +int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.releasedir) { + if (1) + libfuse_print("releasedir[%llu] flags: 0x%x", + (unsigned long long) fi->fh, fi->flags); + + return fs->op.releasedir(path, fi); + } else { + return 0; + } +} + +static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type, + ino_t ino) +{ + int res; + struct stat stbuf; + + memset(&stbuf, 0, sizeof(stbuf)); + stbuf.st_mode = type << 12; + stbuf.st_ino = ino; + + res = dh->filler(dh->buf, name, &stbuf, 0); + return res ? -ENOMEM : 0; +} + +int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, + fuse_fill_dir_t filler, off_t off, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.readdir) { + if (1) + libfuse_print("readdir[%llu] from %llu", + (unsigned long long) fi->fh, + (unsigned long long) off); + + return fs->op.readdir(path, buf, filler, off, fi); + } else if (fs->op.getdir) { + struct fuse_dirhandle dh; + + if (1) + libfuse_print("getdir[%llu]", + (unsigned long long) fi->fh); + + dh.filler = filler; + dh.buf = buf; + return fs->op.getdir(path, &dh, fill_dir_old); + } else { + return -ENOSYS; + } +} + +int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.create) { + int err; + + if (1) + fprintf(stderr, + "create flags: 0x%x %s 0%o umask=0%03o", + fi->flags, path, mode, + fuse_get_context()->umask); + + err = fs->op.create(path, mode, fi); + + if (1 && !err) + libfuse_print(" create[%llu] flags: 0x%x %s", + (unsigned long long) fi->fh, fi->flags, path); + + return err; + } else { + return -ENOSYS; + } +} + +int fuse_fs_lock(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, int cmd, struct flock *lock) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.lock) { + if (1) + libfuse_print("lock[%llu] %s %s start: %llu len: %llu pid: %llu", + (unsigned long long) fi->fh, + (cmd == F_GETLK ? "F_GETLK" : + (cmd == F_SETLK ? "F_SETLK" : + (cmd == F_SETLKW ? "F_SETLKW" : "???"))), + (lock->l_type == F_RDLCK ? "F_RDLCK" : + (lock->l_type == F_WRLCK ? "F_WRLCK" : + (lock->l_type == F_UNLCK ? "F_UNLCK" : + "???"))), + (unsigned long long) lock->l_start, + (unsigned long long) lock->l_len, + (unsigned long long) lock->l_pid); + + return fs->op.lock(path, fi, cmd, lock); + } else { + return -ENOSYS; + } +} + +int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.chown) { + if (1) + libfuse_print("chown %s %lu %lu", path, + (unsigned long) uid, (unsigned long) gid); + + return fs->op.chown(path, uid, gid); + } else { + return -ENOSYS; + } +} + +int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.truncate) { + if (1) + libfuse_print("truncate %s %llu", path, + (unsigned long long) size); + + return fs->op.truncate(path, size); + } else { + return -ENOSYS; + } +} + +int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size, + struct fuse_file_info *fi) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.ftruncate) { + if (1) + libfuse_print("ftruncate[%llu] %s %llu", + (unsigned long long) fi->fh, path, + (unsigned long long) size); + + return fs->op.ftruncate(path, size, fi); + } else if (path && fs->op.truncate) { + if (1) + libfuse_print("truncate %s %llu", path, + (unsigned long long) size); + + return fs->op.truncate(path, size); + } else { + return -ENOSYS; + } +} + +int fuse_fs_utimens(struct fuse_fs *fs, const char *path, + const struct timespec tv[2]) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.utimens) { + if (1) + libfuse_print("utimens %s %li.%09lu %li.%09lu", + path, tv[0].tv_sec, tv[0].tv_nsec, + tv[1].tv_sec, tv[1].tv_nsec); + + return fs->op.utimens(path, tv); + } else if(fs->op.utime) { + struct utimbuf buf; + + if (1) + libfuse_print("utime %s %li %li", path, + tv[0].tv_sec, tv[1].tv_sec); + + buf.actime = tv[0].tv_sec; + buf.modtime = tv[1].tv_sec; + return fs->op.utime(path, &buf); + } else { + return -ENOSYS; + } +} + +int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.access) { + if (1) + libfuse_print("access %s 0%o", path, mask); + + return fs->op.access(path, mask); + } else { + return -ENOSYS; + } +} + +int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, + size_t len) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.readlink) { + if (1) + libfuse_print("readlink %s %lu", path, + (unsigned long) len); + + return fs->op.readlink(path, buf, len); + } else { + return -ENOSYS; + } +} + +int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, + dev_t rdev) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.mknod) { + if (1) + libfuse_print("mknod %s 0%o 0x%llx umask=0%03o", + path, mode, (unsigned long long) rdev, + fuse_get_context()->umask); + + return fs->op.mknod(path, mode, rdev); + } else { + return -ENOSYS; + } +} + +int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.mkdir) { + if (1) + libfuse_print("mkdir %s 0%o umask=0%03o", + path, mode, fuse_get_context()->umask); + + return fs->op.mkdir(path, mode); + } else { + return -ENOSYS; + } +} + +int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, + const char *value, size_t size, int flags) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.setxattr) { + if (1) + libfuse_print("setxattr %s %s %lu 0x%x", + path, name, (unsigned long) size, flags); + + return fs->op.setxattr(path, name, value, size, flags); + } else { + return -ENOSYS; + } +} + +int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, + char *value, size_t size) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.getxattr) { + if (1) + libfuse_print("getxattr %s %s %lu", + path, name, (unsigned long) size); + + return fs->op.getxattr(path, name, value, size); + } else { + return -ENOSYS; + } +} + +int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, + size_t size) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.listxattr) { + if (1) + libfuse_print("listxattr %s %lu", + path, (unsigned long) size); + + return fs->op.listxattr(path, list, size); + } else { + return -ENOSYS; + } +} + +int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, + uint64_t *idx) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.bmap) { + if (1) + libfuse_print("bmap %s blocksize: %lu index: %llu", + path, (unsigned long) blocksize, + (unsigned long long) *idx); + + return fs->op.bmap(path, blocksize, idx); + } else { + return -ENOSYS; + } +} + +int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, const char *name) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.removexattr) { + if (1) + libfuse_print("removexattr %s %s", path, name); + + return fs->op.removexattr(path, name); + } else { + return -ENOSYS; + } +} + +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, void *data) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.ioctl) { + if (1) + libfuse_print("ioctl[%llu] 0x%x flags: 0x%x", + (unsigned long long) fi->fh, cmd, flags); + + return fs->op.ioctl(path, cmd, arg, fi, flags, data); + } else + return -ENOSYS; +} + +int fuse_fs_poll(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, struct fuse_pollhandle *ph, + unsigned *reventsp) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.poll) { + int res; + + if (1) + libfuse_print("poll[%llu] ph: %p", + (unsigned long long) fi->fh, ph); + + res = fs->op.poll(path, fi, ph, reventsp); + + if (1 && !res) + libfuse_print(" poll[%llu] revents: 0x%x", + (unsigned long long) fi->fh, *reventsp); + + return res; + } else + return -ENOSYS; +} + +static int is_open(struct fuse *f, fuse_ino_t dir, const char *name) +{ + struct node *node; + int isopen = 0; + pthread_mutex_lock(&f->lock); + node = lookup_node(f, dir, name); + if (node && node->open_count > 0) + isopen = 1; + pthread_mutex_unlock(&f->lock); + return isopen; +} + +static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname, + char *newname, size_t bufsize) +{ + struct stat buf; + struct node *node; + struct node *newnode; + char *newpath; + int res; + int failctr = 10; + + do { + pthread_mutex_lock(&f->lock); + node = lookup_node(f, dir, oldname); + if (node == NULL) { + pthread_mutex_unlock(&f->lock); + return NULL; + } + do { + f->hidectr ++; + snprintf(newname, bufsize, ".fuse_hidden%08x%08x", + (unsigned int) node->nodeid, f->hidectr); + newnode = lookup_node(f, dir, newname); + } while(newnode); + + try_get_path(f, dir, newname, &newpath, NULL, 0); + pthread_mutex_unlock(&f->lock); + + if (!newpath) + break; + + res = fuse_fs_getattr(f->fs, newpath, &buf); + if (res == -ENOENT) + break; + free(newpath); + newpath = NULL; + } while(res == 0 && --failctr); + + return newpath; +} + +static int hide_node(struct fuse *f, const char *oldpath, + fuse_ino_t dir, const char *oldname) +{ + char newname[64]; + char *newpath; + int err = -EBUSY; + + newpath = hidden_name(f, dir, oldname, newname, sizeof(newname)); + if (newpath) { + err = fuse_fs_rename(f->fs, oldpath, newpath); + if (!err) + err = rename_node(f, dir, oldname, dir, newname, 1); + free(newpath); + } + return err; +} + +static int mtime_eq(const struct stat *stbuf, const struct timespec *ts) +{ + return stbuf->st_mtime == ts->tv_sec && + ST_MTIM_NSEC(stbuf) == ts->tv_nsec; +} + +#ifndef CLOCK_MONOTONIC +#define CLOCK_MONOTONIC CLOCK_REALTIME +#endif + +static void curr_time(struct timespec *now) +{ + static clockid_t clockid = CLOCK_MONOTONIC; + int res = clock_gettime(clockid, now); + if (res == -1 && errno == EINVAL) { + clockid = CLOCK_REALTIME; + res = clock_gettime(clockid, now); + } + if (res == -1) { + perror("fuse: clock_gettime"); + abort(); + } +} + +static void update_stat(struct node *node, const struct stat *stbuf) +{ + if (node->cache_valid && (!mtime_eq(stbuf, &node->mtime) || + stbuf->st_size != node->size)) + node->cache_valid = 0; + node->mtime.tv_sec = stbuf->st_mtime; + node->mtime.tv_nsec = ST_MTIM_NSEC(stbuf); + node->size = stbuf->st_size; + curr_time(&node->stat_updated); +} + +static int lookup_path(struct fuse *f, fuse_ino_t nodeid, + const char *name, const char *path, + struct fuse_entry_param *e, struct fuse_file_info *fi) +{ + int res; + + memset(e, 0, sizeof(struct fuse_entry_param)); + if (fi) + res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi); + else + res = fuse_fs_getattr(f->fs, path, &e->attr); + if (res == 0) { + struct node *node; + + node = find_node(f, nodeid, name, e->attr.st_mode); + if (node == NULL) + res = -ENOMEM; + else { + e->ino = node->nodeid; + e->generation = node->generation; + e->entry_timeout = f->conf.entry_timeout; + e->attr_timeout = f->conf.attr_timeout; + if (f->conf.auto_cache) { + pthread_mutex_lock(&f->lock); + update_stat(node, &e->attr); + pthread_mutex_unlock(&f->lock); + } + set_stat(f, e->ino, &e->attr); + if (f->conf.debug) + libfuse_print(" NODEID: %lu", + (unsigned long) e->ino); + } + } + return res; +} + +static struct fuse_context_i *fuse_get_context_internal(void) +{ + struct fuse_context_i *c; + + c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key); + if (c == NULL) { + c = (struct fuse_context_i *) + malloc(sizeof(struct fuse_context_i)); + if (c == NULL) { + /* This is hard to deal with properly, so just + abort. If memory is so low that the + context cannot be allocated, there's not + much hope for the filesystem anyway */ + libfuse_print("fuse: failed to allocate thread specific data"); + abort(); + } + pthread_setspecific(fuse_context_key, c); + } + return c; +} + +static void fuse_freecontext(void *data) +{ + free(data); +} + +static int fuse_create_context_key(void) +{ + int err = 0; + pthread_mutex_lock(&fuse_context_lock); + if (!fuse_context_ref) { + err = pthread_key_create(&fuse_context_key, fuse_freecontext); + if (err) { + libfuse_print("fuse: failed to create thread specific key: %s", + strerror(err)); + pthread_mutex_unlock(&fuse_context_lock); + return -1; + } + } + fuse_context_ref++; + pthread_mutex_unlock(&fuse_context_lock); + return 0; +} + +static void fuse_delete_context_key(void) +{ + pthread_mutex_lock(&fuse_context_lock); + fuse_context_ref--; + if (!fuse_context_ref) { + free(pthread_getspecific(fuse_context_key)); + pthread_key_delete(fuse_context_key); + } + pthread_mutex_unlock(&fuse_context_lock); +} + +static struct fuse *req_fuse_prepare(fuse_req_t req) +{ + struct fuse_context_i *c = fuse_get_context_internal(); + const struct fuse_ctx *ctx = fuse_req_ctx(req); + c->req = req; + c->ctx.fuse = req_fuse(req); + c->ctx.uid = ctx->uid; + c->ctx.gid = ctx->gid; + c->ctx.pid = ctx->pid; + c->ctx.umask = ctx->umask; + return c->ctx.fuse; +} + +static inline void reply_err(fuse_req_t req, int err) +{ + /* fuse_reply_err() uses non-negated errno values */ + fuse_reply_err(req, -err); +} + +static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e, + int err) +{ + if (!err) { + struct fuse *f = req_fuse(req); + if (fuse_reply_entry(req, e) == -ENOENT) { + /* Skip forget for negative result */ + if (e->ino != 0) + forget_node(f, e->ino, 1); + } + } else + reply_err(req, err); +} + +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.init) + fs->user_data = fs->op.init(conn); +} + +static void fuse_lib_init(void *data, struct fuse_conn_info *conn) +{ + struct fuse *f = (struct fuse *) data; + struct fuse_context_i *c = fuse_get_context_internal(); + + memset(c, 0, sizeof(*c)); + c->ctx.fuse = f; + conn->want |= FUSE_CAP_EXPORT_SUPPORT; + fuse_fs_init(f->fs, conn); +} + +void fuse_fs_destroy(struct fuse_fs *fs) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.destroy) + fs->op.destroy(fs->user_data); + if (fs->m) + fuse_put_module(fs->m); + free(fs); +} + +static void fuse_lib_destroy(void *data) +{ + struct fuse *f = (struct fuse *) data; + struct fuse_context_i *c = fuse_get_context_internal(); + + memset(c, 0, sizeof(*c)); + c->ctx.fuse = f; + fuse_fs_destroy(f->fs); + f->fs = NULL; +} + +static void fuse_lib_lookup(fuse_req_t req, fuse_ino_t parent, + const char *name) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_entry_param e; + char *path; + int err; + struct node *dot = NULL; +/* +Modified by F.KUMAGAE, 06/03/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + char *org_name = NULL; + int len = strlen(name); + if (name[0] == '.') { + if (len == 1 || (name[1] == '.' && len == 2)) { + pthread_mutex_lock(&f->lock); + if (len == 1) { + if (f->conf.debug) + libfuse_print("LOOKUP-DOT"); + dot = get_node_nocheck(f, parent); + if (dot == NULL) { + pthread_mutex_unlock(&f->lock); + reply_entry(req, &e, -ESTALE); + return; + } + dot->refctr++; + } else { + if (f->conf.debug) + libfuse_print("LOOKUP-DOTDOT"); + parent = get_node(f, parent)->parent->nodeid; + } + pthread_mutex_unlock(&f->lock); + name = NULL; + } + } +/* +Modified by F.KUMAGAE, 06/03/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +#define LOOKUP_ISLASTCN_ADDED ('?') + if(name && len && name[len-1] == LOOKUP_ISLASTCN_ADDED){ + org_name = strdup(name); + if(org_name){ + org_name[len-1] = '\0'; + err = get_path_name(f, parent, org_name, &path); + }else{ + err = -ENOMEM; + } + }else{ + err = get_path_name(f, parent, name, &path); + } + if (!err) { + struct fuse_intr_data d; + if (f->conf.debug) + libfuse_print("LOOKUP %s", path); + fuse_prepare_interrupt(f, req, &d); +/* +Modified by F.KUMAGAE, 06/03/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + if(org_name){ + err = lookup_path(f, parent, org_name, path, &e, NULL); + }else{ + struct node *node; + memset(&e, 0, sizeof(struct fuse_entry_param)); + e.attr.st_mode = S_IFDIR | S_IRWXU; + e.attr.st_ino = -1; + e.attr.st_dev = -1; + e.attr.st_size = 0x1000; + node = find_node(f, parent, name, e.attr.st_mode); + if (node == NULL) + err = -ENOMEM; + else { + e.ino = node->nodeid; + e.generation = node->generation; + e.entry_timeout = f->conf.entry_timeout; + e.attr_timeout = f->conf.attr_timeout; + if (f->conf.auto_cache) { + pthread_mutex_lock(&f->lock); + update_stat(node, &e.attr); + pthread_mutex_unlock(&f->lock); + } + set_stat(f, e.ino, &e.attr); + if (f->conf.debug) + libfuse_print(" NODEID: %lu", + (unsigned long) e.ino); + } + } + if (err == -ENOENT && f->conf.negative_timeout != 0.0) { + e.ino = 0; + e.entry_timeout = f->conf.negative_timeout; + err = 0; + } + fuse_finish_interrupt(f, req, &d); + free_path(f, parent, path); + } +/* +Modified by F.KUMAGAE, 06/03/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + if(org_name){ + free(org_name); + org_name = NULL; + } + if (dot) { + pthread_mutex_lock(&f->lock); + unref_node(f, dot); + pthread_mutex_unlock(&f->lock); + } + reply_entry(req, &e, err); +} + +static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, + unsigned long nlookup) +{ + struct fuse *f = req_fuse(req); + if (f->conf.debug) + libfuse_print("FORGET %llu/%lu", (unsigned long long)ino, + nlookup); + forget_node(f, ino, nlookup); + fuse_reply_none(req); +} + +static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct stat buf; + char *path; + int err; + + memset(&buf, 0, sizeof(buf)); + + if (fi != NULL) + err = get_path_nullok(f, ino, &path); + else + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + if (fi) + err = fuse_fs_fgetattr(f->fs, path, &buf, fi); + else + err = fuse_fs_getattr(f->fs, path, &buf); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + if (!err) { + if (f->conf.auto_cache) { + pthread_mutex_lock(&f->lock); + update_stat(get_node(f, ino), &buf); + pthread_mutex_unlock(&f->lock); + } + set_stat(f, ino, &buf); + fuse_reply_attr(req, &buf, f->conf.attr_timeout); + } else + reply_err(req, err); +} + +int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode) +{ + fuse_get_context()->private_data = fs->user_data; + if (fs->op.chmod) + return fs->op.chmod(path, mode); + else + return -ENOSYS; +} + +static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int valid, struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct stat buf; + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = 0; + if (!err && (valid & FUSE_SET_ATTR_MODE)) + err = fuse_fs_chmod(f->fs, path, attr->st_mode); + if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) { + uid_t uid = (valid & FUSE_SET_ATTR_UID) ? + attr->st_uid : (uid_t) -1; + gid_t gid = (valid & FUSE_SET_ATTR_GID) ? + attr->st_gid : (gid_t) -1; + err = fuse_fs_chown(f->fs, path, uid, gid); + } + if (!err && (valid & FUSE_SET_ATTR_SIZE)) { + if (fi) + err = fuse_fs_ftruncate(f->fs, path, + attr->st_size, fi); + else + err = fuse_fs_truncate(f->fs, path, + attr->st_size); + } + if (!err && + (valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) == + (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) { + struct timespec tv[2]; + tv[0].tv_sec = attr->st_atime; + tv[0].tv_nsec = ST_ATIM_NSEC(attr); + tv[1].tv_sec = attr->st_mtime; + tv[1].tv_nsec = ST_MTIM_NSEC(attr); + err = fuse_fs_utimens(f->fs, path, tv); + } + if (!err) + err = fuse_fs_getattr(f->fs, path, &buf); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + if (!err) { + if (f->conf.auto_cache) { + pthread_mutex_lock(&f->lock); + update_stat(get_node(f, ino), &buf); + pthread_mutex_unlock(&f->lock); + } + set_stat(f, ino, &buf); + fuse_reply_attr(req, &buf, f->conf.attr_timeout); + } else + reply_err(req, err); +} + +static void fuse_lib_access(fuse_req_t req, fuse_ino_t ino, int mask) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_access(f->fs, path, mask); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + +static void fuse_lib_readlink(fuse_req_t req, fuse_ino_t ino) +{ + struct fuse *f = req_fuse_prepare(req); + char linkname[PATH_MAX + 1]; + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_readlink(f->fs, path, linkname, sizeof(linkname)); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + if (!err) { + linkname[PATH_MAX] = '\0'; + fuse_reply_readlink(req, linkname); + } else + reply_err(req, err); +} + +static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_entry_param e; + char *path; + int err; + + err = get_path_name(f, parent, name, &path); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = -ENOSYS; + if (S_ISREG(mode)) { + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.flags = O_CREAT | O_EXCL | O_WRONLY; + err = fuse_fs_create(f->fs, path, mode, &fi); + if (!err) { + err = lookup_path(f, parent, name, path, &e, + &fi); + fuse_fs_release(f->fs, path, &fi); + } + } + if (err == -ENOSYS) { + err = fuse_fs_mknod(f->fs, path, mode, rdev); + if (!err) + err = lookup_path(f, parent, name, path, &e, + NULL); + } + fuse_finish_interrupt(f, req, &d); + free_path(f, parent, path); + } + reply_entry(req, &e, err); +} + +static void fuse_lib_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_entry_param e; + char *path; + int err; + + err = get_path_name(f, parent, name, &path); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_mkdir(f->fs, path, mode); + if (!err) + err = lookup_path(f, parent, name, path, &e, NULL); + fuse_finish_interrupt(f, req, &d); + free_path(f, parent, path); + } + reply_entry(req, &e, err); +} + +static void fuse_lib_unlink(fuse_req_t req, fuse_ino_t parent, + const char *name) +{ + struct fuse *f = req_fuse_prepare(req); + struct node *wnode; + char *path; + int err; + + err = get_path_wrlock(f, parent, name, &path, &wnode); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + if (!f->conf.hard_remove && is_open(f, parent, name)) { + err = hide_node(f, path, parent, name); + } else { + err = fuse_fs_unlink(f->fs, path); + if (!err) + remove_node(f, parent, name); + } + fuse_finish_interrupt(f, req, &d); + free_path_wrlock(f, parent, wnode, path); + } + reply_err(req, err); +} + +static void fuse_lib_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name) +{ + struct fuse *f = req_fuse_prepare(req); + struct node *wnode; + char *path; + int err; + + err = get_path_wrlock(f, parent, name, &path, &wnode); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_rmdir(f->fs, path); + fuse_finish_interrupt(f, req, &d); + if (!err) + remove_node(f, parent, name); + free_path_wrlock(f, parent, wnode, path); + } + reply_err(req, err); +} + +static void fuse_lib_symlink(fuse_req_t req, const char *linkname, + fuse_ino_t parent, const char *name) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_entry_param e; + char *path; + int err; + + err = get_path_name(f, parent, name, &path); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_symlink(f->fs, linkname, path); + if (!err) + err = lookup_path(f, parent, name, path, &e, NULL); + fuse_finish_interrupt(f, req, &d); + free_path(f, parent, path); + } + reply_entry(req, &e, err); +} + +static void fuse_lib_rename(fuse_req_t req, fuse_ino_t olddir, + const char *oldname, fuse_ino_t newdir, + const char *newname) +{ + struct fuse *f = req_fuse_prepare(req); + char *oldpath; + char *newpath; + struct node *wnode1; + struct node *wnode2; + int err; + + err = get_path2(f, olddir, oldname, newdir, newname, + &oldpath, &newpath, &wnode1, &wnode2); + if (!err) { + struct fuse_intr_data d; + err = 0; + fuse_prepare_interrupt(f, req, &d); + if (!f->conf.hard_remove && is_open(f, newdir, newname)) + err = hide_node(f, newpath, newdir, newname); + if (!err) { + err = fuse_fs_rename(f->fs, oldpath, newpath); + if (!err) + err = rename_node(f, olddir, oldname, newdir, + newname, 0); + } + fuse_finish_interrupt(f, req, &d); + free_path2(f, olddir, newdir, wnode1, wnode2, oldpath, newpath); + } + reply_err(req, err); +} + +static void fuse_lib_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_entry_param e; + char *oldpath; + char *newpath; + int err; + + err = get_path2(f, ino, NULL, newparent, newname, + &oldpath, &newpath, NULL, NULL); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_link(f->fs, oldpath, newpath); + if (!err) + err = lookup_path(f, newparent, newname, newpath, + &e, NULL); + fuse_finish_interrupt(f, req, &d); + free_path2(f, ino, newparent, NULL, NULL, oldpath, newpath); + } + reply_entry(req, &e, err); +} + +static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path, + struct fuse_file_info *fi) +{ + struct node *node; + int unlink_hidden = 0; + + fuse_fs_release(f->fs, (path || f->nullpath_ok) ? path : "-", fi); + + pthread_mutex_lock(&f->lock); + node = get_node(f, ino); + assert(node->open_count > 0); + --node->open_count; + if (node->is_hidden && !node->open_count) { + unlink_hidden = 1; + node->is_hidden = 0; + } + pthread_mutex_unlock(&f->lock); + + if(unlink_hidden && path) + fuse_fs_unlink(f->fs, path); +} + +static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent, + const char *name, mode_t mode, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + struct fuse_entry_param e; + char *path; + int err; + + err = get_path_name(f, parent, name, &path); + if (!err) { + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_create(f->fs, path, mode, fi); + if (!err) { + err = lookup_path(f, parent, name, path, &e, fi); + if (err) + fuse_fs_release(f->fs, path, fi); + else if (!S_ISREG(e.attr.st_mode)) { + err = -EIO; + fuse_fs_release(f->fs, path, fi); + forget_node(f, e.ino, 1); + } else { + if (f->conf.direct_io) + fi->direct_io = 1; + if (f->conf.kernel_cache) + fi->keep_cache = 1; + + } + } + fuse_finish_interrupt(f, req, &d); + } + if (!err) { + pthread_mutex_lock(&f->lock); + get_node(f, e.ino)->open_count++; + pthread_mutex_unlock(&f->lock); + if (fuse_reply_create(req, &e, fi) == -ENOENT) { +/* +Modified by Y.ITO, 02/16/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /* The open syscall was interrupted, so it + must be cancelled */ + fuse_do_release(f, e.ino, path, fi); + forget_node(f, e.ino, 1); + } + } else { + reply_err(req, err); + } + + free_path(f, parent, path); +} + +static double diff_timespec(const struct timespec *t1, + const struct timespec *t2) +{ + return (t1->tv_sec - t2->tv_sec) + + ((double) t1->tv_nsec - (double) t2->tv_nsec) / 1000000000.0; +} + +static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path, + struct fuse_file_info *fi) +{ + struct node *node; + + pthread_mutex_lock(&f->lock); + node = get_node(f, ino); + if (node->cache_valid) { + struct timespec now; + + curr_time(&now); + if (diff_timespec(&now, &node->stat_updated) > + f->conf.ac_attr_timeout) { + struct stat stbuf; + int err; + pthread_mutex_unlock(&f->lock); + err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi); + pthread_mutex_lock(&f->lock); + if (!err) + update_stat(node, &stbuf); + else + node->cache_valid = 0; + } + } + if (node->cache_valid) + fi->keep_cache = 1; + + node->cache_valid = 1; + pthread_mutex_unlock(&f->lock); +} + +static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_open(f->fs, path, fi); + if (!err) { + if (f->conf.direct_io) + fi->direct_io = 1; + if (f->conf.kernel_cache) + fi->keep_cache = 1; + + if (f->conf.auto_cache) + open_auto_cache(f, ino, path, fi); + } + fuse_finish_interrupt(f, req, &d); + } + if (!err) { + pthread_mutex_lock(&f->lock); + get_node(f, ino)->open_count++; + pthread_mutex_unlock(&f->lock); + if (fuse_reply_open(req, fi) == -ENOENT) { +/* +Modified by Y.ITO, 02/16/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /* The open syscall was interrupted, so it + must be cancelled */ + fuse_do_release(f, ino, path, fi); + } + } else + reply_err(req, err); + + free_path(f, ino, path); +} + +static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size, + off_t off, struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + char *buf; + int res; + + buf = (char *) malloc(size); + if (buf == NULL) { + reply_err(req, -ENOMEM); + return; + } + + res = get_path_nullok(f, ino, &path); + if (res == 0) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + res = fuse_fs_read(f->fs, path, buf, size, off, fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + + if (res >= 0) + fuse_reply_buf(req, buf, res); + else + reply_err(req, res); + + free(buf); +} + +static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int res; + + res = get_path_nullok(f, ino, &path); + if (res == 0) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + res = fuse_fs_write(f->fs, path, buf, size, off, fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + + if (res >= 0) + fuse_reply_write(req, res); + else + reply_err(req, res); +} + +static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path_nullok(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_fsync(f->fs, path, datasync, fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + +static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi, + struct fuse_file_info *fi) +{ + struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh; + memset(fi, 0, sizeof(struct fuse_file_info)); + fi->fh = dh->fh; + fi->fh_old = dh->fh; + return dh; +} + +static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *llfi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + struct fuse_dh *dh; + struct fuse_file_info fi; + char *path; + int err; + + dh = (struct fuse_dh *) malloc(sizeof(struct fuse_dh)); + if (dh == NULL) { + reply_err(req, -ENOMEM); + return; + } + memset(dh, 0, sizeof(struct fuse_dh)); + dh->fuse = f; + dh->contents = NULL; + dh->len = 0; + dh->filled = 0; + dh->nodeid = ino; + fuse_mutex_init(&dh->lock); + + llfi->fh = (uintptr_t) dh; + + memset(&fi, 0, sizeof(fi)); + fi.flags = llfi->flags; + + err = get_path(f, ino, &path); + if (!err) { + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_opendir(f->fs, path, &fi); + fuse_finish_interrupt(f, req, &d); + dh->fh = fi.fh; + } + if (!err) { + if (fuse_reply_open(req, llfi) == -ENOENT) { +/* +Modified by Y.ITO, 02/16/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /* The opendir syscall was interrupted, so it + must be cancelled */ + fuse_fs_releasedir(f->fs, path, &fi); + pthread_mutex_destroy(&dh->lock); + free(dh); + } + } else { + reply_err(req, err); + pthread_mutex_destroy(&dh->lock); + free(dh); + } + free_path(f, ino, path); +} + +static int extend_contents(struct fuse_dh *dh, unsigned minsize) +{ + if (minsize > dh->size) { + char *newptr; + unsigned newsize = dh->size; + if (!newsize) + newsize = 1024; + while (newsize < minsize) { + if (newsize >= 0x80000000) + newsize = 0xffffffff; + else + newsize *= 2; + } + + newptr = (char *) realloc(dh->contents, newsize); + if (!newptr) { + dh->error = -ENOMEM; + return -1; + } + dh->contents = newptr; + dh->size = newsize; + } + return 0; +} + +static int fill_dir(void *dh_, const char *name, const struct stat *statp, + off_t off) +{ + struct fuse_dh *dh = (struct fuse_dh *) dh_; + struct stat stbuf; + size_t newlen; + + if (statp) + stbuf = *statp; + else { + memset(&stbuf, 0, sizeof(stbuf)); + stbuf.st_ino = FUSE_UNKNOWN_INO; + } + + if (!dh->fuse->conf.use_ino) { + stbuf.st_ino = FUSE_UNKNOWN_INO; + if (dh->fuse->conf.readdir_ino) { + struct node *node; + pthread_mutex_lock(&dh->fuse->lock); + node = lookup_node(dh->fuse, dh->nodeid, name); + if (node) + stbuf.st_ino = (ino_t) node->nodeid; + pthread_mutex_unlock(&dh->fuse->lock); + } + } + + if (off) { + if (extend_contents(dh, dh->needlen) == -1) + return 1; + + dh->filled = 0; + newlen = dh->len + + fuse_add_direntry(dh->req, dh->contents + dh->len, + dh->needlen - dh->len, name, + &stbuf, off); + if (newlen > dh->needlen) + return 1; + } else { + newlen = dh->len + + fuse_add_direntry(dh->req, NULL, 0, name, NULL, 0); + if (extend_contents(dh, newlen) == -1) + return 1; + + fuse_add_direntry(dh->req, dh->contents + dh->len, + dh->size - dh->len, name, &stbuf, newlen); + } + dh->len = newlen; + return 0; +} + +static int readdir_fill(struct fuse *f, fuse_req_t req, fuse_ino_t ino, + size_t size, off_t off, struct fuse_dh *dh, + struct fuse_file_info *fi) +{ + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + + dh->len = 0; + dh->error = 0; + dh->needlen = size; + dh->filled = 1; + dh->req = req; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_readdir(f->fs, path, dh, fill_dir, off, fi); + fuse_finish_interrupt(f, req, &d); + dh->req = NULL; + if (!err) + err = dh->error; + if (err) + dh->filled = 0; + free_path(f, ino, path); + } + return err; +} + +static void fuse_lib_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, + off_t off, struct fuse_file_info *llfi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_file_info fi; + struct fuse_dh *dh = get_dirhandle(llfi, &fi); + + pthread_mutex_lock(&dh->lock); + /* According to SUS, directory contents need to be refreshed on + rewinddir() */ + if (!off) + dh->filled = 0; + + if (!dh->filled) { + int err = readdir_fill(f, req, ino, size, off, dh, &fi); + if (err) { + reply_err(req, err); + goto out; + } + } + if (dh->filled) { + if (off < dh->len) { + if (off + size > dh->len) + size = dh->len - off; + } else + size = 0; + } else { + size = dh->len; + off = 0; + } + fuse_reply_buf(req, dh->contents + off, size); +out: + pthread_mutex_unlock(&dh->lock); +} + +static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *llfi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + struct fuse_file_info fi; + struct fuse_dh *dh = get_dirhandle(llfi, &fi); + char *path; + + get_path(f, ino, &path); + fuse_prepare_interrupt(f, req, &d); + fuse_fs_releasedir(f->fs, (path || f->nullpath_ok) ? path : "-", &fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + + pthread_mutex_lock(&dh->lock); + pthread_mutex_unlock(&dh->lock); + pthread_mutex_destroy(&dh->lock); + free(dh->contents); + free(dh); + reply_err(req, 0); +} + +static void fuse_lib_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *llfi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_file_info fi; + char *path; + int err; + + get_dirhandle(llfi, &fi); + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_fsyncdir(f->fs, path, datasync, &fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + +static void fuse_lib_statfs(fuse_req_t req, fuse_ino_t ino) +{ + struct fuse *f = req_fuse_prepare(req); + struct statvfs buf; + char *path = NULL; + int err = 0; + + memset(&buf, 0, sizeof(buf)); + if (ino) + err = get_path(f, ino, &path); + + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_statfs(f->fs, path ? path : "/", &buf); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + + if (!err) + fuse_reply_statfs(req, &buf); + else + reply_err(req, err); +} + +static void fuse_lib_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_setxattr(f->fs, path, name, value, size, flags); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + +static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, + const char *name, char *value, size_t size) +{ + int err; + char *path; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_getxattr(f->fs, path, name, value, size); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + return err; +} + +static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size) +{ + struct fuse *f = req_fuse_prepare(req); + int res; + + if (size) { + char *value = (char *) malloc(size); + if (value == NULL) { + reply_err(req, -ENOMEM); + return; + } + res = common_getxattr(f, req, ino, name, value, size); + if (res > 0) + fuse_reply_buf(req, value, res); + else + reply_err(req, res); + free(value); + } else { + res = common_getxattr(f, req, ino, name, NULL, 0); + if (res >= 0) + fuse_reply_xattr(req, res); + else + reply_err(req, res); + } +} + +static int common_listxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino, + char *list, size_t size) +{ + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_listxattr(f->fs, path, list, size); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + return err; +} + +static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) +{ + struct fuse *f = req_fuse_prepare(req); + int res; + + if (size) { + char *list = (char *) malloc(size); + if (list == NULL) { + reply_err(req, -ENOMEM); + return; + } + res = common_listxattr(f, req, ino, list, size); + if (res > 0) + fuse_reply_buf(req, list, res); + else + reply_err(req, res); + free(list); + } else { + res = common_listxattr(f, req, ino, NULL, 0); + if (res >= 0) + fuse_reply_xattr(req, res); + else + reply_err(req, res); + } +} + +static void fuse_lib_removexattr(fuse_req_t req, fuse_ino_t ino, + const char *name) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_removexattr(f->fs, path, name); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + reply_err(req, err); +} + +static struct lock *locks_conflict(struct node *node, const struct lock *lock) +{ + struct lock *l; + + for (l = node->locks; l; l = l->next) + if (l->owner != lock->owner && + lock->start <= l->end && l->start <= lock->end && + (l->type == F_WRLCK || lock->type == F_WRLCK)) + break; + + return l; +} + +static void delete_lock(struct lock **lockp) +{ + struct lock *l = *lockp; + *lockp = l->next; + free(l); +} + +static void insert_lock(struct lock **pos, struct lock *lock) +{ + lock->next = *pos; + *pos = lock; +} + +static int locks_insert(struct node *node, struct lock *lock) +{ + struct lock **lp; + struct lock *newl1 = NULL; + struct lock *newl2 = NULL; + + if (lock->type != F_UNLCK || lock->start != 0 || + lock->end != OFFSET_MAX) { + newl1 = malloc(sizeof(struct lock)); + newl2 = malloc(sizeof(struct lock)); + + if (!newl1 || !newl2) { + free(newl1); + free(newl2); + return -ENOLCK; + } + } + + for (lp = &node->locks; *lp;) { + struct lock *l = *lp; + if (l->owner != lock->owner) + goto skip; + + if (lock->type == l->type) { + if (l->end < lock->start - 1) + goto skip; + if (lock->end < l->start - 1) + break; + if (l->start <= lock->start && lock->end <= l->end) + goto out; + if (l->start < lock->start) + lock->start = l->start; + if (lock->end < l->end) + lock->end = l->end; + goto delete; + } else { + if (l->end < lock->start) + goto skip; + if (lock->end < l->start) + break; + if (lock->start <= l->start && l->end <= lock->end) + goto delete; + if (l->end <= lock->end) { + l->end = lock->start - 1; + goto skip; + } + if (lock->start <= l->start) { + l->start = lock->end + 1; + break; + } + *newl2 = *l; + newl2->start = lock->end + 1; + l->end = lock->start - 1; + insert_lock(&l->next, newl2); + newl2 = NULL; + } + skip: + lp = &l->next; + continue; + + delete: + delete_lock(lp); + } + if (lock->type != F_UNLCK) { + *newl1 = *lock; + insert_lock(lp, newl1); + newl1 = NULL; + } +out: + free(newl1); + free(newl2); + return 0; +} + +static void flock_to_lock(struct flock *flock, struct lock *lock) +{ + memset(lock, 0, sizeof(struct lock)); + lock->type = flock->l_type; + lock->start = flock->l_start; + lock->end = + flock->l_len ? flock->l_start + flock->l_len - 1 : OFFSET_MAX; + lock->pid = flock->l_pid; +} + +static void lock_to_flock(struct lock *lock, struct flock *flock) +{ + flock->l_type = lock->type; + flock->l_start = lock->start; + flock->l_len = + (lock->end == OFFSET_MAX) ? 0 : lock->end - lock->start + 1; + flock->l_pid = lock->pid; +} + +static int fuse_flush_common(struct fuse *f, fuse_req_t req, fuse_ino_t ino, + const char *path, struct fuse_file_info *fi) +{ + struct fuse_intr_data d; + struct flock lock; + struct lock l; + int err; + int errlock; + + fuse_prepare_interrupt(f, req, &d); + memset(&lock, 0, sizeof(lock)); + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + err = fuse_fs_flush(f->fs, path, fi); + errlock = fuse_fs_lock(f->fs, path, fi, F_SETLK, &lock); + fuse_finish_interrupt(f, req, &d); + + if (errlock != -ENOSYS) { + flock_to_lock(&lock, &l); + l.owner = fi->lock_owner; + pthread_mutex_lock(&f->lock); + locks_insert(get_node(f, ino), &l); + pthread_mutex_unlock(&f->lock); + + /* if op.lock() is defined FLUSH is needed regardless + of op.flush() */ + if (err == -ENOSYS) + err = 0; + } + return err; +} + +static void fuse_lib_release(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int err = 0; + + get_path(f, ino, &path); + if (fi->flush) { + err = fuse_flush_common(f, req, ino, path, fi); + if (err == -ENOSYS) + err = 0; + } + + fuse_prepare_interrupt(f, req, &d); + fuse_do_release(f, ino, path, fi); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + + reply_err(req, err); +} + +static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + get_path(f, ino, &path); + err = fuse_flush_common(f, req, ino, path, fi); + free_path(f, ino, path); + + reply_err(req, err); +} + +static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock, + int cmd) +{ + struct fuse *f = req_fuse_prepare(req); + char *path; + int err; + + err = get_path_nullok(f, ino, &path); + if (!err) { + struct fuse_intr_data d; + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_lock(f->fs, path, fi, cmd, lock); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + return err; +} + +static void fuse_lib_getlk(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock) +{ + int err; + struct lock l; + struct lock *conflict; + struct fuse *f = req_fuse(req); + + flock_to_lock(lock, &l); + l.owner = fi->lock_owner; + pthread_mutex_lock(&f->lock); + conflict = locks_conflict(get_node(f, ino), &l); + if (conflict) + lock_to_flock(conflict, lock); + pthread_mutex_unlock(&f->lock); + if (!conflict) + err = fuse_lock_common(req, ino, fi, lock, F_GETLK); + else + err = 0; + + if (!err) + fuse_reply_lock(req, lock); + else + reply_err(req, err); +} + +static void fuse_lib_setlk(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock, + int sleep) +{ + int err = fuse_lock_common(req, ino, fi, lock, + sleep ? F_SETLKW : F_SETLK); + if (!err) { + struct fuse *f = req_fuse(req); + struct lock l; + flock_to_lock(lock, &l); + l.owner = fi->lock_owner; + pthread_mutex_lock(&f->lock); + locks_insert(get_node(f, ino), &l); + pthread_mutex_unlock(&f->lock); + } + reply_err(req, err); +} + +static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t idx) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int err; + + err = get_path(f, ino, &path); + if (!err) { + fuse_prepare_interrupt(f, req, &d); + err = fuse_fs_bmap(f->fs, path, blocksize, &idx); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + if (!err) + fuse_reply_bmap(req, idx); + else + reply_err(req, err); +} + +static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, + size_t out_bufsz) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path, *out_buf = NULL; + int err; + + err = -EPERM; + if (flags & FUSE_IOCTL_UNRESTRICTED) + goto err; + + if (out_bufsz) { + err = -ENOMEM; + out_buf = malloc(out_bufsz); + if (!out_buf) + goto err; + } + + assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz); + if (out_buf) + memcpy(out_buf, in_buf, in_bufsz); + + err = get_path(f, ino, &path); + if (err) + goto err; + + fuse_prepare_interrupt(f, req, &d); + + err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags, + out_buf ?: (void *)in_buf); + + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + + fuse_reply_ioctl(req, err, out_buf, out_bufsz); + goto out; +err: + reply_err(req, err); +out: + free(out_buf); +} + +static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct fuse_pollhandle *ph) +{ + struct fuse *f = req_fuse_prepare(req); + struct fuse_intr_data d; + char *path; + int ret; + unsigned revents = 0; + + ret = get_path(f, ino, &path); + if (!ret) { + fuse_prepare_interrupt(f, req, &d); + ret = fuse_fs_poll(f->fs, path, fi, ph, &revents); + fuse_finish_interrupt(f, req, &d); + free_path(f, ino, path); + } + if (!ret) + fuse_reply_poll(req, revents); + else + reply_err(req, ret); +} + +static struct fuse_lowlevel_ops fuse_path_ops = { + .init = fuse_lib_init, + .destroy = fuse_lib_destroy, + .lookup = fuse_lib_lookup, + .forget = fuse_lib_forget, + .getattr = fuse_lib_getattr, + .setattr = fuse_lib_setattr, + .access = fuse_lib_access, + .readlink = fuse_lib_readlink, + .mknod = fuse_lib_mknod, + .mkdir = fuse_lib_mkdir, + .unlink = fuse_lib_unlink, + .rmdir = fuse_lib_rmdir, + .symlink = fuse_lib_symlink, + .rename = fuse_lib_rename, + .link = fuse_lib_link, + .create = fuse_lib_create, + .open = fuse_lib_open, + .read = fuse_lib_read, + .write = fuse_lib_write, + .flush = fuse_lib_flush, + .release = fuse_lib_release, + .fsync = fuse_lib_fsync, + .opendir = fuse_lib_opendir, + .readdir = fuse_lib_readdir, + .releasedir = fuse_lib_releasedir, + .fsyncdir = fuse_lib_fsyncdir, + .statfs = fuse_lib_statfs, + .setxattr = fuse_lib_setxattr, + .getxattr = fuse_lib_getxattr, + .listxattr = fuse_lib_listxattr, + .removexattr = fuse_lib_removexattr, + .getlk = fuse_lib_getlk, + .setlk = fuse_lib_setlk, + .bmap = fuse_lib_bmap, + .ioctl = fuse_lib_ioctl, + .poll = fuse_lib_poll, +}; + +int fuse_notify_poll(struct fuse_pollhandle *ph) +{ + return fuse_lowlevel_notify_poll(ph); +} + +static void free_cmd(struct fuse_cmd *cmd) +{ + free(cmd->buf); + free(cmd); +} + +void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) +{ + fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch); + free_cmd(cmd); +} + +int fuse_exited(struct fuse *f) +{ + return fuse_session_exited(f->se); +} + +struct fuse_session *fuse_get_session(struct fuse *f) +{ + return f->se; +} + +static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize) +{ + struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd)); + if (cmd == NULL) { + libfuse_print("fuse: failed to allocate cmd"); + return NULL; + } + cmd->buf = (char *) malloc(bufsize); + if (cmd->buf == NULL) { + libfuse_print("fuse: failed to allocate read buffer"); + free(cmd); + return NULL; + } + return cmd; +} + +struct fuse_cmd *fuse_read_cmd(struct fuse *f) +{ + struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL); + size_t bufsize = fuse_chan_bufsize(ch); + struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize); + if (cmd != NULL) { + int res = fuse_chan_recv(&ch, cmd->buf, bufsize); + if (res <= 0) { + free_cmd(cmd); + if (res < 0 && res != -EINTR && res != -EAGAIN) + fuse_exit(f); + return NULL; + } + cmd->buflen = res; + cmd->ch = ch; + } + return cmd; +} + +int fuse_loop(struct fuse *f) +{ + if (f) + return fuse_session_loop(f->se); + else + return -1; +} + +int fuse_invalidate(struct fuse *f, const char *path) +{ + (void) f; + (void) path; + return -EINVAL; +} + +void fuse_exit(struct fuse *f) +{ + fuse_session_exit(f->se); +} + +struct fuse_context *fuse_get_context(void) +{ + return &fuse_get_context_internal()->ctx; +} + +/* + * The size of fuse_context got extended, so need to be careful about + * incompatibility (i.e. a new binary cannot work with an old + * library). + */ +struct fuse_context *fuse_get_context_compat22(void); +struct fuse_context *fuse_get_context_compat22(void) +{ + return &fuse_get_context_internal()->ctx; +} +FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2"); + +int fuse_getgroups(int size, gid_t list[]) +{ + fuse_req_t req = fuse_get_context_internal()->req; + return fuse_req_getgroups(req, size, list); +} + +int fuse_interrupted(void) +{ + return fuse_req_interrupted(fuse_get_context_internal()->req); +} + +void fuse_set_getcontext_func(struct fuse_context *(*func)(void)) +{ + (void) func; + /* no-op */ +} + +enum { + KEY_HELP, +}; + +#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v } + +static const struct fuse_opt fuse_lib_opts[] = { + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), + FUSE_LIB_OPT("debug", debug, 1), + FUSE_LIB_OPT("-d", debug, 1), + FUSE_LIB_OPT("hard_remove", hard_remove, 1), + FUSE_LIB_OPT("use_ino", use_ino, 1), + FUSE_LIB_OPT("readdir_ino", readdir_ino, 1), + FUSE_LIB_OPT("direct_io", direct_io, 1), + FUSE_LIB_OPT("kernel_cache", kernel_cache, 1), + FUSE_LIB_OPT("auto_cache", auto_cache, 1), + FUSE_LIB_OPT("noauto_cache", auto_cache, 0), + FUSE_LIB_OPT("umask=", set_mode, 1), + FUSE_LIB_OPT("umask=%o", umask, 0), + FUSE_LIB_OPT("uid=", set_uid, 1), + FUSE_LIB_OPT("uid=%d", uid, 0), + FUSE_LIB_OPT("gid=", set_gid, 1), + FUSE_LIB_OPT("gid=%d", gid, 0), + FUSE_LIB_OPT("entry_timeout=%lf", entry_timeout, 0), + FUSE_LIB_OPT("attr_timeout=%lf", attr_timeout, 0), + FUSE_LIB_OPT("ac_attr_timeout=%lf", ac_attr_timeout, 0), + FUSE_LIB_OPT("ac_attr_timeout=", ac_attr_timeout_set, 1), + FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0), + FUSE_LIB_OPT("noforget", noforget, 1), + FUSE_LIB_OPT("intr", intr, 1), + FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0), + FUSE_LIB_OPT("modules=%s", modules, 0), + FUSE_OPT_END +}; + +static void fuse_lib_help(void) +{ + fprintf(stderr, +" -o hard_remove immediate removal (don't hide files)" +" -o use_ino let filesystem set inode numbers" +" -o readdir_ino try to fill in d_ino in readdir" +" -o direct_io use direct I/O" +" -o kernel_cache cache files in kernel" +" -o [no]auto_cache enable caching based on modification times (off)" +" -o umask=M set file permissions (octal)" +" -o uid=N set file owner" +" -o gid=N set file group" +" -o entry_timeout=T cache timeout for names (1.0s)" +" -o negative_timeout=T cache timeout for deleted names (0.0s)" +" -o attr_timeout=T cache timeout for attributes (1.0s)" +" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)" +" -o intr allow requests to be interrupted" +" -o intr_signal=NUM signal to send on interrupt (%i)" +" -o modules=M1[:M2...] names of modules to push onto filesystem stack" +"", FUSE_DEFAULT_INTR_SIGNAL); +} + +static void fuse_lib_help_modules(void) +{ + struct fuse_module *m; + libfuse_print("\nModule options:"); + pthread_mutex_lock(&fuse_context_lock); + for (m = fuse_modules; m; m = m->next) { + struct fuse_fs *fs = NULL; + struct fuse_fs *newfs; + struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + if (fuse_opt_add_arg(&args, "") != -1 && + fuse_opt_add_arg(&args, "-h") != -1) { + libfuse_print("\n[%s]", m->name); + newfs = m->factory(&args, &fs); + assert(newfs == NULL); + } + fuse_opt_free_args(&args); + } + pthread_mutex_unlock(&fuse_context_lock); +} + +static int fuse_lib_opt_proc(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + (void) arg; (void) outargs; + + if (key == KEY_HELP) { + struct fuse_config *conf = (struct fuse_config *) data; + fuse_lib_help(); + conf->help = 1; + } + + return 1; +} + +int fuse_is_lib_option(const char *opt) +{ + return fuse_lowlevel_is_lib_option(opt) || + fuse_opt_match(fuse_lib_opts, opt); +} + +static int fuse_init_intr_signal(int signum, int *installed) +{ + struct sigaction old_sa; + + if (sigaction(signum, NULL, &old_sa) == -1) { + perror("fuse: cannot get old signal handler"); + return -1; + } + + if (old_sa.sa_handler == SIG_DFL) { + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = fuse_intr_sighandler; + sigemptyset(&sa.sa_mask); + + if (sigaction(signum, &sa, NULL) == -1) { + perror("fuse: cannot set interrupt signal handler"); + return -1; + } + *installed = 1; + } + return 0; +} + +static void fuse_restore_intr_signal(int signum) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = SIG_DFL; + sigaction(signum, &sa, NULL); +} + + +static int fuse_push_module(struct fuse *f, const char *module, + struct fuse_args *args) +{ + struct fuse_fs *fs[2] = { f->fs, NULL }; + struct fuse_fs *newfs; + struct fuse_module *m = fuse_get_module(module); + + if (!m) + return -1; + + newfs = m->factory(args, fs); + if (!newfs) { + fuse_put_module(m); + return -1; + } + newfs->m = m; + f->fs = newfs; + f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok; + return 0; +} + +struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, + void *user_data) +{ + struct fuse_fs *fs; + + if (sizeof(struct fuse_operations) < op_size) { + libfuse_print("fuse: warning: library too old, some operations may not not work"); + op_size = sizeof(struct fuse_operations); + } + + fs = (struct fuse_fs *) calloc(1, sizeof(struct fuse_fs)); + if (!fs) { + libfuse_print("fuse: failed to allocate fuse_fs object"); + return NULL; + } + + fs->user_data = user_data; + if (op) + memcpy(&fs->op, op, op_size); + return fs; +} + +struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, + size_t op_size, void *user_data, int compat) +{ + struct fuse *f; + struct node *root; + struct fuse_fs *fs; + struct fuse_lowlevel_ops llop = fuse_path_ops; + + if (fuse_create_context_key() == -1) + goto out; + + f = (struct fuse *) calloc(1, sizeof(struct fuse)); + if (f == NULL) { + libfuse_print("fuse: failed to allocate fuse object"); + goto out_delete_context_key; + } + + fs = fuse_fs_new(op, op_size, user_data); + if (!fs) + goto out_free; + + fs->compat = compat; + f->fs = fs; + f->nullpath_ok = fs->op.flag_nullpath_ok; + + /* Oh f**k, this is ugly! */ + if (!fs->op.lock) { + llop.getlk = NULL; + llop.setlk = NULL; + } + + f->conf.entry_timeout = 1.0; + f->conf.attr_timeout = 1.0; + f->conf.negative_timeout = 0.0; + f->conf.intr_signal = FUSE_DEFAULT_INTR_SIGNAL; + + if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, + fuse_lib_opt_proc) == -1) + goto out_free_fs; + + if (f->conf.modules) { + char *module; + char *next; + + for (module = f->conf.modules; module; module = next) { + char *p; + for (p = module; *p && *p != ':'; p++); + next = *p ? p + 1 : NULL; + *p = '\0'; + if (module[0] && + fuse_push_module(f, module, args) == -1) + goto out_free_fs; + } + } + + if (!f->conf.ac_attr_timeout_set) + f->conf.ac_attr_timeout = f->conf.attr_timeout; + +#ifdef __FreeBSD__ + /* + * In FreeBSD, we always use these settings as inode numbers + * are needed to make getcwd(3) work. + */ + f->conf.readdir_ino = 1; +#endif + + if (compat && compat <= 25) { + if (fuse_sync_compat_args(args) == -1) + goto out_free_fs; + } + + f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f); + if (f->se == NULL) { + if (f->conf.help) + fuse_lib_help_modules(); + goto out_free_fs; + } + + fuse_session_add_chan(f->se, ch); + + if (f->conf.debug) + libfuse_print("nullpath_ok: %i", f->nullpath_ok); + + /* Trace topmost layer by default */ + fs->debug = f->conf.debug; + f->ctr = 0; + f->generation = 0; + /* FIXME: Dynamic hash table */ + f->name_table_size = 14057; + f->name_table = (struct node **) + calloc(1, sizeof(struct node *) * f->name_table_size); + if (f->name_table == NULL) { + libfuse_print("fuse: memory allocation failed"); + goto out_free_session; + } + + f->id_table_size = 14057; + f->id_table = (struct node **) + calloc(1, sizeof(struct node *) * f->id_table_size); + if (f->id_table == NULL) { + libfuse_print("fuse: memory allocation failed"); + goto out_free_name_table; + } + + fuse_mutex_init(&f->lock); + + root = (struct node *) calloc(1, sizeof(struct node)); + if (root == NULL) { + libfuse_print("fuse: memory allocation failed"); + goto out_free_id_table; + } + + root->name = strdup("/"); + if (root->name == NULL) { + libfuse_print("fuse: memory allocation failed"); + goto out_free_root; + } + + if (f->conf.intr && + fuse_init_intr_signal(f->conf.intr_signal, + &f->intr_installed) == -1) + goto out_free_root_name; + + root->parent = NULL; + root->nodeid = FUSE_ROOT_ID; + root->generation = 0; + root->refctr = 1; + root->nlookup = 1; + hash_id(f, root); + + return f; + +out_free_root_name: + free(root->name); +out_free_root: + free(root); +out_free_id_table: + free(f->id_table); +out_free_name_table: + free(f->name_table); +out_free_session: + fuse_session_destroy(f->se); +out_free_fs: + /* Horrible compatibility hack to stop the destructor from being + called on the filesystem without init being called first */ + fs->op.destroy = NULL; + fuse_fs_destroy(f->fs); + free(f->conf.modules); +out_free: + free(f); +out_delete_context_key: + fuse_delete_context_key(); +out: + return NULL; +} + +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, size_t op_size, + void *user_data) +{ + return fuse_new_common(ch, args, op, op_size, user_data, 0); +} + +void fuse_destroy(struct fuse *f) +{ + size_t i; + + if (f->conf.intr && f->intr_installed) + fuse_restore_intr_signal(f->conf.intr_signal); + + if (f->fs) { + struct fuse_context_i *c = fuse_get_context_internal(); + + memset(c, 0, sizeof(*c)); + c->ctx.fuse = f; + + for (i = 0; i < f->id_table_size; i++) { + struct node *node; + + for (node = f->id_table[i]; node != NULL; + node = node->id_next) { + if (node->is_hidden) { + char *path; + if (try_get_path(f, node->nodeid, NULL, &path, NULL, 0) == 0) { + fuse_fs_unlink(f->fs, path); + free(path); + } + } + } + } + } + for (i = 0; i < f->id_table_size; i++) { + struct node *node; + struct node *next; + + for (node = f->id_table[i]; node != NULL; node = next) { + next = node->id_next; + free_node(node); + } + } + free(f->id_table); + free(f->name_table); + pthread_mutex_destroy(&f->lock); + fuse_session_destroy(f->se); + free(f->conf.modules); + free(f); + fuse_delete_context_key(); +} + +static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args, + const struct fuse_operations *op, + size_t op_size, int compat) +{ + struct fuse *f = NULL; + struct fuse_chan *ch = fuse_kern_chan_new(fd); + + if (ch) + f = fuse_new_common(ch, args, op, op_size, NULL, compat); + + return f; +} + +/* called with fuse_context_lock held or during initialization (before + main() has been called) */ +void fuse_register_module(struct fuse_module *mod) +{ + mod->ctr = 0; + mod->so = fuse_current_so; + if (mod->so) + mod->so->ctr++; + mod->next = fuse_modules; + fuse_modules = mod; +} + +#ifndef __FreeBSD__ + +static struct fuse *fuse_new_common_compat(int fd, const char *opts, + const struct fuse_operations *op, + size_t op_size, int compat) +{ + struct fuse *f; + struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + + if (fuse_opt_add_arg(&args, "") == -1) + return NULL; + if (opts && + (fuse_opt_add_arg(&args, "-o") == -1 || + fuse_opt_add_arg(&args, opts) == -1)) { + fuse_opt_free_args(&args); + return NULL; + } + f = fuse_new_common_compat25(fd, &args, op, op_size, compat); + fuse_opt_free_args(&args); + + return f; +} + +struct fuse *fuse_new_compat22(int fd, const char *opts, + const struct fuse_operations_compat22 *op, + size_t op_size) +{ + return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, + op_size, 22); +} + +struct fuse *fuse_new_compat2(int fd, const char *opts, + const struct fuse_operations_compat2 *op) +{ + return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, + sizeof(struct fuse_operations_compat2), + 21); +} + +struct fuse *fuse_new_compat1(int fd, int flags, + const struct fuse_operations_compat1 *op) +{ + const char *opts = NULL; + if (flags & FUSE_DEBUG_COMPAT1) + opts = "debug"; + return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op, + sizeof(struct fuse_operations_compat1), + 11); +} + +FUSE_SYMVER(".symver fuse_exited,__fuse_exited@"); +FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@"); +FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@"); +FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@"); +FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@"); +FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2"); + +#endif /* __FreeBSD__ */ + +struct fuse *fuse_new_compat25(int fd, struct fuse_args *args, + const struct fuse_operations_compat25 *op, + size_t op_size) +{ + return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op, + op_size, 25); +} + +FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5"); diff --git a/external/libfuse/source/fuse_i.h b/external/libfuse/source/fuse_i.h new file mode 100644 index 0000000..5a4f34d --- /dev/null +++ b/external/libfuse/source/fuse_i.h @@ -0,0 +1,108 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse.h" +#include "fuse_lowlevel.h" + +struct fuse_chan; +struct fuse_ll; + +struct fuse_session { + struct fuse_session_ops op; + + void *data; + + volatile int exited; + + struct fuse_chan *ch; +}; + +struct fuse_req { + struct fuse_ll *f; + uint64_t unique; + int ctr; + pthread_mutex_t lock; + struct fuse_ctx ctx; + struct fuse_chan *ch; + int interrupted; + union { + struct { + uint64_t unique; + } i; + struct { + fuse_interrupt_func_t func; + void *data; + } ni; + } u; + struct fuse_req *next; + struct fuse_req *prev; +}; + +struct fuse_ll { + int debug; + int allow_root; + int atomic_o_trunc; + int no_remote_lock; + int big_writes; + struct fuse_lowlevel_ops op; + int got_init; + struct cuse_data *cuse_data; + void *userdata; + uid_t owner; + struct fuse_conn_info conn; + struct fuse_req list; + struct fuse_req interrupts; + pthread_mutex_t lock; + int got_destroy; +}; + +struct fuse_cmd { + char *buf; + size_t buflen; + struct fuse_chan *ch; +}; + +struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, + size_t op_size, void *user_data, int compat); + +int fuse_sync_compat_args(struct fuse_args *args); + +struct fuse_chan *fuse_kern_chan_new(int fd); + +struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata); + +void fuse_kern_unmount_compat22(const char *mountpoint); +void fuse_kern_unmount(const char *mountpoint, int fd); +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +int fuse_kern_mount(const char *mountpoint, struct fuse_args *args, const struct fuse_operations *op); + +int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, + int count); +void fuse_free_req(fuse_req_t req); + + +struct fuse *fuse_setup_common(int argc, char *argv[], + const struct fuse_operations *op, + size_t op_size, + char **mountpoint, + int *multithreaded, + int *fd, + void *user_data, + int compat); + +void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg); diff --git a/external/libfuse/source/fuse_kern_chan.c b/external/libfuse/source/fuse_kern_chan.c new file mode 100644 index 0000000..1ade4e4 --- /dev/null +++ b/external/libfuse/source/fuse_kern_chan.c @@ -0,0 +1,103 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_lowlevel.h" +#include "fuse_kernel.h" +#include "fuse_i.h" + +#include +#include +#include +#include + +static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf, + size_t size) +{ + struct fuse_chan *ch = *chp; + int err; + ssize_t res; + struct fuse_session *se = fuse_chan_session(ch); + assert(se != NULL); + +restart: + res = read(fuse_chan_fd(ch), buf, size); + err = errno; + + if (fuse_session_exited(se)) + return 0; + if (res == -1) { + /* ENOENT means the operation was interrupted, it's safe + to restart */ + if (err == ENOENT) + goto restart; + + if (err == ENODEV) { + fuse_session_exit(se); + return 0; + } + /* Errors occuring during normal operation: EINTR (read + interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem + umounted) */ + if (err != EINTR && err != EAGAIN) + perror("fuse: reading device"); + return -err; + } + if ((size_t) res < sizeof(struct fuse_in_header)) { + libfuse_print("short read on fuse device"); + return -EIO; + } + return res; +} + +static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[], + size_t count) +{ + if (iov) { + ssize_t res = writev(fuse_chan_fd(ch), iov, count); + int err = errno; + + if (res == -1) { + struct fuse_session *se = fuse_chan_session(ch); + + assert(se != NULL); + + /* ENOENT means the operation was interrupted */ + if (!fuse_session_exited(se) && err != ENOENT) + perror("fuse: writing device"); + return -err; + } + } + return 0; +} + +static void fuse_kern_chan_destroy(struct fuse_chan *ch) +{ + close(fuse_chan_fd(ch)); +} + +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +#define MIN_BUFSIZE 0x41000 + +struct fuse_chan *fuse_kern_chan_new(int fd) +{ + struct fuse_chan_ops op = { + .receive = fuse_kern_chan_receive, + .send = fuse_kern_chan_send, + .destroy = fuse_kern_chan_destroy, + }; + size_t bufsize = getpagesize() + 0x1000; + bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize; + return fuse_chan_new(&op, fd, bufsize, NULL); +} diff --git a/external/libfuse/source/fuse_loop.c b/external/libfuse/source/fuse_loop.c new file mode 100644 index 0000000..91ea556 --- /dev/null +++ b/external/libfuse/source/fuse_loop.c @@ -0,0 +1,39 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_lowlevel.h" + +#include +#include +#include + +int fuse_session_loop(struct fuse_session *se) +{ + int res = 0; + struct fuse_chan *ch = fuse_session_next_chan(se, NULL); + size_t bufsize = fuse_chan_bufsize(ch); + char *buf = (char *) malloc(bufsize); + if (!buf) { + libfuse_print("fuse: failed to allocate read buffer"); + return -1; + } + + while (!fuse_session_exited(se)) { + struct fuse_chan *tmpch = ch; + res = fuse_chan_recv(&tmpch, buf, bufsize); + if (res == -EINTR) + continue; + if (res <= 0) + break; + fuse_session_process(se, buf, res, tmpch); + } + + free(buf); + fuse_session_reset(se); + return res < 0 ? -1 : 0; +} diff --git a/external/libfuse/source/fuse_loop_mt.c b/external/libfuse/source/fuse_loop_mt.c new file mode 100644 index 0000000..05d55ef --- /dev/null +++ b/external/libfuse/source/fuse_loop_mt.c @@ -0,0 +1,292 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include "fuse_lowlevel.h" +#include "fuse_misc.h" +#include "fuse_kernel.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Environment var controlling the thread stack size */ +#define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK" +/* +Modified by F.KUMAGAE, 06/17/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- +*/ +#define SCE_DECI_FUSE_THR_PRIO_BASE (SCE_ULPMGR_THREAD_PRIO_BASE) +#define SCE_DECI_FUSE_THR_PRIO_WORK (SCE_DECI_FUSE_THR_PRIO_BASE) + +/* +Modified by Y.ITO, 05/09/2017 + +--------------- +Copyright (c) 2017 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +#define SCE_DECI_FUSE_WORKER_THREAD_MAX 10 + +struct fuse_worker { + struct fuse_worker *prev; + struct fuse_worker *next; + pthread_t thread_id; + size_t bufsize; + char *buf; + struct fuse_mt *mt; +}; + +struct fuse_mt { + pthread_mutex_t lock; + int numworker; + int numavail; + struct fuse_session *se; + struct fuse_chan *prevch; + struct fuse_worker main; + sem_t finish; + int exit; + int error; +}; + +static void list_add_worker(struct fuse_worker *w, struct fuse_worker *next) +{ + struct fuse_worker *prev = next->prev; + w->next = next; + w->prev = prev; + prev->next = w; + next->prev = w; +} + +static void list_del_worker(struct fuse_worker *w) +{ + struct fuse_worker *prev = w->prev; + struct fuse_worker *next = w->next; + prev->next = next; + next->prev = prev; +} + +static int fuse_start_thread(struct fuse_mt *mt); + +static void *fuse_do_work(void *data) +{ + struct fuse_worker *w = (struct fuse_worker *) data; + struct fuse_mt *mt = w->mt; +/* +Modified by F.KUMAGAE, 06/17/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + sceKernelSetBesteffort(SCE_DECI_FUSE_THR_PRIO_WORK, 255); + + while (!fuse_session_exited(mt->se)) { + int isforget = 0; + struct fuse_chan *ch = mt->prevch; + int res; + + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + res = fuse_chan_recv(&ch, w->buf, w->bufsize); + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + if (res == -EINTR) + continue; + if (res <= 0) { + if (res < 0) { + fuse_session_exit(mt->se); + mt->error = -1; + } + break; + } + + pthread_mutex_lock(&mt->lock); + if (mt->exit) { + pthread_mutex_unlock(&mt->lock); + return NULL; + } + + /* + * This disgusting hack is needed so that zillions of threads + * are not created on a burst of FORGET messages + */ + if (((struct fuse_in_header *) w->buf)->opcode == FUSE_FORGET) + isforget = 1; + +/* +Modified by Y.ITO, 05/09/2017 + +--------------- +Copyright (c) 2017 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + if (!isforget) + mt->numavail--; + if (mt->numavail == 0 && mt->numworker < SCE_DECI_FUSE_WORKER_THREAD_MAX) + fuse_start_thread(mt); + pthread_mutex_unlock(&mt->lock); + + fuse_session_process(mt->se, w->buf, res, ch); + + pthread_mutex_lock(&mt->lock); + if (!isforget) + mt->numavail++; + if (mt->numavail > SCE_DECI_FUSE_WORKER_THREAD_MAX) { + if (mt->exit) { + pthread_mutex_unlock(&mt->lock); + return NULL; + } + list_del_worker(w); + mt->numavail--; + mt->numworker--; + pthread_mutex_unlock(&mt->lock); + + pthread_detach(w->thread_id); + free(w->buf); + free(w); + return NULL; + } + pthread_mutex_unlock(&mt->lock); + } + + sem_post(&mt->finish); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pause(); + + return NULL; +} + +static int fuse_start_thread(struct fuse_mt *mt) +{ +/* +Modified by F.KUMAGAE, 06/17/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +// struct sched_param sparam; + sigset_t oldset; + sigset_t newset; + int res; +// pthread_attr_t attr; +// char *stack_size; + struct fuse_worker *w = malloc(sizeof(struct fuse_worker)); + if (!w) { + libfuse_print("fuse: failed to allocate worker structure"); + return -1; + } + memset(w, 0, sizeof(struct fuse_worker)); + w->bufsize = fuse_chan_bufsize(mt->prevch); + w->buf = malloc(w->bufsize); + w->mt = mt; + if (!w->buf) { + libfuse_print("fuse: failed to allocate read buffer"); + free(w); + return -1; + } + +// /* Override default stack size */ +// scePthreadAttrInit(&attr); +// scePthreadAttrSetinheritsched(&attr, SCE_PTHREAD_EXPLICIT_SCHED); +// stack_size = getenv(ENVNAME_THREAD_STACK); +// if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size))) +// libfuse_print("fuse: invalid stack size: %s", stack_size); + + /* Disallow signal reception in worker threads */ + sigemptyset(&newset); + sigaddset(&newset, SIGTERM); + sigaddset(&newset, SIGINT); + sigaddset(&newset, SIGHUP); + sigaddset(&newset, SIGQUIT); + pthread_sigmask(SIG_BLOCK, &newset, &oldset); +// res = pthread_create(&w->thread_id, &attr, fuse_do_work, w); + char Thrname[THREAD_NAME_MAXLEN]; + snprintf(Thrname, THREAD_NAME_MAXLEN, SCE_DRFP_FUSEWORKTHREAD_NAME, mt->numworker); +// sparam.sched_priority = SCE_DECI_FUSE_THR_PRIO_WORK; +// scePthreadAttrSetschedparam(&attr, &sparam); + res = scePthreadCreate(&w->thread_id, NULL, fuse_do_work, w, Thrname); + pthread_sigmask(SIG_SETMASK, &oldset, NULL); +// scePthreadAttrDestroy(&attr); + if (res != 0) { + libfuse_print("fuse: error creating thread: %s", + strerror(res)); + free(w->buf); + free(w); + return -1; + } + list_add_worker(w, &mt->main); + mt->numavail ++; + mt->numworker ++; + + return 0; +} + +static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w) +{ +// pthread_join(w->thread_id, NULL); + scePthreadJoin(w->thread_id, NULL); + pthread_mutex_lock(&mt->lock); + list_del_worker(w); + pthread_mutex_unlock(&mt->lock); + free(w->buf); + free(w); +} + +int fuse_session_loop_mt(struct fuse_session *se) +{ + int err; + struct fuse_mt mt; + struct fuse_worker *w; + + memset(&mt, 0, sizeof(struct fuse_mt)); + mt.se = se; + mt.prevch = fuse_session_next_chan(se, NULL); + mt.error = 0; + mt.numworker = 0; + mt.numavail = 0; + mt.main.thread_id = pthread_self(); + mt.main.prev = mt.main.next = &mt.main; + sem_init(&mt.finish, 0, 0); + fuse_mutex_init(&mt.lock); + + pthread_mutex_lock(&mt.lock); + err = fuse_start_thread(&mt); + pthread_mutex_unlock(&mt.lock); + if (!err) { + /* sem_wait() is interruptible */ + while (!fuse_session_exited(se)) + sem_wait(&mt.finish); + + for (w = mt.main.next; w != &mt.main; w = w->next) + scePthreadCancel(w->thread_id); +// pthread_cancel(w->thread_id); + mt.exit = 1; + pthread_mutex_unlock(&mt.lock); + + while (mt.main.next != &mt.main) + fuse_join_worker(&mt, mt.main.next); + + err = mt.error; + } + + pthread_mutex_destroy(&mt.lock); + sem_destroy(&mt.finish); + fuse_session_reset(se); + return err; +} diff --git a/external/libfuse/source/fuse_lowlevel.c b/external/libfuse/source/fuse_lowlevel.c new file mode 100644 index 0000000..8393df9 --- /dev/null +++ b/external/libfuse/source/fuse_lowlevel.c @@ -0,0 +1,1873 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_i.h" +#include "fuse_kernel.h" +#include "fuse_opt.h" +#include "fuse_misc.h" +#include "fuse_common_compat.h" +#include "fuse_lowlevel_compat.h" + +#include +#include +#include +#include +#include +#include +#include + +#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) +#define OFFSET_MAX 0x7fffffffffffffffLL + +struct fuse_pollhandle { + uint64_t kh; + struct fuse_chan *ch; + struct fuse_ll *f; +}; + +static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) +{ + attr->ino = stbuf->st_ino; + attr->mode = stbuf->st_mode; + attr->nlink = stbuf->st_nlink; + attr->uid = stbuf->st_uid; + attr->gid = stbuf->st_gid; + attr->rdev = stbuf->st_rdev; + attr->size = stbuf->st_size; + attr->blksize = stbuf->st_blksize; + attr->blocks = stbuf->st_blocks; + attr->atime = stbuf->st_atime; + attr->mtime = stbuf->st_mtime; + attr->ctime = stbuf->st_ctime; + attr->atimensec = ST_ATIM_NSEC(stbuf); + attr->mtimensec = ST_MTIM_NSEC(stbuf); + attr->ctimensec = ST_CTIM_NSEC(stbuf); +} + +static void convert_attr(const struct fuse_setattr_in *attr, struct stat *stbuf) +{ + stbuf->st_mode = attr->mode; + stbuf->st_uid = attr->uid; + stbuf->st_gid = attr->gid; + stbuf->st_size = attr->size; + stbuf->st_atime = attr->atime; + stbuf->st_mtime = attr->mtime; + ST_ATIM_NSEC_SET(stbuf, attr->atimensec); + ST_MTIM_NSEC_SET(stbuf, attr->mtimensec); +} + +static size_t iov_length(const struct iovec *iov, size_t count) +{ + size_t seg; + size_t ret = 0; + + for (seg = 0; seg < count; seg++) + ret += iov[seg].iov_len; + return ret; +} + +static void list_init_req(struct fuse_req *req) +{ + req->next = req; + req->prev = req; +} + +static void list_del_req(struct fuse_req *req) +{ + struct fuse_req *prev = req->prev; + struct fuse_req *next = req->next; + prev->next = next; + next->prev = prev; +} + +static void list_add_req(struct fuse_req *req, struct fuse_req *next) +{ + struct fuse_req *prev = next->prev; + req->next = next; + req->prev = prev; + prev->next = req; + next->prev = req; +} + +static void destroy_req(fuse_req_t req) +{ + pthread_mutex_destroy(&req->lock); + free(req); +} + +void fuse_free_req(fuse_req_t req) +{ + int ctr; + struct fuse_ll *f = req->f; + + pthread_mutex_lock(&f->lock); + req->u.ni.func = NULL; + req->u.ni.data = NULL; + list_del_req(req); + ctr = --req->ctr; + pthread_mutex_unlock(&f->lock); + if (!ctr) + destroy_req(req); +} + +int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, + int count) +{ + struct fuse_out_header out; + + if (error <= -1000 || error > 0) { + libfuse_print("fuse: bad error value: %i", error); + error = -ERANGE; + } + + out.unique = req->unique; + out.error = error; + iov[0].iov_base = &out; + iov[0].iov_len = sizeof(struct fuse_out_header); + out.len = iov_length(iov, count); + + if (req->f->debug) { + if (out.error) { + fprintf(stderr, + " unique: %llu, error: %i (%s), outsize: %i", + (unsigned long long) out.unique, out.error, + strerror(-out.error), out.len); + } else { + fprintf(stderr, + " unique: %llu, success, outsize: %i", + (unsigned long long) out.unique, out.len); + } + } + + return fuse_chan_send(req->ch, iov, count); +} + +static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, + int count) +{ + int res; + + res = fuse_send_reply_iov_nofree(req, error, iov, count); + fuse_free_req(req); + return res; +} + +static int send_reply(fuse_req_t req, int error, const void *arg, + size_t argsize) +{ + struct iovec iov[2]; + int count = 1; + if (argsize) { + iov[1].iov_base = (void *) arg; + iov[1].iov_len = argsize; + count++; + } + return send_reply_iov(req, error, iov, count); +} + +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count) +{ + int res; + struct iovec *padded_iov; + + padded_iov = malloc((count + 1) * sizeof(struct iovec)); + if (padded_iov == NULL) + return fuse_reply_err(req, -ENOMEM); + + memcpy(padded_iov + 1, iov, count * sizeof(struct iovec)); + count++; + + res = send_reply_iov(req, 0, padded_iov, count); + free(padded_iov); + + return res; +} + +size_t fuse_dirent_size(size_t namelen) +{ + return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen); +} + +char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf, + off_t off) +{ + unsigned namelen = strlen(name); + unsigned entlen = FUSE_NAME_OFFSET + namelen; + unsigned entsize = fuse_dirent_size(namelen); + unsigned padlen = entsize - entlen; + struct fuse_dirent *dirent = (struct fuse_dirent *) buf; + + dirent->ino = stbuf->st_ino; + dirent->off = off; + dirent->namelen = namelen; + dirent->type = (stbuf->st_mode & 0170000) >> 12; + strncpy(dirent->name, name, namelen); + if (padlen) + memset(buf + entlen, 0, padlen); + + return buf + entsize; +} + +size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, + const char *name, const struct stat *stbuf, off_t off) +{ + size_t entsize; + + (void) req; + entsize = fuse_dirent_size(strlen(name)); + if (entsize <= bufsize && buf) + fuse_add_dirent(buf, name, stbuf, off); + return entsize; +} + +static void convert_statfs(const struct statvfs *stbuf, + struct fuse_kstatfs *kstatfs) +{ + kstatfs->bsize = stbuf->f_bsize; + kstatfs->frsize = stbuf->f_frsize; + kstatfs->blocks = stbuf->f_blocks; + kstatfs->bfree = stbuf->f_bfree; + kstatfs->bavail = stbuf->f_bavail; + kstatfs->files = stbuf->f_files; + kstatfs->ffree = stbuf->f_ffree; + kstatfs->namelen = stbuf->f_namemax; +} + +static int send_reply_ok(fuse_req_t req, const void *arg, size_t argsize) +{ + return send_reply(req, 0, arg, argsize); +} + +int fuse_reply_err(fuse_req_t req, int err) +{ + return send_reply(req, -err, NULL, 0); +} + +void fuse_reply_none(fuse_req_t req) +{ + fuse_chan_send(req->ch, NULL, 0); + fuse_free_req(req); +} + +static unsigned long calc_timeout_sec(double t) +{ + if (t > (double) ULONG_MAX) + return ULONG_MAX; + else if (t < 0.0) + return 0; + else + return (unsigned long) t; +} + +static unsigned int calc_timeout_nsec(double t) +{ + double f = t - (double) calc_timeout_sec(t); + if (f < 0.0) + return 0; + else if (f >= 0.999999999) + return 999999999; + else + return (unsigned int) (f * 1.0e9); +} + +static void fill_entry(struct fuse_entry_out *arg, + const struct fuse_entry_param *e) +{ + arg->nodeid = e->ino; + arg->generation = e->generation; + arg->entry_valid = calc_timeout_sec(e->entry_timeout); + arg->entry_valid_nsec = calc_timeout_nsec(e->entry_timeout); + arg->attr_valid = calc_timeout_sec(e->attr_timeout); + arg->attr_valid_nsec = calc_timeout_nsec(e->attr_timeout); + convert_stat(&e->attr, &arg->attr); +} + +static void fill_open(struct fuse_open_out *arg, + const struct fuse_file_info *f) +{ + arg->fh = f->fh; + if (f->direct_io) + arg->open_flags |= FOPEN_DIRECT_IO; + if (f->keep_cache) + arg->open_flags |= FOPEN_KEEP_CACHE; + if (f->nonseekable) + arg->open_flags |= FOPEN_NONSEEKABLE; +} + +int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e) +{ + struct fuse_entry_out arg; + size_t size = req->f->conn.proto_minor < 9 ? + FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg); + + /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant + negative entry */ + if (!e->ino && req->f->conn.proto_minor < 4) + return fuse_reply_err(req, ENOENT); + + memset(&arg, 0, sizeof(arg)); + fill_entry(&arg, e); + return send_reply_ok(req, &arg, size); +} + +int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, + const struct fuse_file_info *f) +{ + char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)]; + size_t entrysize = req->f->conn.proto_minor < 9 ? + FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out); + struct fuse_entry_out *earg = (struct fuse_entry_out *) buf; + struct fuse_open_out *oarg = (struct fuse_open_out *) (buf + entrysize); + + memset(buf, 0, sizeof(buf)); + fill_entry(earg, e); + fill_open(oarg, f); + return send_reply_ok(req, buf, + entrysize + sizeof(struct fuse_open_out)); +} + +int fuse_reply_attr(fuse_req_t req, const struct stat *attr, + double attr_timeout) +{ + struct fuse_attr_out arg; + size_t size = req->f->conn.proto_minor < 9 ? + FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg); + + memset(&arg, 0, sizeof(arg)); + arg.attr_valid = calc_timeout_sec(attr_timeout); + arg.attr_valid_nsec = calc_timeout_nsec(attr_timeout); + convert_stat(attr, &arg.attr); + + return send_reply_ok(req, &arg, size); +} + +int fuse_reply_readlink(fuse_req_t req, const char *linkname) +{ + return send_reply_ok(req, linkname, strlen(linkname)); +} + +int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) +{ + struct fuse_open_out arg; + + memset(&arg, 0, sizeof(arg)); + fill_open(&arg, f); + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_write(fuse_req_t req, size_t count) +{ + struct fuse_write_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.size = count; + + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size) +{ + return send_reply_ok(req, buf, size); +} + +int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf) +{ + struct fuse_statfs_out arg; + size_t size = req->f->conn.proto_minor < 4 ? + FUSE_COMPAT_STATFS_SIZE : sizeof(arg); + + memset(&arg, 0, sizeof(arg)); + convert_statfs(stbuf, &arg.st); + + return send_reply_ok(req, &arg, size); +} + +int fuse_reply_xattr(fuse_req_t req, size_t count) +{ + struct fuse_getxattr_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.size = count; + + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_lock(fuse_req_t req, struct flock *lock) +{ + struct fuse_lk_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.lk.type = lock->l_type; + if (lock->l_type != F_UNLCK) { + arg.lk.start = lock->l_start; + if (lock->l_len == 0) + arg.lk.end = OFFSET_MAX; + else + arg.lk.end = lock->l_start + lock->l_len - 1; + } + arg.lk.pid = lock->l_pid; + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_bmap(fuse_req_t req, uint64_t idx) +{ + struct fuse_bmap_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.block = idx; + + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_ioctl_retry(fuse_req_t req, + const struct iovec *in_iov, size_t in_count, + const struct iovec *out_iov, size_t out_count) +{ + struct fuse_ioctl_out arg; + struct iovec iov[4]; + size_t count = 1; + + memset(&arg, 0, sizeof(arg)); + arg.flags |= FUSE_IOCTL_RETRY; + arg.in_iovs = in_count; + arg.out_iovs = out_count; + iov[count].iov_base = &arg; + iov[count].iov_len = sizeof(arg); + count++; + + if (in_count) { + iov[count].iov_base = (void *)in_iov; + iov[count].iov_len = sizeof(in_iov[0]) * in_count; + count++; + } + + if (out_count) { + iov[count].iov_base = (void *)out_iov; + iov[count].iov_len = sizeof(out_iov[0]) * out_count; + count++; + } + + return send_reply_iov(req, 0, iov, count); +} + +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size) +{ + struct fuse_ioctl_out arg; + struct iovec iov[3]; + size_t count = 1; + + memset(&arg, 0, sizeof(arg)); + arg.result = result; + iov[count].iov_base = &arg; + iov[count].iov_len = sizeof(arg); + count++; + + if (size) { + iov[count].iov_base = (char *) buf; + iov[count].iov_len = size; + count++; + } + + return send_reply_iov(req, 0, iov, count); +} + +int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, + int count) +{ + struct iovec *padded_iov; + struct fuse_ioctl_out arg; + int res; + + padded_iov = malloc((count + 2) * sizeof(struct iovec)); + if (padded_iov == NULL) + return fuse_reply_err(req, -ENOMEM); + + memset(&arg, 0, sizeof(arg)); + arg.result = result; + padded_iov[1].iov_base = &arg; + padded_iov[1].iov_len = sizeof(arg); + + memcpy(&padded_iov[2], iov, count * sizeof(struct iovec)); + + res = send_reply_iov(req, 0, padded_iov, count + 2); + free(padded_iov); + + return res; +} + +int fuse_reply_poll(fuse_req_t req, unsigned revents) +{ + struct fuse_poll_out arg; + + memset(&arg, 0, sizeof(arg)); + arg.revents = revents; + + return send_reply_ok(req, &arg, sizeof(arg)); +} + +static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + char *name = (char *) inarg; + + if (req->f->op.lookup) + req->f->op.lookup(req, nodeid, name); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_forget_in *arg = (struct fuse_forget_in *) inarg; + + if (req->f->op.forget) + req->f->op.forget(req, nodeid, arg->nlookup); + else + fuse_reply_none(req); +} + +static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_file_info *fip = NULL; + struct fuse_file_info fi; + + if (req->f->conn.proto_minor >= 9) { + struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg; + + if (arg->getattr_flags & FUSE_GETATTR_FH) { + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + fip = &fi; + } + } + + if (req->f->op.getattr) + req->f->op.getattr(req, nodeid, fip); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_setattr_in *arg = (struct fuse_setattr_in *) inarg; + + if (req->f->op.setattr) { + struct fuse_file_info *fi = NULL; + struct fuse_file_info fi_store; + struct stat stbuf; + memset(&stbuf, 0, sizeof(stbuf)); + convert_attr(arg, &stbuf); + if (arg->valid & FATTR_FH) { + arg->valid &= ~FATTR_FH; + memset(&fi_store, 0, sizeof(fi_store)); + fi = &fi_store; + fi->fh = arg->fh; + fi->fh_old = fi->fh; + } + arg->valid &= + FUSE_SET_ATTR_MODE | + FUSE_SET_ATTR_UID | + FUSE_SET_ATTR_GID | + FUSE_SET_ATTR_SIZE | + FUSE_SET_ATTR_ATIME | + FUSE_SET_ATTR_MTIME | + FUSE_SET_ATTR_ATIME_NOW | + FUSE_SET_ATTR_MTIME_NOW; + + req->f->op.setattr(req, nodeid, &stbuf, arg->valid, fi); + } else + fuse_reply_err(req, ENOSYS); +} + +static void do_access(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_access_in *arg = (struct fuse_access_in *) inarg; + + if (req->f->op.access) + req->f->op.access(req, nodeid, arg->mask); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_readlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + (void) inarg; + + if (req->f->op.readlink) + req->f->op.readlink(req, nodeid); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_mknod(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_mknod_in *arg = (struct fuse_mknod_in *) inarg; + char *name = PARAM(arg); + + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else + name = (char *) inarg + FUSE_COMPAT_MKNOD_IN_SIZE; + + if (req->f->op.mknod) + req->f->op.mknod(req, nodeid, name, arg->mode, arg->rdev); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_mkdir_in *arg = (struct fuse_mkdir_in *) inarg; + + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + + if (req->f->op.mkdir) + req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + char *name = (char *) inarg; + + if (req->f->op.unlink) + req->f->op.unlink(req, nodeid, name); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + char *name = (char *) inarg; + + if (req->f->op.rmdir) + req->f->op.rmdir(req, nodeid, name); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + char *name = (char *) inarg; + char *linkname = ((char *) inarg) + strlen((char *) inarg) + 1; + + if (req->f->op.symlink) + req->f->op.symlink(req, linkname, nodeid, name); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_rename(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_rename_in *arg = (struct fuse_rename_in *) inarg; + char *oldname = PARAM(arg); + char *newname = oldname + strlen(oldname) + 1; + + if (req->f->op.rename) + req->f->op.rename(req, nodeid, oldname, arg->newdir, newname); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_link(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_link_in *arg = (struct fuse_link_in *) inarg; + + if (req->f->op.link) + req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg)); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_create(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_create_in *arg = (struct fuse_create_in *) inarg; + + if (req->f->op.create) { + struct fuse_file_info fi; + char *name = PARAM(arg); + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + + if (req->f->conn.proto_minor >= 12) + req->ctx.umask = arg->umask; + else + name = (char *) inarg + sizeof(struct fuse_open_in); + + req->f->op.create(req, nodeid, name, arg->mode, &fi); + } else + fuse_reply_err(req, ENOSYS); +} + +static void do_open(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + + if (req->f->op.open) + req->f->op.open(req, nodeid, &fi); + else + fuse_reply_open(req, &fi); +} + +static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + + if (req->f->op.read) { + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; +/* +Modified by Y.ITO, 07/27/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + // fi.ra_hint: 8 + fi.ra_hint = arg->read_flags >> 8; + // fi.seq_count: 8 + fi.seq_count = arg->read_flags; + if (req->f->conn.proto_minor >= 9) { + fi.lock_owner = arg->lock_owner; + fi.flags = arg->flags; + } + req->f->op.read(req, nodeid, arg->size, arg->offset, &fi); + } else + fuse_reply_err(req, ENOSYS); +} + +static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_write_in *arg = (struct fuse_write_in *) inarg; + struct fuse_file_info fi; + char *param; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + fi.writepage = arg->write_flags & 1; + + if (req->f->conn.proto_minor < 9) { + param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE; + } else { + fi.lock_owner = arg->lock_owner; + fi.flags = arg->flags; + param = PARAM(arg); + } + + if (req->f->op.write) + req->f->op.write(req, nodeid, param, arg->size, + arg->offset, &fi); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_flush_in *arg = (struct fuse_flush_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + fi.flush = 1; + if (req->f->conn.proto_minor >= 7) + fi.lock_owner = arg->lock_owner; + + if (req->f->op.flush) + req->f->op.flush(req, nodeid, &fi); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_release_in *arg = (struct fuse_release_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + fi.fh = arg->fh; + fi.fh_old = fi.fh; + if (req->f->conn.proto_minor >= 8) { + fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0; + fi.lock_owner = arg->lock_owner; + } + + if (req->f->op.release) + req->f->op.release(req, nodeid, &fi); + else + fuse_reply_err(req, 0); +} + +static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.fsync) + req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_opendir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_open_in *arg = (struct fuse_open_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + + if (req->f->op.opendir) + req->f->op.opendir(req, nodeid, &fi); + else + fuse_reply_open(req, &fi); +} + +static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_read_in *arg = (struct fuse_read_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.readdir) + req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_release_in *arg = (struct fuse_release_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.flags = arg->flags; + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.releasedir) + req->f->op.releasedir(req, nodeid, &fi); + else + fuse_reply_err(req, 0); +} + +static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_fsync_in *arg = (struct fuse_fsync_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.fsyncdir) + req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_statfs(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + (void) nodeid; + (void) inarg; + + if (req->f->op.statfs) + req->f->op.statfs(req, nodeid); + else { + struct statvfs buf = { + .f_namemax = 255, + .f_bsize = 512, + }; + fuse_reply_statfs(req, &buf); + } +} + +static void do_setxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_setxattr_in *arg = (struct fuse_setxattr_in *) inarg; + char *name = PARAM(arg); + char *value = name + strlen(name) + 1; + + if (req->f->op.setxattr) + req->f->op.setxattr(req, nodeid, name, value, arg->size, + arg->flags); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_getxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; + + if (req->f->op.getxattr) + req->f->op.getxattr(req, nodeid, PARAM(arg), arg->size); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_listxattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_getxattr_in *arg = (struct fuse_getxattr_in *) inarg; + + if (req->f->op.listxattr) + req->f->op.listxattr(req, nodeid, arg->size); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_removexattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + char *name = (char *) inarg; + + if (req->f->op.removexattr) + req->f->op.removexattr(req, nodeid, name); + else + fuse_reply_err(req, ENOSYS); +} + +static void convert_fuse_file_lock(struct fuse_file_lock *fl, + struct flock *flock) +{ + memset(flock, 0, sizeof(struct flock)); + flock->l_type = fl->type; + flock->l_whence = SEEK_SET; + flock->l_start = fl->start; + if (fl->end == OFFSET_MAX) + flock->l_len = 0; + else + flock->l_len = fl->end - fl->start + 1; + flock->l_pid = fl->pid; +} + +static void do_getlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; + struct fuse_file_info fi; + struct flock flock; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.lock_owner = arg->owner; + + convert_fuse_file_lock(&arg->lk, &flock); + if (req->f->op.getlk) + req->f->op.getlk(req, nodeid, &fi, &flock); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_setlk_common(fuse_req_t req, fuse_ino_t nodeid, + const void *inarg, int sleep) +{ + struct fuse_lk_in *arg = (struct fuse_lk_in *) inarg; + struct fuse_file_info fi; + struct flock flock; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.lock_owner = arg->owner; + + convert_fuse_file_lock(&arg->lk, &flock); + if (req->f->op.setlk) + req->f->op.setlk(req, nodeid, &fi, &flock, sleep); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_setlk(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + do_setlk_common(req, nodeid, inarg, 0); +} + +static void do_setlkw(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + do_setlk_common(req, nodeid, inarg, 1); +} + +static int find_interrupted(struct fuse_ll *f, struct fuse_req *req) +{ + struct fuse_req *curr; + + for (curr = f->list.next; curr != &f->list; curr = curr->next) { + if (curr->unique == req->u.i.unique) { + fuse_interrupt_func_t func; + void *data; + + curr->ctr++; + pthread_mutex_unlock(&f->lock); + + /* Ugh, ugly locking */ + pthread_mutex_lock(&curr->lock); + pthread_mutex_lock(&f->lock); + curr->interrupted = 1; + func = curr->u.ni.func; + data = curr->u.ni.data; + pthread_mutex_unlock(&f->lock); + if (func) + func(curr, data); + pthread_mutex_unlock(&curr->lock); + + pthread_mutex_lock(&f->lock); + curr->ctr--; + if (!curr->ctr) + destroy_req(curr); + + return 1; + } + } + for (curr = f->interrupts.next; curr != &f->interrupts; + curr = curr->next) { + if (curr->u.i.unique == req->u.i.unique) + return 1; + } + return 0; +} + +static void do_interrupt(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_interrupt_in *arg = (struct fuse_interrupt_in *) inarg; + struct fuse_ll *f = req->f; + + (void) nodeid; + if (f->debug) + libfuse_print("INTERRUPT: %llu", + (unsigned long long) arg->unique); + + req->u.i.unique = arg->unique; + + pthread_mutex_lock(&f->lock); + if (find_interrupted(f, req)) + destroy_req(req); + else + list_add_req(req, &f->interrupts); + pthread_mutex_unlock(&f->lock); +} + +static struct fuse_req *check_interrupt(struct fuse_ll *f, struct fuse_req *req) +{ + struct fuse_req *curr; + + for (curr = f->interrupts.next; curr != &f->interrupts; + curr = curr->next) { + if (curr->u.i.unique == req->unique) { + req->interrupted = 1; + list_del_req(curr); + free(curr); + return NULL; + } + } + curr = f->interrupts.next; + if (curr != &f->interrupts) { + list_del_req(curr); + list_init_req(curr); + return curr; + } else + return NULL; +} + +static void do_bmap(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_bmap_in *arg = (struct fuse_bmap_in *) inarg; + + if (req->f->op.bmap) + req->f->op.bmap(req, nodeid, arg->blocksize, arg->block); + else + fuse_reply_err(req, ENOSYS); +} + +static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_ioctl_in *arg = (struct fuse_ioctl_in *) inarg; + unsigned int flags = arg->flags; + void *in_buf = arg->in_size ? PARAM(arg) : NULL; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.ioctl) + req->f->op.ioctl(req, nodeid, arg->cmd, + (void *)(uintptr_t)arg->arg, &fi, flags, + in_buf, arg->in_size, arg->out_size); + else + fuse_reply_err(req, ENOSYS); +} + +void fuse_pollhandle_destroy(struct fuse_pollhandle *ph) +{ + free(ph); +} + +static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_poll_in *arg = (struct fuse_poll_in *) inarg; + struct fuse_file_info fi; + + memset(&fi, 0, sizeof(fi)); + fi.fh = arg->fh; + fi.fh_old = fi.fh; + + if (req->f->op.poll) { + struct fuse_pollhandle *ph = NULL; + + if (arg->flags & FUSE_POLL_SCHEDULE_NOTIFY) { + ph = malloc(sizeof(struct fuse_pollhandle)); + if (ph == NULL) { + fuse_reply_err(req, ENOMEM); + return; + } + ph->kh = arg->kh; + ph->ch = req->ch; + ph->f = req->f; + } + + req->f->op.poll(req, nodeid, &fi, ph); + } else { + fuse_reply_err(req, ENOSYS); + } +} + +static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_init_in *arg = (struct fuse_init_in *) inarg; + struct fuse_init_out outarg; + struct fuse_ll *f = req->f; + size_t bufsize = fuse_chan_bufsize(req->ch); + + (void) nodeid; + if (f->debug) { + libfuse_print("INIT: %u.%u", arg->major, arg->minor); + if (arg->major == 7 && arg->minor >= 6) { + libfuse_print("flags=0x%08x", arg->flags); + libfuse_print("max_readahead=0x%08x", + arg->max_readahead); + } + } + f->conn.proto_major = arg->major; + f->conn.proto_minor = arg->minor; + f->conn.capable = 0; + f->conn.want = 0; + + memset(&outarg, 0, sizeof(outarg)); + outarg.major = FUSE_KERNEL_VERSION; + outarg.minor = FUSE_KERNEL_MINOR_VERSION; + + if (arg->major < 7) { + libfuse_print("fuse: unsupported protocol version: %u.%u", + arg->major, arg->minor); + fuse_reply_err(req, EPROTO); + return; + } + + if (arg->major > 7) { + /* Wait for a second INIT request with a 7.X version */ + send_reply_ok(req, &outarg, sizeof(outarg)); + return; + } + + if (arg->minor >= 6) { + if (f->conn.async_read) + f->conn.async_read = arg->flags & FUSE_ASYNC_READ; + if (arg->max_readahead < f->conn.max_readahead) + f->conn.max_readahead = arg->max_readahead; + if (arg->flags & FUSE_ASYNC_READ) + f->conn.capable |= FUSE_CAP_ASYNC_READ; + if (arg->flags & FUSE_POSIX_LOCKS) + f->conn.capable |= FUSE_CAP_POSIX_LOCKS; + if (arg->flags & FUSE_ATOMIC_O_TRUNC) + f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC; + if (arg->flags & FUSE_EXPORT_SUPPORT) + f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT; + if (arg->flags & FUSE_BIG_WRITES) + f->conn.capable |= FUSE_CAP_BIG_WRITES; + if (arg->flags & FUSE_DONT_MASK) + f->conn.capable |= FUSE_CAP_DONT_MASK; + } else { + f->conn.async_read = 0; + f->conn.max_readahead = 0; + } + + if (f->atomic_o_trunc) + f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC; + if (f->op.getlk && f->op.setlk && !f->no_remote_lock) + f->conn.want |= FUSE_CAP_POSIX_LOCKS; + if (f->big_writes) + f->conn.want |= FUSE_CAP_BIG_WRITES; + + if (bufsize < FUSE_MIN_READ_BUFFER) { + libfuse_print("fuse: warning: buffer size too small: %zu", + bufsize); + bufsize = FUSE_MIN_READ_BUFFER; + } + + bufsize -= 4096; + if (bufsize < f->conn.max_write) + f->conn.max_write = bufsize; + + f->got_init = 1; + if (f->op.init) + f->op.init(f->userdata, &f->conn); + + if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ)) + outarg.flags |= FUSE_ASYNC_READ; + if (f->conn.want & FUSE_CAP_POSIX_LOCKS) + outarg.flags |= FUSE_POSIX_LOCKS; + if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC) + outarg.flags |= FUSE_ATOMIC_O_TRUNC; + if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT) + outarg.flags |= FUSE_EXPORT_SUPPORT; + if (f->conn.want & FUSE_CAP_BIG_WRITES) + outarg.flags |= FUSE_BIG_WRITES; + if (f->conn.want & FUSE_CAP_DONT_MASK) + outarg.flags |= FUSE_DONT_MASK; + outarg.max_readahead = f->conn.max_readahead; + outarg.max_write = f->conn.max_write; + + if (f->debug) { + libfuse_print(" INIT: %u.%u", outarg.major, outarg.minor); + libfuse_print(" flags=0x%08x", outarg.flags); + libfuse_print(" max_readahead=0x%08x", + outarg.max_readahead); + libfuse_print(" max_write=0x%08x", outarg.max_write); + } + + send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg)); +} + +static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg) +{ + struct fuse_ll *f = req->f; + + (void) nodeid; + (void) inarg; + + f->got_destroy = 1; + if (f->op.destroy) + f->op.destroy(f->userdata); + + send_reply_ok(req, NULL, 0); +} + +static int send_notify_iov(struct fuse_ll *f, struct fuse_chan *ch, + int notify_code, struct iovec *iov, int count) +{ + struct fuse_out_header out; + + out.unique = 0; + out.error = notify_code; + iov[0].iov_base = &out; + iov[0].iov_len = sizeof(struct fuse_out_header); + out.len = iov_length(iov, count); + + if (f->debug) + libfuse_print("NOTIFY: code=%d count=%d length=%u", + notify_code, count, out.len); + + return fuse_chan_send(ch, iov, count); +} + +int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph) +{ + if (ph != NULL) { + struct fuse_notify_poll_wakeup_out outarg; + struct iovec iov[2]; + + outarg.kh = ph->kh; + + iov[1].iov_base = &outarg; + iov[1].iov_len = sizeof(outarg); + + return send_notify_iov(ph->f, ph->ch, FUSE_NOTIFY_POLL, iov, 2); + } else { + return 0; + } +} + +int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, + off_t off, off_t len) +{ + struct fuse_notify_inval_inode_out outarg; + struct fuse_ll *f; + struct iovec iov[2]; + + if (!ch) + return -EINVAL; + + f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + if (!f) + return -ENODEV; + + outarg.ino = ino; + outarg.off = off; + outarg.len = len; + + iov[1].iov_base = &outarg; + iov[1].iov_len = sizeof(outarg); + + return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2); +} + +int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, + const char *name, size_t namelen) +{ + struct fuse_notify_inval_entry_out outarg; + struct fuse_ll *f; + struct iovec iov[3]; + + if (!ch) + return -EINVAL; + + f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch)); + if (!f) + return -ENODEV; + + outarg.parent = parent; + outarg.namelen = namelen; + outarg.padding = 0; + + iov[1].iov_base = &outarg; + iov[1].iov_len = sizeof(outarg); + iov[2].iov_base = (void *)name; + iov[2].iov_len = namelen + 1; + + return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3); +} + +void *fuse_req_userdata(fuse_req_t req) +{ + return req->f->userdata; +} + +const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) +{ + return &req->ctx; +} + +/* + * The size of fuse_ctx got extended, so need to be careful about + * incompatibility (i.e. a new binary cannot work with an old + * library). + */ +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req); +const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req) +{ + return fuse_req_ctx(req); +} +FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4"); + + +void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, + void *data) +{ + pthread_mutex_lock(&req->lock); + pthread_mutex_lock(&req->f->lock); + req->u.ni.func = func; + req->u.ni.data = data; + pthread_mutex_unlock(&req->f->lock); + if (req->interrupted && func) + func(req, data); + pthread_mutex_unlock(&req->lock); +} + +int fuse_req_interrupted(fuse_req_t req) +{ + int interrupted; + + pthread_mutex_lock(&req->f->lock); + interrupted = req->interrupted; + pthread_mutex_unlock(&req->f->lock); + + return interrupted; +} + +static struct { + void (*func)(fuse_req_t, fuse_ino_t, const void *); + const char *name; +} fuse_ll_ops[] = { + [FUSE_LOOKUP] = { do_lookup, "LOOKUP" }, + [FUSE_FORGET] = { do_forget, "FORGET" }, + [FUSE_GETATTR] = { do_getattr, "GETATTR" }, + [FUSE_SETATTR] = { do_setattr, "SETATTR" }, + [FUSE_READLINK] = { do_readlink, "READLINK" }, + [FUSE_SYMLINK] = { do_symlink, "SYMLINK" }, + [FUSE_MKNOD] = { do_mknod, "MKNOD" }, + [FUSE_MKDIR] = { do_mkdir, "MKDIR" }, + [FUSE_UNLINK] = { do_unlink, "UNLINK" }, + [FUSE_RMDIR] = { do_rmdir, "RMDIR" }, + [FUSE_RENAME] = { do_rename, "RENAME" }, + [FUSE_LINK] = { do_link, "LINK" }, + [FUSE_OPEN] = { do_open, "OPEN" }, + [FUSE_READ] = { do_read, "READ" }, + [FUSE_WRITE] = { do_write, "WRITE" }, + [FUSE_STATFS] = { do_statfs, "STATFS" }, + [FUSE_RELEASE] = { do_release, "RELEASE" }, + [FUSE_FSYNC] = { do_fsync, "FSYNC" }, + [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" }, + [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" }, + [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" }, + [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" }, + [FUSE_FLUSH] = { do_flush, "FLUSH" }, + [FUSE_INIT] = { do_init, "INIT" }, + [FUSE_OPENDIR] = { do_opendir, "OPENDIR" }, + [FUSE_READDIR] = { do_readdir, "READDIR" }, + [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" }, + [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" }, + [FUSE_GETLK] = { do_getlk, "GETLK" }, + [FUSE_SETLK] = { do_setlk, "SETLK" }, + [FUSE_SETLKW] = { do_setlkw, "SETLKW" }, + [FUSE_ACCESS] = { do_access, "ACCESS" }, + [FUSE_CREATE] = { do_create, "CREATE" }, + [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, + [FUSE_BMAP] = { do_bmap, "BMAP" }, + [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, + [FUSE_POLL] = { do_poll, "POLL" }, + [FUSE_DESTROY] = { do_destroy, "DESTROY" }, + [CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" }, +}; + +#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0])) + +static const char *opname(enum fuse_opcode opcode) +{ + if (opcode >= FUSE_MAXOP || !fuse_ll_ops[opcode].name) + return "???"; + else + return fuse_ll_ops[opcode].name; +} + +static void fuse_ll_process(void *data, const char *buf, size_t len, + struct fuse_chan *ch) +{ + struct fuse_ll *f = (struct fuse_ll *) data; + struct fuse_in_header *in = (struct fuse_in_header *) buf; + const void *inarg = buf + sizeof(struct fuse_in_header); + struct fuse_req *req; + int err; + + if (f->debug) + fprintf(stderr, + "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu", + (unsigned long long) in->unique, + opname((enum fuse_opcode) in->opcode), in->opcode, + (unsigned long) in->nodeid, len); + + req = (struct fuse_req *) calloc(1, sizeof(struct fuse_req)); + if (req == NULL) { + libfuse_print("fuse: failed to allocate request"); + return; + } + + req->f = f; + req->unique = in->unique; + req->ctx.uid = in->uid; + req->ctx.gid = in->gid; + req->ctx.pid = in->pid; + req->ch = ch; + req->ctr = 1; + list_init_req(req); + fuse_mutex_init(&req->lock); + + err = EIO; + if (!f->got_init) { + enum fuse_opcode expected; + + expected = f->cuse_data ? CUSE_INIT : FUSE_INIT; + if (in->opcode != expected) + goto reply_err; + } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT) + goto reply_err; + + err = EACCES; + if (f->allow_root && in->uid != f->owner && in->uid != 0 && + in->opcode != FUSE_INIT && in->opcode != FUSE_READ && + in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC && + in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR && + in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) + goto reply_err; + + err = ENOSYS; + if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func) + goto reply_err; + if (in->opcode != FUSE_INTERRUPT) { + struct fuse_req *intr; + pthread_mutex_lock(&f->lock); + intr = check_interrupt(f, req); + list_add_req(req, &f->list); + pthread_mutex_unlock(&f->lock); + if (intr) + fuse_reply_err(intr, EAGAIN); + } + fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg); + return; + + reply_err: + fuse_reply_err(req, err); +} + +enum { + KEY_HELP, + KEY_VERSION, +}; + +static struct fuse_opt fuse_ll_opts[] = { + { "debug", offsetof(struct fuse_ll, debug), 1 }, + { "-d", offsetof(struct fuse_ll, debug), 1 }, + { "allow_root", offsetof(struct fuse_ll, allow_root), 1 }, + { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 }, + { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 }, + { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 }, + { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 }, + { "atomic_o_trunc", offsetof(struct fuse_ll, atomic_o_trunc), 1}, + { "no_remote_lock", offsetof(struct fuse_ll, no_remote_lock), 1}, + { "big_writes", offsetof(struct fuse_ll, big_writes), 1}, + FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_END +}; + +static void fuse_ll_version(void) +{ + libfuse_print("using FUSE kernel interface version %i.%i", + FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION); +} + +static void fuse_ll_help(void) +{ + fprintf(stderr, +" -o max_write=N set maximum size of write requests" +" -o max_readahead=N set maximum readahead" +" -o async_read perform reads asynchronously (default)" +" -o sync_read perform reads synchronously" +" -o atomic_o_trunc enable atomic open+truncate support" +" -o big_writes enable larger than 4kB writes" +" -o no_remote_lock disable remote file locking"); +} + +static int fuse_ll_opt_proc(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + (void) data; (void) outargs; + + switch (key) { + case KEY_HELP: + fuse_ll_help(); + break; + + case KEY_VERSION: + fuse_ll_version(); + break; + + default: + libfuse_print("fuse: unknown option `%s'", arg); + } + + return -1; +} + +int fuse_lowlevel_is_lib_option(const char *opt) +{ + return fuse_opt_match(fuse_ll_opts, opt); +} + +static void fuse_ll_destroy(void *data) +{ + struct fuse_ll *f = (struct fuse_ll *) data; + + if (f->got_init && !f->got_destroy) { + if (f->op.destroy) + f->op.destroy(f->userdata); + } + + pthread_mutex_destroy(&f->lock); + free(f->cuse_data); + free(f); +} + +/* + * always call fuse_lowlevel_new_common() internally, to work around a + * misfeature in the FreeBSD runtime linker, which links the old + * version of a symbol to internal references. + */ +struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata) +{ + struct fuse_ll *f; + struct fuse_session *se; + struct fuse_session_ops sop = { + .process = fuse_ll_process, + .destroy = fuse_ll_destroy, + }; + + if (sizeof(struct fuse_lowlevel_ops) < op_size) { + libfuse_print("fuse: warning: library too old, some operations may not work"); + op_size = sizeof(struct fuse_lowlevel_ops); + } + + f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll)); + if (f == NULL) { + libfuse_print("fuse: failed to allocate fuse object"); + goto out; + } + + f->conn.async_read = 1; + f->conn.max_write = UINT_MAX; + f->conn.max_readahead = UINT_MAX; + f->atomic_o_trunc = 0; + list_init_req(&f->list); + list_init_req(&f->interrupts); + fuse_mutex_init(&f->lock); + + if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1) + goto out_free; + + if (f->debug) + libfuse_print("FUSE library version: %s", PACKAGE_VERSION); + + memcpy(&f->op, op, op_size); + f->owner = getuid(); + f->userdata = userdata; + + se = fuse_session_new(&sop, f); + if (!se) + goto out_free; + + return se; + +out_free: + free(f); +out: + return NULL; +} + + +struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata) +{ + return fuse_lowlevel_new_common(args, op, op_size, userdata); +} + +#ifdef linux +int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) +{ + char *buf; + size_t bufsize = 1024; + char path[128]; + int ret; + int fd; + unsigned long pid = req->ctx.pid; + char *s; + + sprintf(path, "/proc/%lu/task/%lu/status", pid, pid); + +retry: + buf = malloc(bufsize); + if (buf == NULL) + return -ENOMEM; + + ret = -EIO; + fd = open(path, O_RDONLY); + if (fd == -1) + goto out_free; + + ret = read(fd, buf, bufsize); + close(fd); + if (ret == -1) { + ret = -EIO; + goto out_free; + } + + if (ret == bufsize) { + free(buf); + bufsize *= 4; + goto retry; + } + + ret = -EIO; + s = strstr(buf, "\nGroups:"); + if (s == NULL) + goto out_free; + + s += 8; + ret = 0; + while (1) { + char *end; + unsigned long val = strtoul(s, &end, 0); + if (end == s) + break; + + s = end; + if (ret < size) + list[ret] = val; + ret++; + } + +out_free: + free(buf); + return ret; +} +#else /* linux */ +/* + * This is currently not implemented on other than Linux... + */ +int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]) +{ + return -ENOSYS; +} +#endif + +#ifndef __FreeBSD__ + +static void fill_open_compat(struct fuse_open_out *arg, + const struct fuse_file_info_compat *f) +{ + arg->fh = f->fh; + if (f->direct_io) + arg->open_flags |= FOPEN_DIRECT_IO; + if (f->keep_cache) + arg->open_flags |= FOPEN_KEEP_CACHE; +} + +static void convert_statfs_compat(const struct statfs *compatbuf, + struct statvfs *buf) +{ + buf->f_bsize = compatbuf->f_bsize; + buf->f_blocks = compatbuf->f_blocks; + buf->f_bfree = compatbuf->f_bfree; + buf->f_bavail = compatbuf->f_bavail; + buf->f_files = compatbuf->f_files; + buf->f_ffree = compatbuf->f_ffree; + buf->f_namemax = compatbuf->f_namelen; +} + +int fuse_reply_open_compat(fuse_req_t req, + const struct fuse_file_info_compat *f) +{ + struct fuse_open_out arg; + + memset(&arg, 0, sizeof(arg)); + fill_open_compat(&arg, f); + return send_reply_ok(req, &arg, sizeof(arg)); +} + +int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf) +{ + struct statvfs newbuf; + + memset(&newbuf, 0, sizeof(newbuf)); + convert_statfs_compat(stbuf, &newbuf); + + return fuse_reply_statfs(req, &newbuf); +} + +struct fuse_session *fuse_lowlevel_new_compat(const char *opts, + const struct fuse_lowlevel_ops_compat *op, + size_t op_size, void *userdata) +{ + struct fuse_session *se; + struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + + if (opts && + (fuse_opt_add_arg(&args, "") == -1 || + fuse_opt_add_arg(&args, "-o") == -1 || + fuse_opt_add_arg(&args, opts) == -1)) { + fuse_opt_free_args(&args); + return NULL; + } + se = fuse_lowlevel_new(&args, (const struct fuse_lowlevel_ops *) op, + op_size, userdata); + fuse_opt_free_args(&args); + + return se; +} + +struct fuse_ll_compat_conf { + unsigned max_read; + int set_max_read; +}; + +static const struct fuse_opt fuse_ll_opts_compat[] = { + { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 }, + { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 }, + FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP), + FUSE_OPT_END +}; + +int fuse_sync_compat_args(struct fuse_args *args) +{ + struct fuse_ll_compat_conf conf; + + memset(&conf, 0, sizeof(conf)); + if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1) + return -1; + + if (fuse_opt_insert_arg(args, 1, "-osync_read")) + return -1; + + if (conf.set_max_read) { + char tmpbuf[64]; + + sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read); + if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1) + return -1; + } + return 0; +} + +FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4"); +FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4"); +FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4"); + +#else /* __FreeBSD__ */ + +int fuse_sync_compat_args(struct fuse_args *args) +{ + (void) args; + return 0; +} + +#endif /* __FreeBSD__ */ + +struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args, + const struct fuse_lowlevel_ops_compat25 *op, + size_t op_size, void *userdata) +{ + if (fuse_sync_compat_args(args) == -1) + return NULL; + + return fuse_lowlevel_new_common(args, + (const struct fuse_lowlevel_ops *) op, + op_size, userdata); +} + +FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5"); diff --git a/external/libfuse/source/fuse_misc.h b/external/libfuse/source/fuse_misc.h new file mode 100644 index 0000000..c230156 --- /dev/null +++ b/external/libfuse/source/fuse_misc.h @@ -0,0 +1,67 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "config.h" +#include + +/* +Modified by T.MOMOZONO, 08/05/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +#define THREAD_NAME_MAXLEN (32) +#define SCE_ULPMGR_OBJNAME_DECI4H_PREFIX "SceDeci4h" +#define SCE_ULPMGR_OBJNAME_DECI4H_PREFIX_DRFP SCE_ULPMGR_OBJNAME_DECI4H_PREFIX "Drfp" +#define SCE_DRFP_FUSEWORKTHREAD_NAME SCE_ULPMGR_OBJNAME_DECI4H_PREFIX_DRFP "Fus%d" +#define SCE_ULPMGR_THREAD_PRIO_BASE (903) + +/* Versioned symbols confuse the dynamic linker in uClibc */ +#ifndef __UCLIBC__ +#define FUSE_SYMVER(x) __asm__(x) +#else +#define FUSE_SYMVER(x) +#endif + +#ifndef USE_UCLIBC +#define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL) +#else +/* Is this hack still needed? */ +static inline void fuse_mutex_init(pthread_mutex_t *mut) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); + pthread_mutex_init(mut, &attr); + pthread_mutexattr_destroy(&attr); +} +#endif + +#ifdef HAVE_STRUCT_STAT_ST_ATIM +/* Linux */ +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atim.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctim.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtim.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atim.tv_nsec = (val) +#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtim.tv_nsec = (val) +#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC) +/* FreeBSD */ +#define ST_ATIM_NSEC(stbuf) ((stbuf)->st_atimespec.tv_nsec) +#define ST_CTIM_NSEC(stbuf) ((stbuf)->st_ctimespec.tv_nsec) +#define ST_MTIM_NSEC(stbuf) ((stbuf)->st_mtimespec.tv_nsec) +#define ST_ATIM_NSEC_SET(stbuf, val) (stbuf)->st_atimespec.tv_nsec = (val) +#define ST_MTIM_NSEC_SET(stbuf, val) (stbuf)->st_mtimespec.tv_nsec = (val) +#else +#define ST_ATIM_NSEC(stbuf) 0 +#define ST_CTIM_NSEC(stbuf) 0 +#define ST_MTIM_NSEC(stbuf) 0 +#define ST_ATIM_NSEC_SET(stbuf, val) do { } while (0) +#define ST_MTIM_NSEC_SET(stbuf, val) do { } while (0) +#endif diff --git a/external/libfuse/source/fuse_mt.c b/external/libfuse/source/fuse_mt.c new file mode 100644 index 0000000..95c3a5c --- /dev/null +++ b/external/libfuse/source/fuse_mt.c @@ -0,0 +1,116 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include "fuse_i.h" +#include "fuse_misc.h" +#include "fuse_lowlevel.h" + +#include +#include +#include +#include +#include + +struct procdata { + struct fuse *f; + struct fuse_chan *prevch; + struct fuse_session *prevse; + fuse_processor_t proc; + void *data; +}; + +static void mt_session_proc(void *data, const char *buf, size_t len, + struct fuse_chan *ch) +{ + struct procdata *pd = (struct procdata *) data; + struct fuse_cmd *cmd = *(struct fuse_cmd **) buf; + + (void) len; + (void) ch; + pd->proc(pd->f, cmd, pd->data); +} + +static void mt_session_exit(void *data, int val) +{ + struct procdata *pd = (struct procdata *) data; + if (val) + fuse_session_exit(pd->prevse); + else + fuse_session_reset(pd->prevse); +} + +static int mt_session_exited(void *data) +{ + struct procdata *pd = (struct procdata *) data; + return fuse_session_exited(pd->prevse); +} + +static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size) +{ + struct fuse_cmd *cmd; + struct procdata *pd = (struct procdata *) fuse_chan_data(*chp); + + assert(size >= sizeof(cmd)); + + cmd = fuse_read_cmd(pd->f); + if (cmd == NULL) + return 0; + + *(struct fuse_cmd **) buf = cmd; + + return sizeof(cmd); +} + +int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data) +{ + int res; + struct procdata pd; + struct fuse_session *prevse = fuse_get_session(f); + struct fuse_session *se; + struct fuse_chan *prevch = fuse_session_next_chan(prevse, NULL); + struct fuse_chan *ch; + struct fuse_session_ops sop = { + .exit = mt_session_exit, + .exited = mt_session_exited, + .process = mt_session_proc, + }; + struct fuse_chan_ops cop = { + .receive = mt_chan_receive, + }; + + pd.f = f; + pd.prevch = prevch; + pd.prevse = prevse; + pd.proc = proc; + pd.data = data; + + se = fuse_session_new(&sop, &pd); + if (se == NULL) + return -1; + + ch = fuse_chan_new(&cop, fuse_chan_fd(prevch), + sizeof(struct fuse_cmd *), &pd); + if (ch == NULL) { + fuse_session_destroy(se); + return -1; + } + fuse_session_add_chan(se, ch); + res = fuse_session_loop_mt(se); + fuse_session_destroy(se); + return res; +} + +int fuse_loop_mt(struct fuse *f) +{ + if (f == NULL) + return -1; + + return fuse_session_loop_mt(fuse_get_session(f)); +} + +FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@"); diff --git a/external/libfuse/source/fuse_opt.c b/external/libfuse/source/fuse_opt.c new file mode 100644 index 0000000..890d2fd --- /dev/null +++ b/external/libfuse/source/fuse_opt.c @@ -0,0 +1,430 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_opt.h" +#include "fuse_misc.h" + +#include +#include +#include +#include + +struct fuse_opt_context { + void *data; + const struct fuse_opt *opt; + fuse_opt_proc_t proc; + int argctr; + int argc; + char **argv; + struct fuse_args outargs; + char *opts; + int nonopt; +}; + +void fuse_opt_free_args(struct fuse_args *args) +{ + if (args) { + if (args->argv && args->allocated) { + int i; + for (i = 0; i < args->argc; i++) + free(args->argv[i]); + free(args->argv); + } + args->argc = 0; + args->argv = NULL; + args->allocated = 0; + } +} + +static int alloc_failed(void) +{ + libfuse_print("fuse: memory allocation failed"); + return -1; +} + +int fuse_opt_add_arg(struct fuse_args *args, const char *arg) +{ + char **newargv; + char *newarg; + + assert(!args->argv || args->allocated); +/* +Modified by Y.ITO, 02/16/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + newarg = strdup(arg); + if (!newarg) + return alloc_failed(); + + newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *)); + if (!newargv) { + free(newarg); + return alloc_failed(); + } + + args->argv = newargv; + args->allocated = 1; + args->argv[args->argc++] = newarg; + args->argv[args->argc] = NULL; + return 0; +} + +static int fuse_opt_insert_arg_common(struct fuse_args *args, int pos, + const char *arg) +{ + assert(pos <= args->argc); + if (fuse_opt_add_arg(args, arg) == -1) + return -1; + + if (pos != args->argc - 1) { + char *newarg = args->argv[args->argc - 1]; + memmove(&args->argv[pos + 1], &args->argv[pos], + sizeof(char *) * (args->argc - pos - 1)); + args->argv[pos] = newarg; + } + return 0; +} + +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg) +{ + return fuse_opt_insert_arg_common(args, pos, arg); +} + +int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, + const char *arg); +int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, const char *arg) +{ + return fuse_opt_insert_arg_common(args, pos, arg); +} + +static int next_arg(struct fuse_opt_context *ctx, const char *opt) +{ + if (ctx->argctr + 1 >= ctx->argc) { + libfuse_print("fuse: missing argument after `%s'", opt); + return -1; + } + ctx->argctr++; + return 0; +} + +static int add_arg(struct fuse_opt_context *ctx, const char *arg) +{ + return fuse_opt_add_arg(&ctx->outargs, arg); +} + +static int add_opt_common(char **opts, const char *opt, int esc) +{ + unsigned oldlen = *opts ? strlen(*opts) : 0; + char *d = realloc(*opts, oldlen + 1 + strlen(opt) * 2 + 1); + + if (!d) + return alloc_failed(); + + *opts = d; + if (oldlen) { + d += oldlen; + *d++ = ','; + } + + for (; *opt; opt++) { + if (esc && (*opt == ',' || *opt == '\\')) + *d++ = '\\'; + *d++ = *opt; + } + *d = '\0'; + + return 0; +} + +int fuse_opt_add_opt(char **opts, const char *opt) +{ + return add_opt_common(opts, opt, 0); +} + +int fuse_opt_add_opt_escaped(char **opts, const char *opt) +{ + return add_opt_common(opts, opt, 1); +} + +static int add_opt(struct fuse_opt_context *ctx, const char *opt) +{ + return add_opt_common(&ctx->opts, opt, 1); +} + +static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key, + int iso) +{ + if (key == FUSE_OPT_KEY_DISCARD) + return 0; + + if (key != FUSE_OPT_KEY_KEEP && ctx->proc) { + int res = ctx->proc(ctx->data, arg, key, &ctx->outargs); + if (res == -1 || !res) + return res; + } + if (iso) + return add_opt(ctx, arg); + else + return add_arg(ctx, arg); +} + +static int match_template(const char *t, const char *arg, unsigned *sepp) +{ + int arglen = strlen(arg); + const char *sep = strchr(t, '='); + sep = sep ? sep : strchr(t, ' '); + if (sep && (!sep[1] || sep[1] == '%')) { + int tlen = sep - t; + if (sep[0] == '=') + tlen ++; + if (arglen >= tlen && strncmp(arg, t, tlen) == 0) { + *sepp = sep - t; + return 1; + } + } + if (strcmp(t, arg) == 0) { + *sepp = 0; + return 1; + } + return 0; +} + +static const struct fuse_opt *find_opt(const struct fuse_opt *opt, + const char *arg, unsigned *sepp) +{ + for (; opt && opt->templ; opt++) + if (match_template(opt->templ, arg, sepp)) + return opt; + return NULL; +} + +int fuse_opt_match(const struct fuse_opt *opts, const char *opt) +{ + unsigned dummy; + return find_opt(opts, opt, &dummy) ? 1 : 0; +} + +static int process_opt_param(void *var, const char *format, const char *param, + const char *arg) +{ + assert(format[0] == '%'); + if (format[1] == 's') { + char *copy = strdup(param); + if (!copy) + return alloc_failed(); + + *(char **) var = copy; + } else { + if (sscanf(param, format, var) != 1) { + libfuse_print("fuse: invalid parameter in option `%s'", arg); + return -1; + } + } + return 0; +} + +static int process_opt(struct fuse_opt_context *ctx, + const struct fuse_opt *opt, unsigned sep, + const char *arg, int iso) +{ + if (opt->offset == -1U) { + if (call_proc(ctx, arg, opt->value, iso) == -1) + return -1; + } else { + void *var = ctx->data + opt->offset; + if (sep && opt->templ[sep + 1]) { + const char *param = arg + sep; + if (opt->templ[sep] == '=') + param ++; + if (process_opt_param(var, opt->templ + sep + 1, + param, arg) == -1) + return -1; + } else + *(int *)var = opt->value; + } + return 0; +} + +static int process_opt_sep_arg(struct fuse_opt_context *ctx, + const struct fuse_opt *opt, unsigned sep, + const char *arg, int iso) +{ + int res; + char *newarg; + char *param; + + if (next_arg(ctx, arg) == -1) + return -1; + + param = ctx->argv[ctx->argctr]; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + size_t newargsize = sep + strlen(param) + 1; + newarg = malloc(newargsize); + if (!newarg) + return alloc_failed(); + + memcpy(newarg, arg, sep); + strncpy(newarg + sep, param, newargsize - sep); + res = process_opt(ctx, opt, sep, newarg, iso); + free(newarg); + + return res; +} + +static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso) +{ + unsigned sep; + const struct fuse_opt *opt = find_opt(ctx->opt, arg, &sep); + if (opt) { + for (; opt; opt = find_opt(opt + 1, arg, &sep)) { + int res; + if (sep && opt->templ[sep] == ' ' && !arg[sep]) + res = process_opt_sep_arg(ctx, opt, sep, arg, + iso); + else + res = process_opt(ctx, opt, sep, arg, iso); + if (res == -1) + return -1; + } + return 0; + } else + return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso); +} + +static int process_real_option_group(struct fuse_opt_context *ctx, char *opts) +{ + char *s = opts; + char *d = s; + int end = 0; + + while (!end) { + if (*s == '\0') + end = 1; + if (*s == ',' || end) { + int res; + + *d = '\0'; + res = process_gopt(ctx, opts, 1); + if (res == -1) + return -1; + d = opts; + } else { + if (s[0] == '\\' && s[1] != '\0') + s++; + *d++ = *s; + } + s++; + } + + return 0; +} + +static int process_option_group(struct fuse_opt_context *ctx, const char *opts) +{ + int res; + char *copy = strdup(opts); + + if (!copy) { + libfuse_print("fuse: memory allocation failed"); + return -1; + } + res = process_real_option_group(ctx, copy); + free(copy); + return res; +} + +static int process_one(struct fuse_opt_context *ctx, const char *arg) +{ + if (ctx->nonopt || arg[0] != '-') + return call_proc(ctx, arg, FUSE_OPT_KEY_NONOPT, 0); + else if (arg[1] == 'o') { + if (arg[2]) + return process_option_group(ctx, arg + 2); + else { + if (next_arg(ctx, arg) == -1) + return -1; + + return process_option_group(ctx, + ctx->argv[ctx->argctr]); + } + } else if (arg[1] == '-' && !arg[2]) { + if (add_arg(ctx, arg) == -1) + return -1; + ctx->nonopt = ctx->outargs.argc; + return 0; + } else + return process_gopt(ctx, arg, 0); +} + +static int opt_parse(struct fuse_opt_context *ctx) +{ + if (ctx->argc) { + if (add_arg(ctx, ctx->argv[0]) == -1) + return -1; + } + + for (ctx->argctr = 1; ctx->argctr < ctx->argc; ctx->argctr++) + if (process_one(ctx, ctx->argv[ctx->argctr]) == -1) + return -1; + + if (ctx->opts) { + if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 || + fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1) + return -1; + } + + /* If option separator ("--") is the last argument, remove it */ + if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc && + strcmp(ctx->outargs.argv[ctx->outargs.argc - 1], "--") == 0) { + free(ctx->outargs.argv[ctx->outargs.argc - 1]); + ctx->outargs.argv[--ctx->outargs.argc] = NULL; + } + + return 0; +} + +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc) +{ + int res; + struct fuse_opt_context ctx = { + .data = data, + .opt = opts, + .proc = proc, + }; + + if (!args || !args->argv || !args->argc) + return 0; + + ctx.argc = args->argc; + ctx.argv = args->argv; + + res = opt_parse(&ctx); + if (res != -1) { + struct fuse_args tmp = *args; + *args = ctx.outargs; + ctx.outargs = tmp; + } + free(ctx.opts); + fuse_opt_free_args(&ctx.outargs); + return res; +} + +/* This symbol version was mistakenly added to the version script */ +FUSE_SYMVER(".symver fuse_opt_insert_arg_compat,fuse_opt_insert_arg@FUSE_2.5"); diff --git a/external/libfuse/source/fuse_session.c b/external/libfuse/source/fuse_session.c new file mode 100644 index 0000000..5de6ceb --- /dev/null +++ b/external/libfuse/source/fuse_session.c @@ -0,0 +1,205 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_i.h" +#include "fuse_misc.h" +#include "fuse_common_compat.h" +#include "fuse_lowlevel_compat.h" + +#include +#include +#include +#include +#include + +struct fuse_chan { + struct fuse_chan_ops op; + + struct fuse_session *se; + + int fd; + + size_t bufsize; + + void *data; + + int compat; +}; + +struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data) +{ + struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se)); + if (se == NULL) { + libfuse_print("fuse: failed to allocate session"); + return NULL; + } + + memset(se, 0, sizeof(*se)); + se->op = *op; + se->data = data; + + return se; +} + +void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch) +{ + assert(se->ch == NULL); + assert(ch->se == NULL); + se->ch = ch; + ch->se = se; +} + +void fuse_session_remove_chan(struct fuse_chan *ch) +{ + struct fuse_session *se = ch->se; + if (se) { + assert(se->ch == ch); + se->ch = NULL; + ch->se = NULL; + } +} + +struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, + struct fuse_chan *ch) +{ + assert(ch == NULL || ch == se->ch); + if (ch == NULL) + return se->ch; + else + return NULL; +} + +void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, + struct fuse_chan *ch) +{ + se->op.process(se->data, buf, len, ch); +} + +void fuse_session_destroy(struct fuse_session *se) +{ + if (se->op.destroy) + se->op.destroy(se->data); + if (se->ch != NULL) + fuse_chan_destroy(se->ch); + free(se); +} + +void fuse_session_exit(struct fuse_session *se) +{ + if (se->op.exit) + se->op.exit(se->data, 1); + se->exited = 1; +} + +void fuse_session_reset(struct fuse_session *se) +{ + if (se->op.exit) + se->op.exit(se->data, 0); + se->exited = 0; +} + +int fuse_session_exited(struct fuse_session *se) +{ + if (se->op.exited) + return se->op.exited(se->data); + else + return se->exited; +} + +void *fuse_session_data(struct fuse_session *se) +{ + return se->data; +} + +static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data, + int compat) +{ + struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch)); + if (ch == NULL) { + libfuse_print("fuse: failed to allocate channel"); + return NULL; + } + + memset(ch, 0, sizeof(*ch)); + ch->op = *op; + ch->fd = fd; + ch->bufsize = bufsize; + ch->data = data; + ch->compat = compat; + + return ch; +} + +struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data) +{ + return fuse_chan_new_common(op, fd, bufsize, data, 0); +} + +struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, + int fd, size_t bufsize, void *data) +{ + return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize, + data, 24); +} + +int fuse_chan_fd(struct fuse_chan *ch) +{ + return ch->fd; +} + +size_t fuse_chan_bufsize(struct fuse_chan *ch) +{ + return ch->bufsize; +} + +void *fuse_chan_data(struct fuse_chan *ch) +{ + return ch->data; +} + +struct fuse_session *fuse_chan_session(struct fuse_chan *ch) +{ + return ch->se; +} + +int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size) +{ + struct fuse_chan *ch = *chp; + if (ch->compat) + return ((struct fuse_chan_ops_compat24 *) &ch->op) + ->receive(ch, buf, size); + else + return ch->op.receive(chp, buf, size); +} + +int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size) +{ + int res; + + res = fuse_chan_recv(&ch, buf, size); + return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0; +} + +int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count) +{ + return ch->op.send(ch, iov, count); +} + +void fuse_chan_destroy(struct fuse_chan *ch) +{ + fuse_session_remove_chan(ch); + if (ch->op.destroy) + ch->op.destroy(ch); + free(ch); +} + +#ifndef __FreeBSD__ +FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4"); +#endif diff --git a/external/libfuse/source/fuse_signals.c b/external/libfuse/source/fuse_signals.c new file mode 100644 index 0000000..88510da --- /dev/null +++ b/external/libfuse/source/fuse_signals.c @@ -0,0 +1,89 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +#include "fuse_lowlevel.h" + +#include +#include +#include + +static struct fuse_session *fuse_instance; + +static void exit_handler(int sig) +{ + (void) sig; + if (fuse_instance) + fuse_session_exit(fuse_instance); +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGPIPE, SIG_DFL); +} + +static int set_one_signal_handler(int sig, void (*handler)(int)) +{ + struct sigaction sa; + struct sigaction old_sa; + + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = handler; + sigemptyset(&(sa.sa_mask)); + sa.sa_flags = 0; + + if (sigaction(sig, NULL, &old_sa) == -1) { + perror("fuse: cannot get old signal handler"); + return -1; + } + + if (old_sa.sa_handler == SIG_DFL && + sigaction(sig, &sa, NULL) == -1) { + perror("fuse: cannot set signal handler"); + return -1; + } + return 0; +} + +int fuse_set_signal_handlers(struct fuse_session *se) +{ + if (set_one_signal_handler(SIGHUP, exit_handler) == -1 || + set_one_signal_handler(SIGINT, exit_handler) == -1 || + set_one_signal_handler(SIGTERM, exit_handler) == -1 || + set_one_signal_handler(SIGPIPE, SIG_IGN) == -1) + return -1; + + fuse_instance = se; + return 0; +} + +void fuse_remove_signal_handlers(struct fuse_session *se) +{ +/* +Modified by Y.OGATA, 06/05/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + if (fuse_instance == se) + fuse_instance = NULL; + + set_one_signal_handler(SIGHUP, SIG_DFL); + set_one_signal_handler(SIGINT, SIG_DFL); + set_one_signal_handler(SIGTERM, SIG_DFL); + set_one_signal_handler(SIGPIPE, SIG_DFL); +} + diff --git a/external/libfuse/source/fuse_versionscript b/external/libfuse/source/fuse_versionscript new file mode 100644 index 0000000..aad7ab3 --- /dev/null +++ b/external/libfuse/source/fuse_versionscript @@ -0,0 +1,184 @@ +FUSE_2.2 { + global: + fuse_destroy; + fuse_exit; + fuse_exited; + fuse_invalidate; + fuse_is_lib_option; + fuse_loop; + fuse_loop_mt; + fuse_loop_mt_proc; + fuse_main; + fuse_main_compat1; + fuse_main_compat2; + fuse_mount_compat1; + fuse_new_compat1; + fuse_new_compat2; + fuse_process_cmd; + fuse_read_cmd; + fuse_set_getcontext_func; + fuse_setup_compat2; +}; + +FUSE_2.4 { + global: + fuse_add_dirent; + fuse_chan_bufsize; + fuse_chan_data; + fuse_chan_destroy; + fuse_chan_fd; + fuse_chan_receive; + fuse_chan_send; + fuse_chan_session; + fuse_dirent_size; + fuse_kern_chan_new; + fuse_lowlevel_is_lib_option; + fuse_reply_attr; + fuse_reply_buf; + fuse_reply_entry; + fuse_reply_err; + fuse_reply_none; + fuse_reply_readlink; + fuse_reply_write; + fuse_reply_xattr; + fuse_req_userdata; + fuse_session_add_chan; + fuse_session_destroy; + fuse_session_exit; + fuse_session_exited; + fuse_session_loop; + fuse_session_loop_mt; + fuse_session_new; + fuse_session_next_chan; + fuse_session_process; + fuse_session_reset; +} FUSE_2.2; + +FUSE_2.5 { + global: + fuse_lowlevel_new_compat; + fuse_main_real_compat22; + fuse_mount_compat22; + fuse_new_compat22; + fuse_opt_parse; + fuse_opt_add_opt; + fuse_opt_add_arg; + fuse_opt_free_args; + fuse_opt_match; + fuse_parse_cmdline; + fuse_remove_signal_handlers; + fuse_reply_create; + fuse_reply_open; + fuse_reply_open_compat; + fuse_reply_statfs; + fuse_reply_statfs_compat; + fuse_setup_compat22; + fuse_set_signal_handlers; +} FUSE_2.4; + +FUSE_2.6 { + global: + fuse_add_direntry; + fuse_chan_new; + fuse_chan_new_compat24; + fuse_chan_recv; + fuse_daemonize; + fuse_get_session; + fuse_interrupted; + fuse_lowlevel_new; + fuse_lowlevel_new_compat25; + fuse_main_real; + fuse_main_real_compat25; + fuse_mount; + fuse_mount_compat25; + fuse_new; + fuse_new_compat25; + fuse_opt_insert_arg; + fuse_reply_lock; + fuse_req_interrupt_func; + fuse_req_interrupted; + fuse_session_remove_chan; + fuse_setup; + fuse_setup_compat25; + fuse_teardown; + fuse_teardown_compat22; + fuse_unmount; + fuse_unmount_compat22; +} FUSE_2.5; + +FUSE_2.7 { + global: + fuse_fs_access; + fuse_fs_bmap; + fuse_fs_chmod; + fuse_fs_chown; + fuse_fs_create; + fuse_fs_destroy; + fuse_fs_fgetattr; + fuse_fs_flush; + fuse_fs_fsync; + fuse_fs_fsyncdir; + fuse_fs_ftruncate; + fuse_fs_getattr; + fuse_fs_getxattr; + fuse_fs_init; + fuse_fs_link; + fuse_fs_listxattr; + fuse_fs_lock; + fuse_fs_mkdir; + fuse_fs_mknod; + fuse_fs_new; + fuse_fs_open; + fuse_fs_opendir; + fuse_fs_read; + fuse_fs_readdir; + fuse_fs_readlink; + fuse_fs_release; + fuse_fs_releasedir; + fuse_fs_removexattr; + fuse_fs_rename; + fuse_fs_rmdir; + fuse_fs_setxattr; + fuse_fs_statfs; + fuse_fs_symlink; + fuse_fs_truncate; + fuse_fs_unlink; + fuse_fs_utimens; + fuse_fs_write; + fuse_register_module; + fuse_reply_iov; + fuse_version; +} FUSE_2.6; + +FUSE_2.7.5 { + global: + fuse_reply_bmap; +} FUSE_2.7; + +FUSE_2.8 { + global: + cuse_lowlevel_new; + cuse_lowlevel_main; + cuse_lowlevel_setup; + cuse_lowlevel_teardown; + fuse_fs_ioctl; + fuse_fs_poll; + fuse_get_context; + fuse_getgroups; + fuse_lowlevel_notify_inval_entry; + fuse_lowlevel_notify_inval_inode; + fuse_lowlevel_notify_poll; + fuse_notify_poll; + fuse_opt_add_opt_escaped; + fuse_pollhandle_destroy; + fuse_reply_ioctl; + fuse_reply_ioctl_iov; + fuse_reply_ioctl_retry; + fuse_reply_poll; + fuse_req_ctx; + fuse_req_getgroups; + fuse_session_data; + + local: + *; +} FUSE_2.7.5; diff --git a/external/libfuse/source/helper.c b/external/libfuse/source/helper.c new file mode 100644 index 0000000..1f55bff --- /dev/null +++ b/external/libfuse/source/helper.c @@ -0,0 +1,536 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include "config.h" +#include "fuse_i.h" +#include "fuse_misc.h" +#include "fuse_opt.h" +#include "fuse_lowlevel.h" +#include "fuse_common_compat.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + KEY_HELP, + KEY_HELP_NOHEADER, + KEY_VERSION, +}; + +struct helper_opts { + int singlethread; + int foreground; + int nodefault_subtype; + char *mountpoint; +}; + + +void libfuse_print(char* format, ...) +{ + char buff[1024]; + memset(&buff[0], 0, 1024); + + va_list args; + va_start(args, format); + vsprintf(&buff[0], format, args); + va_end(args); + + snprintf(&buff[0], 1023, "%s\n", &buff[0]); + sceKernelDebugOutText(0, &buff[0]); + + int fd = sceKernelOpen("/user/app/ITEM00001/libfuse.log", O_WRONLY | O_CREAT | O_APPEND, 0777); + if (fd >= 0) + { + sceKernelWrite(fd, &buff[0], strlen(&buff[0])); + sceKernelClose(fd); + } +} + +#define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 } + +static const struct fuse_opt fuse_helper_opts[] = { + FUSE_HELPER_OPT("-d", foreground), + FUSE_HELPER_OPT("debug", foreground), + FUSE_HELPER_OPT("-f", foreground), + FUSE_HELPER_OPT("-s", singlethread), + FUSE_HELPER_OPT("fsname=", nodefault_subtype), + FUSE_HELPER_OPT("subtype=", nodefault_subtype), + + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP), + FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP), + FUSE_OPT_END +}; + +static void usage(const char *progname) +{ + fprintf(stderr, + "usage: %s mountpoint [options]\n", progname); + fprintf(stderr, + "general options:" + " -o opt,[opt...] mount options" + " -h --help print help" + " -V --version print version" + ""); +} + +static void helper_help(void) +{ + fprintf(stderr, + "FUSE options:" + " -d -o debug enable debug output (implies -f)" + " -f foreground operation" + " -s disable multi-threaded operation" + "" + ); +} + +static void helper_version(void) +{ + libfuse_print("FUSE library version: %s", PACKAGE_VERSION); +} + +static int fuse_helper_opt_proc(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + struct helper_opts *hopts = data; + + switch (key) { + case KEY_HELP: + usage(outargs->argv[0]); + /* fall through */ + + case KEY_HELP_NOHEADER: + helper_help(); + return fuse_opt_add_arg(outargs, "-h"); + + case KEY_VERSION: + helper_version(); + return 1; + + case FUSE_OPT_KEY_NONOPT: + if (!hopts->mountpoint) { + char mountpoint[PATH_MAX]; +/* +Modified by Y.OGATA, 06/05/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /* + if (realpath(arg, mountpoint) == NULL) { + fprintf(stderr, + "fuse: bad mount point `%s': %s", + arg, strerror(errno)); + return -1; + } + */ + strncpy(mountpoint, arg, 9); /* /hostapp + 1 */ + return fuse_opt_add_opt(&hopts->mountpoint, mountpoint); + } else { + libfuse_print("fuse: invalid argument `%s'", arg); + return -1; + } + + default: + return 1; + } +} + +static int add_default_subtype(const char *progname, struct fuse_args *args) +{ + int res; + char *subtype_opt; + const char *basename = strrchr(progname, '/'); + if (basename == NULL) + basename = progname; + else if (basename[1] != '\0') + basename++; +/* +Modified by F.KUMAGAE, 05/15/2014 + +--------------- +Copyright (c) 2014 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + size_t subtype_opt_size = strlen(basename) + 64; + subtype_opt = (char *) malloc(subtype_opt_size); + if (subtype_opt == NULL) { + libfuse_print("fuse: memory allocation failed"); + return -1; + } + snprintf(subtype_opt, subtype_opt_size, "-osubtype=%s", basename); + res = fuse_opt_add_arg(args, subtype_opt); + free(subtype_opt); + return res; +} + +int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, + int *multithreaded, int *foreground) +{ + int res; + struct helper_opts hopts; + + memset(&hopts, 0, sizeof(hopts)); + res = fuse_opt_parse(args, &hopts, fuse_helper_opts, + fuse_helper_opt_proc); + if (res == -1) + return -1; + + if (!hopts.nodefault_subtype) { + res = add_default_subtype(args->argv[0], args); + if (res == -1) + goto err; + } + if (mountpoint) + *mountpoint = hopts.mountpoint; + else + free(hopts.mountpoint); + + if (multithreaded) + *multithreaded = !hopts.singlethread; + if (foreground) + *foreground = hopts.foreground; + return 0; + +err: + free(hopts.mountpoint); + return -1; +} + +int fuse_daemonize(int foreground) +{ + int res; + + if (!foreground) { + res = daemon(0, 0); + if (res == -1) { + perror("fuse: failed to daemonize program"); + return -1; + } + } + return 0; +} + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +static struct fuse_chan *fuse_mount_common(const char *mountpoint, + struct fuse_args *args, const struct fuse_operations *op) +{ + struct fuse_chan *ch; + int fd; + + /* + * Make sure file descriptors 0, 1 and 2 are open, otherwise chaos + * would ensue. + */ + do { + fd = open("/dev/null", O_RDWR); + if (fd > 2) + close(fd); + } while (fd >= 0 && fd <= 2); + + fd = fuse_mount_compat25(mountpoint, args, op); + if (fd == -1) + return NULL; + + ch = fuse_kern_chan_new(fd); + + return ch; +} +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +/* +struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) +{ + return fuse_mount_common(mountpoint, args); +} +*/ +static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch) +{ + //ch ? fuse_chan_fd(ch) : -1; + //fuse_kern_unmount(mountpoint, fd); + fuse_chan_destroy(ch); +} + +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) +{ + fuse_unmount_common(mountpoint, ch); +} + +struct fuse *fuse_setup_common(int argc, char *argv[], + const struct fuse_operations *op, + size_t op_size, + char **mountpoint, + int *multithreaded, + int *fd, + void *user_data, + int compat) +{ + struct fuse_args args = FUSE_ARGS_INIT(argc, argv); + struct fuse_chan *ch; + struct fuse *fuse; + int foreground; + int res; + + libfuse_print("libfuse: STARTING %s", __func__); + + res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground); + if (res == -1){ + libfuse_print("libfuse: Failed to parse cmd args"); + return NULL; + } + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + ch = fuse_mount_common(*mountpoint, &args, op); + if (!ch) { + fuse_opt_free_args(&args); + libfuse_print("libfuse: fuse_mount_common failed"); + goto err_free; + } + + fuse = fuse_new_common(ch, &args, op, op_size, user_data, compat); + fuse_opt_free_args(&args); + if (fuse == NULL){ + libfuse_print("libfuse: fuse_new_common failed"); + goto err_unmount; + } + + + res = fuse_set_signal_handlers(fuse_get_session(fuse)); + if (res == -1){ + libfuse_print("libfuse: fuse_set_signal_handlers failed"); + goto err_unmount; + } + + if (fd) + *fd = fuse_chan_fd(ch); + + libfuse_print("[libfuse] fuse: %p: fuse_setup_common() done", fuse); + + return fuse; + +err_unmount: + fuse_unmount_common(*mountpoint, ch); + libfuse_print("[ERROR] Libfuse unmouting..."); + if (fuse) + fuse_destroy(fuse); +err_free: + free(*mountpoint); + libfuse_print("[ERROR] Libfuse: %s failed", __func__); + return NULL; +} + +struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + char **mountpoint, int *multithreaded, void *user_data) +{ + return fuse_setup_common(argc, argv, op, op_size, mountpoint, + multithreaded, NULL, user_data, 0); +} + +static void fuse_teardown_common(struct fuse *fuse, char *mountpoint) +{ + struct fuse_session *se = fuse_get_session(fuse); + struct fuse_chan *ch = fuse_session_next_chan(se, NULL); + fuse_remove_signal_handlers(se); + fuse_unmount_common(mountpoint, ch); + fuse_destroy(fuse); + free(mountpoint); +} + +void fuse_teardown(struct fuse *fuse, char *mountpoint) +{ + fuse_teardown_common(fuse, mountpoint); +} + +static int fuse_main_common(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + void *user_data, int compat) +{ + struct fuse *fuse; + char *mountpoint; + int multithreaded; + int res; + + fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint, + &multithreaded, NULL, user_data, compat); + if (fuse == NULL) + return 1; + + if (multithreaded) + res = fuse_loop_mt(fuse); + else + res = fuse_loop(fuse); + + fuse_teardown_common(fuse, mountpoint); + if (res == -1) + return 1; + + return 0; +} + +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, + size_t op_size, void *user_data) +{ + libfuse_print("libfuse: # of args %d", argc); + return fuse_main_common(argc, argv, op, op_size, user_data, 0); +} + +#undef fuse_main +int fuse_main(void); +int fuse_main(void) +{ + libfuse_print("fuse_main(): This function does not exist"); + return -1; +} + +int fuse_version(void) +{ + return FUSE_VERSION; +} + +#include "fuse_compat.h" + +#ifndef __FreeBSD__ + +struct fuse *fuse_setup_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd) +{ + return fuse_setup_common(argc, argv, (struct fuse_operations *) op, + op_size, mountpoint, multithreaded, fd, NULL, + 22); +} + +struct fuse *fuse_setup_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op, + char **mountpoint, int *multithreaded, + int *fd) +{ + return fuse_setup_common(argc, argv, (struct fuse_operations *) op, + sizeof(struct fuse_operations_compat2), + mountpoint, multithreaded, fd, NULL, 21); +} + +int fuse_main_real_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size) +{ + return fuse_main_common(argc, argv, (struct fuse_operations *) op, + op_size, NULL, 22); +} + +void fuse_main_compat1(int argc, char *argv[], + const struct fuse_operations_compat1 *op) +{ + fuse_main_common(argc, argv, (struct fuse_operations *) op, + sizeof(struct fuse_operations_compat1), NULL, 11); +} + +int fuse_main_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op) +{ + return fuse_main_common(argc, argv, (struct fuse_operations *) op, + sizeof(struct fuse_operations_compat2), NULL, + 21); +} + +int fuse_mount_compat1(const char *mountpoint, const char *args[]) +{ + /* just ignore mount args for now */ + (void) args; + return fuse_mount_compat22(mountpoint, NULL); +} + +FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@"); +FUSE_SYMVER(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2"); +FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@"); +FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@"); +FUSE_SYMVER(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2"); + +#endif /* __FreeBSD__ */ + + +struct fuse *fuse_setup_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd) +{ + return fuse_setup_common(argc, argv, (struct fuse_operations *) op, + op_size, mountpoint, multithreaded, fd, NULL, + 25); +} + +int fuse_main_real_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size) +{ + return fuse_main_common(argc, argv, (struct fuse_operations *) op, + op_size, NULL, 25); +} + +void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint) +{ + (void) fd; + fuse_teardown_common(fuse, mountpoint); +} + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args, const struct fuse_operations *op) +{ + return fuse_kern_mount(mountpoint, args, op); +} + +FUSE_SYMVER(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5"); +FUSE_SYMVER(".symver fuse_teardown_compat22,fuse_teardown@FUSE_2.2"); +FUSE_SYMVER(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5"); +FUSE_SYMVER(".symver fuse_mount_compat25,fuse_mount@FUSE_2.5"); diff --git a/external/libfuse/source/mount_bsd.c b/external/libfuse/source/mount_bsd.c new file mode 100644 index 0000000..8c84ee8 --- /dev/null +++ b/external/libfuse/source/mount_bsd.c @@ -0,0 +1,339 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2005-2008 Csaba Henk + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include "fuse_i.h" +#include "fuse_misc.h" +#include "fuse_opt.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FUSERMOUNT_PROG "/system/sys/mount_fusefs.elf" +#define FUSE_DEV_TRUNK "/dev/fuse" + +enum { + KEY_ALLOW_ROOT, + KEY_RO, + KEY_HELP, + KEY_VERSION, + KEY_KERN +}; + +struct mount_opts { + int allow_other; + int allow_root; + int ishelp; + char *kernel_opts; +}; + + +void build_iovec(struct iovec** iov, int* iovlen, const char* name, const void* val, size_t len) { + int i; + + if (*iovlen < 0) + return; + + i = *iovlen; + *iov = (struct iovec*)realloc((void*)(*iov), sizeof(struct iovec) * (i + 2)); + if (*iov == NULL) { + *iovlen = -1; + return; + } + + (*iov)[i].iov_base = strdup(name); + (*iov)[i].iov_len = strlen(name) + 1; + ++i; + + (*iov)[i].iov_base = (void*)val; + if (len == (size_t)-1) { + if (val != NULL) + len = strlen((const char*)val) + 1; + else + len = 0; + } + (*iov)[i].iov_len = (int)len; + + *iovlen = ++i; +} + + +int mount_fuse(const char* device, const char* mountpoint) +{ + struct iovec* iov = NULL; + int iovlen = 0; + //char buff[200]; + + build_iovec(&iov, &iovlen, "private", "__private", -1); + build_iovec(&iov, &iovlen, "allow_other", "", -1); + build_iovec(&iov, &iovlen, "subtype=", "dummy", -1);//private + build_iovec(&iov, &iovlen, "sync_unmount", "__sync_unmount", -1); + build_iovec(&iov, &iovlen, "max_read=", "262144", -1); + build_iovec(&iov, &iovlen, "fstype", "fusefs", -1); + build_iovec(&iov, &iovlen, "fspath", mountpoint, -1); + build_iovec(&iov, &iovlen, "from", device, -1); + //build_iovec(&iov, &iovlen, "max_read=", "262144", -1); + + + libfuse_print("##^ [I] Mounting \"%s\" to \"%s\" ", device, mountpoint); + int ret = nmount(iov, iovlen, 0); + if (ret < 0) { + libfuse_print("##^ [E] Failed: %d (errno: %d).", ret, errno); + return ret; + } + else + libfuse_print("##^ [I] Success."); + + + return 0; +} + + +#define FUSE_DUAL_OPT_KEY(templ, key) \ + FUSE_OPT_KEY(templ, key), FUSE_OPT_KEY("no" templ, key) + +static const struct fuse_opt fuse_mount_opts[] = { + { "allow_other", offsetof(struct mount_opts, allow_other), 1 }, + { "allow_root", offsetof(struct mount_opts, allow_root), 1 }, + FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT), + FUSE_OPT_KEY("-r", KEY_RO), + FUSE_OPT_KEY("-h", KEY_HELP), + FUSE_OPT_KEY("--help", KEY_HELP), + FUSE_OPT_KEY("-V", KEY_VERSION), + FUSE_OPT_KEY("--version", KEY_VERSION), + /* standard FreeBSD mount options */ + FUSE_DUAL_OPT_KEY("dev", KEY_KERN), + FUSE_DUAL_OPT_KEY("async", KEY_KERN), + FUSE_DUAL_OPT_KEY("atime", KEY_KERN), + FUSE_DUAL_OPT_KEY("dev", KEY_KERN), + FUSE_DUAL_OPT_KEY("exec", KEY_KERN), + FUSE_DUAL_OPT_KEY("suid", KEY_KERN), + FUSE_DUAL_OPT_KEY("symfollow", KEY_KERN), + FUSE_DUAL_OPT_KEY("rdonly", KEY_KERN), + FUSE_DUAL_OPT_KEY("sync", KEY_KERN), + FUSE_DUAL_OPT_KEY("union", KEY_KERN), + FUSE_DUAL_OPT_KEY("userquota", KEY_KERN), + FUSE_DUAL_OPT_KEY("groupquota", KEY_KERN), + FUSE_DUAL_OPT_KEY("clusterr", KEY_KERN), + FUSE_DUAL_OPT_KEY("clusterw", KEY_KERN), + FUSE_DUAL_OPT_KEY("suiddir", KEY_KERN), + FUSE_DUAL_OPT_KEY("snapshot", KEY_KERN), + FUSE_DUAL_OPT_KEY("multilabel", KEY_KERN), + FUSE_DUAL_OPT_KEY("acls", KEY_KERN), + FUSE_DUAL_OPT_KEY("force", KEY_KERN), + FUSE_DUAL_OPT_KEY("update", KEY_KERN), + FUSE_DUAL_OPT_KEY("ro", KEY_KERN), + FUSE_DUAL_OPT_KEY("rw", KEY_KERN), + FUSE_DUAL_OPT_KEY("auto", KEY_KERN), + /* options supported under both Linux and FBSD */ + FUSE_DUAL_OPT_KEY("allow_other", KEY_KERN), + FUSE_DUAL_OPT_KEY("default_permissions",KEY_KERN), + FUSE_OPT_KEY("max_read=", KEY_KERN), + FUSE_OPT_KEY("subtype=", KEY_KERN), + /* FBSD FUSE specific mount options */ + FUSE_DUAL_OPT_KEY("private", KEY_KERN), + FUSE_DUAL_OPT_KEY("neglect_shares", KEY_KERN), + FUSE_DUAL_OPT_KEY("push_symlinks_in", KEY_KERN), + FUSE_OPT_KEY("nosync_unmount", KEY_KERN), + /* stock FBSD mountopt parsing routine lets anything be negated... */ + /* + * Linux specific mount options, but let just the mount util + * handle them + */ + FUSE_OPT_KEY("fsname=", KEY_KERN), + FUSE_OPT_KEY("nonempty", KEY_KERN), + FUSE_OPT_KEY("large_read", KEY_KERN), + FUSE_OPT_END +}; + +static void mount_help(void) +{ + fprintf(stderr, + " -o allow_root allow access to root" + ); + system(FUSERMOUNT_PROG " --help"); + fputc('\n', stderr); +} + +static void mount_version(void) +{ + system(FUSERMOUNT_PROG " --version"); +} + +static int fuse_mount_opt_proc(void *data, const char *arg, int key, + struct fuse_args *outargs) +{ + struct mount_opts *mo = data; + + switch (key) { + case KEY_ALLOW_ROOT: + if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 || + fuse_opt_add_arg(outargs, "-oallow_root") == -1) + return -1; + return 0; + + case KEY_RO: + arg = "ro"; + /* fall through */ + + case KEY_KERN: + return fuse_opt_add_opt(&mo->kernel_opts, arg); + + case KEY_HELP: + mount_help(); + mo->ishelp = 1; + break; + + case KEY_VERSION: + mount_version(); + mo->ishelp = 1; + break; + } + return 1; +} +#if 0 +/* +Modified by F.KUMAGAE, 01/23/2015 + +--------------- +Copyright (c) 2015 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +void fuse_unmount_compat22(const char *mountpoint) +{ + char dev[128]; + char *ssc, *umount_cmd; + FILE *sf; + int rv; + char seekscript[] = + /* error message is annoying in help output */ + "exec 2>/dev/null; " + "/usr/bin/fstat " FUSE_DEV_TRUNK "* | " + "/usr/bin/awk 'BEGIN{ getline; if (! ($3 == \"PID\" && $10 == \"NAME\")) exit 1; }; " + " { if ($3 == %d) print $10; }' | " + "/usr/bin/sort | " + "/usr/bin/uniq | " + "/usr/bin/awk '{ i += 1; if (i > 1){ exit 1; }; printf; }; END{ if (i == 0) exit 1; }'"; + + (void) mountpoint; + + /* + * If we don't know the fd, we have to resort to the scripted + * solution -- iterating over the fd-s is unpractical, as we + * don't know how many of open files we have. (This could be + * looked up in procfs -- however, that's optional on FBSD; or + * read out from the kmem -- however, that's bound to + * privileges (in fact, that's what happens when we call the + * setgid kmem fstat(1) utility). + */ + if (asprintf(&ssc, seekscript, getpid()) == -1) + return; + + errno = 0; + sf = popen(ssc, "r"); + free(ssc); + if (! sf) + return; + + fgets(dev, sizeof(dev), sf); + rv = pclose(sf); + if (rv) + return; + + if (asprintf(&umount_cmd, "/sbin/umount %s", dev) == -1) + return; + system(umount_cmd); + free(umount_cmd); +} +#endif +static void do_unmount(char *dev, int fd) +{ + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + return; + +} + +/* +Modified by T.MOMOZONO, 04/27/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +static int fuse_mount_core(const char *mountpoint, const char *opts, const struct fuse_operations *op) +{ + int fd = open("/dev/fuse", O_RDWR); + libfuse_print("open /dev/fuse fd = %d", fd); + if (fd == -1) + libfuse_print("fuse: failed to open /dev/fuse: %s", strerror(errno)); + + mount_fuse("/dev/fuse0", mountpoint); + + return fd; +} + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +int fuse_kern_mount(const char *mountpoint, struct fuse_args *args, const struct fuse_operations *op) +{ + struct mount_opts mo; + int res = -1; + + libfuse_print("fuse_kern_mount start"); + + memset(&mo, 0, sizeof(mo)); + /* mount util should not try to spawn the daemon */ + setenv("MOUNT_FUSEFS_SAFE", "1", 1); + /* to notify the mount util it's called from lib */ + setenv("MOUNT_FUSEFS_CALL_BY_LIB", "1", 1); + + if (args && + fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1){ + libfuse_print("fuse: failed to parse options"); + return -1; + } + + if (mo.allow_other && mo.allow_root) { + libfuse_print("fuse: 'allow_other' and 'allow_root' options are mutually exclusive"); + goto out; + } + if (mo.ishelp) + return 0; + + res = fuse_mount_core(mountpoint, mo.kernel_opts, op); + libfuse_print("fuse_mount_core res = %d", res); +out: + free(mo.kernel_opts); + return res; +} + +FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2"); diff --git a/external/libfuse/source/ulockmgr.c b/external/libfuse/source/ulockmgr.c new file mode 100644 index 0000000..158b8f9 --- /dev/null +++ b/external/libfuse/source/ulockmgr.c @@ -0,0 +1,444 @@ +/* + libulockmgr: Userspace Lock Manager Library + Copyright (C) 2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB +*/ + +/* #define DEBUG 1 */ + +#include "ulockmgr.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct message { + unsigned intr : 1; + unsigned nofd : 1; + pthread_t thr; + int cmd; + int fd; + struct flock lock; + int error; +}; + +struct fd_store { + struct fd_store *next; + int fd; + int inuse; +}; + +struct owner { + struct owner *next; + struct owner *prev; + struct fd_store *fds; + void *id; + size_t id_len; + int cfd; +}; + +static pthread_mutex_t ulockmgr_lock; +static int ulockmgr_cfd = -1; +static struct owner owner_list = { .next = &owner_list, .prev = &owner_list }; + +#define MAX_SEND_FDS 2 + +static void list_del_owner(struct owner *owner) +{ + struct owner *prev = owner->prev; + struct owner *next = owner->next; + prev->next = next; + next->prev = prev; +} + +static void list_add_owner(struct owner *owner, struct owner *next) +{ + struct owner *prev = next->prev; + owner->next = next; + owner->prev = prev; + prev->next = owner; + next->prev = owner; +} + +/* + * There's a bug in the linux kernel (< 2.6.22) recv() implementation + * on AF_UNIX, SOCK_STREAM sockets, that could cause it to return + * zero, even if data was available. Retrying the recv will return + * the data in this case. + */ +static int do_recv(int sock, void *buf, size_t len, int flags) +{ + int res = recv(sock, buf, len, flags); + if (res == 0) + res = recv(sock, buf, len, flags); + + return res; +} + +static int ulockmgr_send_message(int sock, void *buf, size_t buflen, + int *fdp, int numfds) +{ + struct msghdr msg; + struct cmsghdr *p_cmsg; + struct iovec vec; + size_t cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)]; + int res; + + assert(numfds <= MAX_SEND_FDS); + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + p_cmsg = CMSG_FIRSTHDR(&msg); + p_cmsg->cmsg_level = SOL_SOCKET; + p_cmsg->cmsg_type = SCM_RIGHTS; + p_cmsg->cmsg_len = CMSG_LEN(sizeof(int) * numfds); + memcpy(CMSG_DATA(p_cmsg), fdp, sizeof(int) * numfds); + msg.msg_controllen = p_cmsg->cmsg_len; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + vec.iov_base = buf; + vec.iov_len = buflen; + res = sendmsg(sock, &msg, MSG_NOSIGNAL); + if (res == -1) { + perror("libulockmgr: sendmsg"); + return -1; + } + if ((size_t) res != buflen) { + libfuse_print("libulockmgr: sendmsg short"); + return -1; + } + return 0; +} + +static int ulockmgr_start_daemon(void) +{ + int sv[2]; + int res; + char tmp[64]; + + res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); + if (res == -1) { + perror("libulockmgr: socketpair"); + return -1; + } + snprintf(tmp, sizeof(tmp), "exec ulockmgr_server %i", sv[0]); + res = system(tmp); + close(sv[0]); + if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) { + close(sv[1]); + return -1; + } + ulockmgr_cfd = sv[1]; + return 0; +} + +static struct owner *ulockmgr_new_owner(const void *id, size_t id_len) +{ + int sv[2]; + int res; + char c = 'm'; + struct owner *o; + + if (ulockmgr_cfd == -1 && ulockmgr_start_daemon() == -1) + return NULL; + + o = calloc(1, sizeof(struct owner) + id_len); + if (!o) { + libfuse_print("libulockmgr: failed to allocate memory"); + return NULL; + } + o->id = o + 1; + o->id_len = id_len; + res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); + if (res == -1) { + perror("libulockmgr: socketpair"); + goto out_free; + } + res = ulockmgr_send_message(ulockmgr_cfd, &c, sizeof(c), &sv[0], 1); + close(sv[0]); + if (res == -1) { + close(ulockmgr_cfd); + ulockmgr_cfd = -1; + goto out_close; + } + + o->cfd = sv[1]; + memcpy(o->id, id, id_len); + list_add_owner(o, &owner_list); + + return o; + +out_close: + close(sv[1]); +out_free: + free(o); + return NULL; +} + +static int ulockmgr_send_request(struct message *msg, const void *id, + size_t id_len) +{ + int sv[2]; + int cfd; + struct owner *o; + struct fd_store *f = NULL; + struct fd_store *newf = NULL; + struct fd_store **fp; + int fd = msg->fd; + int cmd = msg->cmd; + int res; + int unlockall = (cmd == F_SETLK && msg->lock.l_type == F_UNLCK && + msg->lock.l_start == 0 && msg->lock.l_len == 0); + + for (o = owner_list.next; o != &owner_list; o = o->next) + if (o->id_len == id_len && memcmp(o->id, id, id_len) == 0) + break; + + if (o == &owner_list) + o = NULL; + + if (!o && cmd != F_GETLK && msg->lock.l_type != F_UNLCK) + o = ulockmgr_new_owner(id, id_len); + + if (!o) { + if (cmd == F_GETLK) { + res = fcntl(msg->fd, F_GETLK, &msg->lock); + return (res == -1) ? -errno : 0; + } else if (msg->lock.l_type == F_UNLCK) + return 0; + else + return -ENOLCK; + } + + if (unlockall) + msg->nofd = 1; + else { + for (fp = &o->fds; *fp; fp = &(*fp)->next) { + f = *fp; + if (f->fd == fd) { + msg->nofd = 1; + break; + } + } + } + + if (!msg->nofd) { + newf = f = calloc(1, sizeof(struct fd_store)); + if (!f) { + libfuse_print("libulockmgr: failed to allocate memory"); + return -ENOLCK; + } + } + + res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); + if (res == -1) { + perror("libulockmgr: socketpair"); + free(newf); + return -ENOLCK; + } + + cfd = sv[1]; + sv[1] = msg->fd; + res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv, + msg->nofd ? 1 : 2); + close(sv[0]); + if (res == -1) { + free(newf); + close(cfd); + return -EIO; + } + + if (newf) { + newf->fd = msg->fd; + newf->next = o->fds; + o->fds = newf; + } + if (f) + f->inuse++; + + res = do_recv(cfd, msg, sizeof(struct message), MSG_WAITALL); + if (res == -1) { + perror("libulockmgr: recv"); + msg->error = EIO; + } else if (res != sizeof(struct message)) { + libfuse_print("libulockmgr: recv short"); + msg->error = EIO; + } else if (cmd == F_SETLKW && msg->error == EAGAIN) { + pthread_mutex_unlock(&ulockmgr_lock); + while (1) { + sigset_t old; + sigset_t unblock; + int errno_save; + + sigemptyset(&unblock); + sigaddset(&unblock, SIGUSR1); + pthread_sigmask(SIG_UNBLOCK, &unblock, &old); + res = do_recv(cfd, msg, sizeof(struct message), + MSG_WAITALL); + errno_save = errno; + pthread_sigmask(SIG_SETMASK, &old, NULL); + if (res == sizeof(struct message)) + break; + else if (res >= 0) { + libfuse_print("libulockmgr: recv short"); + msg->error = EIO; + break; + } else if (errno_save != EINTR) { + errno = errno_save; + perror("libulockmgr: recv"); + msg->error = EIO; + break; + } + msg->intr = 1; + res = send(o->cfd, msg, sizeof(struct message), + MSG_NOSIGNAL); + if (res == -1) { + perror("libulockmgr: send"); + msg->error = EIO; + break; + } + if (res != sizeof(struct message)) { + libfuse_print("libulockmgr: send short"); + msg->error = EIO; + break; + } + } + pthread_mutex_lock(&ulockmgr_lock); + + } + if (f) + f->inuse--; + close(cfd); + if (unlockall) { + for (fp = &o->fds; *fp;) { + f = *fp; + if (f->fd == fd && !f->inuse) { + *fp = f->next; + free(f); + } else + fp = &f->next; + } + if (!o->fds) { + list_del_owner(o); + close(o->cfd); + free(o); + } + /* Force OK on unlock-all, since it _will_ succeed once the + owner is deleted */ + msg->error = 0; + } + + return -msg->error; +} + +#ifdef DEBUG +static uint32_t owner_hash(const unsigned char *id, size_t id_len) +{ + uint32_t h = 0; + size_t i; + for (i = 0; i < id_len; i++) + h = ((h << 8) | (h >> 24)) ^ id[i]; + + return h; +} +#endif + +static int ulockmgr_canonicalize(int fd, struct flock *lock) +{ + off_t offset; + if (lock->l_whence == SEEK_CUR) { + offset = lseek(fd, 0, SEEK_CUR); + if (offset == (off_t) -1) + return -errno; + } else if (lock->l_whence == SEEK_END) { + struct stat stbuf; + int res = fstat(fd, &stbuf); + if (res == -1) + return -errno; + + offset = stbuf.st_size; + } else + offset = 0; + + lock->l_whence = SEEK_SET; + lock->l_start += offset; + + if (lock->l_start < 0) + return -EINVAL; + + if (lock->l_len < 0) { + lock->l_start += lock->l_len; + if (lock->l_start < 0) + return -EINVAL; + lock->l_len = -lock->l_len; + } + if (lock->l_len && lock->l_start + lock->l_len - 1 < 0) + return -EINVAL; + + return 0; +} + +int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner, + size_t owner_len) +{ + int err; + struct message msg; + sigset_t old; + sigset_t block; + + if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW) + return -EINVAL; + + if (lock->l_type != F_RDLCK && lock->l_type != F_WRLCK && + lock->l_type != F_UNLCK) + return -EINVAL; + + if (lock->l_whence != SEEK_SET && lock->l_whence != SEEK_CUR && + lock->l_whence != SEEK_END) + return -EINVAL; + +#ifdef DEBUG + libfuse_print("libulockmgr: %i %i %i %lli %lli own: 0x%08x", + cmd, lock->l_type, lock->l_whence, lock->l_start, lock->l_len, + owner_hash(owner, owner_len)); +#endif + + /* Unlock should never block anyway */ + if (cmd == F_SETLKW && lock->l_type == F_UNLCK) + cmd = F_SETLK; + + memset(&msg, 0, sizeof(struct message)); + msg.cmd = cmd; + msg.fd = fd; + msg.lock = *lock; + err = ulockmgr_canonicalize(fd, &msg.lock); + if (err) + return err; + + sigemptyset(&block); + sigaddset(&block, SIGUSR1); + pthread_sigmask(SIG_BLOCK, &block, &old); + pthread_mutex_lock(&ulockmgr_lock); + err = ulockmgr_send_request(&msg, owner, owner_len); + pthread_mutex_unlock(&ulockmgr_lock); + pthread_sigmask(SIG_SETMASK, &old, NULL); + if (!err && cmd == F_GETLK) { + if (msg.lock.l_type == F_UNLCK) + lock->l_type = F_UNLCK; + else + *lock = msg.lock; + } + + return err; +} diff --git a/external/taglib/Makefile b/external/taglib/Makefile new file mode 100644 index 0000000..02cd71d --- /dev/null +++ b/external/taglib/Makefile @@ -0,0 +1,24 @@ +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target := ps4_lib +OutPath := lib +TargetFile := libtag +AllTarget = $(OutPath)/$(TargetFile).a + +include $(ORBISDEV)/make/ps4sdklib.mk +CompilerFlagsCpp += -std=c++17 -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -D__ORBIS__=1 -D_ORBIS_ -DNDEBUG -D_BSD_SOURCE -fexceptions -frtti +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -Iinclude + + +$(OutPath)/$(TargetFile).a: $(ObjectFiles) + $(dirp) + $(archive) + +install: + @cp $(OutPath)/$(TargetFile).a $(DESTDIR)$(ORBISDEV)/usr/lib + @mkdir $(DESTDIR)$(ORBISDEV)/usr/include/libtag + @cp -r include/* $(DESTDIR)$(ORBISDEV)/usr/include/libtag + @echo "$(TargetFile) Installed!" + diff --git a/external/taglib/include/aifffile.h b/external/taglib/include/aifffile.h new file mode 100644 index 0000000..ceac576 --- /dev/null +++ b/external/taglib/include/aifffile.h @@ -0,0 +1,157 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFFILE_H +#define TAGLIB_AIFFFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "aiffproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of AIFF metadata + + /*! + * This is implementation of AIFF metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace AIFF { + + //! An implementation of TagLib::File with AIFF specific methods + + /*! + * This implements and provides an interface for AIFF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to AIFF files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + /*! + * Constructs an AIFF file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an AIFF file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ + virtual ID3v2::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the AIFF::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Save using a specific ID3v2 version (e.g. v3) + */ + bool save(ID3v2::Version version); + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Check if the given \a stream can be opened as an AIFF file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + friend class Properties; + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/aiffproperties.h b/external/taglib/include/aiffproperties.h new file mode 100644 index 0000000..dbb4c21 --- /dev/null +++ b/external/taglib/include/aiffproperties.h @@ -0,0 +1,166 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFPROPERTIES_H +#define TAGLIB_AIFFPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace RIFF { + + namespace AIFF { + + class File; + + //! An implementation of audio property reading for AIFF + + /*! + * This reads the data from an AIFF stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of AIFF::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); + + /*! + * Create an instance of AIFF::Properties with the data read from the + * AIFF::File \a file. + */ + Properties(File *file, ReadStyle style); + + /*! + * Destroys this AIFF::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the number of bits per audio sample. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Returns the number of sample frames + */ + unsigned int sampleFrames() const; + + /*! + * Returns true if the file is in AIFF-C format, false if AIFF format. + */ + bool isAiffC() const; + + /*! + * Returns the compression type of the AIFF-C file. For example, "NONE" for + * not compressed, "ACE2" for ACE 2-to-1. + * + * If the file is in AIFF format, always returns an empty vector. + * + * \see isAiffC() + */ + ByteVector compressionType() const; + + /*! + * Returns the concrete compression name of the AIFF-C file. + * + * If the file is in AIFF format, always returns an empty string. + * + * \see isAiffC() + */ + String compressionName() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/apefile.h b/external/taglib/include/apefile.h new file mode 100644 index 0000000..267778b --- /dev/null +++ b/external/taglib/include/apefile.h @@ -0,0 +1,235 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFILE_H +#define TAGLIB_APEFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "apeproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of APE metadata + + /*! + * This is implementation of APE metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace APE { + + //! An implementation of TagLib::File with APE specific methods + + /*! + * This implements and provides an interface for APE files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to APE files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an APE file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an APE file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only APE + * will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Creates an APEv2 tag if necessary. A potentially existing ID3v1 + * tag will be updated as well. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the APE::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * \note According to the official Monkey's Audio SDK, an APE file + * can only have either ID3V1 or APE tags, so a parameter is used here. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an APE + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/apefooter.h b/external/taglib/include/apefooter.h new file mode 100644 index 0000000..47741d0 --- /dev/null +++ b/external/taglib/include/apefooter.h @@ -0,0 +1,173 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFOOTER_H +#define TAGLIB_APEFOOTER_H + +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE footers + + /*! + * This class implements APE footers (and headers). It attempts to follow, both + * semantically and programmatically, the structure specified in + * the APE v2.0 standard. The API is based on the properties of APE footer and + * headers specified there. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty APE footer. + */ + Footer(); + + /*! + * Constructs an APE footer based on \a data. parse() is called + * immediately. + */ + Footer(const ByteVector &data); + + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the version number. (Note: This is the 1000 or 2000.) + */ + unsigned int version() const; + + /*! + * Returns true if a header is present in the tag. + */ + bool headerPresent() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + + /*! + * Returns true this is actually the header. + */ + bool isHeader() const; + + /*! + * Sets whether the header should be rendered or not + */ + void setHeaderPresent(bool b) const; + + /*! + * Returns the number of items in the tag. + */ + unsigned int itemCount() const; + + /*! + * Set the item count to \a s. + * \see itemCount() + */ + void setItemCount(unsigned int s); + + /*! + * Returns the tag size in bytes. This is the size of the frame content and footer. + * The size of the \e entire tag will be this plus the header size, if present. + * + * \see completeTagSize() + */ + unsigned int tagSize() const; + + /*! + * Returns the tag size, including if present, the header + * size. + * + * \see tagSize() + */ + unsigned int completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(unsigned int s); + + /*! + * Returns the size of the footer. Presently this is always 32 bytes. + */ + static unsigned int size(); + + /*! + * Returns the string used to identify an APE tag inside of a file. + * Presently this is always "APETAGEX". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the footer. 32 bytes, + * starting from \a data will be used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the footer back to binary format. + */ + ByteVector renderFooter() const; + + /*! + * Renders the header corresponding to the footer. If headerPresent is + * set to false, it returns an empty ByteVector. + */ + ByteVector renderHeader() const; + + protected: + /*! + * Called by setData() to parse the footer data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by renderFooter and renderHeader + */ + ByteVector render(bool isHeader) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/apeitem.h b/external/taglib/include/apeitem.h new file mode 100644 index 0000000..cfd157c --- /dev/null +++ b/external/taglib/include/apeitem.h @@ -0,0 +1,224 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEITEM_H +#define TAGLIB_APEITEM_H + +#include "tbytevector.h" +#include "tstring.h" +#include "tstringlist.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE-items + + /*! + * This class provides the features of items in the APEv2 standard. + */ + class TAGLIB_EXPORT Item + { + public: + /*! + * Enum of types an Item can have. The value of 3 is reserved. + */ + enum ItemTypes { + //! Item contains text information coded in UTF-8 + Text = 0, + //! Item contains binary information + Binary = 1, + //! Item is a locator of external stored information + Locator = 2 + }; + /*! + * Constructs an empty item. + */ + Item(); + + /*! + * Constructs a text item with \a key and \a value. + */ + // BIC: Remove this, StringList has a constructor from a single string + Item(const String &key, const String &value); + + /*! + * Constructs a text item with \a key and \a values. + */ + Item(const String &key, const StringList &values); + + /*! + * Constructs an item with \a key and \a value. + * If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text + */ + Item(const String &key, const ByteVector &value, bool binary); + + /*! + * Construct an item as a copy of \a item. + */ + Item(const Item &item); + + /*! + * Destroys the item. + */ + virtual ~Item(); + + /*! + * Copies the contents of \a item into this item. + */ + Item &operator=(const Item &item); + + /*! + * Exchanges the content of this item by the content of \a item. + */ + void swap(Item &item); + + /*! + * Returns the key. + */ + String key() const; + + /*! + * Returns the binary value. + * If the item type is not \a Binary, always returns an empty ByteVector. + */ + ByteVector binaryData() const; + + /*! + * Set the binary value to \a value + * The item's type will also be set to \a Binary + */ + void setBinaryData(const ByteVector &value); + +#ifndef DO_NOT_DOCUMENT + /* Remove in next binary incompatible release */ + ByteVector value() const; +#endif + + /*! + * Sets the key for the item to \a key. + */ + void setKey(const String &key); + + /*! + * Sets the text value of the item to \a value and clears any previous contents. + * + * \see toString() + */ + void setValue(const String &value); + + /*! + * Sets the text value of the item to the list of values in \a value and clears + * any previous contents. + * + * \see toStringList() + */ + void setValues(const StringList &values); + + /*! + * Appends \a value to create (or extend) the current list of text values. + * + * \see toString() + */ + void appendValue(const String &value); + + /*! + * Appends \a values to extend the current list of text values. + * + * \see toStringList() + */ + void appendValues(const StringList &values); + + /*! + * Returns the size of the full item. + */ + int size() const; + + /*! + * Returns the value as a single string. In case of multiple strings, + * the first is returned. If the data type is not \a Text, always returns + * an empty String. + */ + String toString() const; + +#ifndef DO_NOT_DOCUMENT + /* Remove in next binary incompatible release */ + StringList toStringList() const; +#endif + + /*! + * Returns the list of text values. If the data type is not \a Text, always + * returns an empty StringList. + */ + StringList values() const; + + /*! + * Render the item to a ByteVector. + */ + ByteVector render() const; + + /*! + * Parse the item from the ByteVector \a data. + */ + void parse(const ByteVector& data); + + /*! + * Set the item to read-only. + */ + void setReadOnly(bool readOnly); + + /*! + * Return true if the item is read-only. + */ + bool isReadOnly() const; + + /*! + * Sets the type of the item to \a type. + * + * \see ItemTypes + */ + void setType(ItemTypes type); + + /*! + * Returns the type of the item. + */ + ItemTypes type() const; + + /*! + * Returns if the item has any real content. + */ + bool isEmpty() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + } + +} + +#endif + + diff --git a/external/taglib/include/apeproperties.h b/external/taglib/include/apeproperties.h new file mode 100644 index 0000000..ebbf949 --- /dev/null +++ b/external/taglib/include/apeproperties.h @@ -0,0 +1,143 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEPROPERTIES_H +#define TAGLIB_APEPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace APE { + + class File; + + //! An implementation of audio property reading for APE + + /*! + * This reads the data from an APE stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of APE::Properties with the data read from the + * APE::File \a file. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average); + + /*! + * Create an instance of APE::Properties with the data read from the + * APE::File \a file. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this APE::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the total number of audio samples in file. + */ + unsigned int sampleFrames() const; + + /*! + * Returns APE version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file, long streamLength); + + void analyzeCurrent(File *file); + void analyzeOld(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/apetag.h b/external/taglib/include/apetag.h new file mode 100644 index 0000000..f4d4fba --- /dev/null +++ b/external/taglib/include/apetag.h @@ -0,0 +1,208 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APETAG_H +#define TAGLIB_APETAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tmap.h" +#include "tstring.h" +#include "taglib_export.h" + +#include "apeitem.h" + +namespace TagLib { + + class File; + + //! An implementation of the APE tagging format + + namespace APE { + + class Footer; + + /*! + * A mapping between a list of item names, or keys, and the associated item. + * + * \see APE::Tag::itemListMap() + */ + typedef Map ItemListMap; + + + //! An APE tag implementation + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an APE tag with default values. + */ + Tag(); + + /*! + * Create an APE tag and parse the data in \a file with APE footer at + * \a tagOffset. + */ + Tag(TagLib::File *file, long footerLocation); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "APETAGEX" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + /*! + * Implements the unified tag dictionary interface -- export function. + * APE tags are perfectly compatible with the dictionary interface because they + * support both arbitrary tag names and multiple values. Currently only + * APE items of type *Text* are handled by the dictionary interface; all *Binary* + * and *Locator* items will be put into the unsupportedData list and can be + * deleted on request using removeUnsupportedProperties(). The same happens + * to Text items if their key is invalid for PropertyMap (which should actually + * never happen). + * + * The only conversion done by this export function is to rename the APE tags + * TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively, + * in order to be compliant with the names used in other formats. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified tag dictionary interface -- import function. The same + * comments as for the export function apply; additionally note that the APE tag + * specification requires keys to have between 2 and 16 printable ASCII characters + * with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+". + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Check if the given String is a valid APE tag key. + */ + static bool checkKey(const String&); + + /*! + * Returns a pointer to the tag's footer. + */ + Footer *footer() const; + + /*! + * Returns a reference to the item list map. This is an ItemListMap of + * all of the items in the tag. + * + * This is the most powerful structure for accessing the items of the tag. + * + * APE tags are case-insensitive, all keys in this map have been converted + * to upper case. + * + * \warning You should not modify this data structure directly, instead + * use setItem() and removeItem(). + */ + const ItemListMap &itemListMap() const; + + /*! + * Removes the \a key item from the tag + */ + void removeItem(const String &key); + + /*! + * Adds to the text item specified by \a key the data \a value. If \a replace + * is true, then all of the other values on the same key will be removed + * first. If a binary item exists for \a key it will be removed first. + */ + void addValue(const String &key, const String &value, bool replace = true); + + /*! + * Set the binary data for the key specified by \a item to \a value + * This will convert the item to type \a Binary if it isn't already and + * all of the other values on the same key will be removed. + */ + void setData(const String &key, const ByteVector &value); + + /*! + * Sets the \a key item to the value of \a item. If an item with the \a key is already + * present, it will be replaced. + */ + void setItem(const String &key, const Item &item); + + /*! + * Returns true if the tag does not contain any data. + */ + bool isEmpty() const; + + protected: + + /*! + * Reads from the file specified in the constructor. + */ + void read(); + + /*! + * Parses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/asfattribute.h b/external/taglib/include/asfattribute.h new file mode 100644 index 0000000..1738eb4 --- /dev/null +++ b/external/taglib/include/asfattribute.h @@ -0,0 +1,208 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFATTRIBUTE_H +#define TAGLIB_ASFATTRIBUTE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "asfpicture.h" + +namespace TagLib +{ + + namespace ASF + { + + class File; + class Picture; + + class TAGLIB_EXPORT Attribute + { + public: + + /*! + * Enum of types an Attribute can have. + */ + enum AttributeTypes { + UnicodeType = 0, + BytesType = 1, + BoolType = 2, + DWordType = 3, + QWordType = 4, + WordType = 5, + GuidType = 6 + }; + + /*! + * Constructs an empty attribute. + */ + Attribute(); + + /*! + * Constructs an attribute with \a key and a UnicodeType \a value. + */ + Attribute(const String &value); + + /*! + * Constructs an attribute with \a key and a BytesType \a value. + */ + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ + Attribute(const Picture &value); + + /*! + * Constructs an attribute with \a key and a DWordType \a value. + */ + Attribute(unsigned int value); + + /*! + * Constructs an attribute with \a key and a QWordType \a value. + */ + Attribute(unsigned long long value); + + /*! + * Constructs an attribute with \a key and a WordType \a value. + */ + Attribute(unsigned short value); + + /*! + * Constructs an attribute with \a key and a BoolType \a value. + */ + Attribute(bool value); + + /*! + * Construct an attribute as a copy of \a other. + */ + Attribute(const Attribute &item); + + /*! + * Copies the contents of \a other into this item. + */ + Attribute &operator=(const Attribute &other); + + /*! + * Exchanges the content of the Attribute by the content of \a other. + */ + void swap(Attribute &other); + + /*! + * Destroys the attribute. + */ + virtual ~Attribute(); + + /*! + * Returns type of the value. + */ + AttributeTypes type() const; + + /*! + * Returns the BoolType \a value. + */ + unsigned short toBool() const; + + /*! + * Returns the WordType \a value. + */ + unsigned short toUShort() const; + + /*! + * Returns the DWordType \a value. + */ + unsigned int toUInt() const; + + /*! + * Returns the QWordType \a value. + */ + unsigned long long toULongLong() const; + + /*! + * Returns the UnicodeType \a value. + */ + String toString() const; + + /*! + * Returns the BytesType \a value. + */ + ByteVector toByteVector() const; + + /*! + * Returns the Picture \a value. + */ + Picture toPicture() const; + + /*! + * Returns the language number, or 0 is no stream number was set. + */ + int language() const; + + /*! + * Sets the language number. + */ + void setLanguage(int value); + + /*! + * Returns the stream number, or 0 is no stream number was set. + */ + int stream() const; + + /*! + * Sets the stream number. + */ + void setStream(int value); + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + String parse(ASF::File &file, int kind = 0); +#endif + + //! Returns the size of the stored data + int dataSize() const; + + private: + friend class File; + + ByteVector render(const String &name, int kind = 0) const; + + class AttributePrivate; + AttributePrivate *d; + }; + } + +} + +#endif diff --git a/external/taglib/include/asffile.h b/external/taglib/include/asffile.h new file mode 100644 index 0000000..05cf4ee --- /dev/null +++ b/external/taglib/include/asffile.h @@ -0,0 +1,138 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFFILE_H +#define TAGLIB_ASFFILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "asfproperties.h" +#include "asftag.h" + +namespace TagLib { + + //! An implementation of ASF (WMA) metadata + namespace ASF { + + /*! + * This implements and provides an interface for ASF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to ASF files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + + /*! + * Constructs an ASF file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an ASF file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + virtual Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the ASF audio properties for this file. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as an ASF + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + void read(); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/asfpicture.h b/external/taglib/include/asfpicture.h new file mode 100644 index 0000000..17233ba --- /dev/null +++ b/external/taglib/include/asfpicture.h @@ -0,0 +1,222 @@ +/************************************************************************** + copyright : (C) 2010 by Anton Sergunov + email : setosha@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef ASFPICTURE_H +#define ASFPICTURE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "attachedpictureframe.h" + +namespace TagLib +{ + namespace ASF + { + + //! An ASF attached picture interface implementation + + /*! + * This is an implementation of ASF attached pictures interface. Pictures may be + * included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture + * attribute in a single tag). These pictures are usually in either JPEG or + * PNG format. + * \see Attribute::toPicture() + * \see Attribute::Attribute(const Picture& picture) + */ + class TAGLIB_EXPORT Picture { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture. + */ + Picture(); + + /*! + * Construct an picture as a copy of \a other. + */ + Picture(const Picture& other); + + /*! + * Destroys the picture. + */ + virtual ~Picture(); + + /*! + * Copies the contents of \a other into this picture. + */ + Picture& operator=(const Picture& other); + + /*! + * Exchanges the content of the Picture by the content of \a other. + */ + void swap(Picture &other); + + /*! + * Returns true if Picture stores valid picture + */ + bool isValid() const; + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + void setMimeType(const String &value); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(const ASF::Picture::Type& t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + */ + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + */ + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + /*! + * Returns picture as binary raw data \a value + */ + ByteVector render() const; + + /*! + * Returns picture as binary raw data \a value + */ + int dataSize() const; + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + void parse(const ByteVector& ); + static Picture fromInvalid(); +#endif + + private: + class PicturePrivate; + PicturePrivate *d; + }; + } +} + +#endif // ASFPICTURE_H diff --git a/external/taglib/include/asfproperties.h b/external/taglib/include/asfproperties.h new file mode 100644 index 0000000..317bf10 --- /dev/null +++ b/external/taglib/include/asfproperties.h @@ -0,0 +1,186 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFPROPERTIES_H +#define TAGLIB_ASFPROPERTIES_H + +#include "audioproperties.h" +#include "tstring.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ASF { + + //! An implementation of ASF audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + + /*! + * Audio codec types can be used in ASF file. + */ + enum Codec + { + /*! + * Couldn't detect the codec. + */ + Unknown = 0, + + /*! + * Windows Media Audio 1 + */ + WMA1, + + /*! + * Windows Media Audio 2 or above + */ + WMA2, + + /*! + * Windows Media Audio 9 Professional + */ + WMA9Pro, + + /*! + * Windows Media Audio 9 Lossless + */ + WMA9Lossless, + }; + + /*! + * Creates an instance of ASF::Properties. + */ + Properties(); + + /*! + * Destroys this ASF::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the codec used in the file. + * + * \see codecName() + * \see codecDescription() + */ + Codec codec() const; + + /*! + * Returns the concrete codec name, for example "Windows Media Audio 9.1" + * used in the file if available, otherwise an empty string. + * + * \see codec() + * \see codecDescription() + */ + String codecName() const; + + /*! + * Returns the codec description, typically contains the encoder settings, + * for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available, + * otherwise an empty string. + * + * \see codec() + * \see codecName() + */ + String codecDescription() const; + + /*! + * Returns whether or not the file is encrypted. + */ + bool isEncrypted() const; + +#ifndef DO_NOT_DOCUMENT + // deprecated + void setLength(int value); + + void setLengthInMilliseconds(int value); + void setBitrate(int value); + void setSampleRate(int value); + void setChannels(int value); + void setBitsPerSample(int value); + void setCodec(int value); + void setCodecName(const String &value); + void setCodecDescription(const String &value); + void setEncrypted(bool value); +#endif + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/asftag.h b/external/taglib/include/asftag.h new file mode 100644 index 0000000..bbd9821 --- /dev/null +++ b/external/taglib/include/asftag.h @@ -0,0 +1,210 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFTAG_H +#define TAGLIB_ASFTAG_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" +#include "asfattribute.h" + +namespace TagLib { + + namespace ASF { + + typedef List AttributeList; + typedef Map AttributeListMap; + + class TAGLIB_EXPORT Tag : public TagLib::Tag { + + friend class File; + + public: + + Tag(); + + virtual ~Tag(); + + /*! + * Returns the track name. + */ + virtual String title() const; + + /*! + * Returns the artist name. + */ + virtual String artist() const; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const; + + /*! + * Returns the track comment. + */ + virtual String comment() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const; + + /*! + * Returns the rating. + */ + virtual String rating() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String copyright() const; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual unsigned int year() const; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual unsigned int track() const; + + /*! + * Sets the title to \a s. + */ + virtual void setTitle(const String &s); + + /*! + * Sets the artist to \a s. + */ + virtual void setArtist(const String &s); + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s); + + /*! + * Sets the comment to \a s. + */ + virtual void setComment(const String &s); + + /*! + * Sets the rating to \a s. + */ + virtual void setRating(const String &s); + + /*! + * Sets the copyright to \a s. + */ + virtual void setCopyright(const String &s); + + /*! + * Sets the genre to \a s. + */ + virtual void setGenre(const String &s); + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(unsigned int i); + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(unsigned int i); + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * \deprecated + */ + AttributeListMap &attributeListMap(); + + /*! + * Returns a reference to the item list map. This is an AttributeListMap of + * all of the items in the tag. + */ + // BIC: return by value + const AttributeListMap &attributeListMap() const; + + /*! + * \return True if a value for \a attribute is currently set. + */ + bool contains(const String &name) const; + + /*! + * Removes the \a key attribute from the tag + */ + void removeItem(const String &name); + + /*! + * \return The list of values for the key \a name, or an empty list if no + * values have been set. + */ + AttributeList attribute(const String &name) const; + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be replaced. + */ + void setAttribute(const String &name, const Attribute &attribute); + + /*! + * Sets multiple \a values to the key \a name. + */ + void setAttribute(const String &name, const AttributeList &values); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ + void addAttribute(const String &name, const Attribute &attribute); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList& properties); + PropertyMap setProperties(const PropertyMap &properties); + + private: + + class TagPrivate; + TagPrivate *d; + }; + } +} +#endif diff --git a/external/taglib/include/asfutils.h b/external/taglib/include/asfutils.h new file mode 100644 index 0000000..a8ecd70 --- /dev/null +++ b/external/taglib/include/asfutils.h @@ -0,0 +1,104 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFUTILS_H +#define TAGLIB_ASFUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace ASF + { + namespace + { + + inline unsigned short readWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(2); + if(v.size() != 2) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toUShort(false); + } + + inline unsigned int readDWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(4); + if(v.size() != 4) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toUInt(false); + } + + inline long long readQWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(8); + if(v.size() != 8) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toLongLong(false); + } + + inline String readString(File *file, int length) + { + ByteVector data = file->readBlock(length); + unsigned int size = data.size(); + while (size >= 2) { + if(data[size - 1] != '\0' || data[size - 2] != '\0') { + break; + } + size -= 2; + } + if(size != data.size()) { + data.resize(size); + } + return String(data, String::UTF16LE); + } + + inline ByteVector renderString(const String &str, bool includeLength = false) + { + ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false); + if(includeLength) { + data = ByteVector::fromShort(data.size(), false) + data; + } + return data; + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/include/attachedpictureframe.h b/external/taglib/include/attachedpictureframe.h new file mode 100644 index 0000000..55067bd --- /dev/null +++ b/external/taglib/include/attachedpictureframe.h @@ -0,0 +1,230 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ATTACHEDPICTUREFRAME_H +#define TAGLIB_ATTACHEDPICTUREFRAME_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 attached picture frame implementation + + /*! + * This is an implementation of ID3v2 attached pictures. Pictures may be + * included in tags, one per APIC frame (but there may be multiple APIC + * frames in a single tag). These pictures are usually in either JPEG or + * PNG format. + */ + + class TAGLIB_EXPORT AttachedPictureFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture frame. The description, content and text + * encoding should be set manually. + */ + AttachedPictureFrame(); + + /*! + * Constructs an AttachedPicture frame based on \a data. + */ + explicit AttachedPictureFrame(const ByteVector &data); + + /*! + * Destroys the AttahcedPictureFrame instance. + */ + virtual ~AttachedPictureFrame(); + + /*! + * Returns a string containing the description and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description. + * + * \see setTextEncoding() + * \see description() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description. + * + * \see description() + */ + void setTextEncoding(String::Type t); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(Type t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + class AttachedPictureFramePrivate; + AttachedPictureFramePrivate *d; + + private: + AttachedPictureFrame(const AttachedPictureFrame &); + AttachedPictureFrame &operator=(const AttachedPictureFrame &); + AttachedPictureFrame(const ByteVector &data, Header *h); + + }; + + //! support for ID3v2.2 PIC frames + class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame + { + protected: + virtual void parseFields(const ByteVector &data); + private: + AttachedPictureFrameV22(const ByteVector &data, Header *h); + friend class FrameFactory; + }; + } +} + +#endif diff --git a/external/taglib/include/audioproperties.h b/external/taglib/include/audioproperties.h new file mode 100644 index 0000000..f27aefc --- /dev/null +++ b/external/taglib/include/audioproperties.h @@ -0,0 +1,127 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIOPROPERTIES_H +#define TAGLIB_AUDIOPROPERTIES_H + +#include "taglib_export.h" + +namespace TagLib { + + //! A simple, abstract interface to common audio properties + + /*! + * The values here are common to most audio formats. For more specific, codec + * dependent values, please see see the subclasses APIs. This is meant to + * compliment the TagLib::File and TagLib::Tag APIs in providing a simple + * interface that is sufficient for most applications. + */ + + class TAGLIB_EXPORT AudioProperties + { + public: + + /*! + * Reading audio properties from a file can sometimes be very time consuming + * and for the most accurate results can often involve reading the entire + * file. Because in many situations speed is critical or the accuracy of the + * values is not particularly important this allows the level of desired + * accuracy to be set. + */ + enum ReadStyle { + //! Read as little of the file as possible + Fast, + //! Read more of the file and make better values guesses + Average, + //! Read as much of the file as needed to report accurate values + Accurate + }; + + /*! + * Destroys this AudioProperties instance. + */ + virtual ~AudioProperties(); + + /*! + * Returns the length of the file in seconds. + */ + virtual int length() const = 0; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the most appropriate bit rate for the file in kb/s. For constant + * bitrate formats this is simply the bitrate of the file. For variable + * bitrate formats this is either the average or nominal bitrate. + */ + virtual int bitrate() const = 0; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const = 0; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const = 0; + + protected: + + /*! + * Construct an audio properties instance. This is protected as this class + * should not be instantiated directly, but should be instantiated via its + * subclasses and can be fetched from the FileRef or File APIs. + * + * \see ReadStyle + */ + AudioProperties(ReadStyle style); + + private: + AudioProperties(const AudioProperties &); + AudioProperties &operator=(const AudioProperties &); + + class AudioPropertiesPrivate; + AudioPropertiesPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/include/chapterframe.h b/external/taglib/include/chapterframe.h new file mode 100644 index 0000000..0eaa140 --- /dev/null +++ b/external/taglib/include/chapterframe.h @@ -0,0 +1,249 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_CHAPTERFRAME +#define TAGLIB_CHAPTERFRAME + +#include "id3v2tag.h" +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 chapter frames. The purpose of this + * frame is to describe a single chapter within an audio file. + */ + + //! An implementation of ID3v2 chapter frames + + class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a chapter frame based on \a data. \a tagHeader is required as + * the internal frames are parsed based on the tag version. + */ + ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data); + + /*! + * Creates a chapter frame with the element ID \a elementID, start time + * \a startTime, end time \a endTime, start offset \a startOffset, + * end offset \a endOffset and optionally a list of embedded frames, + * whose ownership will then be taken over by this Frame, in + * \a embeddedFrames; + * + * All times are in milliseconds. + */ + ChapterFrame(const ByteVector &elementID, + unsigned int startTime, unsigned int endTime, + unsigned int startOffset, unsigned int endOffset, + const FrameList &embeddedFrames = FrameList()); + + /*! + * Destroys the frame. + */ + virtual ~ChapterFrame(); + + /*! + * Returns the element ID of the frame. Element ID + * is a null terminated string, however it's not human-readable. + * + * \see setElementID() + */ + ByteVector elementID() const; + + /*! + * Returns time of chapter's start (in milliseconds). + * + * \see setStartTime() + */ + unsigned int startTime() const; + + /*! + * Returns time of chapter's end (in milliseconds). + * + * \see setEndTime() + */ + unsigned int endTime() const; + + /*! + * Returns zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's start. + * + * \note If returned value is 0xFFFFFFFF, start time should be used instead. + * \see setStartOffset() + */ + unsigned int startOffset() const; + + /*! + * Returns zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's end. + * + * \note If returned value is 0xFFFFFFFF, end time should be used instead. + * \see setEndOffset() + */ + unsigned int endOffset() const; + + /*! + * Sets the element ID of the frame to \a eID. If \a eID isn't + * null terminated, a null char is appended automatically. + * + * \see elementID() + */ + void setElementID(const ByteVector &eID); + + /*! + * Sets time of chapter's start (in milliseconds) to \a sT. + * + * \see startTime() + */ + void setStartTime(const unsigned int &sT); + + /*! + * Sets time of chapter's end (in milliseconds) to \a eT. + * + * \see endTime() + */ + void setEndTime(const unsigned int &eT); + + /*! + * Sets zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's start to \a sO. + * + * \see startOffset() + */ + void setStartOffset(const unsigned int &sO); + + /*! + * Sets zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's end to \a eO. + * + * \see endOffset() + */ + void setEndOffset(const unsigned int &eO); + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames embedded in the CHAP frame. + * + * This is the most convenient structure for accessing the CHAP frame's + * embedded frames. Many frame types allow multiple instances of the same + * frame type so this is a map of lists. In most cases however there will + * only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ + const FrameListMap &embeddedFrameListMap() const; + + /*! + * Returns a reference to the embedded frame list. This is an FrameList + * of all of the frames embedded in the CHAP frame in the order that they + * were parsed. + * + * This can be useful if for example you want iterate over the CHAP frame's + * embedded frames in the order that they occur in the CHAP frame. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + */ + const FrameList &embeddedFrameList() const; + + /*! + * Returns the embedded frame list for frames with the id \a frameID + * or an empty list if there are no embedded frames of that type. This + * is just a convenience and is equivalent to: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ + const FrameList &embeddedFrameList(const ByteVector &frameID) const; + + /*! + * Add an embedded frame to the CHAP frame. At this point the CHAP frame + * takes ownership of the embedded frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void addEmbeddedFrame(Frame *frame); + + /*! + * Remove an embedded frame from the CHAP frame. If \a del is true the frame's + * memory will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrame(Frame *frame, bool del = true); + + /*! + * Remove all embedded frames of type \a id from the CHAP frame and free their + * memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrames(const ByteVector &id); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * CHAP frames each have a unique element ID. This searches for a CHAP + * frame with the element ID \a eID and returns a pointer to it. This + * can be used to link CTOC and CHAP frames together. + * + * \see elementID() + */ + static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h); + ChapterFrame(const ChapterFrame &); + ChapterFrame &operator=(const ChapterFrame &); + + class ChapterFramePrivate; + ChapterFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/commentsframe.h b/external/taglib/include/commentsframe.h new file mode 100644 index 0000000..4da9d53 --- /dev/null +++ b/external/taglib/include/commentsframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_COMMENTSFRAME_H +#define TAGLIB_COMMENTSFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 comments + + /*! + * This implements the ID3v2 comment format. An ID3v2 comment consists of + * a language encoding, a description and a single text field. + */ + + class TAGLIB_EXPORT CommentsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty comment frame that will use the text encoding + * \a encoding. + */ + explicit CommentsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a comment based on the data in \a data. + */ + explicit CommentsFrame(const ByteVector &data); + + /*! + * Destroys this CommentFrame instance. + */ + virtual ~CommentsFrame(); + + /*! + * Returns the text of this comment. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this comment. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this comment. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the comment to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the comment to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Parses this frame as PropertyMap with a single key. + * - if description() is empty or "COMMENT", the key will be "COMMENT" + * - if description() is not a valid PropertyMap key, the frame will be + * marked unsupported by an entry "COMM/" in the unsupportedData() + * attribute of the returned map. + * - otherwise, the key will be "COMMENT:" + * - The single value will be the frame's text(). + */ + PropertyMap asProperties() const; + + /*! + * Comments each have a unique description. This searches for a comment + * frame with the description \a d and returns a pointer to it. If no + * frame is found that matches the given description null is returned. + * + * \see description() + */ + static CommentsFrame *findByDescription(const Tag *tag, const String &d); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + CommentsFrame(const ByteVector &data, Header *h); + CommentsFrame(const CommentsFrame &); + CommentsFrame &operator=(const CommentsFrame &); + + class CommentsFramePrivate; + CommentsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/config.h b/external/taglib/include/config.h new file mode 100644 index 0000000..e69de29 diff --git a/external/taglib/include/eventtimingcodesframe.h b/external/taglib/include/eventtimingcodesframe.h new file mode 100644 index 0000000..3dcedb9 --- /dev/null +++ b/external/taglib/include/eventtimingcodesframe.h @@ -0,0 +1,185 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_EVENTTIMINGCODESFRAME_H +#define TAGLIB_EVENTTIMINGCODESFRAME_H + +#include "id3v2frame.h" +#include "tlist.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 event timing codes frame + /*! + * An implementation of ID3v2 event timing codes. + */ + class TAGLIB_EXPORT EventTimingCodesFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Specifies the timestamp format used. + */ + enum TimestampFormat { + //! The timestamp is of unknown format. + Unknown = 0x00, + //! The timestamp represents the number of MPEG frames since + //! the beginning of the audio stream. + AbsoluteMpegFrames = 0x01, + //! The timestamp represents the number of milliseconds since + //! the beginning of the audio stream. + AbsoluteMilliseconds = 0x02 + }; + + /*! + * Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes. + */ + enum EventType { + Padding = 0x00, + EndOfInitialSilence = 0x01, + IntroStart = 0x02, + MainPartStart = 0x03, + OutroStart = 0x04, + OutroEnd = 0x05, + VerseStart = 0x06, + RefrainStart = 0x07, + InterludeStart = 0x08, + ThemeStart = 0x09, + VariationStart = 0x0a, + KeyChange = 0x0b, + TimeChange = 0x0c, + MomentaryUnwantedNoise = 0x0d, + SustainedNoise = 0x0e, + SustainedNoiseEnd = 0x0f, + IntroEnd = 0x10, + MainPartEnd = 0x11, + VerseEnd = 0x12, + RefrainEnd = 0x13, + ThemeEnd = 0x14, + Profanity = 0x15, + ProfanityEnd = 0x16, + NotPredefinedSynch0 = 0xe0, + NotPredefinedSynch1 = 0xe1, + NotPredefinedSynch2 = 0xe2, + NotPredefinedSynch3 = 0xe3, + NotPredefinedSynch4 = 0xe4, + NotPredefinedSynch5 = 0xe5, + NotPredefinedSynch6 = 0xe6, + NotPredefinedSynch7 = 0xe7, + NotPredefinedSynch8 = 0xe8, + NotPredefinedSynch9 = 0xe9, + NotPredefinedSynchA = 0xea, + NotPredefinedSynchB = 0xeb, + NotPredefinedSynchC = 0xec, + NotPredefinedSynchD = 0xed, + NotPredefinedSynchE = 0xee, + NotPredefinedSynchF = 0xef, + AudioEnd = 0xfd, + AudioFileEnds = 0xfe + }; + + /*! + * Single entry of time stamp and event. + */ + struct SynchedEvent { + SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {} + unsigned int time; + EventType type; + }; + + /*! + * List of synchronized events. + */ + typedef TagLib::List SynchedEventList; + + /*! + * Construct an empty event timing codes frame. + */ + explicit EventTimingCodesFrame(); + + /*! + * Construct a event timing codes frame based on the data in \a data. + */ + explicit EventTimingCodesFrame(const ByteVector &data); + + /*! + * Destroys this EventTimingCodesFrame instance. + */ + virtual ~EventTimingCodesFrame(); + + /*! + * Returns a null string. + */ + virtual String toString() const; + + /*! + * Returns the timestamp format. + */ + TimestampFormat timestampFormat() const; + + /*! + * Returns the events with the time stamps. + */ + SynchedEventList synchedEvents() const; + + /*! + * Set the timestamp format. + * + * \see timestampFormat() + */ + void setTimestampFormat(TimestampFormat f); + + /*! + * Sets the text with the time stamps. + * + * \see text() + */ + void setSynchedEvents(const SynchedEventList &e); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + EventTimingCodesFrame(const ByteVector &data, Header *h); + EventTimingCodesFrame(const EventTimingCodesFrame &); + EventTimingCodesFrame &operator=(const EventTimingCodesFrame &); + + class EventTimingCodesFramePrivate; + EventTimingCodesFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/fileref.h b/external/taglib/include/fileref.h new file mode 100644 index 0000000..75d1492 --- /dev/null +++ b/external/taglib/include/fileref.h @@ -0,0 +1,297 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILEREF_H +#define TAGLIB_FILEREF_H + +#include "tfile.h" +#include "tstringlist.h" + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + class Tag; + + //! This class provides a simple abstraction for creating and handling files + + /*! + * FileRef exists to provide a minimal, generic and value-based wrapper around + * a File. It is lightweight and implicitly shared, and as such suitable for + * pass-by-value use. This hides some of the uglier details of TagLib::File + * and the non-generic portions of the concrete file implementations. + * + * This class is useful in a "simple usage" situation where it is desirable + * to be able to get and set some of the tag information that is similar + * across file types. + * + * Also note that it is probably a good idea to plug this into your mime + * type system rather than using the constructor that accepts a file name using + * the FileTypeResolver. + * + * \see FileTypeResolver + * \see addFileTypeResolver() + */ + + class TAGLIB_EXPORT FileRef + { + public: + + //! A class for pluggable file type resolution. + + /*! + * This class is used to add extend TagLib's very basic file name based file + * type resolution. + * + * This can be accomplished with: + * + * \code + * + * class MyFileTypeResolver : FileTypeResolver + * { + * TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const + * { + * if(someCheckForAnMP3File(fileName)) + * return new TagLib::MPEG::File(fileName); + * return 0; + * } + * } + * + * FileRef::addFileTypeResolver(new MyFileTypeResolver); + * + * \endcode + * + * Naturally a less contrived example would be slightly more complex. This + * can be used to plug in mime-type detection systems or to add new file types + * to TagLib. + */ + + class TAGLIB_EXPORT FileTypeResolver + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + /*! + * This method must be overridden to provide an additional file type + * resolver. If the resolver is able to determine the file type it should + * return a valid File object; if not it should return 0. + * + * \note The created file is then owned by the FileRef and should not be + * deleted. Deletion will happen automatically when the FileRef passes + * out of scope. + */ + virtual File *createFile(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average) const = 0; + }; + + class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + virtual File *createFileFromStream(IOStream *stream, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average) const = 0; + }; + + /*! + * Creates a null FileRef. + */ + FileRef(); + + /*! + * Create a FileRef from \a fileName. If \a readAudioProperties is true then + * the audio properties will be read using \a audioPropertiesStyle. If + * \a readAudioProperties is false then \a audioPropertiesStyle will be + * ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + */ + explicit FileRef(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average); + + /*! + * Construct a FileRef from an opened \a IOStream. If \a readAudioProperties + * is true then the audio properties will be read using \a audioPropertiesStyle. + * If \a readAudioProperties is false then \a audioPropertiesStyle will be + * ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + explicit FileRef(IOStream* stream, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average); + + /*! + * Construct a FileRef using \a file. The FileRef now takes ownership of the + * pointer and will delete the File when it passes out of scope. + */ + explicit FileRef(File *file); + + /*! + * Make a copy of \a ref. + */ + FileRef(const FileRef &ref); + + /*! + * Destroys this FileRef instance. + */ + virtual ~FileRef(); + + /*! + * Returns a pointer to represented file's tag. + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + * + * \warning Do not cast it to any subclasses of Tag. + * Use tag returning methods of appropriate subclasses of File instead. + * + * \see File::tag() + */ + Tag *tag() const; + + /*! + * Returns the audio properties for this FileRef. If no audio properties + * were read then this will returns a null pointer. + */ + AudioProperties *audioProperties() const; + + /*! + * Returns a pointer to the file represented by this handler class. + * + * As a general rule this call should be avoided since if you need to work + * with file objects directly, you are probably better served instantiating + * the File subclasses (i.e. MPEG::File) manually and working with their APIs. + * + * This handle exists to provide a minimal, generic and value-based + * wrapper around a File. Accessing the file directly generally indicates + * a moving away from this simplicity (and into things beyond the scope of + * FileRef). + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + */ + File *file() const; + + /*! + * Saves the file. Returns true on success. + */ + bool save(); + + /*! + * Adds a FileTypeResolver to the list of those used by TagLib. Each + * additional FileTypeResolver is added to the front of a list of resolvers + * that are tried. If the FileTypeResolver returns zero the next resolver + * is tried. + * + * Returns a pointer to the added resolver (the same one that's passed in -- + * this is mostly so that static initializers have something to use for + * assignment). + * + * \see FileTypeResolver + */ + static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver); + + /*! + * As is mentioned elsewhere in this class's documentation, the default file + * type resolution code provided by TagLib only works by comparing file + * extensions. + * + * This method returns the list of file extensions that are used by default. + * + * The extensions are all returned in lowercase, though the comparison used + * by TagLib for resolution is case-insensitive. + * + * \note This does not account for any additional file type resolvers that + * are plugged in. Also note that this is not intended to replace a proper + * mime-type resolution system, but is just here for reference. + * + * \see FileTypeResolver + */ + static StringList defaultFileExtensions(); + + /*! + * Returns true if the file (and as such other pointers) are null. + */ + bool isNull() const; + + /*! + * Assign the file pointed to by \a ref to this FileRef. + */ + FileRef &operator=(const FileRef &ref); + + /*! + * Exchanges the content of the FileRef by the content of \a ref. + */ + void swap(FileRef &ref); + + /*! + * Returns true if this FileRef and \a ref point to the same File object. + */ + bool operator==(const FileRef &ref) const; + + /*! + * Returns true if this FileRef and \a ref do not point to the same File + * object. + */ + bool operator!=(const FileRef &ref) const; + + /*! + * A simple implementation of file type guessing. If \a readAudioProperties + * is true then the audio properties will be read using + * \a audioPropertiesStyle. If \a readAudioProperties is false then + * \a audioPropertiesStyle will be ignored. + * + * \note You generally shouldn't use this method, but instead the constructor + * directly. + * + * \deprecated + */ + static File *create(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); + + private: + void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle); + void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle); + + class FileRefPrivate; + FileRefPrivate *d; + }; + +} // namespace TagLib + +#endif diff --git a/external/taglib/include/flacfile.h b/external/taglib/include/flacfile.h new file mode 100644 index 0000000..1b8654e --- /dev/null +++ b/external/taglib/include/flacfile.h @@ -0,0 +1,343 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACFILE_H +#define TAGLIB_FLACFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tlist.h" +#include "tag.h" + +#include "flacpicture.h" +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + namespace ID3v2 { class FrameFactory; class Tag; } + namespace ID3v1 { class Tag; } + namespace Ogg { class XiphComment; } + + //! An implementation of FLAC metadata + + /*! + * This is implementation of FLAC metadata for non-Ogg FLAC files. At some + * point when Ogg / FLAC is more common there will be a similar implementation + * under the Ogg hierarchy. + * + * This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream + * properties from the file. + */ + + namespace FLAC { + + //! An implementation of TagLib::File with FLAC specific methods + + /*! + * This implements and provides an interface for FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to FLAC files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches Vorbis comments. + XiphComment = 0x0001, + //! Matches ID3v1 tags. + ID3v1 = 0x0002, + //! Matches ID3v2 tags. + ID3v2 = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a FLAC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an FLAC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a FLAC file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be a union of XiphComment, + * ID3v1 and ID3v2 tags. + * + * \see ID3v2Tag() + * \see ID3v1Tag() + * \see XiphComment() + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains more than one tag (e.g. XiphComment and ID3v1), + * only the first one (in the order XiphComment, ID3v2, ID3v1) will be + * converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &); + + /*! + * Implements the unified property interface -- import function. + * This always creates a Xiph comment, if none exists. The return value + * relates to the Xiph comment only. + * Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed + * in the FLAC specification. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. This will primarily save the XiphComment, but + * will also keep any old ID3-tags up to date. If the file + * has no XiphComment, one will be constructed from the ID3-tags. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the XiphComment for the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid XiphComment. If \a create is true it will create + * a XiphComment if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has a XiphComment. Use hasXiphComment() to check if the + * file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasXiphComment() + */ + Ogg::XiphComment *xiphComment(bool create = false); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. This + * can be used to specify the way that ID3v2 frames will be interpreted + * when + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the block of data used by FLAC::Properties for parsing the + * stream properties. + * + * \deprecated Always returns an empty vector. + */ + TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + * + * \deprecated Always returns zero. + */ + TAGLIB_DEPRECATED long streamLength(); // BIC: remove + + /*! + * Returns a list of pictures attached to the FLAC file. + */ + List pictureList(); + + /*! + * Removes an attached picture. If \a del is true the picture's memory + * will be freed; if it is false, it must be deleted by the user. + */ + void removePicture(Picture *picture, bool del = true); + + /*! + * Remove all attached images. + */ + void removePictures(); + + /*! + * Add a new picture to the file. The file takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(Picture *picture); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from + * the file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags as their memory + * will be freed. + * + * \note In order to make the removal permanent save() still needs to be + * called. + * + * \note This won't remove the Vorbis comment block completely. The + * vendor ID will be preserved. + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see xiphComment() + */ + bool hasXiphComment() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a FLAC + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + void scan(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/flacmetadatablock.h b/external/taglib/include/flacmetadatablock.h new file mode 100644 index 0000000..41bca31 --- /dev/null +++ b/external/taglib/include/flacmetadatablock.h @@ -0,0 +1,75 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACMETADATABLOCK_H +#define TAGLIB_FLACMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT MetadataBlock + { + public: + MetadataBlock(); + virtual ~MetadataBlock(); + + enum BlockType { + StreamInfo = 0, + Padding, + Application, + SeekTable, + VorbisComment, + CueSheet, + Picture + }; + + /*! + * Returns the FLAC metadata block type. + */ + virtual int code() const = 0; + + /*! + * Render the content of the block. + */ + virtual ByteVector render() const = 0; + + private: + MetadataBlock(const MetadataBlock &item); + MetadataBlock &operator=(const MetadataBlock &item); + + class MetadataBlockPrivate; + MetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/flacpicture.h b/external/taglib/include/flacpicture.h new file mode 100644 index 0000000..b6def57 --- /dev/null +++ b/external/taglib/include/flacpicture.h @@ -0,0 +1,208 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPICTURE_H +#define TAGLIB_FLACPICTURE_H + +#include "tlist.h" +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT Picture : public MetadataBlock + { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + Picture(); + Picture(const ByteVector &data); + ~Picture(); + + /*! + * Returns the type of the image. + */ + Type type() const; + + /*! + * Sets the type of the image. + */ + void setType(Type type); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns a text description of the image. + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + */ + + void setDescription(const String &desc); + + /*! + * Returns the width of the image. + */ + int width() const; + + /*! + * Sets the width of the image. + */ + void setWidth(int w); + + /*! + * Returns the height of the image. + */ + int height() const; + + /*! + * Sets the height of the image. + */ + void setHeight(int h); + + /*! + * Returns the color depth (in bits-per-pixel) of the image. + */ + int colorDepth() const; + + /*! + * Sets the color depth (in bits-per-pixel) of the image. + */ + void setColorDepth(int depth); + + /*! + * Returns the number of colors used on the image.. + */ + int numColors() const; + + /*! + * Sets the number of colors used on the image (for indexed images). + */ + void setNumColors(int numColors); + + /*! + * Returns the image data. + */ + ByteVector data() const; + + /*! + * Sets the image data. + */ + void setData(const ByteVector &data); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Render the content to the FLAC picture block format. + */ + ByteVector render() const; + + /*! + * Parse the picture data in the FLAC picture block format. + */ + bool parse(const ByteVector &rawData); + + private: + Picture(const Picture &item); + Picture &operator=(const Picture &item); + + class PicturePrivate; + PicturePrivate *d; + }; + + typedef List PictureList; + + } + +} + +#endif diff --git a/external/taglib/include/flacproperties.h b/external/taglib/include/flacproperties.h new file mode 100644 index 0000000..743e587 --- /dev/null +++ b/external/taglib/include/flacproperties.h @@ -0,0 +1,148 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPROPERTIES_H +#define TAGLIB_FLACPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace FLAC { + + class File; + + //! An implementation of audio property reading for FLAC + + /*! + * This reads the data from an FLAC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of FLAC::Properties with the data read from the + * ByteVector \a data. + */ + // BIC: switch to const reference + Properties(ByteVector data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of FLAC::Properties with the data read from the + * FLAC::File \a file. + */ + // BIC: remove + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this FLAC::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample as read from the FLAC + * identification header. + */ + int bitsPerSample() const; + + /*! + * Returns the sample width as read from the FLAC identification + * header. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Return the number of sample frames. + */ + unsigned long long sampleFrames() const; + + /*! + * Returns the MD5 signature of the uncompressed audio stream as read + * from the stream info header. + */ + ByteVector signature() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/flacunknownmetadatablock.h b/external/taglib/include/flacunknownmetadatablock.h new file mode 100644 index 0000000..3030254 --- /dev/null +++ b/external/taglib/include/flacunknownmetadatablock.h @@ -0,0 +1,81 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACUNKNOWNMETADATABLOCK_H +#define TAGLIB_FLACUNKNOWNMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock + { + public: + UnknownMetadataBlock(int blockType, const ByteVector &data); + ~UnknownMetadataBlock(); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setCode(int code); + + /*! + * Returns the FLAC metadata block type. + */ + ByteVector data() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setData(const ByteVector &data); + + /*! + * Render the content of the block. + */ + ByteVector render() const; + + private: + UnknownMetadataBlock(const MetadataBlock &item); + UnknownMetadataBlock &operator=(const MetadataBlock &item); + + class UnknownMetadataBlockPrivate; + UnknownMetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/generalencapsulatedobjectframe.h b/external/taglib/include/generalencapsulatedobjectframe.h new file mode 100644 index 0000000..769dfb0 --- /dev/null +++ b/external/taglib/include/generalencapsulatedobjectframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Aaron VonderHaar + email : avh4@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_GENERALENCAPSULATEDOBJECT_H +#define TAGLIB_GENERALENCAPSULATEDOBJECT_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 general encapsulated object frame implementation + + /*! + * This is an implementation of ID3v2 general encapsulated objects. + * Arbitrary binary data may be included in tags, stored in GEOB frames. + * There may be multiple GEOB frames in a single tag. Each GEOB it + * labelled with a content description (which may be blank), a required + * mime-type, and a file name (may be blank). The content description + * uniquely identifies the GEOB frame in the tag. + */ + + class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Constructs an empty object frame. The description, file name and text + * encoding should be set manually. + */ + GeneralEncapsulatedObjectFrame(); + + /*! + * Constructs a GeneralEncapsulatedObjectFrame frame based on \a data. + * + * \warning This is \em not data for the encapsulated object, for that use + * setObject(). This constructor is used when reading the frame from the + * disk. + */ + explicit GeneralEncapsulatedObjectFrame(const ByteVector &data); + + /*! + * Destroys the GeneralEncapsulatedObjectFrame instance. + */ + virtual ~GeneralEncapsulatedObjectFrame(); + + /*! + * Returns a string containing the description, file name and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description and file name. + * + * \see setTextEncoding() + * \see description() + * \see fileName() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description and file name. + * + * \see description() + * \see fileName() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the mime type of the object. + */ + String mimeType() const; + + /*! + * Sets the mime type of the object. + */ + void setMimeType(const String &type); + + /*! + * Returns the file name of the object. + * + * \see setFileName() + */ + String fileName() const; + + /*! + * Sets the file name for the object. + * + * \see fileName() + */ + void setFileName(const String &name); + + /*! + * Returns the content description of the object. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets the content description of the object to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the object data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setObject() + * \see mimeType() + */ + ByteVector object() const; + + /*! + * Sets the object data to \a data. \a data should be of the type specified in + * this frame's mime-type specification. + * + * \see object() + * \see mimeType() + * \see setMimeType() + */ + void setObject(const ByteVector &object); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h); + GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &); + GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &); + + class GeneralEncapsulatedObjectFramePrivate; + GeneralEncapsulatedObjectFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/id3v1genres.h b/external/taglib/include/id3v1genres.h new file mode 100644 index 0000000..0a0dd97 --- /dev/null +++ b/external/taglib/include/id3v1genres.h @@ -0,0 +1,66 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1GENRE_H +#define TAGLIB_ID3V1GENRE_H + +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" + +namespace TagLib { + namespace ID3v1 { + + typedef Map GenreMap; + + /*! + * Returns the list of canonical ID3v1 genre names in the order that they + * are listed in the standard. + */ + StringList TAGLIB_EXPORT genreList(); + + /*! + * A "reverse mapping" that goes from the canonical ID3v1 genre name to the + * respective genre number. genreMap()["Rock"] == + */ + GenreMap TAGLIB_EXPORT genreMap(); + + /*! + * Returns the name of the genre at \a index in the ID3v1 genre list. If + * \a index is out of range -- less than zero or greater than 191 -- a null + * string will be returned. + */ + String TAGLIB_EXPORT genre(int index); + + /*! + * Returns the genre index for the (case sensitive) genre \a name. If the + * genre is not in the list 255 (which signifies an unknown genre in ID3v1) + * will be returned. + */ + int TAGLIB_EXPORT genreIndex(const String &name); + } +} + +#endif diff --git a/external/taglib/include/id3v1tag.h b/external/taglib/include/id3v1tag.h new file mode 100644 index 0000000..b61f06a --- /dev/null +++ b/external/taglib/include/id3v1tag.h @@ -0,0 +1,202 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1TAG_H +#define TAGLIB_ID3V1TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class File; + + //! An ID3v1 implementation + + namespace ID3v1 { + + //! A abstraction for the string to data encoding in ID3v1 tags. + + /*! + * ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In + * practice it does not. TagLib by default only supports ISO-8859-1 data + * in ID3v1 tags. + * + * However by subclassing this class and reimplementing parse() and render() + * and setting your reimplementation as the default with + * ID3v1::Tag::setStringHandler() you can define how you would like these + * transformations to be done. + * + * \warning It is advisable not to write non-ISO-8859-1 data to ID3v1 + * tags. Please consider disabling the writing of ID3v1 tags in the case + * that the data is not ISO-8859-1. + * + * \see ID3v1::Tag::setStringHandler() + */ + + class TAGLIB_EXPORT StringHandler + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + // BIC: Add virtual destructor. + StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ + virtual String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation + * assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is + * does not conform to ISO-8859-1, no value is written. + * + * \warning It is recommended that you not override this method, but + * instead do not write an ID3v1 tag in the case that the data is not + * ISO-8859-1. + */ + virtual ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v1 implementation + + /*! + * This is an implementation of the ID3v1 format. ID3v1 is both the simplest + * and most common of tag formats but is rather limited. Because of its + * pervasiveness and the way that applications have been written around the + * fields that it provides, the generic TagLib::Tag API is a mirror of what is + * provided by ID3v1. + * + * ID3v1 tags should generally only contain Latin1 information. However because + * many applications do not follow this rule there is now support for overriding + * the ID3v1 string handling using the ID3v1::StringHandler class. Please see + * the documentation for that class for more information. + * + * \see StringHandler + * + * \note Most fields are truncated to a maximum of 28-30 bytes. The + * truncation happens automatically when the tag is rendered. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an ID3v1 tag with default values. + */ + Tag(); + + /*! + * Create an ID3v1 tag and parse the data in \a file starting at + * \a tagOffset. + */ + Tag(File *file, long tagOffset); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "TAG" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + /*! + * Returns the genre in number. + * + * \note Normally 255 indicates that this tag contains no genre. + */ + unsigned int genreNumber() const; + + /*! + * Sets the genre in number to \a i. + * + * \note Valid value is from 0 up to 255. Normally 255 indicates that + * this tag contains no genre. + */ + void setGenreNumber(unsigned int i); + + /*! + * Sets the string handler that decides how the ID3v1 data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see StringHandler + */ + static void setStringHandler(const StringHandler *handler); + + protected: + /*! + * Reads from the file specified in the constructor. + */ + void read(); + /*! + * Pareses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/id3v2.h b/external/taglib/include/id3v2.h new file mode 100644 index 0000000..bef8251 --- /dev/null +++ b/external/taglib/include/id3v2.h @@ -0,0 +1,24 @@ +#ifndef TAGLIB_ID3V2_H +#define TAGLIB_ID3V2_H + +namespace TagLib { + //! An ID3v2 implementation + + /*! + * This is a relatively complete and flexible framework for working with ID3v2 + * tags. + * + * \see ID3v2::Tag + */ + namespace ID3v2 { + /*! + * Used to specify which version of the ID3 standard to use when saving tags. + */ + enum Version { + v3 = 3, //3.2) + */ + + class TAGLIB_EXPORT ExtendedHeader + { + public: + /*! + * Constructs an empty ID3v2 extended header. + */ + ExtendedHeader(); + + /*! + * Destroys the extended header. + */ + virtual ~ExtendedHeader(); + + /*! + * Returns the size of the extended header. This is variable for the + * extended header. + */ + unsigned int size() const; + + /*! + * Sets the data that will be used as the extended header. Since the + * length is not known before the extended header has been parsed, this + * should just be a pointer to the first byte of the extended header. It + * will determine the length internally and make that available through + * size(). + */ + void setData(const ByteVector &data); + + protected: + /*! + * Called by setData() to parse the extended header data. It makes this + * information available through the public API. + */ + void parse(const ByteVector &data); + + private: + ExtendedHeader(const ExtendedHeader &); + ExtendedHeader &operator=(const ExtendedHeader &); + + class ExtendedHeaderPrivate; + ExtendedHeaderPrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/id3v2footer.h b/external/taglib/include/id3v2footer.h new file mode 100644 index 0000000..5eb3800 --- /dev/null +++ b/external/taglib/include/id3v2footer.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FOOTER_H +#define TAGLIB_ID3V2FOOTER_H + +#include "taglib_export.h" +#include "tbytevector.h" + +namespace TagLib { + + namespace ID3v2 { + + class Header; + + //! ID3v2 footer implementation + + /*! + * Per the ID3v2 specification, the tag's footer is just a copy of the + * information in the header. As such there is no API for reading the + * data from the header, it can just as easily be done from the header. + * + * In fact, at this point, TagLib does not even parse the footer since + * it is not useful internally. However, if the flag to include a footer + * has been set in the ID3v2::Tag, TagLib will render a footer. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty ID3v2 footer. + */ + Footer(); + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the size of the footer. Presently this is always 10 bytes. + */ + static unsigned int size(); + + /*! + * Renders the footer based on the data in \a header. + */ + ByteVector render(const Header *header) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/id3v2frame.h b/external/taglib/include/id3v2frame.h new file mode 100644 index 0000000..2e744fc --- /dev/null +++ b/external/taglib/include/id3v2frame.h @@ -0,0 +1,523 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAME_H +#define TAGLIB_ID3V2FRAME_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class StringList; + class PropertyMap; + + namespace ID3v2 { + + class Tag; + class FrameFactory; + + //! ID3v2 frame implementation + + /*! + * This class is the main ID3v2 frame implementation. In ID3v2, a tag is + * split between a collection of frames (which are in turn split into fields + * (Structure, 4) + * (Frames). This class provides an API for + * gathering information about and modifying ID3v2 frames. Functionality + * specific to a given frame type is handed in one of the many subclasses. + */ + + class TAGLIB_EXPORT Frame + { + friend class Tag; + friend class FrameFactory; + friend class TableOfContentsFrame; + friend class ChapterFrame; + + public: + + /*! + * Creates a textual frame which corresponds to a single key in the PropertyMap + * interface. These are all (User)TextIdentificationFrames except TIPL and TMCL, + * all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame. + */ + static Frame *createTextualFrame(const String &key, const StringList &values); + + /*! + * Destroys this Frame instance. + */ + virtual ~Frame(); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Returns the size of the frame. + */ + unsigned int size() const; + + /*! + * Returns the size of the frame header + * + * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use + * the call below which accepts an ID3v2 version number. In the next + * non-binary compatible release this will be made into a non-static + * member that checks the internal ID3v2 version. + */ + static unsigned int headerSize(); // BIC: make non-static + + /*! + * Returns the size of the frame header for the given ID3v2 version. + * + * \deprecated Please see the explanation above. + */ + // BIC: remove + static unsigned int headerSize(unsigned int version); + + /*! + * Sets the data that will be used as the frame. Since the length is not + * known before the frame has been parsed, this should just be a pointer to + * the first byte of the frame. It will determine the length internally + * and make that available through size(). + */ + void setData(const ByteVector &data); + + /*! + * Set the text of frame in the sanest way possible. This should only be + * reimplemented in frames where there is some logical mapping to text. + * + * \note If the frame type supports multiple text encodings, this will not + * change the text encoding of the frame; the string will be converted to + * that frame's encoding. Please use the specific APIs of the frame types + * to set the encoding if that is desired. + */ + virtual void setText(const String &text); + + /*! + * This returns the textual representation of the data in the frame. + * Subclasses must reimplement this method to provide a string + * representation of the frame's data. + */ + virtual String toString() const = 0; + + /*! + * Render the frame back to its binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * Returns the text delimiter that is used between fields for the string + * type \a t. + */ + static ByteVector textDelimiter(String::Type t); + + /*! + * The string with which an instrument name is prefixed to build a key in a PropertyMap; + * used to translate PropertyMaps to TMCL frames. In the current implementation, this + * is "PERFORMER:". + */ + static const String instrumentPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX + * frame for a non-standard key. In the current implementation, this is "COMMENT:". + */ + static const String commentPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX + * frame for a non-standard key. In the current implementation, this is "LYRICS:". + */ + static const String lyricsPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX + * frame for a non-standard key. In the current implementation, this is "URL:". + */ + static const String urlPrefix; + + protected: + class Header; + + /*! + * Constructs an ID3v2 frame using \a data to read the header information. + * All other processing of \a data should be handled in a subclass. + * + * \note This need not contain anything more than a frame ID, but + * \e must contain at least that. + */ + explicit Frame(const ByteVector &data); + + /*! + * This creates an Frame using the header \a h. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + Frame(Header *h); + + /*! + * Returns a pointer to the frame header. + */ + Header *header() const; + + /*! + * Sets the header to \a h. If \a deleteCurrent is true, this will free + * the memory of the current header. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + void setHeader(Header *h, bool deleteCurrent = true); + + /*! + * Called by setData() to parse the frame data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by parse() to parse the field data. It makes this information + * available through the public API. This must be overridden by the + * subclasses. + */ + virtual void parseFields(const ByteVector &data) = 0; + + /*! + * Render the field data back to a binary format in a ByteVector. This + * must be overridden by subclasses. + */ + virtual ByteVector renderFields() const = 0; + + /*! + * Returns a ByteVector containing the field data given the frame data. + * This correctly adjusts for the header size plus any additional frame + * data that's specified in the frame header flags. + */ + ByteVector fieldData(const ByteVector &frameData) const; + + /*! + * Reads a String of type \a encoding from the ByteVector \a data. If \a + * position is passed in it is used both as the starting point and is + * updated to return the position just after the string that has been read. + * This is useful for reading strings sequentially. + */ + String readStringField(const ByteVector &data, String::Type encoding, + int *position = 0); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. + */ + // BIC: remove and make non-static + static String::Type checkEncoding(const StringList &fields, + String::Type encoding); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. This method + * also checks the ID3v2 version and makes sure the encoding can be used + * in the specified version. + */ + // BIC: remove and make non-static + static String::Type checkEncoding(const StringList &fields, + String::Type encoding, unsigned int version); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. This method + * also checks the ID3v2 version and makes sure the encoding can be used + * in the version specified by the frame's header. + */ + String::Type checkTextEncoding(const StringList &fields, + String::Type encoding) const; + + + /*! + * Parses the contents of this frame as PropertyMap. If that fails, the returned + * PropertyMap will be empty, and its unsupportedData() will contain this frame's + * ID. + * BIC: Will be a virtual function in future releases. + */ + PropertyMap asProperties() const; + + /*! + * Returns an appropriate ID3 frame ID for the given free-form tag key. This method + * will return an empty ByteVector if no specialized translation is found. + */ + static ByteVector keyToFrameID(const String &); + + /*! + * Returns a free-form tag name for the given ID3 frame ID. Note that this does not work + * for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned. + */ + static String frameIDToKey(const ByteVector &); + + /*! + * Returns an appropriate TXXX frame description for the given free-form tag key. + */ + static String keyToTXXX(const String &); + + /*! + * Returns a free-form tag name for the given ID3 frame description. + */ + static String txxxToKey(const String &); + + /*! + * This helper function splits the PropertyMap \a original into three ProperytMaps + * \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that: + * - \a singleFrameProperties contains only of keys which can be represented with + * exactly one ID3 frame per key. In the current implementation + * this is everything except for the fixed "involved people" keys and keys of the + * form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are + * mapped to a TMCL frame. + * - \a tiplProperties will consist of those keys that are present in + * TextIdentificationFrame::involvedPeopleMap() + * - \a tmclProperties contains the "musician credits" keys which should be mapped + * to a TMCL frame + */ + static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, + PropertyMap &tiplProperties, PropertyMap &tmclProperties); + + private: + Frame(const Frame &); + Frame &operator=(const Frame &); + + class FramePrivate; + friend class FramePrivate; + FramePrivate *d; + }; + + //! ID3v2 frame header implementation + + /*! + * The ID3v2 Frame Header (Structure, 4) + * + * Every ID3v2::Frame has an associated header that gives some general + * properties of the frame and also makes it possible to identify the frame + * type. + * + * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the + * frame headers and then creates the appropriate Frame subclass based on + * the type and attaches the header. + */ + + class TAGLIB_EXPORT Frame::Header + { + public: + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \deprecated Please use the constructor below that accepts a version + * number. + */ + TAGLIB_DEPRECATED Header(const ByteVector &data, bool synchSafeInts); + + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \a version should be the ID3v2 version of the tag. + */ + explicit Header(const ByteVector &data, unsigned int version = 4); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Sets the data for the Header. + * + * \deprecated Please use the version below that accepts an ID3v2 version + * number. + */ + TAGLIB_DEPRECATED void setData(const ByteVector &data, bool synchSafeInts); + + /*! + * Sets the data for the Header. \a version should indicate the ID3v2 + * version number of the tag that this frame is contained in. + */ + void setData(const ByteVector &data, unsigned int version = 4); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Sets the frame's ID to \a id. Only the first four bytes of \a id will + * be used. + * + * \warning This method should in general be avoided. It exists simply to + * provide a mechanism for transforming frames from a deprecated frame type + * to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4. + */ + void setFrameID(const ByteVector &id); + + /*! + * Returns the size of the frame data portion, as set when setData() was + * called or set explicitly via setFrameSize(). + */ + unsigned int frameSize() const; + + /*! + * Sets the size of the frame data portion. + */ + void setFrameSize(unsigned int size); + + /*! + * Returns the ID3v2 version of the header, as passed in from the + * construction of the header or set via setVersion(). + */ + unsigned int version() const; + + /*! + * Sets the ID3v2 version of the header, changing has impact on the + * correct parsing/rendering of frame data. + */ + void setVersion(unsigned int version); + + /*! + * Returns the size of the frame header in bytes. + * + * \deprecated Please use the version of this method that accepts a + * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be + * removed in the next binary incompatible release (2.0) and will be + * replaced with a non-static method that checks the frame version. + */ + // BIC: make non-static + static unsigned int size(); + + /*! + * Returns the size of the frame header in bytes for the ID3v2 version + * that's given. + * + * \deprecated Please see the explanation in the version above. + */ + // BIC: remove + static unsigned int size(unsigned int version); + + /*! + * Returns true if the flag for tag alter preservation is set. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see setTagAlterPreservation() + */ + bool tagAlterPreservation() const; + + /*! + * Sets the flag for preservation of this frame if the tag is set. If + * this is set to true the frame will not be written when the tag is + * saved. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see tagAlterPreservation() + */ + void setTagAlterPreservation(bool discard); + + /*! + * Returns true if the flag for file alter preservation is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool fileAlterPreservation() const; + + /*! + * Returns true if the frame is meant to be read only. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool readOnly() const; + + /*! + * Returns true if the flag for the grouping identity is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool groupingIdentity() const; + + /*! + * Returns true if compression is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool compression() const; + + /*! + * Returns true if encryption is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool encryption() const; + +#ifndef DO_NOT_DOCUMENT + bool unsycronisation() const; +#endif + + /*! + * Returns true if unsynchronisation is enabled for this frame. + */ + bool unsynchronisation() const; + + /*! + * Returns true if the flag for a data length indicator is set. + */ + bool dataLengthIndicator() const; + + /*! + * Render the Header back to binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED bool frameAlterPreservation() const; + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/id3v2framefactory.h b/external/taglib/include/id3v2framefactory.h new file mode 100644 index 0000000..9605c78 --- /dev/null +++ b/external/taglib/include/id3v2framefactory.h @@ -0,0 +1,169 @@ + /*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAMEFACTORY_H +#define TAGLIB_ID3V2FRAMEFACTORY_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "id3v2frame.h" +#include "id3v2header.h" + +namespace TagLib { + + namespace ID3v2 { + + class TextIdentificationFrame; + + //! A factory for creating ID3v2 frames during parsing + + /*! + * This factory abstracts away the frame creation process and instantiates + * the appropriate ID3v2::Frame subclasses based on the contents of the + * data. + * + * Reimplementing this factory is the key to adding support for frame types + * not directly supported by TagLib to your application. To do so you would + * subclass this factory and reimplement createFrame(). Then by setting your + * factory to be the default factory in ID3v2::Tag constructor you can + * implement behavior that will allow for new ID3v2::Frame subclasses (also + * provided by you) to be used. + * + * This implements both abstract factory and singleton patterns + * of which more information is available on the web and in software design + * textbooks (Notably Design Patters). + * + * \note You do not need to use this factory to create new frames to add to + * an ID3v2::Tag. You can instantiate frame subclasses directly (with new) + * and add them to a tag using ID3v2::Tag::addFrame() + * + * \see ID3v2::Tag::addFrame() + */ + + class TAGLIB_EXPORT FrameFactory + { + public: + static FrameFactory *instance(); + /*! + * Create a frame based on \a data. \a synchSafeInts should only be set + * false if we are parsing an old tag (v2.3 or older) that does not support + * synchsafe ints. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + TAGLIB_DEPRECATED Frame *createFrame(const ByteVector &data, bool synchSafeInts) const; + + /*! + * Create a frame based on \a data. \a version should indicate the ID3v2 + * version of the tag. As ID3v2.4 is the most current version of the + * standard 4 is the default. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + TAGLIB_DEPRECATED Frame *createFrame(const ByteVector &data, unsigned int version = 4) const; + + /*! + * \deprecated + */ + // BIC: remove + Frame *createFrame(const ByteVector &data, Header *tagHeader) const; + /*! + * Create a frame based on \a data. \a tagHeader should be a valid + * ID3v2::Header instance. + */ + // BIC: make virtual + Frame *createFrame(const ByteVector &data, const Header *tagHeader) const; + + /*! + * After a tag has been read, this tries to rebuild some of them + * information, most notably the recording date, from frames that + * have been deprecated and can't be upgraded directly. + */ + // BIC: Make virtual + void rebuildAggregateFrames(ID3v2::Tag *tag) const; + + /*! + * Returns the default text encoding for text frames. If setTextEncoding() + * has not been explicitly called this will only be used for new text + * frames. However, if this value has been set explicitly all frames will be + * converted to this type (unless it's explicitly set differently for the + * individual frame) when being rendered. + * + * \see setDefaultTextEncoding() + */ + String::Type defaultTextEncoding() const; + + /*! + * Set the default text encoding for all text frames that are created to + * \a encoding. If no value is set the frames with either default to the + * encoding type that was parsed and new frames default to Latin1. + * + * Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE. + * + * \see defaultTextEncoding() + */ + void setDefaultTextEncoding(String::Type encoding); + + protected: + /*! + * Constructs a frame factory. Because this is a singleton this method is + * protected, but may be used for subclasses. + */ + FrameFactory(); + + /*! + * Destroys the frame factory. + */ + virtual ~FrameFactory(); + + /*! + * This method checks for compliance to the current ID3v2 standard (2.4) + * and does nothing in the common case. However if a frame is found that + * is not compatible with the current standard, this method either updates + * the frame or indicates that it should be discarded. + * + * This method with return true (with or without changes to the frame) if + * this frame should be kept or false if it should be discarded. + * + * See the id3v2.4.0-changes.txt document for further information. + */ + virtual bool updateFrame(Frame::Header *header) const; + + private: + FrameFactory(const FrameFactory &); + FrameFactory &operator=(const FrameFactory &); + + static FrameFactory factory; + + class FrameFactoryPrivate; + FrameFactoryPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/id3v2header.h b/external/taglib/include/id3v2header.h new file mode 100644 index 0000000..a1f2985 --- /dev/null +++ b/external/taglib/include/id3v2header.h @@ -0,0 +1,176 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2HEADER_H +#define TAGLIB_ID3V2HEADER_H + +#include "tbytevector.h" +#include "taglib_export.h" +#include "id3v2.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 headers + + /*! + * This class implements ID3v2 headers. It attempts to follow, both + * semantically and programmatically, the structure specified in + * the ID3v2 standard. The API is based on the properties of ID3v2 headers + * specified there. If any of the terms used in this documentation are + * unclear please check the specification in the linked section. + * (Structure, 3.1) + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Constructs an empty ID3v2 header. + */ + Header(); + + /*! + * Constructs an ID3v2 header based on \a data. parse() is called + * immediately. + */ + Header(const ByteVector &data); + + /*! + * Destroys the header. + */ + virtual ~Header(); + + /*! + * Returns the major version number. (Note: This is the 4, not the 2 in + * ID3v2.4.0. The 2 is implied.) + */ + unsigned int majorVersion() const; + + /*! + * Set the the major version number to \a version. (Note: This is + * the 4, not the 2 in ID3v2.4.0. The 2 is implied.) + * \see majorVersion() + * + * \note This is used by the internal parser; this will not change the + * version which is written and in general should not be called by API + * users. + */ + void setMajorVersion(unsigned int version); + + /*! + * Returns the revision number. (Note: This is the 0, not the 4 in + * ID3v2.4.0. The 2 is implied.) + */ + unsigned int revisionNumber() const; + + /*! + * Returns true if unsynchronisation has been applied to all frames. + */ + bool unsynchronisation() const; + + /*! + * Returns true if an extended header is present in the tag. + */ + bool extendedHeader() const; + + /*! + * Returns true if the experimental indicator flag is set. + */ + bool experimentalIndicator() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + /*! + * Returns the tag size in bytes. This is the size of the frame content. + * The size of the \e entire tag will be this plus the header size (10 + * bytes) and, if present, the footer size (potentially another 10 bytes). + * + * \note This is the value as read from the header to which TagLib attempts + * to provide an API to; it was not a design decision on the part of TagLib + * to not include the mentioned portions of the tag in the \e size. + * + * \see completeTagSize() + */ + unsigned int tagSize() const; + + /*! + * Returns the tag size, including the header and, if present, the footer + * size. + * + * \see tagSize() + */ + unsigned int completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(unsigned int s); + + /*! + * Returns the size of the header. Presently this is always 10 bytes. + */ + static unsigned int size(); + + /*! + * Returns the string used to identify and ID3v2 tag inside of a file. + * Presently this is always "ID3". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the header. 10 bytes, starting from + * the beginning of \a data are used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the Header back to binary format. + */ + ByteVector render() const; + + protected: + /*! + * Called by setData() to parse the header data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/id3v2synchdata.h b/external/taglib/include/id3v2synchdata.h new file mode 100644 index 0000000..13e0716 --- /dev/null +++ b/external/taglib/include/id3v2synchdata.h @@ -0,0 +1,70 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2SYNCHDATA_H +#define TAGLIB_ID3V2SYNCHDATA_H + +#include "tbytevector.h" +#include "taglib.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A few functions for ID3v2 synch safe integer conversion + + /*! + * In the ID3v2.4 standard most integer values are encoded as "synch safe" + * integers which are encoded in such a way that they will not give false + * MPEG syncs and confuse MPEG decoders. This namespace provides some + * methods for converting to and from these values to ByteVectors for + * things rendering and parsing ID3v2 data. + */ + + namespace SynchData + { + /*! + * This returns the unsigned integer value of \a data where \a data is a + * ByteVector that contains a \e synchsafe integer (Structure, + * 6.2). The default \a length of + * 4 is used if another value is not specified. + */ + TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data); + + /*! + * Returns a 4 byte (32 bit) synchsafe integer based on \a value. + */ + TAGLIB_EXPORT ByteVector fromUInt(unsigned int value); + + /*! + * Convert the data from unsynchronized data to its original format. + */ + TAGLIB_EXPORT ByteVector decode(const ByteVector &input); + } + + } +} + +#endif diff --git a/external/taglib/include/id3v2tag.h b/external/taglib/include/id3v2tag.h new file mode 100644 index 0000000..74d1df1 --- /dev/null +++ b/external/taglib/include/id3v2tag.h @@ -0,0 +1,411 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2TAG_H +#define TAGLIB_ID3V2TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tstring.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" + +#include "id3v2.h" +#include "id3v2framefactory.h" + +namespace TagLib { + + class File; + + namespace ID3v2 { + + class Header; + class ExtendedHeader; + class Footer; + + typedef List FrameList; + typedef Map FrameListMap; + + //! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags. + + /*! + * ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only + * supports genuine ISO-8859-1 by default. However, in practice, non + * ISO-8859-1 encodings are often used instead of ISO-8859-1, such as + * Windows-1252 for western languages, Shift_JIS for Japanese and so on. + * + * Here is an option to read such tags by subclassing this class, + * reimplementing parse() and setting your reimplementation as the default + * with ID3v2::Tag::setStringHandler(). + * + * \note Writing non-ISO-8859-1 tags is not implemented intentionally. + * Use UTF-16 or UTF-8 instead. + * + * \see ID3v2::Tag::setStringHandler() + */ + class TAGLIB_EXPORT Latin1StringHandler + { + public: + Latin1StringHandler(); + virtual ~Latin1StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ + virtual String parse(const ByteVector &data) const; + }; + + //! The main class in the ID3v2 implementation + + /*! + * This is the main class in the ID3v2 implementation. It serves two + * functions. This first, as is obvious from the public API, is to provide a + * container for the other ID3v2 related classes. In addition, through the + * read() and parse() protected methods, it provides the most basic level of + * parsing. In these methods the ID3v2 tag is extracted from the file and + * split into data components. + * + * ID3v2 tags have several parts, TagLib attempts to provide an interface + * for them all. header(), footer() and extendedHeader() correspond to those + * data structures in the ID3v2 standard and the APIs for the classes that + * they return attempt to reflect this. + * + * Also ID3v2 tags are built up from a list of frames, which are in turn + * have a header and a list of fields. TagLib provides two ways of accessing + * the list of frames that are in a given ID3v2 tag. The first is simply + * via the frameList() method. This is just a list of pointers to the frames. + * The second is a map from the frame type -- i.e. "COMM" for comments -- and + * a list of frames of that type. (In some cases ID3v2 allows for multiple + * frames of the same type, hence this being a map to a list rather than just + * a map to an individual frame.) + * + * More information on the structure of frames can be found in the ID3v2::Frame + * class. + * + * read() and parse() pass binary data to the other ID3v2 class structures, + * they do not handle parsing of flags or fields, for instance. Those are + * handled by similar functions within those classes. + * + * \note All pointers to data structures within the tag will become invalid + * when the tag is destroyed. + * + * \warning Dealing with the nasty details of ID3v2 is not for the faint of + * heart and should not be done without much meditation on the spec. It's + * rather long, but if you're planning on messing with this class and others + * that deal with the details of ID3v2 (rather than the nice, safe, abstract + * TagLib::Tag and friends), it's worth your time to familiarize yourself + * with said spec (which is distributed with the TagLib sources). TagLib + * tries to do most of the work, but with a little luck, you can still + * convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a + * working knowledge of ID3v2 structure. You're been warned. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty ID3v2 tag. + * + * \note You must create at least one frame for this tag to be valid. + */ + Tag(); + + /*! + * Constructs an ID3v2 tag read from \a file starting at \a tagOffset. + * \a factory specifies which FrameFactory will be used for the + * construction of new frames. + * + * \note You should be able to ignore the \a factory parameter in almost + * all situations. You would want to specify your own FrameFactory + * subclass in the case that you are extending TagLib to support additional + * frame types, which would be incorporated into your factory. + * + * \see FrameFactory + */ + Tag(File *file, long tagOffset, + const FrameFactory *factory = FrameFactory::instance()); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns a pointer to the tag's header. + */ + Header *header() const; + + /*! + * Returns a pointer to the tag's extended header or null if there is no + * extended header. + */ + ExtendedHeader *extendedHeader() const; + + /*! + * Returns a pointer to the tag's footer or null if there is no footer. + * + * \deprecated I don't see any reason to keep this around since there's + * nothing useful to be retrieved from the footer, but well, again, I'm + * prone to change my mind, so this gets to stay around until near a + * release. + */ + TAGLIB_DEPRECATED Footer *footer() const; + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames in the tag. + * + * This is the most convenient structure for accessing the tag's frames. + * Many frame types allow multiple instances of the same frame type so this + * is a map of lists. In most cases however there will only be a single + * frame of a certain type. + * + * Let's say for instance that you wanted to access the frame for total + * beats per minute -- the TBPM frame. + * + * \code + * TagLib::MPEG::File f("foo.mp3"); + * + * // Check to make sure that it has an ID3v2 tag + * + * if(f.ID3v2Tag()) { + * + * // Get the list of frames for a specific frame type + * + * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"]; + * + * if(!l.isEmpty()) + * std::cout << l.front()->toString() << std::endl; + * } + * + * \endcode + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + * + * \see frameList() + */ + const FrameListMap &frameListMap() const; + + /*! + * Returns a reference to the frame list. This is an FrameList of all of + * the frames in the tag in the order that they were parsed. + * + * This can be useful if for example you want iterate over the tag's frames + * in the order that they occur in the tag. + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + */ + const FrameList &frameList() const; + + /*! + * Returns the frame list for frames with the id \a frameID or an empty + * list if there are no frames of that type. This is just a convenience + * and is equivalent to: + * + * \code + * frameListMap()[frameID]; + * \endcode + * + * \see frameListMap() + */ + const FrameList &frameList(const ByteVector &frameID) const; + + /*! + * Add a frame to the tag. At this point the tag takes ownership of + * the frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void addFrame(Frame *frame); + + /*! + * Remove a frame from the tag. If \a del is true the frame's memory + * will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrame(Frame *frame, bool del = true); + + /*! + * Remove all frames of type \a id from the tag and free their memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrames(const ByteVector &id); + + /*! + * Implements the unified property interface -- export function. + * This function does some work to translate the hard-specified ID3v2 + * frame types into a free-form string-to-stringlist PropertyMap: + * - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned + * key is used + * - if the frame ID is "TXXX" (user text frame), the description() is + * used as key + * - if the frame ID is "WXXX" (user url frame), + * - if the description is empty or "URL", the key "URL" is used + * - otherwise, the key "URL:" is used; + * - if the frame ID is "COMM" (comments frame), + * - if the description is empty or "COMMENT", the key "COMMENT" + * is used + * - otherwise, the key "COMMENT:" is used; + * - if the frame ID is "USLT" (unsynchronized lyrics), + * - if the description is empty or "LYRICS", the key "LYRICS" is used + * - otherwise, the key "LYRICS:" is used; + * - if the frame ID is "TIPL" (involved peoples list), and if all the + * roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(), + * then "=" will be contained in the returned object for each + * - if the frame ID is "TMCL" (musician credit list), then + * "PERFORMER:=" will be contained in the returned + * PropertyMap for each defined musician + * In any other case, the unsupportedData() of the returned object will contain + * the frame's ID and, in case of a frame ID which is allowed to appear more than + * once, the description, separated by a "/". + * + */ + PropertyMap properties() const; + + /*! + * Removes unsupported frames given by \a properties. The elements of + * \a properties must be taken from properties().unsupportedData(); they + * are of one of the following forms: + * - a four-character frame ID, if the ID3 specification allows only one + * frame with that ID (thus, the frame is uniquely determined) + * - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX", + * "COMM", or "USLT", + * - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib. + * In that case, *all* unknown frames with the given ID will be removed. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * See the comments in properties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Render the tag back to binary data, suitable to be written to disk. + */ + ByteVector render() const; + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED ByteVector render(int version) const; + + /*! + * Render the tag back to binary data, suitable to be written to disk. + * + * The \a version parameter specifies whether ID3v2.4 (default) or ID3v2.3 + * should be used. + */ + ByteVector render(Version version) const; + + /*! + * Gets the current string handler that decides how the "Latin-1" data + * will be converted to and from binary data. + * + * \see Latin1StringHandler + */ + static Latin1StringHandler const *latin1StringHandler(); + + /*! + * Sets the string handler that decides how the "Latin-1" data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see Latin1StringHandler + */ + static void setLatin1StringHandler(const Latin1StringHandler *handler); + + protected: + /*! + * Reads data from the file specified in the constructor. It does basic + * parsing of the data in the largest chunks. It partitions the tag into + * the Header, the body of the tag (which contains the ExtendedHeader and + * frames) and Footer. + */ + void read(); + + /*! + * This is called by read to parse the body of the tag. It determines if an + * extended header exists and adds frames to the FrameListMap. + */ + void parse(const ByteVector &data); + + /*! + * Sets the value of the text frame with the Frame ID \a id to \a value. + * If the frame does not exist, it is created. + */ + void setTextFrame(const ByteVector &id, const String &value); + + /*! + * Downgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3. + */ + void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const; + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/infotag.h b/external/taglib/include/infotag.h new file mode 100644 index 0000000..d1f0297 --- /dev/null +++ b/external/taglib/include/infotag.h @@ -0,0 +1,192 @@ +/*************************************************************************** + copyright : (C) 2012 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_INFOTAG_H +#define TAGLIB_INFOTAG_H + +#include "tag.h" +#include "tmap.h" +#include "tstring.h" +#include "tstringlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class File; + + //! A RIFF INFO tag implementation. + namespace RIFF { + namespace Info { + + typedef Map FieldListMap; + + //! A abstraction for the string to data encoding in Info tags. + + /*! + * RIFF INFO tag has no clear definitions about character encodings. + * In practice, local encoding of each system is largely used and UTF-8 is + * popular too. + * + * Here is an option to read and write tags in your preferred encoding + * by subclassing this class, reimplementing parse() and render() and setting + * your reimplementation as the default with Info::Tag::setStringHandler(). + * + * \see ID3v1::Tag::setStringHandler() + */ + + class TAGLIB_EXPORT StringHandler + { + public: + StringHandler(); + ~StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an UTF-8 character array. + */ + virtual String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation + * assumes that \a s is an UTF-8 string. + */ + virtual ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v2 implementation + + /*! + * This is the main class in the INFO tag implementation. RIFF INFO tag is a + * metadata format found in WAV audio and AVI video files. Though it is a part + * of Microsoft/IBM's RIFF specification, the author could not find the official + * documents about it. So, this implementation is referring to unofficial documents + * online and some applications' behaviors especially Windows Explorer. + */ + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty INFO tag. + */ + Tag(); + + /*! + * Constructs an INFO tag read from \a data which is contents of "LIST" chunk. + */ + Tag(const ByteVector &data); + + virtual ~Tag(); + + // Reimplementations + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns a copy of the internal fields of the tag. The returned map directly + * reflects the contents of the "INFO" chunk. + * + * \note Modifying this map does not affect the tag's internal data. + * Use setFieldText() and removeField() instead. + * + * \see setFieldText() + * \see removeField() + */ + FieldListMap fieldListMap() const; + + /* + * Gets the value of the field with the ID \a id. + */ + String fieldText(const ByteVector &id) const; + + /* + * Sets the value of the field with the ID \a id to \a s. + * If the field does not exist, it is created. + * If \s is empty, the field is removed. + * + * \note fieldId must be four-byte long pure ASCII string. This function + * performs nothing if fieldId is invalid. + */ + void setFieldText(const ByteVector &id, const String &s); + + /* + * Removes the field with the ID \a id. + */ + void removeField(const ByteVector &id); + + /*! + * Render the tag back to binary data, suitable to be written to disk. + * + * \note Returns empty ByteVector is the tag contains no fields. + */ + ByteVector render() const; + + /*! + * Sets the string handler that decides how the text data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default UTF-8 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see StringHandler + */ + static void setStringHandler(const StringHandler *handler); + + protected: + /*! + * Pareses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + }} +} + +#endif diff --git a/external/taglib/include/itfile.h b/external/taglib/include/itfile.h new file mode 100644 index 0000000..19327dc --- /dev/null +++ b/external/taglib/include/itfile.h @@ -0,0 +1,109 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_ITFILE_H +#define TAGLIB_ITFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "itproperties.h" + +namespace TagLib { + + namespace IT { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs a Impulse Tracker file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a Impulse Tracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Forwards to Mod::Tag::properties(). + * BIC: will be removed once File::toDict() is made virtual + */ + PropertyMap properties() const; + + /*! + * Forwards to Mod::Tag::setProperties(). + * BIC: will be removed once File::setProperties() is made virtual + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the IT::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + IT::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Impulse Tracker tags is not supported. + */ + bool save(); + + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/itproperties.h b/external/taglib/include/itproperties.h new file mode 100644 index 0000000..be1c9d2 --- /dev/null +++ b/external/taglib/include/itproperties.h @@ -0,0 +1,107 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ITPROPERTIES_H +#define TAGLIB_ITPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + namespace IT { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + Stereo = 1, + Vol0MixOptimizations = 2, + UseInstruments = 4, + LinearSlides = 8, + OldEffects = 16, + LinkEffects = 32, + UseMidiPitchController = 64, + RequestEmbeddedMidiConf = 128 + }; + + /*! Special bits. */ + enum { + MessageAttached = 1, + MidiConfEmbedded = 8 + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + bool stereo() const; + unsigned short instrumentCount() const; + unsigned short sampleCount() const; + unsigned short patternCount() const; + unsigned short version() const; + unsigned short compatibleVersion() const; + unsigned short flags() const; + unsigned short special() const; + unsigned char globalVolume() const; + unsigned char mixVolume() const; + unsigned char tempo() const; + unsigned char bpmSpeed() const; + unsigned char panningSeparation() const; + unsigned char pitchWheelDepth() const; + + void setChannels(int channels); + void setLengthInPatterns(unsigned short lengthInPatterns); + void setInstrumentCount(unsigned short instrumentCount); + void setSampleCount (unsigned short sampleCount); + void setPatternCount(unsigned short patternCount); + void setVersion (unsigned short version); + void setCompatibleVersion(unsigned short compatibleVersion); + void setFlags (unsigned short flags); + void setSpecial (unsigned short special); + void setGlobalVolume(unsigned char globalVolume); + void setMixVolume (unsigned char mixVolume); + void setTempo (unsigned char tempo); + void setBpmSpeed (unsigned char bpmSpeed); + void setPanningSeparation(unsigned char panningSeparation); + void setPitchWheelDepth (unsigned char pitchWheelDepth); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/modfile.h b/external/taglib/include/modfile.h new file mode 100644 index 0000000..b66452d --- /dev/null +++ b/external/taglib/include/modfile.h @@ -0,0 +1,114 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILE_H +#define TAGLIB_MODFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "modproperties.h" + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT File : public TagLib::Mod::FileBase + { + public: + /*! + * Constructs a Protracker file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a Protracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + /*! + * Returns the Mod::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + Mod::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Protracker tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/modfilebase.h b/external/taglib/include/modfilebase.h new file mode 100644 index 0000000..bae9716 --- /dev/null +++ b/external/taglib/include/modfilebase.h @@ -0,0 +1,66 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILEBASE_H +#define TAGLIB_MODFILEBASE_H + +#include "taglib.h" +#include "tfile.h" +#include "tstring.h" +#include "tlist.h" +#include "taglib_export.h" + +#include + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT FileBase : public TagLib::File + { + protected: + FileBase(FileName file); + FileBase(IOStream *stream); + + void writeString(const String &s, unsigned long size, char padding = 0); + void writeByte(unsigned char byte); + void writeU16L(unsigned short number); + void writeU32L(unsigned long number); + void writeU16B(unsigned short number); + void writeU32B(unsigned long number); + + bool readString(String &s, unsigned long size); + bool readByte(unsigned char &byte); + bool readU16L(unsigned short &number); + bool readU32L(unsigned long &number); + bool readU16B(unsigned short &number); + bool readU32B(unsigned long &number); + }; + + } + +} + +#endif diff --git a/external/taglib/include/modfileprivate.h b/external/taglib/include/modfileprivate.h new file mode 100644 index 0000000..781db74 --- /dev/null +++ b/external/taglib/include/modfileprivate.h @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILEPRIVATE_H +#define TAGLIB_MODFILEPRIVATE_H + +// some helper-macros only used internally by (s3m|it|xm)file.cpp +#define READ_ASSERT(cond) \ + if(!(cond)) \ + { \ + setValid(false); \ + return; \ + } + +#define READ(setter,type,read) \ + { \ + type number; \ + READ_ASSERT(read(number)); \ + setter(number); \ + } + +#define READ_BYTE(setter) READ(setter,unsigned char,readByte) +#define READ_U16L(setter) READ(setter,unsigned short,readU16L) +#define READ_U32L(setter) READ(setter,unsigned long,readU32L) +#define READ_U16B(setter) READ(setter,unsigned short,readU16B) +#define READ_U32B(setter) READ(setter,unsigned long,readU32B) + +#define READ_STRING(setter,size) \ + { \ + String s; \ + READ_ASSERT(readString(s, size)); \ + setter(s); \ + } + +#define READ_AS(type,name,read) \ + type name = 0; \ + READ_ASSERT(read(name)); + +#define READ_BYTE_AS(name) READ_AS(unsigned char,name,readByte) +#define READ_U16L_AS(name) READ_AS(unsigned short,name,readU16L) +#define READ_U32L_AS(name) READ_AS(unsigned long,name,readU32L) +#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B) +#define READ_U32B_AS(name) READ_AS(unsigned long,name,readU32B) + +#define READ_STRING_AS(name,size) \ + String name; \ + READ_ASSERT(readString(name, size)); + +#endif diff --git a/external/taglib/include/modproperties.h b/external/taglib/include/modproperties.h new file mode 100644 index 0000000..4712294 --- /dev/null +++ b/external/taglib/include/modproperties.h @@ -0,0 +1,71 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODPROPERTIES_H +#define TAGLIB_MODPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned int instrumentCount() const; + unsigned char lengthInPatterns() const; + + void setChannels(int channels); + + void setInstrumentCount(unsigned int sampleCount); + void setLengthInPatterns(unsigned char lengthInPatterns); + + private: + friend class File; + + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/modtag.h b/external/taglib/include/modtag.h new file mode 100644 index 0000000..dee0661 --- /dev/null +++ b/external/taglib/include/modtag.h @@ -0,0 +1,194 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODTAG_H +#define TAGLIB_MODTAG_H + +#include "tag.h" + +namespace TagLib { + + namespace Mod { + + /*! + * Tags for module files (Mod, S3M, IT, XM). + * + * Note that only the \a title is supported as such by most + * module file formats. Except for XM files the \a trackerName + * is derived from the file format or the flavour of the file + * format. For XM files it is stored in the file. + * + * The \a comment tag is not strictly supported by module files, + * but it is common practice to abuse instrument/sample/pattern + * names as multiline comments. TagLib does so as well. + */ + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + Tag(); + virtual ~Tag(); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String artist() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String album() const; + + /*! + * Returns the track comment derived from the instrument/sample/pattern + * names; if no comment is present in the tag String::null will be + * returned. + */ + virtual String comment() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String genre() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual unsigned int year() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual unsigned int track() const; + + /*! + * Returns the name of the tracker used to create/edit the module file. + * Only XM files store this tag to the file as such, for other formats + * (Mod, S3M, IT) this is derived from the file type or the flavour of + * the file type. Therefore only XM files might have an empty + * (String::null) tracker name. + */ + String trackerName() const; + + /*! + * Sets the title to \a title. If \a title is String::null then this + * value will be cleared. + * + * The length limits per file type are (1 character = 1 byte): + * Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20 + * characters. + */ + virtual void setTitle(const String &title); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setArtist(const String &artist); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setAlbum(const String &album); + + /*! + * Sets the comment to \a comment. If \a comment is String::null then + * this value will be cleared. + * + * Note that module file formats don't actually support a comment tag. + * Instead the names of instruments/patterns/samples are abused as + * a multiline comment. Because of this the number of lines in a + * module file is fixed to the number of instruments/patterns/samples. + * + * Also note that the instrument/pattern/sample name length is limited + * an thus the line length in comments are limited. Too big comments + * will be truncated. + * + * The line length limits per file type are (1 character = 1 byte): + * Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22 + * characters. + */ + virtual void setComment(const String &comment); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setGenre(const String &genre); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setYear(unsigned int year); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setTrack(unsigned int track); + + /*! + * Sets the tracker name to \a trackerName. If \a trackerName is + * String::null then this value will be cleared. + * + * Note that only XM files support this tag. Setting the + * tracker name for other module file formats will be ignored. + * + * The length of this tag is limited to 20 characters (1 character + * = 1 byte). + */ + void setTrackerName(const String &trackerName); + + /*! + * Implements the unified property interface -- export function. + * Since the module tag is very limited, the exported map is as well. + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Because of the limitations of the module file tag, any tags besides + * COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be + * returned. Additionally, if the map contains tags with multiple values, + * all but the first will be contained in the returned map of unsupported + * properties. + */ + PropertyMap setProperties(const PropertyMap &); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/mp4atom.h b/external/taglib/include/mp4atom.h new file mode 100644 index 0000000..5e234cc --- /dev/null +++ b/external/taglib/include/mp4atom.h @@ -0,0 +1,111 @@ +/************************************************************************** + copyright : (C) 2007,2011 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +// This file is not part of the public API! + +#ifndef DO_NOT_DOCUMENT + +#ifndef TAGLIB_MP4ATOM_H +#define TAGLIB_MP4ATOM_H + +#include "tfile.h" +#include "tlist.h" + +namespace TagLib { + + namespace MP4 { + + class Atom; + typedef TagLib::List AtomList; + + enum AtomDataType + { + TypeImplicit = 0, // for use with tags for which no type needs to be indicated because only one type is allowed + TypeUTF8 = 1, // without any count or null terminator + TypeUTF16 = 2, // also known as UTF-16BE + TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters + TypeHTML = 6, // the HTML file header specifies which HTML version + TypeXML = 7, // the XML header must identify the DTD or schemas + TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID) + TypeISRC = 9, // stored as UTF-8 text (valid as an ID) + TypeMI3P = 10, // stored as UTF-8 text (valid as an ID) + TypeGIF = 12, // (deprecated) a GIF image + TypeJPEG = 13, // a JPEG image + TypePNG = 14, // a PNG image + TypeURL = 15, // absolute, in UTF-8 characters + TypeDuration = 16, // in milliseconds, 32-bit integer + TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits + TypeGenred = 18, // a list of enumerated values + TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes + TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer + TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID) + TypeBMP = 27, // Windows bitmap image + TypeUndefined = 255 // undefined + }; + + struct AtomData { + AtomData(AtomDataType type, ByteVector data) : type(type), locale(0), data(data) {} + AtomDataType type; + int locale; + ByteVector data; + }; + + typedef TagLib::List AtomDataList; + + class TAGLIB_EXPORT Atom + { + public: + Atom(File *file); + ~Atom(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0); + AtomList findall(const char *name, bool recursive = false); + long offset; + long length; + TagLib::ByteVector name; + AtomList children; + private: + static const int numContainers = 11; + static const char *const containers[11]; + }; + + //! Root-level atoms + class TAGLIB_EXPORT Atoms + { + public: + Atoms(File *file); + ~Atoms(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList atoms; + }; + + } + +} + +#endif + +#endif diff --git a/external/taglib/include/mp4coverart.h b/external/taglib/include/mp4coverart.h new file mode 100644 index 0000000..ebfb3f9 --- /dev/null +++ b/external/taglib/include/mp4coverart.h @@ -0,0 +1,84 @@ +/************************************************************************** + copyright : (C) 2009 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4COVERART_H +#define TAGLIB_MP4COVERART_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "mp4atom.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT CoverArt + { + public: + /*! + * This describes the image type. + */ + enum Format { + JPEG = TypeJPEG, + PNG = TypePNG, + BMP = TypeBMP, + GIF = TypeGIF, + Unknown = TypeImplicit, + }; + + CoverArt(Format format, const ByteVector &data); + ~CoverArt(); + + CoverArt(const CoverArt &item); + + /*! + * Copies the contents of \a item into this CoverArt. + */ + CoverArt &operator=(const CoverArt &item); + + /*! + * Exchanges the content of the CoverArt by the content of \a item. + */ + void swap(CoverArt &item); + + //! Format of the image + Format format() const; + + //! The image data + ByteVector data() const; + + private: + class CoverArtPrivate; + CoverArtPrivate *d; + }; + + typedef List CoverArtList; + + } + +} + +#endif diff --git a/external/taglib/include/mp4file.h b/external/taglib/include/mp4file.h new file mode 100644 index 0000000..a8bb488 --- /dev/null +++ b/external/taglib/include/mp4file.h @@ -0,0 +1,165 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILE_H +#define TAGLIB_MP4FILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "mp4properties.h" +#include "mp4tag.h" + +namespace TagLib { + + //! An implementation of MP4 (AAC, ALAC, ...) metadata + namespace MP4 { + + class Atoms; + + /*! + * This implements and provides an interface for MP4 files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MP4 files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for strip() and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches MP4 tags. + MP4 = 0x0001, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MP4 file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle audioPropertiesStyle = Properties::Average); + + /*! + * Constructs an MP4 file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle audioPropertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the MP4 tag of the file. + * + * MP4::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the MP4::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MP4 audio properties for this file. + */ + Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + bool save(); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * \note This will update the file immediately. + */ + bool strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an MP4 tag, or the + * file has a Metadata Item List (ilst) atom. + */ + bool hasMP4Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an ASF + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/mp4item.h b/external/taglib/include/mp4item.h new file mode 100644 index 0000000..3821135 --- /dev/null +++ b/external/taglib/include/mp4item.h @@ -0,0 +1,93 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4ITEM_H +#define TAGLIB_MP4ITEM_H + +#include "tstringlist.h" +#include "mp4coverart.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT Item + { + public: + struct IntPair { + int first, second; + }; + + Item(); + Item(const Item &item); + + /*! + * Copies the contents of \a item into this Item. + */ + Item &operator=(const Item &item); + + /*! + * Exchanges the content of the Item by the content of \a item. + */ + void swap(Item &item); + + ~Item(); + + Item(int value); + Item(unsigned char value); + Item(unsigned int value); + Item(long long value); + Item(bool value); + Item(int first, int second); + Item(const StringList &value); + Item(const ByteVectorList &value); + Item(const CoverArtList &value); + + void setAtomDataType(AtomDataType type); + AtomDataType atomDataType() const; + + int toInt() const; + unsigned char toByte() const; + unsigned int toUInt() const; + long long toLongLong() const; + bool toBool() const; + IntPair toIntPair() const; + StringList toStringList() const; + ByteVectorList toByteVectorList() const; + CoverArtList toCoverArtList() const; + + bool isValid() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/mp4properties.h b/external/taglib/include/mp4properties.h new file mode 100644 index 0000000..492a48c --- /dev/null +++ b/external/taglib/include/mp4properties.h @@ -0,0 +1,120 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4PROPERTIES_H +#define TAGLIB_MP4PROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MP4 { + + class Atoms; + class File; + + //! An implementation of MP4 audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + enum Codec { + Unknown = 0, + AAC, + ALAC + }; + + Properties(File *file, Atoms *atoms, ReadStyle style = Average); + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + virtual int bitsPerSample() const; + + /*! + * Returns whether or not the file is encrypted. + */ + bool isEncrypted() const; + + /*! + * Returns the codec used in the file. + */ + Codec codec() const; + + private: + void read(File *file, Atoms *atoms); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/mp4tag.h b/external/taglib/include/mp4tag.h new file mode 100644 index 0000000..2f55114 --- /dev/null +++ b/external/taglib/include/mp4tag.h @@ -0,0 +1,169 @@ +/************************************************************************** + copyright : (C) 2007,2011 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4TAG_H +#define TAGLIB_MP4TAG_H + +#include "tag.h" +#include "tbytevectorlist.h" +#include "tfile.h" +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" +#include "mp4atom.h" +#include "mp4item.h" + +namespace TagLib { + + namespace MP4 { + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED typedef TagLib::Map ItemListMap; + typedef TagLib::Map ItemMap; + + class TAGLIB_EXPORT Tag: public TagLib::Tag + { + public: + Tag(); + Tag(TagLib::File *file, Atoms *atoms); + virtual ~Tag(); + bool save(); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &value); + virtual void setArtist(const String &value); + virtual void setAlbum(const String &value); + virtual void setComment(const String &value); + virtual void setGenre(const String &value); + virtual void setYear(unsigned int value); + virtual void setTrack(unsigned int value); + + virtual bool isEmpty() const; + + /*! + * \deprecated Use the item() and setItem() API instead + */ + TAGLIB_DEPRECATED ItemMap &itemListMap(); + + /*! + * Returns a string-keyed map of the MP4::Items for this tag. + */ + const ItemMap &itemMap() const; + + /*! + * \return The item, if any, corresponding to \a key. + */ + Item item(const String &key) const; + + /*! + * Sets the value of \a key to \a value, overwriting any previous value. + */ + void setItem(const String &key, const Item &value); + + /*! + * Removes the entry with \a key from the tag, or does nothing if it does + * not exist. + */ + void removeItem(const String &key); + + /*! + * \return True if the tag contains an entry for \a key. + */ + bool contains(const String &key) const; + + /*! + * Saves the associated file with the tag stripped. + */ + bool strip(); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList& properties); + PropertyMap setProperties(const PropertyMap &properties); + + protected: + /*! + * Sets the value of \a key to \a value, overwriting any previous value. + * If \a value is empty, the item is removed. + */ + void setTextItem(const String &key, const String &value); + + private: + AtomDataList parseData2(const Atom *atom, int expectedFlags = -1, + bool freeForm = false); + ByteVectorList parseData(const Atom *atom, int expectedFlags = -1, + bool freeForm = false); + void parseText(const Atom *atom, int expectedFlags = 1); + void parseFreeForm(const Atom *atom); + void parseInt(const Atom *atom); + void parseByte(const Atom *atom); + void parseUInt(const Atom *atom); + void parseLongLong(const Atom *atom); + void parseGnre(const Atom *atom); + void parseIntPair(const Atom *atom); + void parseBool(const Atom *atom); + void parseCovr(const Atom *atom); + + ByteVector padIlst(const ByteVector &data, int length = -1) const; + ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const; + ByteVector renderData(const ByteVector &name, int flags, + const ByteVectorList &data) const; + ByteVector renderText(const ByteVector &name, const Item &item, + int flags = TypeUTF8) const; + ByteVector renderFreeForm(const String &name, const Item &item) const; + ByteVector renderBool(const ByteVector &name, const Item &item) const; + ByteVector renderInt(const ByteVector &name, const Item &item) const; + ByteVector renderByte(const ByteVector &name, const Item &item) const; + ByteVector renderUInt(const ByteVector &name, const Item &item) const; + ByteVector renderLongLong(const ByteVector &name, const Item &item) const; + ByteVector renderIntPair(const ByteVector &name, const Item &item) const; + ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const; + ByteVector renderCovr(const ByteVector &name, const Item &item) const; + + void updateParents(const AtomList &path, long delta, int ignore = 0); + void updateOffsets(long delta, long offset); + + void saveNew(ByteVector data); + void saveExisting(ByteVector data, const AtomList &path); + + void addItem(const String &name, const Item &value); + + class TagPrivate; + TagPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/include/mpcfile.h b/external/taglib/include/mpcfile.h new file mode 100644 index 0000000..eb3ec54 --- /dev/null +++ b/external/taglib/include/mpcfile.h @@ -0,0 +1,238 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCFILE_H +#define TAGLIB_MPCFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tag.h" + +#include "mpcproperties.h" + +#include "tlist.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of MPC metadata + + /*! + * This is implementation of MPC metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped + * and ignored. + */ + + namespace MPC { + + //! An implementation of TagLib::File with MPC specific methods + + /*! + * This implements and provides an interface for MPC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MPC files. + * The only invalid tag combination supported is an ID3v1 tag after an APE tag. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MPC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPC file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only the APE + * tag will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Affects only the APEv2 tag which will be created if necessary. + * If an ID3v1 tag exists, it will be updated as well. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. If + * there already be an ID3v1 tag, the new APE tag will be placed before it. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags + * as their memory will be freed. + * + * \note In order to make the removal permanent save() still needs to be called. + */ + void strip(int tags = AllTags); + + /*! + * \deprecated + * \see strip + */ + TAGLIB_DEPRECATED void remove(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an MPC + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/mpcproperties.h b/external/taglib/include/mpcproperties.h new file mode 100644 index 0000000..9a902dc --- /dev/null +++ b/external/taglib/include/mpcproperties.h @@ -0,0 +1,158 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCPROPERTIES_H +#define TAGLIB_MPCPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MPC { + + class File; + + static const unsigned int HeaderSize = 8 * 7; + + //! An implementation of audio property reading for MPC + + /*! + * This reads the data from an MPC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPC::Properties with the data read from the + * ByteVector \a data. + * + * This constructor is deprecated. It only works for MPC version up to 7. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of MPC::Properties with the data read directly + * from a MPC::File. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this MPC::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the version of the bitstream (SV4-SV8) + */ + int mpcVersion() const; + + unsigned int totalFrames() const; + unsigned int sampleFrames() const; + + /*! + * Returns the track gain as an integer value, + * to convert to dB: trackGain in dB = 64.82 - (trackGain / 256) + */ + int trackGain() const; + + /*! + * Returns the track peak as an integer value, + * to convert to dB: trackPeak in dB = trackPeak / 256 + * to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768 + */ + int trackPeak() const; + + /*! + * Returns the album gain as an integer value, + * to convert to dB: albumGain in dB = 64.82 - (albumGain / 256) + */ + int albumGain() const; + + /*! + * Returns the album peak as an integer value, + * to convert to dB: albumPeak in dB = albumPeak / 256 + * to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768 + */ + int albumPeak() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void readSV7(const ByteVector &data, long streamLength); + void readSV8(File *file, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/mpegfile.h b/external/taglib/include/mpegfile.h new file mode 100644 index 0000000..3fcb727 --- /dev/null +++ b/external/taglib/include/mpegfile.h @@ -0,0 +1,387 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGFILE_H +#define TAGLIB_MPEGFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tag.h" + +#include "mpegproperties.h" + +#include "id3v2.h" + +namespace TagLib { + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of TagLib::File with MPEG (MP3) specific methods + + namespace MPEG { + + //! An MPEG file class with some useful methods specific to MPEG + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to MPEG files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MPEG file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPEG file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPEG file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to a tag that is the union of the ID3v2 and ID3v1 + * tags. The ID3v2 tag is given priority in reading the information -- if + * requested information exists in both the ID3v2 tag and the ID3v1 tag, + * the information from the ID3v2 tag will be returned. + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use the tag-type specific calls. + * + * \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag, + * but a union of the two this pointer may not be cast to the specific + * tag types. + * + * \see ID3v1Tag() + * \see ID3v2Tag() + * \see APETag() + */ + virtual Tag *tag() const; + + /*! + * Implements the reading part of the unified property interface. + * If the file contains more than one tag, only the + * first one (in the order ID3v2, APE, ID3v1) will be converted to the + * PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the writing part of the unified tag dictionary interface. + * In order to avoid problems with deprecated tag formats, this method + * always creates an ID3v2 tag if necessary. + * If an ID3v1 tag exists, it will be updated as well, within the + * limitations of that format. + * The returned PropertyMap refers to the ID3v2 tag only. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MPEG::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this + * will duplicate its content into the other tag. This returns true + * if saving was successful. + * + * If neither exists or if both tags are empty, this will strip the tags + * from the file. + * + * This is the same as calling save(AllTags); + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use parameterized save call below. + * + * \see save(int tags) + */ + virtual bool save(); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. The save() method above + * uses AllTags. This returns true if saving was successful. + * + * This strips all tags not included in the mask, but does not modify them + * in memory, so later calls to save() which make use of these tags will + * remain valid. This also strips empty tags. + */ + bool save(int tags); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. + * + * \a strip can be set to strip all tags except those in \a tags. Those + * tags will not be modified in memory, and thus remain valid. + * + * \a version specifies the ID3v2 version to be used for writing tags. By + * default, the latest standard, ID3v2.4 is used. + * + * If \a duplicate is set to DuplicateTags and at least one tag -- ID3v1 + * or ID3v2 -- exists this will duplicate its content into the other tag. + */ + bool save(int tags, StripTags strip, + ID3v2::Version version = ID3v2::v4, + DuplicateTags duplicate = Duplicate); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * This is equivalent to strip(tags, true) + * + * \note This will also invalidate pointers to the ID3 and APE tags + * as their memory will be freed. + * + * \note This will update the file immediately. + */ + bool strip(int tags = AllTags); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * If \a freeMemory is true the ID3 and APE tags will be deleted and + * pointers to them will be invalidated. + * + * \note This will update the file immediately. + */ + // BIC: merge with the method above + bool strip(int tags, bool freeMemory); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the position in the file of the first MPEG frame. + */ + long firstFrameOffset(); + + /*! + * Returns the position in the file of the next MPEG frame, + * using the current position as start + */ + long nextFrameOffset(long position); + + /*! + * Returns the position in the file of the previous MPEG frame, + * using the current position as start + */ + long previousFrameOffset(long position); + + /*! + * Returns the position in the file of the last MPEG frame. + */ + long lastFrameOffset(); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an MPEG + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/mpegheader.h b/external/taglib/include/mpegheader.h new file mode 100644 index 0000000..ca51184 --- /dev/null +++ b/external/taglib/include/mpegheader.h @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGHEADER_H +#define TAGLIB_MPEGHEADER_H + +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + class File; + + namespace MPEG { + + //! An implementation of MP3 frame headers + + /*! + * This is an implementation of MPEG Layer III headers. The API follows more + * or less the binary format of these headers. I've used + * this + * document as a reference. + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Parses an MPEG header based on \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Header(const ByteVector &data); + + /*! + * Parses an MPEG header based on \a file and \a offset. + * + * \note If \a checkLength is true, this requires the next MPEG frame to + * check if the frame length is parsed and calculated correctly. So it's + * suitable for seeking for the first valid frame. + */ + Header(File *file, long offset, bool checkLength = true); + + /*! + * Does a shallow copy of \a h. + */ + Header(const Header &h); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Returns true if the frame is at least an appropriate size and has + * legal values. + */ + bool isValid() const; + + /*! + * The MPEG Version. + */ + enum Version { + //! MPEG Version 1 + Version1 = 0, + //! MPEG Version 2 + Version2 = 1, + //! MPEG Version 2.5 + Version2_5 = 2 + }; + + /*! + * Returns the MPEG Version of the header. + */ + Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the bitrate encoded in the header. + */ + int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + int sampleRate() const; + + /*! + * Returns true if the frame is padded. + */ + bool isPadded() const; + + /*! + * There are a few combinations or one or two channel audio that are + * possible: + */ + enum ChannelMode { + //! Stereo + Stereo = 0, + //! Stereo + JointStereo = 1, + //! Dual Mono + DualChannel = 2, + //! Mono + SingleChannel = 3 + }; + + /*! + * Returns the channel mode for this frame. + */ + ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + /*! + * Returns the frame length in bytes. + */ + int frameLength() const; + + /*! + * Returns the number of frames per sample. + */ + int samplesPerFrame() const; + + /*! + * Makes a shallow copy of the header. + */ + Header &operator=(const Header &h); + + private: + void parse(File *file, long offset, bool checkLength); + + class HeaderPrivate; + HeaderPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/mpegproperties.h b/external/taglib/include/mpegproperties.h new file mode 100644 index 0000000..a1a1af4 --- /dev/null +++ b/external/taglib/include/mpegproperties.h @@ -0,0 +1,152 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGPROPERTIES_H +#define TAGLIB_MPEGPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +#include "mpegheader.h" + +namespace TagLib { + + namespace MPEG { + + class File; + class XingHeader; + + //! An implementation of audio property reading for MP3 + + /*! + * This reads the data from an MPEG Layer III stream found in the + * AudioProperties API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPEG::Properties with the data read from the + * MPEG::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this MPEG Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns a pointer to the Xing/VBRI header if one exists or null if no + * Xing/VBRI header was found. + */ + const XingHeader *xingHeader() const; + + /*! + * Returns the MPEG Version of the file. + */ + Header::Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the channel mode for this frame. + */ + Header::ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/mpegutils.h b/external/taglib/include/mpegutils.h new file mode 100644 index 0000000..31b45a4 --- /dev/null +++ b/external/taglib/include/mpegutils.h @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGUTILS_H +#define TAGLIB_MPEGUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace MPEG + { + namespace + { + + /*! + * MPEG frames can be recognized by the bit pattern 11111111 111, so the + * first byte is easy to check for, however checking to see if the second byte + * starts with \e 111 is a bit more tricky, hence these functions. + * + * \note This does not check the length of the vector, since this is an + * internal utility function. + */ + inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0) + { + // 0xFF in the second byte is possible in theory, but it's very unlikely. + + const unsigned char b1 = bytes[offset + 0]; + const unsigned char b2 = bytes[offset + 1]; + return (b1 == 0xFF && b2 != 0xFF && (b2 & 0xE0) == 0xE0); + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/include/oggfile.h b/external/taglib/include/oggfile.h new file mode 100644 index 0000000..7d889c2 --- /dev/null +++ b/external/taglib/include/oggfile.h @@ -0,0 +1,127 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "taglib_export.h" +#include "tfile.h" +#include "tbytevectorlist.h" + +#ifndef TAGLIB_OGGFILE_H +#define TAGLIB_OGGFILE_H + +namespace TagLib { + + //! A namespace for the classes used by Ogg-based metadata files + + namespace Ogg { + + class PageHeader; + + //! An implementation of TagLib::File with some helpers for Ogg based formats + + /*! + * This is an implementation of Ogg file page and packet rendering and is of + * use to Ogg based formats. While the API is small this handles the + * non-trivial details of breaking up an Ogg stream into packets and makes + * these available (via subclassing) to the codec meta data implementations. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + virtual ~File(); + + /*! + * Returns the packet contents for the i-th packet (starting from zero) + * in the Ogg bitstream. + * + * \warning This requires reading at least the packet header for every page + * up to the requested page. + */ + ByteVector packet(unsigned int i); + + /*! + * Sets the packet with index \a i to the value \a p. + */ + void setPacket(unsigned int i, const ByteVector &p); + + /*! + * Returns a pointer to the PageHeader for the first page in the stream or + * null if the page could not be found. + */ + const PageHeader *firstPageHeader(); + + /*! + * Returns a pointer to the PageHeader for the last page in the stream or + * null if the page could not be found. + */ + const PageHeader *lastPageHeader(); + + virtual bool save(); + + protected: + /*! + * Constructs an Ogg file from \a file. + * + * \note This constructor is protected since Ogg::File shouldn't be + * instantiated directly but rather should be used through the codec + * specific subclasses. + */ + File(FileName file); + + /*! + * Constructs an Ogg file from \a stream. + * + * \note This constructor is protected since Ogg::File shouldn't be + * instantiated directly but rather should be used through the codec + * specific subclasses. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + /*! + * Reads the pages from the beginning of the file until enough to compose + * the requested packet. + */ + bool readPages(unsigned int i); + + /*! + * Writes the requested packet to the file. + */ + void writePacket(unsigned int i, const ByteVector &packet); + + class FilePrivate; + FilePrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/oggflacfile.h b/external/taglib/include/oggflacfile.h new file mode 100644 index 0000000..b2686e4 --- /dev/null +++ b/external/taglib/include/oggflacfile.h @@ -0,0 +1,170 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGFLACFILE_H +#define TAGLIB_OGGFLACFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + + namespace Ogg { + + //! An implementation of Ogg FLAC metadata + + /*! + * This is implementation of FLAC metadata for Ogg FLAC files. For "pure" + * FLAC files look under the FLAC hierarchy. + * + * Unlike "pure" FLAC-files, Ogg FLAC only supports Xiph-comments, + * while the audio-properties are the same. + */ + namespace FLAC { + + using TagLib::FLAC::Properties; + + //! An implementation of TagLib::File with Ogg/FLAC specific methods + + /*! + * This implements and provides an interface for Ogg/FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to Ogg FLAC files. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs an Ogg/FLAC file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will always be a XiphComment. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has a XiphComment. Use hasXiphComment() to check if + * the file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasXiphComment() + */ + virtual XiphComment *tag() const; + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + + /*! + * Save the file. This will primarily save and update the XiphComment. + * Returns true if the save is successful. + */ + virtual bool save(); + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + */ + long streamLength(); + + /*! + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see tag() + */ + bool hasXiphComment() const; + + /*! + * Check if the given \a stream can be opened as an Ogg FLAC file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + ByteVector streamInfoData(); + ByteVector xiphCommentData(); + + class FilePrivate; + FilePrivate *d; + }; + } // namespace FLAC + } // namespace Ogg +} // namespace TagLib + +#endif diff --git a/external/taglib/include/oggpage.h b/external/taglib/include/oggpage.h new file mode 100644 index 0000000..af3fe2c --- /dev/null +++ b/external/taglib/include/oggpage.h @@ -0,0 +1,228 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGE_H +#define TAGLIB_OGGPAGE_H + +#include "taglib_export.h" +#include "tbytevectorlist.h" + +namespace TagLib { + + namespace Ogg { + + class File; + class PageHeader; + + //! An implementation of Ogg pages + + /*! + * This is an implementation of the pages that make up an Ogg stream. + * This handles parsing pages and breaking them down into packets and handles + * the details of packets spanning multiple pages and pages that contain + * multiple packets. + * + * In most Xiph.org formats the comments are found in the first few packets, + * this however is a reasonably complete implementation of Ogg pages that + * could potentially be useful for non-meta data purposes. + */ + + class TAGLIB_EXPORT Page + { + public: + /*! + * Read an Ogg page from the \a file at the position \a pageOffset. + */ + Page(File *file, long pageOffset); + + virtual ~Page(); + + /*! + * Returns the page's position within the file (in bytes). + */ + long fileOffset() const; + + /*! + * Returns a pointer to the header for this page. This pointer will become + * invalid when the page is deleted. + */ + const PageHeader *header() const; + + /*! + * Returns the index of the page within the Ogg stream. This helps make it + * possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ + int pageSequenceNumber() const; + + /*! + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ + void setPageSequenceNumber(int sequenceNumber); + + /*! + * Returns a copy of the page with \a sequenceNumber set as sequence number. + * + * \see header() + * \see PageHeader::setPageSequenceNumber() + * + * \deprecated Always returns null. + */ + TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the index of the first packet wholly or partially contained in + * this page. + * + * \see setFirstPacketIndex() + */ + int firstPacketIndex() const; + + /*! + * Sets the index of the first packet in the page. + * + * \see firstPacketIndex() + */ + void setFirstPacketIndex(int index); + + /*! + * When checking to see if a page contains a given packet this set of flags + * represents the possible values for that packets status in the page. + * + * \see containsPacket() + */ + enum ContainsPacketFlags { + //! No part of the packet is contained in the page + DoesNotContainPacket = 0x0000, + //! The packet is wholly contained in the page + CompletePacket = 0x0001, + //! The page starts with the given packet + BeginsWithPacket = 0x0002, + //! The page ends with the given packet + EndsWithPacket = 0x0004 + }; + + /*! + * Checks to see if the specified \a packet is contained in the current + * page. + * + * \see ContainsPacketFlags + */ + ContainsPacketFlags containsPacket(int index) const; + + /*! + * Returns the number of packets (whole or partial) in this page. + */ + unsigned int packetCount() const; + + /*! + * Returns a list of the packets in this page. + * + * \note Either or both the first and last packets may be only partial. + * \see PageHeader::firstPacketContinued() + */ + ByteVectorList packets() const; + + /*! + * Returns the size of the page in bytes. + */ + int size() const; + + ByteVector render() const; + + /*! + * Defines a strategy for pagination, or grouping pages into Ogg packets, + * for use with pagination methods. + * + * \note Yes, I'm aware that this is not a canonical "Strategy Pattern", + * the term was simply convenient. + */ + enum PaginationStrategy { + /*! + * Attempt to put the specified set of packets into a single Ogg packet. + * If the sum of the packet data is greater than will fit into a single + * Ogg page -- 65280 bytes -- this will fall back to repagination using + * the recommended page sizes. + */ + SinglePagePerGroup, + /*! + * Split the packet or group of packets into pages that conform to the + * sizes recommended in the Ogg standard. + */ + Repaginate + }; + + /*! + * Pack \a packets into Ogg pages using the \a strategy for pagination. + * The page number indicator inside of the rendered packets will start + * with \a firstPage and be incremented for each page rendered. + * \a containsLastPacket should be set to true if \a packets contains the + * last page in the stream and will set the appropriate flag in the last + * rendered Ogg page's header. \a streamSerialNumber should be set to + * the serial number for this stream. + * + * \note The "absolute granule position" is currently always zeroed using + * this method as this suffices for the comment headers. + * + * \warning The pages returned by this method must be deleted by the user. + * You can use List::setAutoDelete(true) to set these pages to be + * automatically deleted when this list passes out of scope. + * + * \see PaginationStrategy + * \see List::setAutoDelete() + */ + static List paginate(const ByteVectorList &packets, + PaginationStrategy strategy, + unsigned int streamSerialNumber, + int firstPage, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + protected: + /*! + * Creates an Ogg packet based on the data in \a packets. The page number + * for each page will be set to \a pageNumber. + */ + Page(const ByteVectorList &packets, + unsigned int streamSerialNumber, + int pageNumber, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + private: + Page(const Page &); + Page &operator=(const Page &); + + class PagePrivate; + PagePrivate *d; + }; + } +} +#endif diff --git a/external/taglib/include/oggpageheader.h b/external/taglib/include/oggpageheader.h new file mode 100644 index 0000000..571155f --- /dev/null +++ b/external/taglib/include/oggpageheader.h @@ -0,0 +1,232 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGEHEADER_H +#define TAGLIB_OGGPAGEHEADER_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace Ogg { + + class File; + + //! An implementation of the page headers associated with each Ogg::Page + + /*! + * This class implements Ogg page headers which contain the information + * about Ogg pages needed to break them into packets which can be passed on + * to the codecs. + */ + + class TAGLIB_EXPORT PageHeader + { + public: + /*! + * Reads a PageHeader from \a file starting at \a pageOffset. The defaults + * create a page with no (and as such, invalid) data that must be set + * later. + */ + PageHeader(File *file = 0, long pageOffset = -1); + + /*! + * Deletes this instance of the PageHeader. + */ + virtual ~PageHeader(); + + /*! + * Returns true if the header parsed properly and is valid. + */ + bool isValid() const; + + /*! + * Ogg pages contain a list of packets (which are used by the contained + * codecs). The sizes of these pages is encoded in the page header. This + * returns a list of the packet sizes in bytes. + * + * \see setPacketSizes() + */ + List packetSizes() const; + + /*! + * Sets the sizes of the packets in this page to \a sizes. Internally this + * updates the lacing values in the header. + * + * \see packetSizes() + */ + void setPacketSizes(const List &sizes); + + /*! + * Some packets can be continued across multiple pages. If the + * first packet in the current page is a continuation this will return + * true. If this is page starts with a new packet this will return false. + * + * \see lastPacketCompleted() + * \see setFirstPacketContinued() + */ + bool firstPacketContinued() const; + + /*! + * Sets the internal flag indicating if the first packet in this page is + * continued to \a continued. + * + * \see firstPacketContinued() + */ + void setFirstPacketContinued(bool continued); + + /*! + * Returns true if the last packet of this page is completely contained in + * this page. + * + * \see firstPacketContinued() + * \see setLastPacketCompleted() + */ + bool lastPacketCompleted() const; + + /*! + * Sets the internal flag indicating if the last packet in this page is + * complete to \a completed. + * + * \see lastPacketCompleted() + */ + void setLastPacketCompleted(bool completed); + + /*! + * This returns true if this is the first page of the Ogg (logical) stream. + * + * \see setFirstPageOfStream() + */ + bool firstPageOfStream() const; + + /*! + * Marks this page as the first page of the Ogg stream. + * + * \see firstPageOfStream() + */ + void setFirstPageOfStream(bool first); + + /*! + * This returns true if this is the last page of the Ogg (logical) stream. + * + * \see setLastPageOfStream() + */ + bool lastPageOfStream() const; + + /*! + * Marks this page as the last page of the Ogg stream. + * + * \see lastPageOfStream() + */ + void setLastPageOfStream(bool last); + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. In the case of Vorbis this contains the PCM + * value and is used to calculate the length of the stream. + * + * \see setAbsoluteGranularPosition() + */ + long long absoluteGranularPosition() const; + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. It is only supported here so that it may be + * copied from one page to another. + * + * \see absoluteGranularPosition() + */ + void setAbsoluteGranularPosition(long long agp); + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This returns the serial number of + * the stream associated with this packet. + * + * \see setStreamSerialNumber() + */ + unsigned int streamSerialNumber() const; + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This sets this pages serial + * number. This method should be used when adding new pages to a logical + * stream. + * + * \see streamSerialNumber() + */ + void setStreamSerialNumber(unsigned int n); + + /*! + * Returns the index of the page within the Ogg stream. This helps make it + * possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ + int pageSequenceNumber() const; + + /*! + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ + void setPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the complete header size. + */ + int size() const; + + /*! + * Returns the size of the data portion of the page -- i.e. the size of the + * page less the header size. + */ + int dataSize() const; + + /*! + * Render the page header to binary data. + * + * \note The checksum -- bytes 22 - 25 -- will be left empty and must be + * filled in when rendering the entire page. + */ + ByteVector render() const; + + private: + PageHeader(const PageHeader &); + PageHeader &operator=(const PageHeader &); + + void read(Ogg::File *file, long pageOffset); + ByteVector lacingValues() const; + + class PageHeaderPrivate; + PageHeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/include/opusfile.h b/external/taglib/include/opusfile.h new file mode 100644 index 0000000..0e094ea --- /dev/null +++ b/external/taglib/include/opusfile.h @@ -0,0 +1,138 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OPUSFILE_H +#define TAGLIB_OPUSFILE_H + +#include "oggfile.h" +#include "xiphcomment.h" + +#include "opusproperties.h" + +namespace TagLib { + + namespace Ogg { + + //! A namespace containing classes for Opus metadata + + namespace Opus { + + //! An implementation of Ogg::File with Opus specific methods + + /*! + * This is the central class in the Ogg Opus metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Opus specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs an Opus file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an Opus file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Opus::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as an Opus + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/opusproperties.h b/external/taglib/include/opusproperties.h new file mode 100644 index 0000000..2e44dea --- /dev/null +++ b/external/taglib/include/opusproperties.h @@ -0,0 +1,134 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OPUSPROPERTIES_H +#define TAGLIB_OPUSPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace Ogg { + + namespace Opus { + + class File; + + //! An implementation of audio property reading for Ogg Opus + + /*! + * This reads the data from an Ogg Opus stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Opus::Properties with the data read from the + * Opus::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this Opus::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + * + * \note Always returns 48000, because Opus can decode any stream at a + * sample rate of 8, 12, 16, 24, or 48 kHz, + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * The Opus codec supports decoding at multiple sample rates, there is no + * single sample rate of the encoded stream. This returns the sample rate + * of the original audio stream. + */ + int inputSampleRate() const; + + /*! + * Returns the Opus version, in the range 0...255. + */ + int opusVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/ownershipframe.h b/external/taglib/include/ownershipframe.h new file mode 100644 index 0000000..06a1e23 --- /dev/null +++ b/external/taglib/include/ownershipframe.h @@ -0,0 +1,151 @@ +/*************************************************************************** + copyright : (C) 2012 by Rupert Daniel + email : rupert@cancelmonday.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OWNERSHIPFRAME_H +#define TAGLIB_OWNERSHIPFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 "ownership" + + /*! + * This implements the ID3v2 ownership (OWNE frame). It consists of + * a price paid, a date purchased (YYYYMMDD) and the name of the seller. + */ + + class TAGLIB_EXPORT OwnershipFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty ownership frame. + */ + explicit OwnershipFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a ownership based on the data in \a data. + */ + explicit OwnershipFrame(const ByteVector &data); + + /*! + * Destroys this OwnershipFrame instance. + */ + virtual ~OwnershipFrame(); + + /*! + * Returns the text of this popularimeter. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the date purchased. + * + * \see setDatePurchased() + */ + String datePurchased() const; + + /*! + * Set the date purchased. + * + * \see datePurchased() + */ + void setDatePurchased(const String &datePurchased); + + /*! + * Returns the price paid. + * + * \see setPricePaid() + */ + String pricePaid() const; + + /*! + * Set the price paid. + * + * \see pricePaid() + */ + void setPricePaid(const String &pricePaid); + + /*! + * Returns the seller. + * + * \see setSeller() + */ + String seller() const; + + /*! + * Set the seller. + * + * \see seller() + */ + void setSeller(const String &seller); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + OwnershipFrame(const ByteVector &data, Header *h); + OwnershipFrame(const OwnershipFrame &); + OwnershipFrame &operator=(const OwnershipFrame &); + + class OwnershipFramePrivate; + OwnershipFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/podcastframe.h b/external/taglib/include/podcastframe.h new file mode 100644 index 0000000..a71278c --- /dev/null +++ b/external/taglib/include/podcastframe.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2015 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PODCASTFRAME_H +#define TAGLIB_PODCASTFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 podcast frame + /*! + * An implementation of ID3v2 podcast flag, a frame with four zero bytes. + */ + class TAGLIB_EXPORT PodcastFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct a podcast frame. + */ + PodcastFrame(); + + /*! + * Destroys this PodcastFrame instance. + */ + virtual ~PodcastFrame(); + + /*! + * Returns a null string. + */ + virtual String toString() const; + + PropertyMap asProperties() const; + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PodcastFrame(const ByteVector &data, Header *h); + PodcastFrame(const PodcastFrame &); + PodcastFrame &operator=(const PodcastFrame &); + + class PodcastFramePrivate; + PodcastFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/popularimeterframe.h b/external/taglib/include/popularimeterframe.h new file mode 100644 index 0000000..405ca69 --- /dev/null +++ b/external/taglib/include/popularimeterframe.h @@ -0,0 +1,132 @@ +/*************************************************************************** + copyright : (C) 2008 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_POPULARIMETERFRAME_H +#define TAGLIB_POPULARIMETERFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 "popularimeter" + + /*! + * This implements the ID3v2 popularimeter (POPM frame). It consists of + * an email, a rating and an optional counter. + */ + + class TAGLIB_EXPORT PopularimeterFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty popularimeter frame. + */ + explicit PopularimeterFrame(); + + /*! + * Construct a popularimeter based on the data in \a data. + */ + explicit PopularimeterFrame(const ByteVector &data); + + /*! + * Destroys this PopularimeterFrame instance. + */ + virtual ~PopularimeterFrame(); + + /*! + * Returns the text of this popularimeter. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the email. + * + * \see setEmail() + */ + String email() const; + + /*! + * Set the email. + * + * \see email() + */ + void setEmail(const String &email); + + /*! + * Returns the rating. + * + * \see setRating() + */ + int rating() const; + + /*! + * Set the rating. + * + * \see rating() + */ + void setRating(int rating); + + /*! + * Returns the counter. + * + * \see setCounter() + */ + unsigned int counter() const; + + /*! + * Set the counter. + * + * \see counter() + */ + void setCounter(unsigned int counter); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PopularimeterFrame(const ByteVector &data, Header *h); + PopularimeterFrame(const PopularimeterFrame &); + PopularimeterFrame &operator=(const PopularimeterFrame &); + + class PopularimeterFramePrivate; + PopularimeterFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/privateframe.h b/external/taglib/include/privateframe.h new file mode 100644 index 0000000..06f82f3 --- /dev/null +++ b/external/taglib/include/privateframe.h @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2008 by Serkan Kalyoncu + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PRIVATEFRAME_H +#define TAGLIB_PRIVATEFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 privateframe + + class TAGLIB_EXPORT PrivateFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty private frame. + */ + PrivateFrame(); + + /*! + * Construct a private frame based on the data in \a data. + * + * \note This is the constructor used when parsing the frame from a file. + */ + explicit PrivateFrame(const ByteVector &data); + + /*! + * Destroys this private frame instance. + */ + virtual ~PrivateFrame(); + + /*! + * Returns the text of this private frame, currently just the owner. + * + * \see text() + */ + virtual String toString() const; + + /*! + * \return The owner of the private frame. + * \note This should contain an email address or link to a website. + */ + String owner() const; + + /*! + * + */ + ByteVector data() const; + + /*! + * Sets the owner of the frame to \a s. + * \note This should contain an email address or link to a website. + */ + void setOwner(const String &s); + + /*! + * + */ + void setData(const ByteVector &v); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PrivateFrame(const ByteVector &data, Header *h); + + PrivateFrame(const PrivateFrame &); + PrivateFrame &operator=(const PrivateFrame &); + + class PrivateFramePrivate; + PrivateFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/relativevolumeframe.h b/external/taglib/include/relativevolumeframe.h new file mode 100644 index 0000000..55f13fc --- /dev/null +++ b/external/taglib/include/relativevolumeframe.h @@ -0,0 +1,274 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RELATIVEVOLUMEFRAME_H +#define TAGLIB_RELATIVEVOLUMEFRAME_H + +#include "tlist.h" +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 relative volume adjustment frame implementation + + /*! + * This is an implementation of ID3v2 relative volume adjustment. The + * presence of this frame makes it possible to specify an increase in volume + * for an audio file or specific audio tracks in that file. + * + * Multiple relative volume adjustment frames may be present in the tag + * each with a unique identification and describing volume adjustment for + * different channel types. + */ + + class TAGLIB_EXPORT RelativeVolumeFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This indicates the type of volume adjustment that should be applied. + */ + enum ChannelType { + //! A type not enumerated below + Other = 0x00, + //! The master volume for the track + MasterVolume = 0x01, + //! The front right audio channel + FrontRight = 0x02, + //! The front left audio channel + FrontLeft = 0x03, + //! The back right audio channel + BackRight = 0x04, + //! The back left audio channel + BackLeft = 0x05, + //! The front center audio channel + FrontCentre = 0x06, + //! The back center audio channel + BackCentre = 0x07, + //! The subwoofer audio channel + Subwoofer = 0x08 + }; + + //! Struct that stores the relevant values for ID3v2 peak volume + + /*! + * The peak volume is described as a series of bits that is padded to fill + * a block of bytes. These two values should always be updated in tandem. + */ + struct PeakVolume + { + /*! + * Constructs an empty peak volume description. + */ + PeakVolume() : bitsRepresentingPeak(0) {} + /*! + * The number of bits (in the range of 0 to 255) used to describe the + * peak volume. + */ + unsigned char bitsRepresentingPeak; + /*! + * The array of bits (represented as a series of bytes) used to describe + * the peak volume. + */ + ByteVector peakVolume; + }; + + /*! + * Constructs a RelativeVolumeFrame. The relevant data should be set + * manually. + */ + RelativeVolumeFrame(); + + /*! + * Constructs a RelativeVolumeFrame based on the contents of \a data. + */ + RelativeVolumeFrame(const ByteVector &data); + + /*! + * Destroys the RelativeVolumeFrame instance. + */ + virtual ~RelativeVolumeFrame(); + + /*! + * Returns the frame's identification. + * + * \see identification() + */ + virtual String toString() const; + + /*! + * Returns a list of channels with information currently in the frame. + */ + List channels() const; + + /*! + * \deprecated Always returns master volume. + */ + TAGLIB_DEPRECATED ChannelType channelType() const; + + /*! + * \deprecated This method no longer has any effect. + */ + TAGLIB_DEPRECATED void setChannelType(ChannelType t); + + /* + * There was a terrible API goof here, and while this can't be changed to + * the way it appears below for binary compatibility reasons, let's at + * least pretend that it looks clean. + */ + +#ifdef DOXYGEN + + /*! + * Returns the relative volume adjustment "index". As indicated by the + * ID3v2 standard this is a 16-bit signed integer that reflects the + * decibels of adjustment when divided by 512. + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustmentIndex() + * \see volumeAdjustment() + */ + short volumeAdjustmentIndex(ChannelType type = MasterVolume) const; + + /*! + * Set the volume adjustment to \a index. As indicated by the ID3v2 + * standard this is a 16-bit signed integer that reflects the decibels of + * adjustment when divided by 512. + * + * By default this sets the value for the master volume. + * + * \see volumeAdjustmentIndex() + * \see setVolumeAdjustment() + */ + void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume); + + /*! + * Returns the relative volume adjustment in decibels. + * + * \note Because this is actually stored internally as an "index" to this + * value the value returned by this method may not be identical to the + * value set using setVolumeAdjustment(). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + float volumeAdjustment(ChannelType type = MasterVolume) const; + + /*! + * Set the relative volume adjustment in decibels to \a adjustment. + * + * By default this sets the value for the master volume. + * + * \note Because this is actually stored internally as an "index" to this + * value the value set by this method may not be identical to the one + * returned by volumeAdjustment(). + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume); + + /*! + * Returns the peak volume (represented as a length and a string of bits). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setPeakVolume() + */ + PeakVolume peakVolume(ChannelType type = MasterVolume) const; + + /*! + * Sets the peak volume to \a peak. + * + * By default this sets the value for the master volume. + * + * \see peakVolume() + */ + void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume); + +#else + + // BIC: Combine each of the following pairs of functions (or maybe just + // rework this junk altogether). + + short volumeAdjustmentIndex(ChannelType type) const; + short volumeAdjustmentIndex() const; + + void setVolumeAdjustmentIndex(short index, ChannelType type); + void setVolumeAdjustmentIndex(short index); + + float volumeAdjustment(ChannelType type) const; + float volumeAdjustment() const; + + void setVolumeAdjustment(float adjustment, ChannelType type); + void setVolumeAdjustment(float adjustment); + + PeakVolume peakVolume(ChannelType type) const; + PeakVolume peakVolume() const; + + void setPeakVolume(const PeakVolume &peak, ChannelType type); + void setPeakVolume(const PeakVolume &peak); + +#endif + + /*! + * Returns the identification for this frame. + */ + String identification() const; + + /*! + * Sets the identification of the frame to \a s. The string + * is used to identify the situation and/or device where this + * adjustment should apply. + */ + void setIdentification(const String &s); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + RelativeVolumeFrame(const ByteVector &data, Header *h); + RelativeVolumeFrame(const RelativeVolumeFrame &); + RelativeVolumeFrame &operator=(const RelativeVolumeFrame &); + + class RelativeVolumeFramePrivate; + RelativeVolumeFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/rifffile.h b/external/taglib/include/rifffile.h new file mode 100644 index 0000000..5c606b4 --- /dev/null +++ b/external/taglib/include/rifffile.h @@ -0,0 +1,161 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RIFFFILE_H +#define TAGLIB_RIFFFILE_H + +#include "taglib_export.h" +#include "tfile.h" + +namespace TagLib { + + //! An implementation of TagLib::File with RIFF specific methods + + namespace RIFF { + + //! An RIFF file class with some useful methods specific to RIFF + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to RIFF files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + protected: + + enum Endianness { BigEndian, LittleEndian }; + + File(FileName file, Endianness endianness); + File(IOStream *stream, Endianness endianness); + + /*! + * \return The size of the main RIFF chunk. + */ + unsigned int riffSize() const; + + /*! + * \return The number of chunks in the file. + */ + unsigned int chunkCount() const; + + /*! + * \return The offset within the file for the selected chunk number. + */ + unsigned int chunkOffset(unsigned int i) const; + + /*! + * \return The size of the chunk data. + */ + unsigned int chunkDataSize(unsigned int i) const; + + /*! + * \return The size of the padding after the chunk (can be either 0 or 1). + */ + unsigned int chunkPadding(unsigned int i) const; + + /*! + * \return The name of the specified chunk, for instance, "COMM" or "ID3 " + */ + ByteVector chunkName(unsigned int i) const; + + /*! + * Reads the chunk data from the file and returns it. + * + * \note This \e will move the read pointer for the file. + */ + ByteVector chunkData(unsigned int i); + + /*! + * Sets the data for the specified chunk to \a data. + * + * \warning This will update the file immediately. + */ + void setChunkData(unsigned int i, const ByteVector &data); + + /*! + * Sets the data for the chunk \a name to \a data. If a chunk with the + * given name already exists it will be overwritten, otherwise it will be + * created after the existing chunks. + * + * \warning This will update the file immediately. + */ + void setChunkData(const ByteVector &name, const ByteVector &data); + + /*! + * Sets the data for the chunk \a name to \a data. If a chunk with the + * given name already exists it will be overwritten, otherwise it will be + * created after the existing chunks. + * + * \note If \a alwaysCreate is true, a new chunk is created regardless of + * whether or not the chunk \a name exists. It should only be used for + * "LIST" chunks. + * + * \warning This will update the file immediately. + */ + void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate); + + /*! + * Removes the specified chunk. + * + * \warning This will update the file immediately. + */ + void removeChunk(unsigned int i); + + /*! + * Removes the chunk \a name. + * + * \warning This will update the file immediately. + * \warning This removes all the chunks with the given name. + */ + void removeChunk(const ByteVector &name); + + private: + File(const File &); + File &operator=(const File &); + + void read(); + void writeChunk(const ByteVector &name, const ByteVector &data, + unsigned long offset, unsigned long replace = 0); + + /*! + * Update the global RIFF size based on the current internal structure. + */ + void updateGlobalSize(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/riffutils.h b/external/taglib/include/riffutils.h new file mode 100644 index 0000000..ecb985a --- /dev/null +++ b/external/taglib/include/riffutils.h @@ -0,0 +1,60 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RIFFUTILS_H +#define TAGLIB_RIFFUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace RIFF + { + namespace + { + + inline bool isValidChunkName(const ByteVector &name) + { + if(name.size() != 4) + return false; + + for(ByteVector::ConstIterator it = name.begin(); it != name.end(); ++it) { + const int c = static_cast(*it); + if(c < 32 || 127 < c) + return false; + } + + return true; + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/include/s3mfile.h b/external/taglib/include/s3mfile.h new file mode 100644 index 0000000..4011bd1 --- /dev/null +++ b/external/taglib/include/s3mfile.h @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_S3MFILE_H +#define TAGLIB_S3MFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "s3mproperties.h" + +namespace TagLib { + + namespace S3M { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs a ScreamTracker III from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a ScreamTracker III file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the S3M::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + S3M::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving ScreamTracker III tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/s3mproperties.h b/external/taglib/include/s3mproperties.h new file mode 100644 index 0000000..92b2a27 --- /dev/null +++ b/external/taglib/include/s3mproperties.h @@ -0,0 +1,94 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_S3MPROPERTIES_H +#define TAGLIB_S3MPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + namespace S3M { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + ST2Vibrato = 1, + ST2Tempo = 2, + AmigaSlides = 4, + Vol0MixOptimizations = 8, + AmigaLimits = 16, + EnableFilter = 32, + CustomData = 128 + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + bool stereo() const; + unsigned short sampleCount() const; + unsigned short patternCount() const; + unsigned short flags() const; + unsigned short trackerVersion() const; + unsigned short fileFormatVersion() const; + unsigned char globalVolume() const; + unsigned char masterVolume() const; + unsigned char tempo() const; + unsigned char bpmSpeed() const; + + void setChannels(int channels); + + void setLengthInPatterns (unsigned short lengthInPatterns); + void setStereo (bool stereo); + void setSampleCount (unsigned short sampleCount); + void setPatternCount (unsigned short patternCount); + void setFlags (unsigned short flags); + void setTrackerVersion (unsigned short trackerVersion); + void setFileFormatVersion(unsigned short fileFormatVersion); + void setGlobalVolume (unsigned char globalVolume); + void setMasterVolume (unsigned char masterVolume); + void setTempo (unsigned char tempo); + void setBpmSpeed (unsigned char bpmSpeed); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/speexfile.h b/external/taglib/include/speexfile.h new file mode 100644 index 0000000..1be7113 --- /dev/null +++ b/external/taglib/include/speexfile.h @@ -0,0 +1,138 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include "oggfile.h" +#include "xiphcomment.h" + +#include "speexproperties.h" + +namespace TagLib { + + namespace Ogg { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs a Speex file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a Speex file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as a Speex + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/speexproperties.h b/external/taglib/include/speexproperties.h new file mode 100644 index 0000000..3f5a20f --- /dev/null +++ b/external/taglib/include/speexproperties.h @@ -0,0 +1,129 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace Ogg { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Speex::Properties with the data read from the + * Speex::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this Speex::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the nominal bit rate as read from the Speex header in kb/s. + */ + int bitrateNominal() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the Speex version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/synchronizedlyricsframe.h b/external/taglib/include/synchronizedlyricsframe.h new file mode 100644 index 0000000..f520c59 --- /dev/null +++ b/external/taglib/include/synchronizedlyricsframe.h @@ -0,0 +1,231 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_SYNCHRONIZEDLYRICSFRAME_H + +#include "id3v2frame.h" +#include "tlist.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 synchronized lyrics frame + /*! + * An implementation of ID3v2 synchronized lyrics. + */ + class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Specifies the timestamp format used. + */ + enum TimestampFormat { + //! The timestamp is of unknown format. + Unknown = 0x00, + //! The timestamp represents the number of MPEG frames since + //! the beginning of the audio stream. + AbsoluteMpegFrames = 0x01, + //! The timestamp represents the number of milliseconds since + //! the beginning of the audio stream. + AbsoluteMilliseconds = 0x02 + }; + + /*! + * Specifies the type of text contained. + */ + enum Type { + //! The text is some other type of text. + Other = 0x00, + //! The text contains lyrical data. + Lyrics = 0x01, + //! The text contains a transcription. + TextTranscription = 0x02, + //! The text lists the movements in the piece. + Movement = 0x03, + //! The text describes events that occur. + Events = 0x04, + //! The text contains chord changes that occur in the music. + Chord = 0x05, + //! The text contains trivia or "pop up" information about the media. + Trivia = 0x06, + //! The text contains URLs for relevant webpages. + WebpageUrls = 0x07, + //! The text contains URLs for relevant images. + ImageUrls = 0x08 + }; + + /*! + * Single entry of time stamp and lyrics text. + */ + struct SynchedText { + SynchedText(unsigned int ms, String str) : time(ms), text(str) {} + unsigned int time; + String text; + }; + + /*! + * List of synchronized lyrics. + */ + typedef TagLib::List SynchedTextList; + + /*! + * Construct an empty synchronized lyrics frame that will use the text + * encoding \a encoding. + */ + explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a synchronized lyrics frame based on the data in \a data. + */ + explicit SynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this SynchronizedLyricsFrame instance. + */ + virtual ~SynchronizedLyricsFrame(); + + /*! + * Returns the description of this synchronized lyrics frame. + * + * \see description() + */ + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the timestamp format. + */ + TimestampFormat timestampFormat() const; + + /*! + * Returns the type of text contained. + */ + Type type() const; + + /*! + * Returns the description of this synchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text with the time stamps. + */ + SynchedTextList synchedText() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Set the timestamp format. + * + * \see timestampFormat() + */ + void setTimestampFormat(TimestampFormat f); + + /*! + * Set the type of text contained. + * + * \see type() + */ + void setType(Type t); + + /*! + * Sets the description of the synchronized lyrics frame to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text with the time stamps. + * + * \see text() + */ + void setSynchedText(const SynchedTextList &t); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + SynchronizedLyricsFrame(const ByteVector &data, Header *h); + SynchronizedLyricsFrame(const SynchronizedLyricsFrame &); + SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &); + + class SynchronizedLyricsFramePrivate; + SynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/tableofcontentsframe.h b/external/taglib/include/tableofcontentsframe.h new file mode 100644 index 0000000..2e5401e --- /dev/null +++ b/external/taglib/include/tableofcontentsframe.h @@ -0,0 +1,260 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TABLEOFCONTENTSFRAME +#define TAGLIB_TABLEOFCONTENTSFRAME + +#include "id3v2tag.h" +#include "id3v2frame.h" + +#include "tbytevectorlist.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 table of contents frames. Purpose + * of this frame is to allow a table of contents to be defined. + */ + + //! An implementation of ID3v2 table of contents frames + + class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a table of contents frame based on \a data. \a tagHeader is + * required as the internal frames are parsed based on the tag version. + */ + TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data); + + /*! + * Creates a table of contents frame with the element ID \a elementID, + * the child elements \a children and embedded frames, which become owned + * by this frame, in \a embeddedFrames. + */ + TableOfContentsFrame(const ByteVector &elementID, + const ByteVectorList &children = ByteVectorList(), + const FrameList &embeddedFrames = FrameList()); + + /*! + * Destroys the frame. + */ + ~TableOfContentsFrame(); + + /*! + * Returns the elementID of the frame. Element ID + * is a null terminated string, however it's not human-readable. + * + * \see setElementID() + */ + ByteVector elementID() const; + + /*! + * Returns true, if the frame is top-level (doesn't have + * any parent CTOC frame). + * + * \see setIsTopLevel() + */ + bool isTopLevel() const; + + /*! + * Returns true, if the child elements list entries + * are ordered. + * + * \see setIsOrdered() + */ + bool isOrdered() const; + + /*! + * Returns count of child elements of the frame. It always + * corresponds to size of child elements list. + * + * \see childElements() + */ + unsigned int entryCount() const; + + /*! + * Returns list of child elements of the frame. + * + * \see setChildElements() + */ + ByteVectorList childElements() const; + + /*! + * Sets the elementID of the frame to \a eID. If \a eID isn't + * null terminated, a null char is appended automatically. + * + * \see elementID() + */ + void setElementID(const ByteVector &eID); + + /*! + * Sets, if the frame is top-level (doesn't have + * any parent CTOC frame). + * + * \see isTopLevel() + */ + void setIsTopLevel(const bool &t); + + /*! + * Sets, if the child elements list entries + * are ordered. + * + * \see isOrdered() + */ + void setIsOrdered(const bool &o); + + /*! + * Sets list of child elements of the frame to \a l. + * + * \see childElements() + */ + void setChildElements(const ByteVectorList &l); + + /*! + * Adds \a cE to list of child elements of the frame. + * + * \see childElements() + */ + void addChildElement(const ByteVector &cE); + + /*! + * Removes \a cE to list of child elements of the frame. + * + * \see childElements() + */ + void removeChildElement(const ByteVector &cE); + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames embedded in the CTOC frame. + * + * This is the most convenient structure for accessing the CTOC frame's + * embedded frames. Many frame types allow multiple instances of the same + * frame type so this is a map of lists. In most cases however there will + * only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ + const FrameListMap &embeddedFrameListMap() const; + + /*! + * Returns a reference to the embedded frame list. This is an FrameList + * of all of the frames embedded in the CTOC frame in the order that they + * were parsed. + * + * This can be useful if for example you want iterate over the CTOC frame's + * embedded frames in the order that they occur in the CTOC frame. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + */ + const FrameList &embeddedFrameList() const; + + /*! + * Returns the embedded frame list for frames with the id \a frameID + * or an empty list if there are no embedded frames of that type. This + * is just a convenience and is equivalent to: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ + const FrameList &embeddedFrameList(const ByteVector &frameID) const; + + /*! + * Add an embedded frame to the CTOC frame. At this point the CTOC frame + * takes ownership of the embedded frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void addEmbeddedFrame(Frame *frame); + + /*! + * Remove an embedded frame from the CTOC frame. If \a del is true the frame's + * memory will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrame(Frame *frame, bool del = true); + + /*! + * Remove all embedded frames of type \a id from the CTOC frame and free their + * memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrames(const ByteVector &id); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * CTOC frames each have a unique element ID. This searches for a CTOC + * frame with the element ID \a eID and returns a pointer to it. This + * can be used to link together parent and child CTOC frames. + * + * \see elementID() + */ + static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID); + + /*! + * CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't + * any frame, which contains this frame in its child elements list). Only a single frame + * within tag can be top-level. This searches for a top-level CTOC frame. + * + * \see isTopLevel() + */ + static TableOfContentsFrame *findTopLevel(const Tag *tag); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h); + TableOfContentsFrame(const TableOfContentsFrame &); + TableOfContentsFrame &operator=(const TableOfContentsFrame &); + + class TableOfContentsFramePrivate; + TableOfContentsFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/tag.h b/external/taglib/include/tag.h new file mode 100644 index 0000000..be9628c --- /dev/null +++ b/external/taglib/include/tag.h @@ -0,0 +1,201 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAG_H +#define TAGLIB_TAG_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib { + + //! A simple, generic interface to common audio meta data fields + + /*! + * This is an attempt to abstract away the difference in the meta data formats + * of various audio codecs and tagging schemes. As such it is generally a + * subset of what is available in the specific formats but should be suitable + * for most applications. This is meant to compliment the generic APIs found + * in TagLib::AudioProperties, TagLib::File and TagLib::FileRef. + */ + + class PropertyMap; + + class TAGLIB_EXPORT Tag + { + public: + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Exports the tags of the file as dictionary mapping (human readable) tag + * names (Strings) to StringLists of tag values. + * The default implementation in this class considers only the usual built-in + * tags (artist, album, ...) and only one value per key. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties, or a subset of them, from the tag. + * The parameter \a properties must contain only entries from + * properties().unsupportedData(). + * BIC: Will become virtual in future releases. Currently the non-virtual + * standard implementation of TagLib::Tag does nothing, since there are + * no unsupported elements. + */ + void removeUnsupportedProperties(const StringList& properties); + + /*! + * Sets the tags of this File to those specified in \a properties. This default + * implementation sets only the tags for which setter methods exist in this class + * (artist, album, ...), and only one value per key; the rest will be contained + * in the returned PropertyMap. + */ + PropertyMap setProperties(const PropertyMap &properties); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const = 0; + + /*! + * Returns the artist name; if no artist name is present in the tag + * String::null will be returned. + */ + virtual String artist() const = 0; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const = 0; + + /*! + * Returns the track comment; if no comment is present in the tag + * String::null will be returned. + */ + virtual String comment() const = 0; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const = 0; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual unsigned int year() const = 0; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual unsigned int track() const = 0; + + /*! + * Sets the title to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setTitle(const String &s) = 0; + + /*! + * Sets the artist to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setArtist(const String &s) = 0; + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s) = 0; + + /*! + * Sets the comment to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setComment(const String &s) = 0; + + /*! + * Sets the genre to \a s. If \a s is String::null then this value will be + * cleared. For tag formats that use a fixed set of genres, the appropriate + * value will be selected based on a string comparison. A list of available + * genres for those formats should be available in that type's + * implementation. + */ + virtual void setGenre(const String &s) = 0; + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(unsigned int i) = 0; + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(unsigned int i) = 0; + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Copies the generic data from one tag to another. + * + * \note This will no affect any of the lower level details of the tag. For + * instance if any of the tag type specific data (maybe a URL for a band) is + * set, this will not modify or copy that. This just copies using the API + * in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ + static void duplicate(const Tag *source, Tag *target, bool overwrite = true); + + protected: + /*! + * Construct a Tag. This is protected since tags should only be instantiated + * through subclasses. + */ + Tag(); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; +} + +#endif diff --git a/external/taglib/include/taglib.h b/external/taglib/include/taglib.h new file mode 100644 index 0000000..8ea0b99 --- /dev/null +++ b/external/taglib/include/taglib.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_H +#define TAGLIB_H + +#include "taglib_config.h" + +#define TAGLIB_MAJOR_VERSION 1 +#define TAGLIB_MINOR_VERSION 13 +#define TAGLIB_PATCH_VERSION 0 + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__) +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") +#else +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR +#endif + +#if (defined(_MSC_VER) && _MSC_VER >= 1600) +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#else +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#endif + +#if __cplusplus >= 201402 +#define TAGLIB_DEPRECATED [[deprecated]] +#elif defined(__GNUC__) || defined(__clang__) +#define TAGLIB_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define TAGLIB_DEPRECATED __declspec(deprecated) +#else +#define TAGLIB_DEPRECATED +#endif + +#include + +//! A namespace for all TagLib related classes and functions + +/*! + * This namespace contains everything in TagLib. For projects working with + * TagLib extensively it may be convenient to add a + * \code + * using namespace TagLib; + * \endcode + */ + +namespace TagLib { + + class String; + + // These integer types are deprecated. Do not use them. + + typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char. + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; + typedef unsigned long long ulonglong; + + /*! + * Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3) + * so I'm providing something here that should be constant. + */ + typedef std::basic_string wstring; +} + +/*! + * \mainpage TagLib + * + * \section intro Introduction + * + * TagLib is a library for reading and editing audio meta data, commonly know as \e tags. + * + * Features: + * - A clean, high level, C++ API to handling audio meta data. + * - Format specific APIs for advanced API users. + * - ID3v1, ID3v2, APE, FLAC, Xiph, iTunes-style MP4 and WMA tag formats. + * - MP3, MPC, FLAC, MP4, ASF, AIFF, WAV, TrueAudio, WavPack, Ogg FLAC, Ogg Vorbis, Speex and Opus file formats. + * - Basic audio file properties such as length, sample rate, etc. + * - Long term binary and source compatibility. + * - Extensible design, notably the ability to add other formats or extend current formats as a library user. + * - Full support for unicode and internationalized tags. + * - Dual MPL and + * LGPL licenses. + * - No external toolkit dependencies. + * + * \section why Why TagLib? + * + * TagLib originally was written to provide an updated and improved ID3v2 implementation in C++ for use + * in a variety of Open Source projects. Since development began in 2002 and the 1.0 release in 2004 + * it has expanded to cover a wide variety of tag and file formats and is used in a wide variety of + * Open Source and proprietary applications. It now supports a variety of UNIXes, including Apple's OS + * X, as well as Microsoft Windows. + * + * \section commercial Usage in Commercial Applications + * + * TagLib's licenses \e do allow usage within propriety (\e closed) applications, however TagLib is \e not + * public domain. Please note the requirements of the LGPL or MPL, and adhere to at least one of them. + * In simple terms, you must at a minimum note your usage of TagLib, note the licensing terms of TagLib and + * if you make changes to TagLib publish them. Please review the licenses above before using TagLib in your + * software. Note that you may choose either the MPL or the LGPL, you do not have to fulfill the + * requirements of both. + * + * \section installing Installing TagLib + * + * Please see the TagLib website for the latest + * downloads. + * + * TagLib can be built using the CMake build system. TagLib installs a taglib-config and pkg-config file to + * make it easier to integrate into various build systems. Note that TagLib's include install directory \e must + * be included in the header include path. Simply adding will \e not work. + * + * \section start Getting Started + * + * TagLib provides both simple, abstract APIs which make it possible to ignore the differences between tagging + * formats and format specific APIs which allow programmers to work with the features of specific tagging + * schemes. There is a similar abstraction mechanism for AudioProperties. + * + * The best place to start is with the Class Hierarchy linked at the top of the page. The File and + * AudioProperties classes and their subclasses are the core of TagLib. The FileRef class is also a convenient + * way for using a value-based handle. + * + * \note When working with FileRef please consider that it has only the most basic (extension-based) file + * type resolution. Please see its documentation on how to plug in more advanced file type resolution. (Such + * resolution may be part of later TagLib releases by default.) + * + * Here's a very simple example with TagLib: + * + * \code + * + * TagLib::FileRef f("Latex Solar Beef.mp3"); + * TagLib::String artist = f.tag()->artist(); // artist == "Frank Zappa" + * + * f.tag()->setAlbum("Fillmore East"); + * f.save(); + * + * TagLib::FileRef g("Free City Rhymes.ogg"); + * TagLib::String album = g.tag()->album(); // album == "NYC Ghosts & Flowers" + * + * g.tag()->setTrack(1); + * g.save(); + * + * \endcode + * + * More examples can be found in the \e examples directory of the source distribution. + * + * \section Contact + * + * Questions about TagLib should be directed to the TagLib mailing list, not directly to the author. + * + * - TagLib Homepage + * - TagLib Mailing List (taglib-devel@kde.org) + * + * \author TagLib authors. + */ + +#endif diff --git a/external/taglib/include/taglib_config.h b/external/taglib/include/taglib_config.h new file mode 100644 index 0000000..e69de29 diff --git a/external/taglib/include/taglib_export.h b/external/taglib/include/taglib_export.h new file mode 100644 index 0000000..737ae64 --- /dev/null +++ b/external/taglib/include/taglib_export.h @@ -0,0 +1,43 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_EXPORT_H +#define TAGLIB_EXPORT_H + +#if defined(TAGLIB_STATIC) +#define TAGLIB_EXPORT +#elif (defined(_WIN32) || defined(_WIN64)) +#ifdef MAKE_TAGLIB_LIB +#define TAGLIB_EXPORT __declspec(dllexport) +#else +#define TAGLIB_EXPORT __declspec(dllimport) +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) +#define TAGLIB_EXPORT __attribute__ ((visibility("default"))) +#else +#define TAGLIB_EXPORT +#endif + +#endif diff --git a/external/taglib/include/tagunion.h b/external/taglib/include/tagunion.h new file mode 100644 index 0000000..1eb38a0 --- /dev/null +++ b/external/taglib/include/tagunion.h @@ -0,0 +1,98 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAGUNION_H +#define TAGLIB_TAGUNION_H + +#include "tag.h" + +#ifndef DO_NOT_DOCUMENT + +namespace TagLib { + + /*! + * \internal + */ + + class TagUnion : public Tag + { + public: + + enum AccessType { Read, Write }; + + /*! + * Creates a TagLib::Tag that is the union of \a first, \a second, and + * \a third. The TagUnion takes ownership of these tags and will handle + * their deletion. + */ + TagUnion(Tag *first = 0, Tag *second = 0, Tag *third = 0); + + virtual ~TagUnion(); + + Tag *operator[](int index) const; + Tag *tag(int index) const; + + void set(int index, Tag *tag); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList &unsupported); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + virtual bool isEmpty() const; + + template T *access(int index, bool create) + { + if(!create || tag(index)) + return static_cast(tag(index)); + + set(index, new T); + return static_cast(tag(index)); + } + + private: + TagUnion(const Tag &); + TagUnion &operator=(const Tag &); + + class TagUnionPrivate; + TagUnionPrivate *d; + }; +} + +#endif +#endif diff --git a/external/taglib/include/tagutils.h b/external/taglib/include/tagutils.h new file mode 100644 index 0000000..4488a32 --- /dev/null +++ b/external/taglib/include/tagutils.h @@ -0,0 +1,55 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAGUTILS_H +#define TAGLIB_TAGUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +#include + +namespace TagLib { + + class File; + class IOStream; + + namespace Utils { + + long findID3v1(File *file); + + long findID3v2(File *file); + + long findAPE(File *file, long id3v1Location); + + ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2, + long *headerOffset = 0); + } +} + +#endif + +#endif diff --git a/external/taglib/include/tbytevector.h b/external/taglib/include/tbytevector.h new file mode 100644 index 0000000..41373c7 --- /dev/null +++ b/external/taglib/include/tbytevector.h @@ -0,0 +1,635 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTOR_H +#define TAGLIB_BYTEVECTOR_H + +#include "taglib.h" +#include "taglib_export.h" + +#include +#include + +namespace TagLib { + + //! A byte vector + + /*! + * This class provides a byte vector with some methods that are useful for + * tagging purposes. Many of the search functions are tailored to what is + * useful for finding tag related patterns in a data array. + */ + + class TAGLIB_EXPORT ByteVector + { + public: +#ifndef DO_NOT_DOCUMENT + typedef std::vector::iterator Iterator; + typedef std::vector::const_iterator ConstIterator; + typedef std::vector::reverse_iterator ReverseIterator; + typedef std::vector::const_reverse_iterator ConstReverseIterator; +#endif + + /*! + * Constructs an empty byte vector. + */ + ByteVector(); + + /*! + * Construct a vector of size \a size with all values set to \a value by + * default. + */ + ByteVector(unsigned int size, char value = 0); + + /*! + * Constructs a byte vector that is a copy of \a v. + */ + ByteVector(const ByteVector &v); + + /*! + * Constructs a byte vector that is a copy of \a v. + */ + ByteVector(const ByteVector &v, unsigned int offset, unsigned int length); + + /*! + * Constructs a byte vector that contains \a c. + */ + ByteVector(char c); + + /*! + * Constructs a byte vector that copies \a data for up to \a length bytes. + */ + ByteVector(const char *data, unsigned int length); + + /*! + * Constructs a byte vector that copies \a data up to the first null + * byte. This is particularly useful for constructing byte arrays from + * string constants. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ + ByteVector(const char *data); + + /*! + * Destroys this ByteVector instance. + */ + virtual ~ByteVector(); + + /*! + * Sets the data for the byte array using the first \a length bytes of \a data + */ + ByteVector &setData(const char *data, unsigned int length); + + /*! + * Sets the data for the byte array copies \a data up to the first null + * byte. The behavior is undefined if \a data is not null terminated. + */ + ByteVector &setData(const char *data); + + /*! + * Returns a pointer to the internal data structure. + * + * \warning Care should be taken when modifying this data structure as it is + * easy to corrupt the ByteVector when doing so. Specifically, while the + * data may be changed, its length may not be. + */ + char *data(); + + /*! + * Returns a pointer to the internal data structure which may not be modified. + */ + const char *data() const; + + /*! + * Returns a byte vector made up of the bytes starting at \a index and + * for \a length bytes. If \a length is not specified it will return the bytes + * from \a index to the end of the vector. + */ + ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const; + + /*! + * This essentially performs the same as operator[](), but instead of causing + * a runtime error if the index is out of bounds, it will return a null byte. + */ + char at(unsigned int index) const; + + /*! + * Searches the ByteVector for \a pattern starting at \a offset and returns + * the offset. Returns -1 if the pattern was not found. If \a byteAlign is + * specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ + int find(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Searches the char for \a c starting at \a offset and returns + * the offset. Returns \a -1 if the pattern was not found. If \a byteAlign is + * specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ + int find(char c, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Searches the ByteVector for \a pattern starting from either the end of the + * vector or \a offset and returns the offset. Returns -1 if the pattern was + * not found. If \a byteAlign is specified the pattern will only be matched + * if it starts on a byte divisible by \a byteAlign (starting from \a offset). + */ + int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Checks to see if the vector contains the \a pattern starting at position + * \a offset. Optionally, if you only want to search for part of the pattern + * you can specify an offset within the pattern to start from. Also, you can + * specify to only check for the first \a patternLength bytes of \a pattern with + * the \a patternLength argument. + */ + bool containsAt(const ByteVector &pattern, unsigned int offset, + unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const; + + /*! + * Returns true if the vector starts with \a pattern. + */ + bool startsWith(const ByteVector &pattern) const; + + /*! + * Returns true if the vector ends with \a pattern. + */ + bool endsWith(const ByteVector &pattern) const; + + /*! + * Replaces \a oldByte with \a newByte and returns a reference to the + * ByteVector after the operation. This \e does modify the vector. + */ + ByteVector &replace(char oldByte, char newByte); + + /*! + * Replaces \a pattern with \a with and returns a reference to the ByteVector + * after the operation. This \e does modify the vector. + */ + ByteVector &replace(const ByteVector &pattern, const ByteVector &with); + + /*! + * Checks for a partial match of \a pattern at the end of the vector. It + * returns the offset of the partial match within the vector, or -1 if the + * pattern is not found. This method is particularly useful when searching for + * patterns that start in one vector and end in another. When combined with + * startsWith() it can be used to find a pattern that overlaps two buffers. + * + * \note This will not match the complete pattern at the end of the string; use + * endsWith() for that. + */ + int endsWithPartialMatch(const ByteVector &pattern) const; + + /*! + * Appends \a v to the end of the ByteVector. + */ + ByteVector &append(const ByteVector &v); + + /*! + * Appends \a c to the end of the ByteVector. + */ + ByteVector &append(char c); + + /*! + * Clears the data. + */ + ByteVector &clear(); + + /*! + * Returns the size of the array. + */ + unsigned int size() const; + + /*! + * Resize the vector to \a size. If the vector is currently less than + * \a size, pad the remaining spaces with \a padding. Returns a reference + * to the resized vector. + */ + ByteVector &resize(unsigned int size, char padding = 0); + + /*! + * Returns an Iterator that points to the front of the vector. + */ + Iterator begin(); + + /*! + * Returns a ConstIterator that points to the front of the vector. + */ + ConstIterator begin() const; + + /*! + * Returns an Iterator that points to the back of the vector. + */ + Iterator end(); + + /*! + * Returns a ConstIterator that points to the back of the vector. + */ + ConstIterator end() const; + + /*! + * Returns a ReverseIterator that points to the front of the vector. + */ + ReverseIterator rbegin(); + + /*! + * Returns a ConstReverseIterator that points to the front of the vector. + */ + ConstReverseIterator rbegin() const; + + /*! + * Returns a ReverseIterator that points to the back of the vector. + */ + ReverseIterator rend(); + + /*! + * Returns a ConstReverseIterator that points to the back of the vector. + */ + ConstReverseIterator rend() const; + + /*! + * Returns true if the vector is null. + * + * \note A vector may be empty without being null. So do not use this + * method to check if the vector is empty. + * + * \see isEmpty() + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED bool isNull() const; + + /*! + * Returns true if the ByteVector is empty. + * + * \see size() + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns a CRC checksum of the byte vector's data. + * + * \note This uses an uncommon variant of CRC32 specializes in Ogg. + */ + // BIC: Remove or make generic. + unsigned int checksum() const; + + /*! + * Converts the first 4 bytes of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 4 bytes at \a offset of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the \a length bytes at \a offset of the vector to an unsigned + * integer. If \a length is larger than 4, the excess is ignored. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(unsigned int offset, unsigned int length, + bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + short toShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 2 bytes at \a offset of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 2 bytes at \a offset of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 8 bytes of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ + long long toLongLong(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 8 bytes at \a offset of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ + long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /* + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 + * 32-bit little-endian floating point number. + */ + float toFloat32LE(size_t offset) const; + + /* + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 + * 32-bit big-endian floating point number. + */ + float toFloat32BE(size_t offset) const; + + /* + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 + * 64-bit little-endian floating point number. + */ + double toFloat64LE(size_t offset) const; + + /* + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 + * 64-bit big-endian floating point number. + */ + double toFloat64BE(size_t offset) const; + + /* + * Converts the 10 bytes at \a offset of the vector to a long double as an + * IEEE754 80-bit little-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ + long double toFloat80LE(size_t offset) const; + + /* + * Converts the 10 bytes at \a offset of the vector to a long double as an + * IEEE754 80-bit big-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ + long double toFloat80BE(size_t offset) const; + + /*! + * Creates a 4 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see toUInt() + */ + static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 2 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1. + * + * \see toShort() + */ + static ByteVector fromShort(short value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 8 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x0000000000000001 == 1, if false, + * $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see toLongLong() + */ + static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit + * little-endian floating point number. + * + * \see fromFloat32BE() + */ + static ByteVector fromFloat32LE(float value); + + /*! + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit + * big-endian floating point number. + * + * \see fromFloat32LE() + */ + static ByteVector fromFloat32BE(float value); + + /*! + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit + * little-endian floating point number. + * + * \see fromFloat64BE() + */ + static ByteVector fromFloat64LE(double value); + + /*! + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit + * big-endian floating point number. + * + * \see fromFloat64LE() + */ + static ByteVector fromFloat64BE(double value); + + /*! + * Returns a ByteVector based on the CString \a s. + */ + static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff); + + /*! + * Returns a const reference to the byte at \a index. + */ + const char &operator[](int index) const; + + /*! + * Returns a reference to the byte at \a index. + */ + char &operator[](int index); + + /*! + * Returns true if this ByteVector and \a v are equal. + */ + bool operator==(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and \a v are not equal. + */ + bool operator!=(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * contain the same data. + */ + bool operator==(const char *s) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * do not contain the same data. + */ + bool operator!=(const char *s) const; + + /*! + * Returns true if this ByteVector is less than \a v. The value of the + * vectors is determined by evaluating the character from left to right, and + * in the event one vector is a superset of the other, the size is used. + */ + bool operator<(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector is greater than \a v. + */ + bool operator>(const ByteVector &v) const; + + /*! + * Returns a vector that is \a v appended to this vector. + */ + ByteVector operator+(const ByteVector &v) const; + + /*! + * Copies ByteVector \a v. + */ + ByteVector &operator=(const ByteVector &v); + + /*! + * Copies a byte \a c. + */ + ByteVector &operator=(char c); + + /*! + * Copies \a data up to the first null byte. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ + ByteVector &operator=(const char *data); + + /*! + * Exchanges the content of the ByteVector by the content of \a v. + */ + void swap(ByteVector &v); + + /*! + * A static, empty ByteVector which is convenient and fast (since returning + * an empty or "null" value does not require instantiating a new ByteVector). + * + * \warning Do not modify this variable. It will mess up the internal state + * of TagLib. + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED static ByteVector null; + + /*! + * Returns a hex-encoded copy of the byte vector. + */ + ByteVector toHex() const; + + /*! + * Returns a base64 encoded copy of the byte vector + */ + ByteVector toBase64() const; + + /*! + * Decodes the base64 encoded byte vector. + */ + static ByteVector fromBase64(const ByteVector &); + + protected: + /* + * If this ByteVector is being shared via implicit sharing, do a deep copy + * of the data and separate from the shared members. This should be called + * by all non-const subclass members. + */ + void detach(); + + private: + class ByteVectorPrivate; + ByteVectorPrivate *d; + }; +} + +/*! + * \relates TagLib::ByteVector + * Streams the ByteVector \a v to the output stream \a s. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::ByteVector &v); + +#endif diff --git a/external/taglib/include/tbytevectorlist.h b/external/taglib/include/tbytevectorlist.h new file mode 100644 index 0000000..5852583 --- /dev/null +++ b/external/taglib/include/tbytevectorlist.h @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTORLIST_H +#define TAGLIB_BYTEVECTORLIST_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "tlist.h" + +namespace TagLib { + + //! A list of ByteVectors + + /*! + * A List specialization with some handy features useful for ByteVectors. + */ + + class TAGLIB_EXPORT ByteVectorList : public List + { + public: + + /*! + * Construct an empty ByteVectorList. + */ + ByteVectorList(); + + /*! + * Destroys this ByteVectorList instance. + */ + virtual ~ByteVectorList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + ByteVectorList(const ByteVectorList &l); + + /*! + * Convert the ByteVectorList to a ByteVector separated by \a separator. By + * default a space is used. + */ + ByteVector toByteVector(const ByteVector &separator = " ") const; + + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. + */ + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign = 1); + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. \a max is the + * maximum number of entries that will be separated. If \a max for instance + * is 2 then a maximum of 1 match will be found and the vector will be split + * on that match. + */ + // BIC: merge with the function above + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign, int max); + private: + class ByteVectorListPrivate; + ByteVectorListPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/include/tbytevectorstream.h b/external/taglib/include/tbytevectorstream.h new file mode 100644 index 0000000..84327c4 --- /dev/null +++ b/external/taglib/include/tbytevectorstream.h @@ -0,0 +1,145 @@ +/*************************************************************************** + copyright : (C) 2011 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTORSTREAM_H +#define TAGLIB_BYTEVECTORSTREAM_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" +#include "tiostream.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + + //! In-memory Stream class using ByteVector for its storage. + + class TAGLIB_EXPORT ByteVectorStream : public IOStream + { + public: + /*! + * Construct a File object and opens the \a file. \a file should be a + * be a C-string in the local file system encoding. + */ + ByteVectorStream(const ByteVector &data); + + /*! + * Destroys this ByteVectorStream instance. + */ + virtual ~ByteVectorStream(); + + /*! + * Returns the file name in the local file system encoding. + */ + FileName name() const; + + /*! + * Reads a block of size \a length at the current get pointer. + */ + ByteVector readBlock(unsigned long length); + + /*! + * Attempts to write the block \a data at the current get pointer. If the + * file is currently only opened read only -- i.e. readOnly() returns true -- + * this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator + * for a ByteVector. And even this function is significantly slower than + * doing output with a char[]. + */ + void writeBlock(const ByteVector &data); + + /*! + * Insert \a data at position \a start in the file overwriting \a replace + * bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file + * after the insertion point. + */ + void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0); + + /*! + * Removes a block of the file starting a \a start and continuing for + * \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ + void removeBlock(unsigned long start = 0, unsigned long length = 0); + + /*! + * Returns true if the file is read only (or if the file can not be opened). + */ + bool readOnly() const; + + /*! + * Since the file can currently only be opened as an argument to the + * constructor (sort-of by design), this returns if that open succeeded. + */ + bool isOpen() const; + + /*! + * Move the I/O pointer to \a offset in the file from position \a p. This + * defaults to seeking from the beginning of the file. + * + * \see Position + */ + void seek(long offset, Position p = Beginning); + + /*! + * Reset the end-of-file and error flags on the file. + */ + void clear(); + + /*! + * Returns the current offset within the file. + */ + long tell() const; + + /*! + * Returns the length of the file. + */ + long length(); + + /*! + * Truncates the file to a \a length. + */ + void truncate(long length); + + ByteVector *data(); + + protected: + + private: + class ByteVectorStreamPrivate; + ByteVectorStreamPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/include/tdebug.h b/external/taglib/include/tdebug.h new file mode 100644 index 0000000..80d00d3 --- /dev/null +++ b/external/taglib/include/tdebug.h @@ -0,0 +1,70 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_DEBUG_H +#define TAGLIB_DEBUG_H + +namespace TagLib { + + class String; + class ByteVector; + +#ifndef DO_NOT_DOCUMENT +#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE) + + /*! + * A simple function that outputs the debug messages to the listener. + * The default listener redirects the messages to \a stderr when NDEBUG is + * not defined. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debug(const String &s); + + /*! + * For debugging binary data. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debugData(const ByteVector &v); + +#else + + #define debug(x) ((void)0) + #define debugData(x) ((void)0) + +#endif +} + +#endif +#endif diff --git a/external/taglib/include/tdebuglistener.h b/external/taglib/include/tdebuglistener.h new file mode 100644 index 0000000..3c8e118 --- /dev/null +++ b/external/taglib/include/tdebuglistener.h @@ -0,0 +1,74 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_DEBUGLISTENER_H +#define TAGLIB_DEBUGLISTENER_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib +{ + //! An abstraction for the listener to the debug messages. + + /*! + * This class enables you to handle the debug messages in your preferred + * way by subclassing this class, reimplementing printMessage() and setting + * your reimplementation as the default with setDebugListener(). + * + * \see setDebugListener() + */ + class TAGLIB_EXPORT DebugListener + { + public: + DebugListener(); + virtual ~DebugListener(); + + /*! + * When overridden in a derived class, redirects \a msg to your preferred + * channel such as stderr, Windows debugger or so forth. + */ + virtual void printMessage(const String &msg) = 0; + + private: + // Noncopyable + DebugListener(const DebugListener &); + DebugListener &operator=(const DebugListener &); + }; + + /*! + * Sets the listener that decides how the debug messages are redirected. + * If the parameter \a listener is null, the previous listener is released + * and default stderr listener is restored. + * + * \note The caller is responsible for deleting the previous listener + * as needed after it is released. + * + * \see DebugListener + */ + TAGLIB_EXPORT void setDebugListener(DebugListener *listener); +} + +#endif diff --git a/external/taglib/include/textidentificationframe.h b/external/taglib/include/textidentificationframe.h new file mode 100644 index 0000000..e49aa89 --- /dev/null +++ b/external/taglib/include/textidentificationframe.h @@ -0,0 +1,313 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TEXTIDENTIFICATIONFRAME_H +#define TAGLIB_TEXTIDENTIFICATIONFRAME_H + +#include "tstringlist.h" +#include "tmap.h" +#include "taglib_export.h" + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + class Tag; + typedef Map KeyConversionMap; + + //! An ID3v2 text identification frame implementation + + /*! + * This is an implementation of the most common type of ID3v2 frame -- text + * identification frames. There are a number of variations on this. Those + * enumerated in the ID3v2.4 standard are: + * + *
    + *
  • TALB Album/Movie/Show title
  • + *
  • TBPM BPM (beats per minute)
  • + *
  • TCOM Composer
  • + *
  • TCON Content type
  • + *
  • TCOP Copyright message
  • + *
  • TDEN Encoding time
  • + *
  • TDLY Playlist delay
  • + *
  • TDOR Original release time
  • + *
  • TDRC Recording time
  • + *
  • TDRL Release time
  • + *
  • TDTG Tagging time
  • + *
  • TENC Encoded by
  • + *
  • TEXT Lyricist/Text writer
  • + *
  • TFLT File type
  • + *
  • TIPL Involved people list
  • + *
  • TIT1 Content group description
  • + *
  • TIT2 Title/songname/content description
  • + *
  • TIT3 Subtitle/Description refinement
  • + *
  • TKEY Initial key
  • + *
  • TLAN Language(s)
  • + *
  • TLEN Length
  • + *
  • TMCL Musician credits list
  • + *
  • TMED Media type
  • + *
  • TMOO Mood
  • + *
  • TOAL Original album/movie/show title
  • + *
  • TOFN Original filename
  • + *
  • TOLY Original lyricist(s)/text writer(s)
  • + *
  • TOPE Original artist(s)/performer(s)
  • + *
  • TOWN File owner/licensee
  • + *
  • TPE1 Lead performer(s)/Soloist(s)
  • + *
  • TPE2 Band/orchestra/accompaniment
  • + *
  • TPE3 Conductor/performer refinement
  • + *
  • TPE4 Interpreted, remixed, or otherwise modified by
  • + *
  • TPOS Part of a set
  • + *
  • TPRO Produced notice
  • + *
  • TPUB Publisher
  • + *
  • TRCK Track number/Position in set
  • + *
  • TRSN Internet radio station name
  • + *
  • TRSO Internet radio station owner
  • + *
  • TSOA Album sort order
  • + *
  • TSOP Performer sort order
  • + *
  • TSOT Title sort order
  • + *
  • TSRC ISRC (international standard recording code)
  • + *
  • TSSE Software/Hardware and settings used for encoding
  • + *
  • TSST Set subtitle
  • + *
+ * + * The ID3v2 Frames document gives a description of each of these formats + * and the expected order of strings in each. ID3v2::Header::frameID() can + * be used to determine the frame type. + * + * \note If non-Latin1 compatible strings are used with this class, even if + * the text encoding is set to Latin1, the frame will be written using UTF8 + * (with the encoding flag appropriately set in the output). + */ + + class TAGLIB_EXPORT TextIdentificationFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty frame of type \a type. Uses \a encoding as the + * default text encoding. + * + * \note In this case you must specify the text encoding as it + * resolves the ambiguity between constructors. + * + * \note Please see the note in the class description regarding Latin1. + */ + TextIdentificationFrame(const ByteVector &type, String::Type encoding); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit TextIdentificationFrame(const ByteVector &data); + + /*! + * This is a special factory method to create a TIPL (involved people list) + * frame from the given \a properties. Will parse key=[list of values] data + * into the TIPL format as specified in the ID3 standard. + */ + static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties); + + /*! + * This is a special factory method to create a TMCL (musician credits list) + * frame from the given \a properties. Will parse key=[list of values] data + * into the TMCL format as specified in the ID3 standard, where key should be + * of the form instrumentPrefix:instrument. + */ + static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties); + /*! + * Destroys this TextIdentificationFrame instance. + */ + virtual ~TextIdentificationFrame(); + + /*! + * Text identification frames are a list of string fields. + * + * This function will accept either a StringList or a String (using the + * StringList constructor that accepts a single String). + * + * \note This will not change the text encoding of the frame even if the + * strings passed in are not of the same encoding. Please use + * setEncoding(s.type()) if you wish to change the encoding of the frame. + */ + void setText(const StringList &l); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns a list of the strings in this frame. + */ + StringList fieldList() const; + + /*! + * Returns a KeyConversionMap mapping a role as it would be used in a PropertyMap + * to the corresponding key used in a TIPL ID3 frame to describe that role. + */ + static const KeyConversionMap &involvedPeopleMap(); + + PropertyMap asProperties() const; + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + TextIdentificationFrame(const ByteVector &data, Header *h); + + private: + TextIdentificationFrame(const TextIdentificationFrame &); + TextIdentificationFrame &operator=(const TextIdentificationFrame &); + + /*! + * Parses the special structure of a TIPL frame + * Only the whitelisted roles "ARRANGER", "ENGINEER", "PRODUCER", + * "DJMIXER" (ID3: "DJ-MIX") and "MIXER" (ID3: "MIX") are allowed. + */ + PropertyMap makeTIPLProperties() const; + /*! + * Parses the special structure of a TMCL frame. + */ + PropertyMap makeTMCLProperties() const; + class TextIdentificationFramePrivate; + TextIdentificationFramePrivate *d; + }; + + /*! + * This is a specialization of text identification frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a text identification frame has. + * + * This description identifies the frame and must be unique. + */ + + //! An ID3v2 custom text identification frame implementation + + class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined text identification frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1); + + /*! + * Creates a frame based on \a data. + */ + explicit UserTextIdentificationFrame(const ByteVector &data); + + /*! + * Creates a user defined text identification frame with the given \a description + * and \a values. + */ + UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8); + + virtual String toString() const; + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. You can + * check for the presence of another user defined text frame of the same type + * using find() and testing for null. + */ + void setDescription(const String &s); + + StringList fieldList() const; + void setText(const String &text); + void setText(const StringList &fields); + + /*! + * A UserTextIdentificationFrame is parsed into a PropertyMap as follows: + * - the key is the frame's description, uppercased + * - if the description contains '::', only the substring after that + * separator is considered as key (compatibility with exfalso) + * - if the above rules don't yield a valid key (e.g. containing non-ASCII + * characters), the returned map will contain an entry "TXXX/" + * in its unsupportedData() list. + * - The values will be copies of the fieldList(). + * - If the description() appears as value in fieldList(), it will be omitted + * in the value list, in order to be compatible with TagLib which copies + * the description() into the fieldList(). + */ + PropertyMap asProperties() const; + + /*! + * Searches for the user defined text frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserTextIdentificationFrame *find(Tag *tag, const String &description); + + private: + UserTextIdentificationFrame(const ByteVector &data, Header *h); + UserTextIdentificationFrame(const TextIdentificationFrame &); + UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &); + + void checkFields(); + + class UserTextIdentificationFramePrivate; + UserTextIdentificationFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/tfile.h b/external/taglib/include/tfile.h new file mode 100644 index 0000000..bdc4f12 --- /dev/null +++ b/external/taglib/include/tfile.h @@ -0,0 +1,323 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILE_H +#define TAGLIB_FILE_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tag.h" +#include "tbytevector.h" +#include "tiostream.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + class PropertyMap; + + //! A file class with some useful methods for tag manipulation + + /*! + * This class is a basic file class with some methods that are particularly + * useful for tag editors. It has methods to take advantage of + * ByteVector and a binary search method for finding patterns in a file. + */ + + class TAGLIB_EXPORT File + { + public: + /*! + * Position in the file used for seeking. + */ + enum Position { + //! Seek from the beginning of the file. + Beginning, + //! Seek from the current position in the file. + Current, + //! Seek from the end of the file. + End + }; + + /*! + * Specify which tags to strip either explicitly, or on save. + */ + enum StripTags { + StripNone, // + +namespace TagLib { + + //! A generic, implicitly shared list. + + /*! + * This is basic generic list that's somewhere between a std::list and a + * QValueList. This class is implicitly shared. For example: + * + * \code + * + * TagLib::List l = someOtherIntList; + * + * \endcode + * + * The above example is very cheap. This also makes lists suitable for the + * return types of functions. The above example will just copy a pointer rather + * than copying the data in the list. When your \e shared list's data changes, + * only \e then will the data be copied. + */ + + template class List + { + public: +#ifndef DO_NOT_DOCUMENT + typedef typename std::list::iterator Iterator; + typedef typename std::list::const_iterator ConstIterator; +#endif + + /*! + * Constructs an empty list. + */ + List(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List(const List &l); + + /*! + * Destroys this List instance. If auto deletion is enabled and this list + * contains a pointer type all of the members are also deleted. + */ + virtual ~List(); + + /*! + * Returns an STL style iterator to the beginning of the list. See + * std::list::const_iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style constant iterator to the beginning of the list. See + * std::list::iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the list. See + * std::list::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style constant iterator to the end of the list. See + * std::list::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts a copy of \a value before \a it. + */ + Iterator insert(Iterator it, const T &value); + + /*! + * Inserts the \a value into the list. This assumes that the list is + * currently sorted. If \a unique is true then the value will not + * be inserted if it is already in the list. + */ + List &sortedInsert(const T &value, bool unique = false); + + /*! + * Appends \a item to the end of the list and returns a reference to the + * list. + */ + List &append(const T &item); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + List &append(const List &l); + + /*! + * Prepends \a item to the beginning list and returns a reference to the + * list. + */ + List &prepend(const T &item); + + /*! + * Prepends all of the items in \a l to the beginning list and returns a + * reference to the list. + */ + List &prepend(const List &l); + + /*! + * Clears the list. If auto deletion is enabled and this list contains a + * pointer type the members are also deleted. + * + * \see setAutoDelete() + */ + List &clear(); + + /*! + * Returns the number of elements in the list. + * + * \see isEmpty() + */ + unsigned int size() const; + + /*! + * Returns whether or not the list is empty. + * + * \see size() + */ + bool isEmpty() const; + + /*! + * Find the first occurrence of \a value. + */ + Iterator find(const T &value); + + /*! + * Find the first occurrence of \a value. + */ + ConstIterator find(const T &value) const; + + /*! + * Returns true if the list contains \a value. + */ + bool contains(const T &value) const; + + /*! + * Erase the item at \a it from the list. + */ + Iterator erase(Iterator it); + + /*! + * Returns a reference to the first item in the list. + */ + const T &front() const; + + /*! + * Returns a reference to the first item in the list. + */ + T &front(); + + /*! + * Returns a reference to the last item in the list. + */ + const T &back() const; + + /*! + * Returns a reference to the last item in the list. + */ + T &back(); + + /*! + * Auto delete the members of the list when the last reference to the list + * passes out of scope. This will have no effect on lists which do not + * contain a pointer type. + * + * \note This relies on partial template instantiation -- most modern C++ + * compilers should now support this. + */ + void setAutoDelete(bool autoDelete); + + /*! + * Returns a reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + T &operator[](unsigned int i); + + /*! + * Returns a const reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + const T &operator[](unsigned int i) const; + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List &operator=(const List &l); + + /*! + * Exchanges the content of this list by the content of \a l. + */ + void swap(List &l); + + /*! + * Compares this list with \a l and returns true if all of the elements are + * the same. + */ + bool operator==(const List &l) const; + + /*! + * Compares this list with \a l and returns true if the lists differ. + */ + bool operator!=(const List &l) const; + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class ListPrivate; + ListPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tlist.tcc" + +#endif diff --git a/external/taglib/include/tlist.tcc b/external/taglib/include/tlist.tcc new file mode 100644 index 0000000..478f098 --- /dev/null +++ b/external/taglib/include/tlist.tcc @@ -0,0 +1,323 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include "trefcounter.h" + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +// The functionality of List::setAutoDelete() is implemented here partial +// template specialization. This is implemented in such a way that calling +// setAutoDelete() on non-pointer types will simply have no effect. + +// A base for the generic and specialized private class types. New +// non-templatized members should be added here. + +// BIC change to RefCounter +class ListPrivateBase : public RefCounterOld +{ +public: + ListPrivateBase() : autoDelete(false) {} + bool autoDelete; +}; + +// A generic implementation + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + void clear() { + list.clear(); + } + std::list list; +}; + +// A partial specialization for all pointer types that implements the +// setAutoDelete() functionality. + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + ~ListPrivate() { + clear(); + } + void clear() { + if(autoDelete) { + typename std::list::const_iterator it = list.begin(); + for(; it != list.end(); ++it) + delete *it; + } + list.clear(); + } + std::list list; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +template +List::List() : + d(new ListPrivate()) +{ +} + +template +List::List(const List &l) : d(l.d) +{ + d->ref(); +} + +template +List::~List() +{ + if(d->deref()) + delete d; +} + +template +typename List::Iterator List::begin() +{ + detach(); + return d->list.begin(); +} + +template +typename List::ConstIterator List::begin() const +{ + return d->list.begin(); +} + +template +typename List::Iterator List::end() +{ + detach(); + return d->list.end(); +} + +template +typename List::ConstIterator List::end() const +{ + return d->list.end(); +} + +template +typename List::Iterator List::insert(Iterator it, const T &item) +{ + detach(); + return d->list.insert(it, item); +} + +template +List &List::sortedInsert(const T &value, bool unique) +{ + detach(); + Iterator it = begin(); + while(it != end() && *it < value) + ++it; + if(unique && it != end() && *it == value) + return *this; + insert(it, value); + return *this; +} + +template +List &List::append(const T &item) +{ + detach(); + d->list.push_back(item); + return *this; +} + +template +List &List::append(const List &l) +{ + detach(); + d->list.insert(d->list.end(), l.begin(), l.end()); + return *this; +} + +template +List &List::prepend(const T &item) +{ + detach(); + d->list.push_front(item); + return *this; +} + +template +List &List::prepend(const List &l) +{ + detach(); + d->list.insert(d->list.begin(), l.begin(), l.end()); + return *this; +} + +template +List &List::clear() +{ + detach(); + d->clear(); + return *this; +} + +template +unsigned int List::size() const +{ + return static_cast(d->list.size()); +} + +template +bool List::isEmpty() const +{ + return d->list.empty(); +} + +template +typename List::Iterator List::find(const T &value) +{ + detach(); + return std::find(d->list.begin(), d->list.end(), value); +} + +template +typename List::ConstIterator List::find(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value); +} + +template +bool List::contains(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value) != d->list.end(); +} + +template +typename List::Iterator List::erase(Iterator it) +{ + return d->list.erase(it); +} + +template +const T &List::front() const +{ + return d->list.front(); +} + +template +T &List::front() +{ + detach(); + return d->list.front(); +} + +template +const T &List::back() const +{ + return d->list.back(); +} + +template +void List::setAutoDelete(bool autoDelete) +{ + d->autoDelete = autoDelete; +} + +template +T &List::back() +{ + detach(); + return d->list.back(); +} + +template +T &List::operator[](unsigned int i) +{ + Iterator it = d->list.begin(); + std::advance(it, i); + + return *it; +} + +template +const T &List::operator[](unsigned int i) const +{ + ConstIterator it = d->list.begin(); + std::advance(it, i); + + return *it; +} + +template +List &List::operator=(const List &l) +{ + List(l).swap(*this); + return *this; +} + +template +void List::swap(List &l) +{ + using std::swap; + + swap(d, l.d); +} + +template +bool List::operator==(const List &l) const +{ + return d->list == l.d->list; +} + +template +bool List::operator!=(const List &l) const +{ + return d->list != l.d->list; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void List::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new ListPrivate(d->list); + } +} + +} // namespace TagLib diff --git a/external/taglib/include/tmap.h b/external/taglib/include/tmap.h new file mode 100644 index 0000000..2f920d2 --- /dev/null +++ b/external/taglib/include/tmap.h @@ -0,0 +1,212 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MAP_H +#define TAGLIB_MAP_H + +#include + +#include "taglib.h" + +namespace TagLib { + + //! A generic, implicitly shared map. + + /*! + * This implements a standard map container that associates a key with a value + * and has fast key-based lookups. This map is also implicitly shared making + * it suitable for pass-by-value usage. + */ + + template class Map + { + public: +#ifndef DO_NOT_DOCUMENT +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + // Some STL implementations get snippy over the use of the + // class keyword to distinguish different templates; Sun Studio + // in particular finds multiple specializations in certain rare + // cases and complains about that. GCC doesn't seem to mind, + // and uses the typedefs further below without the class keyword. + // Not all the specializations of Map can use the class keyword + // (when T is not actually a class type), so don't apply this + // generally. + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#else + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#endif +#endif + + /*! + * Constructs an empty Map. + */ + Map(); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map(const Map &m); + + /*! + * Destroys this instance of the Map. + */ + virtual ~Map(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts \a value under \a key in the map. If a value for \a key already + * exists it will be overwritten. + */ + Map &insert(const Key &key, const T &value); + + /*! + * Removes all of the elements from elements from the map. This however + * will not delete pointers if the mapped type is a pointer type. + */ + Map &clear(); + + /*! + * The number of elements in the map. + * + * \see isEmpty() + */ + unsigned int size() const; + + /*! + * Returns true if the map is empty. + * + * \see size() + */ + bool isEmpty() const; + + /*! + * Find the first occurrence of \a key. + */ + Iterator find(const Key &key); + + /*! + * Find the first occurrence of \a key. + */ + ConstIterator find(const Key &key) const; + + /*! + * Returns true if the map contains an instance of \a key. + */ + bool contains(const Key &key) const; + + /*! + * Erase the item at \a it from the list. + */ + Map &erase(Iterator it); + + /*! + * Erase the item with \a key from the list. + */ + Map &erase(const Key &key); + + /*! + * Returns the value associated with \a key. + * + * If the map does not contain \a key, it returns defaultValue. + * If no defaultValue is specified, it returns a default-constructed value. + */ + const T value(const Key &key, const T &defaultValue = T()) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + const T &operator[](const Key &key) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + T &operator[](const Key &key); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map &operator=(const Map &m); + + /*! + * Exchanges the content of this map by the content of \a m. + */ + void swap(Map &m); + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class MapPrivate; + MapPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tmap.tcc" + +#endif diff --git a/external/taglib/include/tmap.tcc b/external/taglib/include/tmap.tcc new file mode 100644 index 0000000..18eec11 --- /dev/null +++ b/external/taglib/include/tmap.tcc @@ -0,0 +1,206 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "trefcounter.h" + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +// BIC change to RefCounter +template +template +class Map::MapPrivate : public RefCounterOld +{ +public: + MapPrivate() : RefCounterOld() {} +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} + std::map map; +#else + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} + std::map map; +#endif +}; + +template +Map::Map() : + d(new MapPrivate()) +{ +} + +template +Map::Map(const Map &m) : d(m.d) +{ + d->ref(); +} + +template +Map::~Map() +{ + if(d->deref()) + delete(d); +} + +template +typename Map::Iterator Map::begin() +{ + detach(); + return d->map.begin(); +} + +template +typename Map::ConstIterator Map::begin() const +{ + return d->map.begin(); +} + +template +typename Map::Iterator Map::end() +{ + detach(); + return d->map.end(); +} + +template +typename Map::ConstIterator Map::end() const +{ + return d->map.end(); +} + +template +Map &Map::insert(const Key &key, const T &value) +{ + detach(); + d->map[key] = value; + return *this; +} + +template +Map &Map::clear() +{ + detach(); + d->map.clear(); + return *this; +} + +template +bool Map::isEmpty() const +{ + return d->map.empty(); +} + +template +typename Map::Iterator Map::find(const Key &key) +{ + detach(); + return d->map.find(key); +} + +template +typename Map::ConstIterator Map::find(const Key &key) const +{ + return d->map.find(key); +} + +template +bool Map::contains(const Key &key) const +{ + return d->map.find(key) != d->map.end(); +} + +template +Map &Map::erase(Iterator it) +{ + detach(); + d->map.erase(it); + return *this; +} + +template +Map &Map::erase(const Key &key) +{ + detach(); + d->map.erase(key); + return *this; +} + +template +unsigned int Map::size() const +{ + return static_cast(d->map.size()); +} + +template +const T Map::value(const Key &key, const T &defaultValue) const +{ + ConstIterator it = d->map.find(key); + return it != d->map.end() ? it->second : defaultValue; +} + +template +const T &Map::operator[](const Key &key) const +{ + return d->map[key]; +} + +template +T &Map::operator[](const Key &key) +{ + detach(); + return d->map[key]; +} + +template +Map &Map::operator=(const Map &m) +{ + Map(m).swap(*this); + return *this; +} + +template +void Map::swap(Map &m) +{ + using std::swap; + + swap(d, m.d); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void Map::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new MapPrivate(d->map); + } +} + +} // namespace TagLib diff --git a/external/taglib/include/tpropertymap.h b/external/taglib/include/tpropertymap.h new file mode 100644 index 0000000..de49786 --- /dev/null +++ b/external/taglib/include/tpropertymap.h @@ -0,0 +1,256 @@ +/*************************************************************************** + copyright : (C) 2012 by Michael Helmling + email : helmling@mathematik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PROPERTYMAP_H_ +#define TAGLIB_PROPERTYMAP_H_ + +#include "tmap.h" +#include "tstringlist.h" + +#ifdef _MSC_VER +// Explained at end of tpropertymap.cpp +extern template class TAGLIB_EXPORT TagLib::Map; +#endif + +namespace TagLib { + + typedef Map SimplePropertyMap; + + //! A map for format-independent tag representations. + + /*! + * This map implements a generic representation of textual audio metadata + * ("tags") realized as pairs of a case-insensitive key + * and a nonempty list of corresponding values, each value being an arbitrary + * unicode String. + * + * Note that most metadata formats pose additional conditions on the tag keys. The + * most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of + * length between 2 and 16. + * + * This class can contain any tags, but here is a list of "well-known" tags that + * you might want to use: + * + * Basic tags: + * + * - TITLE + * - ALBUM + * - ARTIST + * - ALBUMARTIST + * - SUBTITLE + * - TRACKNUMBER + * - DISCNUMBER + * - DATE + * - ORIGINALDATE + * - GENRE + * - COMMENT + * + * Sort names: + * + * - TITLESORT + * - ALBUMSORT + * - ARTISTSORT + * - ALBUMARTISTSORT + * - COMPOSERSORT + * + * Credits: + * + * - COMPOSER + * - LYRICIST + * - CONDUCTOR + * - REMIXER + * - PERFORMER:\ + * + * Other tags: + * + * - ISRC + * - ASIN + * - BPM + * - COPYRIGHT + * - ENCODEDBY + * - MOOD + * - COMMENT + * - MEDIA + * - LABEL + * - CATALOGNUMBER + * - BARCODE + * - RELEASECOUNTRY + * - RELEASESTATUS + * - RELEASETYPE + * + * MusicBrainz identifiers: + * + * - MUSICBRAINZ_TRACKID + * - MUSICBRAINZ_ALBUMID + * - MUSICBRAINZ_RELEASEGROUPID + * - MUSICBRAINZ_RELEASETRACKID + * - MUSICBRAINZ_WORKID + * - MUSICBRAINZ_ARTISTID + * - MUSICBRAINZ_ALBUMARTISTID + * - ACOUSTID_ID + * - ACOUSTID_FINGERPRINT + * - MUSICIP_PUID + * + */ + + class TAGLIB_EXPORT PropertyMap: public SimplePropertyMap + { + public: + + typedef SimplePropertyMap::Iterator Iterator; + typedef SimplePropertyMap::ConstIterator ConstIterator; + + PropertyMap(); + + PropertyMap(const PropertyMap &m); + + /*! + * Creates a PropertyMap initialized from a SimplePropertyMap. Copies all + * entries from \a m that have valid keys. + * Invalid keys will be appended to the unsupportedData() list. + */ + PropertyMap(const SimplePropertyMap &m); + + virtual ~PropertyMap(); + + /*! + * Inserts \a values under \a key in the map. If \a key already exists, + * then \a values will be appended to the existing StringList. + * The returned value indicates success, i.e. whether \a key is a + * valid key. + */ + bool insert(const String &key, const StringList &values); + + /*! + * Replaces any existing values for \a key with the given \a values, + * and simply insert them if \a key did not exist before. + * The returned value indicates success, i.e. whether \a key is a + * valid key. + */ + bool replace(const String &key, const StringList &values); + + /*! + * Find the first occurrence of \a key. + */ + Iterator find(const String &key); + + /*! + * Find the first occurrence of \a key. + */ + ConstIterator find(const String &key) const; + + /*! + * Returns true if the map contains values for \a key. + */ + bool contains(const String &key) const; + + /*! + * Returns true if this map contains all keys of \a other + * and the values coincide for that keys. Does not take + * the unsupportedData list into account. + */ + bool contains(const PropertyMap &other) const; + + /*! + * Erase the \a key and its values from the map. + */ + PropertyMap &erase(const String &key); + + /*! + * Erases from this map all keys that appear in \a other. + */ + PropertyMap &erase(const PropertyMap &other); + + /*! + * Merge the contents of \a other into this PropertyMap. + * If a key is contained in both maps, the values of the second + * are appended to that of the first. + * The unsupportedData() lists are concatenated as well. + */ + PropertyMap &merge(const PropertyMap &other); + + /*! + * Returns the value associated with \a key. + * + * If the map does not contain \a key, it returns defaultValue. + * If no defaultValue is specified, it returns an empty string list. + */ + const StringList value(const String &key, + const StringList &defaultValue = StringList()) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty + * StringList is returned without error. + */ + const StringList &operator[](const String &key) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty + * StringList is returned. You can also directly add entries + * by using this function as an lvalue. + */ + StringList &operator[](const String &key); + + /*! + * Returns true if and only if \a other has the same contents as this map. + */ + bool operator==(const PropertyMap &other) const; + + /*! + * Returns false if and only \a other has the same contents as this map. + */ + bool operator!=(const PropertyMap &other) const; + + /*! + * If a PropertyMap is read from a File object using File::properties(), + * the StringList returned from this function will represent metadata + * that could not be parsed into the PropertyMap representation. This could + * be e.g. binary data, unknown ID3 frames, etc. + * You can remove items from the returned list, which tells TagLib to remove + * those unsupported elements if you call File::setProperties() with the + * same PropertyMap as argument. + */ + StringList &unsupportedData(); + const StringList &unsupportedData() const; + + /*! + * Removes all entries which have an empty value list. + */ + void removeEmpty(); + + String toString() const; + + private: + + + StringList unsupported; + }; + +} +#endif /* TAGLIB_PROPERTYMAP_H_ */ diff --git a/external/taglib/include/trefcounter.h b/external/taglib/include/trefcounter.h new file mode 100644 index 0000000..db97c53 --- /dev/null +++ b/external/taglib/include/trefcounter.h @@ -0,0 +1,114 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_REFCOUNTER_H +#define TAGLIB_REFCOUNTER_H + +#include "taglib_export.h" +#include "taglib.h" + +#ifdef __APPLE__ +# define OSATOMIC_DEPRECATED 0 +# include +# define TAGLIB_ATOMIC_MAC +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# define TAGLIB_ATOMIC_WIN +#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ + && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(__x86_64) || defined(__ia64)) \ + && !defined(__INTEL_COMPILER) +# define TAGLIB_ATOMIC_GCC +#elif defined(__ia64) && defined(__INTEL_COMPILER) +# include +# define TAGLIB_ATOMIC_GCC +#endif + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. +/*! + * \internal + * This is just used as a base class for shared classes in TagLib. + * + * \warning This is not part of the TagLib public API! + */ +namespace TagLib +{ + + class TAGLIB_EXPORT RefCounter + { + public: + RefCounter(); + virtual ~RefCounter(); + + void ref(); + bool deref(); + int count() const; + + private: + class RefCounterPrivate; + RefCounterPrivate *d; + }; + + // BIC this old class is needed by tlist.tcc and tmap.tcc + class RefCounterOld + { + public: + RefCounterOld() : refCount(1) {} + +#ifdef TAGLIB_ATOMIC_MAC + void ref() { OSAtomicIncrement32Barrier(const_cast(&refCount)); } + bool deref() { return ! OSAtomicDecrement32Barrier(const_cast(&refCount)); } + int32_t count() { return refCount; } + private: + volatile int32_t refCount; +#elif defined(TAGLIB_ATOMIC_WIN) + void ref() { InterlockedIncrement(&refCount); } + bool deref() { return ! InterlockedDecrement(&refCount); } + long count() { return refCount; } + private: + volatile long refCount; +#elif defined(TAGLIB_ATOMIC_GCC) + void ref() { __sync_add_and_fetch(&refCount, 1); } + bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); } + int count() { return refCount; } + private: + volatile int refCount; +#else + void ref() { refCount++; } + bool deref() { return ! --refCount; } + int count() { return refCount; } + private: + unsigned int refCount; +#endif + }; + +} + +#endif // DO_NOT_DOCUMENT +#endif + diff --git a/external/taglib/include/trueaudiofile.h b/external/taglib/include/trueaudiofile.h new file mode 100644 index 0000000..1f664d2 --- /dev/null +++ b/external/taglib/include/trueaudiofile.h @@ -0,0 +1,259 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOFILE_H +#define TAGLIB_TRUEAUDIOFILE_H + +#include "tfile.h" +#include "trueaudioproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + + //! An implementation of TrueAudio metadata + + /*! + * This is implementation of TrueAudio metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream + * properties from the file. + */ + + namespace TrueAudio { + + //! An implementation of TagLib::File with TrueAudio specific methods + + /*! + * This implements and provides an interface for TrueAudio files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to TrueAudio files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a TrueAudio file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both ID3v1 and v2 tags, only ID3v2 will be + * converted to the PropertyMap. + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Creates in ID3v2 tag if necessary. If an ID3v1 tag exists, it will + * be updated as well, within the limitations of ID3v1. + */ + PropertyMap setProperties(const PropertyMap &); + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Returns the TrueAudio::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a TrueAudio + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/trueaudioproperties.h b/external/taglib/include/trueaudioproperties.h new file mode 100644 index 0000000..d25c7a7 --- /dev/null +++ b/external/taglib/include/trueaudioproperties.h @@ -0,0 +1,133 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOPROPERTIES_H +#define TAGLIB_TRUEAUDIOPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace TrueAudio { + + class File; + + static const unsigned int HeaderSize = 18; + + //! An implementation of audio property reading for TrueAudio + + /*! + * This reads the data from an TrueAudio stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of TrueAudio::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this TrueAudio::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the total number of sample frames + */ + unsigned int sampleFrames() const; + + /*! + * Returns the major version number. + */ + int ttaVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/tstring.h b/external/taglib/include/tstring.h new file mode 100644 index 0000000..7028aab --- /dev/null +++ b/external/taglib/include/tstring.h @@ -0,0 +1,580 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRING_H +#define TAGLIB_STRING_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" + +#include +#include + +/*! + * \relates TagLib::String + * + * Converts a QString to a TagLib::String without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + */ + +#if defined(QT_VERSION) && (QT_VERSION >= 0x040000) +#define QStringToTString(s) TagLib::String(s.toUtf8().data(), TagLib::String::UTF8) +#else +#define QStringToTString(s) TagLib::String(s.utf8().data(), TagLib::String::UTF8) +#endif + +/*! + * \relates TagLib::String + * + * Converts a TagLib::String to a QString without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + * + */ + +#define TStringToQString(s) QString::fromUtf8(s.toCString(true)) + +namespace TagLib { + + class StringList; + + //! A \e wide string class suitable for unicode. + + /*! + * This is an implicitly shared \e wide string. For storage it uses + * TagLib::wstring, but as this is an implementation detail this of + * course could change. Strings are stored internally as UTF-16(without BOM/ + * CPU byte order) + * + * The use of implicit sharing means that copying a string is cheap, the only + * \e cost comes into play when the copy is modified. Prior to that the string + * just has a pointer to the data of the \e parent String. This also makes + * this class suitable as a function return type. + * + * In addition to adding implicit sharing, this class keeps track of four + * possible encodings, which are the four supported by the ID3v2 standard. + */ + + class TAGLIB_EXPORT String + { + public: + +#ifndef DO_NOT_DOCUMENT + typedef TagLib::wstring::iterator Iterator; + typedef TagLib::wstring::const_iterator ConstIterator; +#endif + + /** + * The four types of string encodings supported by the ID3v2 specification. + * ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8. + */ + enum Type { + /*! + * IS08859-1, or Latin1 encoding. 8 bit characters. + */ + Latin1 = 0, + /*! + * UTF16 with a byte order mark. 16 bit characters. + */ + UTF16 = 1, + /*! + * UTF16 big endian. 16 bit characters. This is the encoding used + * internally by TagLib. + */ + UTF16BE = 2, + /*! + * UTF8 encoding. Characters are usually 8 bits but can be up to 32. + */ + UTF8 = 3, + /*! + * UTF16 little endian. 16 bit characters. + */ + UTF16LE = 4 + }; + + /*! + * Constructs an empty String. + */ + String(); + + /*! + * Make a shallow, implicitly shared, copy of \a s. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + String(const String &s); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const std::string &s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. + */ + String(const wstring &s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. + */ + String(const wchar_t *s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a c. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(char c, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a c. + */ + String(wchar_t c, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const char *s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a v. + */ + String(const ByteVector &v, Type t = Latin1); + + /*! + * Destroys this String instance. + */ + virtual ~String(); + + /*! + * Returns a deep copy of this String as an std::string. The returned string + * is encoded in UTF8 if \a unicode is true, otherwise Latin1. + * + * \see toCString() + */ + std::string to8Bit(bool unicode = false) const; + + /*! + * Returns a deep copy of this String as a wstring. The returned string is + * encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t + * is 32-bit wide. + * + * \see toCWString() + */ + wstring toWString() const; + + /*! + * Creates and returns a standard C-style (null-terminated) version of this + * String. The returned string is encoded in UTF8 if \a unicode is true, + * otherwise Latin1. + * + * The returned string is still owned by this String and should not be deleted + * by the user. + * + * The returned pointer remains valid until this String instance is destroyed + * or toCString() is called again. + * + * \warning This however has the side effect that the returned string will remain + * in memory in addition to other memory that is consumed by this + * String instance. So, this method should not be used on large strings or + * where memory is critical. Consider using to8Bit() instead to avoid it. + * + * \see to8Bit() + */ + const char *toCString(bool unicode = false) const; + + /*! + * Returns a standard C-style (null-terminated) wide character version of + * this String. The returned string is encoded in UTF-16 (without BOM/CPU byte + * order), not UTF-32 even if wchar_t is 32-bit wide. + * + * The returned string is still owned by this String and should not be deleted + * by the user. + * + * The returned pointer remains valid until this String instance is destroyed + * or any other method of this String is called. + * + * \note This returns a pointer to the String's internal data without any + * conversions. + * + * \see toWString() + */ + const wchar_t *toCWString() const; + + /*! + * Returns an iterator pointing to the beginning of the string. + */ + Iterator begin(); + + /*! + * Returns a const iterator pointing to the beginning of the string. + */ + ConstIterator begin() const; + + /*! + * Returns an iterator pointing to the end of the string (the position + * after the last character). + */ + Iterator end(); + + /*! + * Returns a const iterator pointing to the end of the string (the position + * after the last character). + */ + ConstIterator end() const; + + /*! + * Finds the first occurrence of pattern \a s in this string starting from + * \a offset. If the pattern is not found, -1 is returned. + */ + int find(const String &s, int offset = 0) const; + + /*! + * Finds the last occurrence of pattern \a s in this string, searched backwards, + * either from the end of the string or starting from \a offset. If the pattern + * is not found, -1 is returned. + */ + int rfind(const String &s, int offset = -1) const; + + /*! + * Splits the string on each occurrence of \a separator. + */ + StringList split(const String &separator = " ") const; + + /*! + * Returns true if the strings starts with the substring \a s. + */ + bool startsWith(const String &s) const; + + /*! + * Extract a substring from this string starting at \a position and + * continuing for \a n characters. + */ + String substr(unsigned int position, unsigned int n = 0xffffffff) const; + + /*! + * Append \a s to the current string and return a reference to the current + * string. + */ + String &append(const String &s); + + /*! + * Clears the string. + */ + String &clear(); + + /*! + * Returns an upper case version of the string. + * + * \warning This only works for the characters in US-ASCII, i.e. A-Z. + */ + String upper() const; + + /*! + * Returns the size of the string. + */ + unsigned int size() const; + + /*! + * Returns the length of the string. Equivalent to size(). + */ + unsigned int length() const; + + /*! + * Returns true if the string is empty. + * + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns true if this string is null -- i.e. it is a copy of the + * String::null string. + * + * \note A string can be empty and not null. So do not use this method to + * check if the string is empty. + * + * \see isEmpty() + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED bool isNull() const; + + /*! + * Returns a ByteVector containing the string's data. If \a t is Latin1 or + * UTF8, this will return a vector of 8 bit characters, otherwise it will use + * 16 bit characters. + * + * \note If \a t is UTF16, the returned data is encoded in little-endian + * format and has a BOM. + * + * \note The returned data is not null terminated. + */ + ByteVector data(Type t) const; + + /*! + * Convert the string to an integer. + * + * Returns the integer if the conversion was successful or 0 if the + * string does not represent a number. + */ + // BIC: merge with the method below + int toInt() const; + + /*! + * Convert the string to an integer. + * + * If the conversion was successful, it sets the value of \a *ok to + * true and returns the integer. Otherwise it sets \a *ok to false + * and the result is undefined. + */ + int toInt(bool *ok) const; + + /*! + * Returns a string with the leading and trailing whitespace stripped. + */ + String stripWhiteSpace() const; + + /*! + * Returns true if the file only uses characters required by Latin1. + */ + bool isLatin1() const; + + /*! + * Returns true if the file only uses characters required by (7-bit) ASCII. + */ + bool isAscii() const; + + /*! + * Converts the base-10 integer \a n to a string. + */ + static String number(int n); + + /*! + * Returns a reference to the character at position \a i. + */ + wchar_t &operator[](int i); + + /*! + * Returns a const reference to the character at position \a i. + */ + const wchar_t &operator[](int i) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const String &s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const String &s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const char *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const char *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const wchar_t *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const wchar_t *s) const; + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const String &s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const wchar_t* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const char* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(wchar_t c); + + /*! + * Appends \a c to the end of the String. + */ + String &operator+=(char c); + + /*! + * Performs a shallow, implicitly shared, copy of \a s, overwriting the + * String's current data. + */ + String &operator=(const String &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const std::string &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wstring &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wchar_t *s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(char c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(wchar_t c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const char *s); + + /*! + * Performs a deep copy of the data in \a v. + */ + String &operator=(const ByteVector &v); + + /*! + * Exchanges the content of the String by the content of \a s. + */ + void swap(String &s); + + /*! + * To be able to use this class in a Map, this operator needed to be + * implemented. Returns true if \a s is less than this string in a byte-wise + * comparison. + */ + bool operator<(const String &s) const; + + /*! + * A null string provided for convenience. + * + * \warning Do not modify this variable. It will mess up the internal state + * of TagLib. + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED static String null; + + protected: + /*! + * If this String is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: + /*! + * \deprecated This variable is no longer used, but NEVER remove this. It + * may lead to a linkage error. + */ + // BIC: remove + TAGLIB_DEPRECATED static const Type WCharByteOrder; + + class StringPrivate; + StringPrivate *d; + }; +} + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const char *s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const char *s2); + + +/*! + * \relates TagLib::String + * + * Send the string to an output stream. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::String &str); + +#endif diff --git a/external/taglib/include/tstringlist.h b/external/taglib/include/tstringlist.h new file mode 100644 index 0000000..ddf0f04 --- /dev/null +++ b/external/taglib/include/tstringlist.h @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRINGLIST_H +#define TAGLIB_STRINGLIST_H + +#include "tstring.h" +#include "tlist.h" +#include "tbytevectorlist.h" +#include "taglib_export.h" + +#include + +namespace TagLib { + + //! A list of strings + + /*! + * This is a specialization of the List class with some members convention for + * string operations. + */ + + class TAGLIB_EXPORT StringList : public List + { + public: + + /*! + * Constructs an empty StringList. + */ + StringList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + StringList(const StringList &l); + + /*! + * Constructs a StringList with \a s as a member. + */ + StringList(const String &s); + + /*! + * Makes a deep copy of the data in \a vl. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + StringList(const ByteVectorList &vl, String::Type t = String::Latin1); + + /*! + * Destroys this StringList instance. + */ + virtual ~StringList(); + + /*! + * Concatenate the list of strings into one string separated by \a separator. + */ + String toString(const String &separator = " ") const; + + /*! + * Appends \a s to the end of the list and returns a reference to the + * list. + */ + StringList &append(const String &s); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + StringList &append(const StringList &l); + + /*! + * Splits the String \a s into several strings at \a pattern. This will not include + * the pattern in the returned strings. + */ + static StringList split(const String &s, const String &pattern); + + private: + class StringListPrivate; + StringListPrivate *d; + }; + +} + +/*! + * \related TagLib::StringList + * Send the StringList to an output stream. + */ +std::ostream TAGLIB_EXPORT &operator<<(std::ostream &s, const TagLib::StringList &l); + +#endif diff --git a/external/taglib/include/tutils.h b/external/taglib/include/tutils.h new file mode 100644 index 0000000..6d96cd1 --- /dev/null +++ b/external/taglib/include/tutils.h @@ -0,0 +1,243 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TUTILS_H +#define TAGLIB_TUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(HAVE_MSC_BYTESWAP) +# include +#elif defined(HAVE_GLIBC_BYTESWAP) +# include +#elif defined(HAVE_MAC_BYTESWAP) +# include +#elif defined(HAVE_OPENBSD_BYTESWAP) +# include +#endif + +#include +#include +#include +#include + +namespace TagLib +{ + namespace Utils + { + namespace + { + + /*! + * Reverses the order of bytes in an 16-bit integer. + */ + inline unsigned short byteSwap(unsigned short x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap16(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_ushort(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_16(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt16(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap16(x); + +#else + + return ((x >> 8) & 0xff) | ((x & 0xff) << 8); + +#endif + } + + /*! + * Reverses the order of bytes in an 32-bit integer. + */ + inline unsigned int byteSwap(unsigned int x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap32(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_ulong(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_32(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt32(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap32(x); + +#else + + return ((x & 0xff000000u) >> 24) + | ((x & 0x00ff0000u) >> 8) + | ((x & 0x0000ff00u) << 8) + | ((x & 0x000000ffu) << 24); + +#endif + } + + /*! + * Reverses the order of bytes in an 64-bit integer. + */ + inline unsigned long long byteSwap(unsigned long long x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap64(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_uint64(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_64(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt64(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap64(x); + +#else + + return ((x & 0xff00000000000000ull) >> 56) + | ((x & 0x00ff000000000000ull) >> 40) + | ((x & 0x0000ff0000000000ull) >> 24) + | ((x & 0x000000ff00000000ull) >> 8) + | ((x & 0x00000000ff000000ull) << 8) + | ((x & 0x0000000000ff0000ull) << 24) + | ((x & 0x000000000000ff00ull) << 40) + | ((x & 0x00000000000000ffull) << 56); + +#endif + } + + /*! + * Returns a formatted string just like standard sprintf(), but makes use of + * safer functions such as snprintf() if available. + */ + inline String formatString(const char *format, ...) + { + // Sufficient buffer size for the current internal uses. + // Consider changing this value when you use this function. + + static const size_t BufferSize = 128; + + va_list args; + va_start(args, format); + + char buf[BufferSize]; + int length; + +#if defined(HAVE_VSNPRINTF) + + length = vsnprintf(buf, BufferSize, format, args); + +#elif defined(HAVE_VSPRINTF_S) + + length = vsprintf_s(buf, format, args); + +#else + + // The last resort. May cause a buffer overflow. + + length = vsprintf(buf, format, args); + if(length >= BufferSize) { + debug("Utils::formatString() - Buffer overflow! Returning an empty string."); + length = -1; + } + +#endif + + va_end(args); + + if(length > 0) + return String(buf); + else + return String(); + } + + /*! + * The types of byte order of the running system. + */ + enum ByteOrder + { + //! Little endian systems. + LittleEndian, + //! Big endian systems. + BigEndian + }; + + /*! + * Returns the byte order of the system. + */ + inline ByteOrder systemByteOrder() + { + union { + int i; + char c; + } u; + + u.i = 1; + if(u.c == 1) + return LittleEndian; + else + return BigEndian; + } + } + } +} + +#endif + +#endif diff --git a/external/taglib/include/tzlib.h b/external/taglib/include/tzlib.h new file mode 100644 index 0000000..dab7828 --- /dev/null +++ b/external/taglib/include/tzlib.h @@ -0,0 +1,54 @@ +/*************************************************************************** + copyright : (C) 2016 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TZLIB_H +#define TAGLIB_TZLIB_H + +#include + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib { + + namespace zlib { + + /*! + * Returns whether or not zlib is installed and ready to use. + */ + bool TAGLIB_EXPORT isAvailable(); + + /*! + * Decompress \a data by zlib. + */ + ByteVector decompress(const ByteVector &data); + + } +} + +#endif + +#endif diff --git a/external/taglib/include/uniquefileidentifierframe.h b/external/taglib/include/uniquefileidentifierframe.h new file mode 100644 index 0000000..decf1b0 --- /dev/null +++ b/external/taglib/include/uniquefileidentifierframe.h @@ -0,0 +1,123 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNIQUEFILEIDENTIFIERFRAME +#define TAGLIB_UNIQUEFILEIDENTIFIERFRAME + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 unique file identifier frames. This + * frame is used to identify the file in an arbitrary database identified + * by the owner field. + */ + + //! An implementation of ID3v2 unique identifier frames + + class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a unique file identifier frame based on \a data. + */ + UniqueFileIdentifierFrame(const ByteVector &data); + + /*! + * Creates a unique file identifier frame with the owner \a owner and + * the identification \a id. + */ + UniqueFileIdentifierFrame(const String &owner, const ByteVector &id); + + /*! + * Destroys the frame. + */ + ~UniqueFileIdentifierFrame(); + + /*! + * Returns the owner for the frame; essentially this is the key for + * determining which identification scheme this key belongs to. This + * will usually either be an email address or URL for the person or tool + * used to create the unique identifier. + * + * \see setOwner() + */ + String owner() const; + + /*! + * Returns the unique identifier. Though sometimes this is a text string + * it also may be binary data and as much should be assumed when handling + * it. + */ + ByteVector identifier() const; + + /*! + * Sets the owner of the identification scheme to \a s. + * + * \see owner() + */ + void setOwner(const String &s); + + /*! + * Sets the unique file identifier to \a v. + * + * \see identifier() + */ + void setIdentifier(const ByteVector &v); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * UFID frames each have a unique owner. This searches for a UFID + * frame with the owner \a o and returns a pointer to it. + * + * \see owner() + */ + static UniqueFileIdentifierFrame *findByOwner(const Tag *tag, const String &o); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UniqueFileIdentifierFrame(const UniqueFileIdentifierFrame &); + UniqueFileIdentifierFrame &operator=(const UniqueFileIdentifierFrame &); + + UniqueFileIdentifierFrame(const ByteVector &data, Header *h); + + class UniqueFileIdentifierFramePrivate; + UniqueFileIdentifierFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/unknownframe.h b/external/taglib/include/unknownframe.h new file mode 100644 index 0000000..6559f4e --- /dev/null +++ b/external/taglib/include/unknownframe.h @@ -0,0 +1,79 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNKNOWNFRAME_H +#define TAGLIB_UNKNOWNFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A frame type \e unknown to TagLib. + + /*! + * This class represents a frame type not known (or more often simply + * unimplemented) in TagLib. This is here provide a basic API for + * manipulating the binary data of unknown frames and to provide a means + * of rendering such \e unknown frames. + * + * Please note that a cleaner way of handling frame types that TagLib + * does not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory + * to have your frame type supported through the standard ID3v2 mechanism. + */ + + class TAGLIB_EXPORT UnknownFrame : public Frame + { + friend class FrameFactory; + + public: + UnknownFrame(const ByteVector &data); + virtual ~UnknownFrame(); + + virtual String toString() const; + + /*! + * Returns the field data (everything but the header) for this frame. + */ + ByteVector data() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UnknownFrame(const ByteVector &data, Header *h); + UnknownFrame(const UnknownFrame &); + UnknownFrame &operator=(const UnknownFrame &); + + class UnknownFramePrivate; + UnknownFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/unsynchronizedlyricsframe.h b/external/taglib/include/unsynchronizedlyricsframe.h new file mode 100644 index 0000000..dad67c7 --- /dev/null +++ b/external/taglib/include/unsynchronizedlyricsframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 unsynchronized lyrics frame + /*! + * An implementation of ID3v2 unsynchronized lyrics. + */ + class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty unsynchronized lyrics frame that will use the text encoding + * \a encoding. + */ + explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a unsynchronized lyrics frame based on the data in \a data. + */ + explicit UnsynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this UnsynchronizedLyricsFrame instance. + */ + virtual ~UnsynchronizedLyricsFrame(); + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this unsynchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the unsynchronized lyrics frame to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the unsynchronized lyrics frame to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + + /*! Parses this frame as PropertyMap with a single key. + * - if description() is empty or "LYRICS", the key will be "LYRICS" + * - if description() is not a valid PropertyMap key, the frame will be + * marked unsupported by an entry "USLT/" in the unsupportedData() + * attribute of the returned map. + * - otherwise, the key will be "LYRICS:" + * - The single value will be the frame's text(). + * Note that currently the language() field is not supported by the PropertyMap + * interface. + */ + PropertyMap asProperties() const; + + /*! + * LyricsFrames each have a unique description. This searches for a lyrics + * frame with the description \a d and returns a pointer to it. If no + * frame is found that matches the given description null is returned. + * + * \see description() + */ + static UnsynchronizedLyricsFrame *findByDescription(const Tag *tag, const String &d); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + UnsynchronizedLyricsFrame(const ByteVector &data, Header *h); + UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &); + UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &); + + class UnsynchronizedLyricsFramePrivate; + UnsynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/urllinkframe.h b/external/taglib/include/urllinkframe.h new file mode 100644 index 0000000..d9ac109 --- /dev/null +++ b/external/taglib/include/urllinkframe.h @@ -0,0 +1,190 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_URLLINKFRAME_H +#define TAGLIB_URLLINKFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 URL frame + /*! + * An implementation of ID3v2 URL link frames. + */ + class TAGLIB_EXPORT UrlLinkFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UrlLinkFrame instance. + */ + virtual ~UrlLinkFrame(); + + /*! + * Returns the URL. + */ + virtual String url() const; + + /*! + * Sets the URL to \a s. + */ + virtual void setUrl(const String &s); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + PropertyMap asProperties() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UrlLinkFrame(const ByteVector &data, Header *h); + + private: + UrlLinkFrame(const UrlLinkFrame &); + UrlLinkFrame &operator=(const UrlLinkFrame &); + + class UrlLinkFramePrivate; + UrlLinkFramePrivate *d; + }; + + //! ID3v2 User defined URL frame + + /*! + * This is a specialization of URL link frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a URL link frame has. + * + * This description identifies the frame and must be unique. + */ + class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined URL link frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserUrlLinkFrame(String::Type encoding = String::Latin1); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UserUrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UserUrlLinkFrame instance. + */ + virtual ~UserUrlLinkFrame(); + + // Reimplementations. + + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. + */ + void setDescription(const String &s); + + /*! + * Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key, + * and the URL as single value. + * - if description() is empty, the key will be "URL". + * - otherwise, if description() is not a valid key (e.g. containing non-ASCII + * characters), the returned map will contain an entry "WXXX/" + * in its unsupportedData() list. + */ + PropertyMap asProperties() const; + + /*! + * Searches for the user defined url frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserUrlLinkFrame *find(Tag *tag, const String &description); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UserUrlLinkFrame(const ByteVector &data, Header *h); + + private: + UserUrlLinkFrame(const UserUrlLinkFrame &); + UserUrlLinkFrame &operator=(const UserUrlLinkFrame &); + + class UserUrlLinkFramePrivate; + UserUrlLinkFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/include/utf8-cpp/checked.h b/external/taglib/include/utf8-cpp/checked.h new file mode 100644 index 0000000..2aef583 --- /dev/null +++ b/external/taglib/include/utf8-cpp/checked.h @@ -0,0 +1,327 @@ +// Copyright 2006-2016 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CHECKED_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include "core.h" +#include + +namespace utf8 +{ + // Base for the exceptions that may be thrown from the library + class exception : public ::std::exception { + }; + + // Exceptions that may be thrown from the library functions. + class invalid_code_point : public exception { + uint32_t cp; + public: + invalid_code_point(uint32_t codepoint) : cp(codepoint) {} + virtual const char* what() const throw() { return "Invalid code point"; } + uint32_t code_point() const {return cp;} + }; + + class invalid_utf8 : public exception { + uint8_t u8; + public: + invalid_utf8 (uint8_t u) : u8(u) {} + virtual const char* what() const throw() { return "Invalid UTF-8"; } + uint8_t utf8_octet() const {return u8;} + }; + + class invalid_utf16 : public exception { + uint16_t u16; + public: + invalid_utf16 (uint16_t u) : u16(u) {} + virtual const char* what() const throw() { return "Invalid UTF-16"; } + uint16_t utf16_word() const {return u16;} + }; + + class not_enough_room : public exception { + public: + virtual const char* what() const throw() { return "Not enough space"; } + }; + + /// The library API - functions intended to be called by the users + + template + octet_iterator append(uint32_t cp, octet_iterator result) + { + if (!utf8::internal::is_code_point_valid(cp)) + throw invalid_code_point(cp); + + if (cp < 0x80) // one octet + *(result++) = static_cast(cp); + else if (cp < 0x800) { // two octets + *(result++) = static_cast((cp >> 6) | 0xc0); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else if (cp < 0x10000) { // three octets + *(result++) = static_cast((cp >> 12) | 0xe0); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + else { // four octets + *(result++) = static_cast((cp >> 18) | 0xf0); + *(result++) = static_cast(((cp >> 12) & 0x3f) | 0x80); + *(result++) = static_cast(((cp >> 6) & 0x3f) | 0x80); + *(result++) = static_cast((cp & 0x3f) | 0x80); + } + return result; + } + + template + output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) + { + while (start != end) { + octet_iterator sequence_start = start; + internal::utf_error err_code = utf8::internal::validate_next(start, end); + switch (err_code) { + case internal::UTF8_OK : + for (octet_iterator it = sequence_start; it != start; ++it) + *out++ = *it; + break; + case internal::NOT_ENOUGH_ROOM: + throw not_enough_room(); + case internal::INVALID_LEAD: + out = utf8::append (replacement, out); + ++start; + break; + case internal::INCOMPLETE_SEQUENCE: + case internal::OVERLONG_SEQUENCE: + case internal::INVALID_CODE_POINT: + out = utf8::append (replacement, out); + ++start; + // just one replacement mark for the sequence + while (start != end && utf8::internal::is_trail(*start)) + ++start; + break; + } + } + return out; + } + + template + inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) + { + static const uint32_t replacement_marker = utf8::internal::mask16(0xfffd); + return utf8::replace_invalid(start, end, out, replacement_marker); + } + + template + uint32_t next(octet_iterator& it, octet_iterator end) + { + uint32_t cp = 0; + internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); + switch (err_code) { + case internal::UTF8_OK : + break; + case internal::NOT_ENOUGH_ROOM : + throw not_enough_room(); + case internal::INVALID_LEAD : + case internal::INCOMPLETE_SEQUENCE : + case internal::OVERLONG_SEQUENCE : + throw invalid_utf8(*it); + case internal::INVALID_CODE_POINT : + throw invalid_code_point(cp); + } + return cp; + } + + template + uint32_t peek_next(octet_iterator it, octet_iterator end) + { + return utf8::next(it, end); + } + + template + uint32_t prior(octet_iterator& it, octet_iterator start) + { + // can't do much if it == start + if (it == start) + throw not_enough_room(); + + octet_iterator end = it; + // Go back until we hit either a lead octet or start + while (utf8::internal::is_trail(*(--it))) + if (it == start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + return utf8::peek_next(it, end); + } + + /// Deprecated in versions that include "prior" + template + uint32_t previous(octet_iterator& it, octet_iterator pass_start) + { + octet_iterator end = it; + while (utf8::internal::is_trail(*(--it))) + if (it == pass_start) + throw invalid_utf8(*it); // error - no lead byte in the sequence + octet_iterator temp = it; + return utf8::next(temp, end); + } + + template + void advance (octet_iterator& it, distance_type n, octet_iterator end) + { + for (distance_type i = 0; i < n; ++i) + utf8::next(it, end); + } + + template + typename std::iterator_traits::difference_type + distance (octet_iterator first, octet_iterator last) + { + typename std::iterator_traits::difference_type dist; + for (dist = 0; first < last; ++dist) + utf8::next(first, last); + return dist; + } + + template + octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) + { + while (start != end) { + uint32_t cp = utf8::internal::mask16(*start++); + // Take care of surrogate pairs first + if (utf8::internal::is_lead_surrogate(cp)) { + if (start != end) { + uint32_t trail_surrogate = utf8::internal::mask16(*start++); + if (utf8::internal::is_trail_surrogate(trail_surrogate)) + cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; + else + throw invalid_utf16(static_cast(trail_surrogate)); + } + else + throw invalid_utf16(static_cast(cp)); + + } + // Lone trail surrogate + else if (utf8::internal::is_trail_surrogate(cp)) + throw invalid_utf16(static_cast(cp)); + + result = utf8::append(cp, result); + } + return result; + } + + template + u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) + { + while (start < end) { + uint32_t cp = utf8::next(start, end); + if (cp > 0xffff) { //make a surrogate pair + *result++ = static_cast((cp >> 10) + internal::LEAD_OFFSET); + *result++ = static_cast((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); + } + else + *result++ = static_cast(cp); + } + return result; + } + + template + octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) + { + while (start != end) + result = utf8::append(*(start++), result); + + return result; + } + + template + u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) + { + while (start < end) + (*result++) = utf8::next(start, end); + + return result; + } + + // The iterator class + template + class iterator : public std::iterator { + octet_iterator it; + octet_iterator range_start; + octet_iterator range_end; + public: + iterator () {} + explicit iterator (const octet_iterator& octet_it, + const octet_iterator& rangestart, + const octet_iterator& rangeend) : + it(octet_it), range_start(rangestart), range_end(rangeend) + { + if (it < range_start || it > range_end) + throw std::out_of_range("Invalid utf-8 iterator position"); + } + // the default "big three" are OK + octet_iterator base () const { return it; } + uint32_t operator * () const + { + octet_iterator temp = it; + return utf8::next(temp, range_end); + } + bool operator == (const iterator& rhs) const + { + if (range_start != rhs.range_start || range_end != rhs.range_end) + throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); + return (it == rhs.it); + } + bool operator != (const iterator& rhs) const + { + return !(operator == (rhs)); + } + iterator& operator ++ () + { + utf8::next(it, range_end); + return *this; + } + iterator operator ++ (int) + { + iterator temp = *this; + utf8::next(it, range_end); + return temp; + } + iterator& operator -- () + { + utf8::prior(it, range_start); + return *this; + } + iterator operator -- (int) + { + iterator temp = *this; + utf8::prior(it, range_start); + return temp; + } + }; // class iterator + +} // namespace utf8 + +#endif //header guard + + diff --git a/external/taglib/include/utf8-cpp/core.h b/external/taglib/include/utf8-cpp/core.h new file mode 100644 index 0000000..ae0f367 --- /dev/null +++ b/external/taglib/include/utf8-cpp/core.h @@ -0,0 +1,332 @@ +// Copyright 2006 Nemanja Trifunovic + +/* +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + + +#ifndef UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 +#define UTF8_FOR_CPP_CORE_H_2675DCD0_9480_4c0c_B92A_CC14C027B731 + +#include + +namespace utf8 +{ + // The typedefs for 8-bit, 16-bit and 32-bit unsigned integers + // You may need to change them to match your system. + // These typedefs have the same names as ones from cstdint, or boost/cstdint + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + +// Helper code - not intended to be directly called by the library users. May be changed at any time +namespace internal +{ + // Unicode constants + // Leading (high) surrogates: 0xd800 - 0xdbff + // Trailing (low) surrogates: 0xdc00 - 0xdfff + const uint16_t LEAD_SURROGATE_MIN = 0xd800u; + const uint16_t LEAD_SURROGATE_MAX = 0xdbffu; + const uint16_t TRAIL_SURROGATE_MIN = 0xdc00u; + const uint16_t TRAIL_SURROGATE_MAX = 0xdfffu; + const uint16_t LEAD_OFFSET = LEAD_SURROGATE_MIN - (0x10000 >> 10); + const uint32_t SURROGATE_OFFSET = 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN; + + // Maximum valid value for a Unicode code point + const uint32_t CODE_POINT_MAX = 0x0010ffffu; + + template + inline uint8_t mask8(octet_type oc) + { + return static_cast(0xff & oc); + } + template + inline uint16_t mask16(u16_type oc) + { + return static_cast(0xffff & oc); + } + template + inline bool is_trail(octet_type oc) + { + return ((utf8::internal::mask8(oc) >> 6) == 0x2); + } + + template + inline bool is_lead_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= LEAD_SURROGATE_MAX); + } + + template + inline bool is_trail_surrogate(u16 cp) + { + return (cp >= TRAIL_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_surrogate(u16 cp) + { + return (cp >= LEAD_SURROGATE_MIN && cp <= TRAIL_SURROGATE_MAX); + } + + template + inline bool is_code_point_valid(u32 cp) + { + return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); + } + + template + inline typename std::iterator_traits::difference_type + sequence_length(octet_iterator lead_it) + { + uint8_t lead = utf8::internal::mask8(*lead_it); + if (lead < 0x80) + return 1; + else if ((lead >> 5) == 0x6) + return 2; + else if ((lead >> 4) == 0xe) + return 3; + else if ((lead >> 3) == 0x1e) + return 4; + else + return 0; + } + + template + inline bool is_overlong_sequence(uint32_t cp, octet_difference_type length) + { + if (cp < 0x80) { + if (length != 1) + return true; + } + else if (cp < 0x800) { + if (length != 2) + return true; + } + else if (cp < 0x10000) { + if (length != 3) + return true; + } + + return false; + } + + enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; + + /// Helper for get_sequence_x + template + utf_error increase_safely(octet_iterator& it, octet_iterator end) + { + if (++it == end) + return NOT_ENOUGH_ROOM; + + if (!utf8::internal::is_trail(*it)) + return INCOMPLETE_SEQUENCE; + + return UTF8_OK; + } + + #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} + + /// get_sequence_x functions decode utf-8 sequences of the length x + template + utf_error get_sequence_1(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + return UTF8_OK; + } + + template + utf_error get_sequence_2(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); + + return UTF8_OK; + } + + template + utf_error get_sequence_3(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + template + utf_error get_sequence_4(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + code_point = utf8::internal::mask8(*it); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (utf8::internal::mask8(*it) << 6) & 0xfff; + + UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) + + code_point += (*it) & 0x3f; + + return UTF8_OK; + } + + #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR + + template + utf_error validate_next(octet_iterator& it, octet_iterator end, uint32_t& code_point) + { + if (it == end) + return NOT_ENOUGH_ROOM; + + // Save the original value of it so we can go back in case of failure + // Of course, it does not make much sense with i.e. stream iterators + octet_iterator original_it = it; + + uint32_t cp = 0; + // Determine the sequence length based on the lead octet + typedef typename std::iterator_traits::difference_type octet_difference_type; + const octet_difference_type length = utf8::internal::sequence_length(it); + + // Get trail octets and calculate the code point + utf_error err = UTF8_OK; + switch (length) { + case 0: + return INVALID_LEAD; + case 1: + err = utf8::internal::get_sequence_1(it, end, cp); + break; + case 2: + err = utf8::internal::get_sequence_2(it, end, cp); + break; + case 3: + err = utf8::internal::get_sequence_3(it, end, cp); + break; + case 4: + err = utf8::internal::get_sequence_4(it, end, cp); + break; + } + + if (err == UTF8_OK) { + // Decoding succeeded. Now, security checks... + if (utf8::internal::is_code_point_valid(cp)) { + if (!utf8::internal::is_overlong_sequence(cp, length)){ + // Passed! Return here. + code_point = cp; + ++it; + return UTF8_OK; + } + else + err = OVERLONG_SEQUENCE; + } + else + err = INVALID_CODE_POINT; + } + + // Failure branch - restore the original value of the iterator + it = original_it; + return err; + } + + template + inline utf_error validate_next(octet_iterator& it, octet_iterator end) { + uint32_t ignored; + return utf8::internal::validate_next(it, end, ignored); + } + +} // namespace internal + + /// The library API - functions intended to be called by the users + + // Byte order mark + const uint8_t bom[] = {0xef, 0xbb, 0xbf}; + + template + octet_iterator find_invalid(octet_iterator start, octet_iterator end) + { + octet_iterator result = start; + while (result != end) { + utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); + if (err_code != internal::UTF8_OK) + return result; + } + return result; + } + + template + inline bool is_valid(octet_iterator start, octet_iterator end) + { + return (utf8::find_invalid(start, end) == end); + } + + template + inline bool starts_with_bom (octet_iterator it, octet_iterator end) + { + return ( + ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && + ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && + ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) + ); + } + + //Deprecated in release 2.3 + template + inline bool is_bom (octet_iterator it) + { + return ( + (utf8::internal::mask8(*it++)) == bom[0] && + (utf8::internal::mask8(*it++)) == bom[1] && + (utf8::internal::mask8(*it)) == bom[2] + ); + } +} // namespace utf8 + +#endif // header guard + + diff --git a/external/taglib/include/vorbisfile.h b/external/taglib/include/vorbisfile.h new file mode 100644 index 0000000..04c0c04 --- /dev/null +++ b/external/taglib/include/vorbisfile.h @@ -0,0 +1,157 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISFILE_H +#define TAGLIB_VORBISFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "vorbisproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + //! A namespace containing classes for Vorbis metadata + + namespace Vorbis { + + + //! An implementation of Ogg::File with Vorbis specific methods + + /*! + * This is the central class in the Ogg Vorbis metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Vorbis specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs a Vorbis file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a Vorbis file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Vorbis::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Check if the given \a stream can be opened as an Ogg Vorbis file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::Vorbis::File File; } } +#endif + +} + +#endif diff --git a/external/taglib/include/vorbisproperties.h b/external/taglib/include/vorbisproperties.h new file mode 100644 index 0000000..472e039 --- /dev/null +++ b/external/taglib/include/vorbisproperties.h @@ -0,0 +1,160 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISPROPERTIES_H +#define TAGLIB_VORBISPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + namespace Vorbis { + + class File; + + //! An implementation of audio property reading for Ogg Vorbis + + /*! + * This reads the data from an Ogg Vorbis stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int vorbisVersion() const; + + /*! + * Returns the maximum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMaximum() const; + + /*! + * Returns the nominal bitrate as read from the Vorbis identification + * header. + */ + int bitrateNominal() const; + + /*! + * Returns the minimum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMinimum() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::AudioProperties AudioProperties; } } +#endif + +} + +#endif diff --git a/external/taglib/include/wavfile.h b/external/taglib/include/wavfile.h new file mode 100644 index 0000000..bc9ce31 --- /dev/null +++ b/external/taglib/include/wavfile.h @@ -0,0 +1,215 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILE_H +#define TAGLIB_WAVFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "infotag.h" +#include "wavproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of WAV metadata + + /*! + * This is implementation of WAV metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace WAV { + + //! An implementation of TagLib::File with WAV specific methods + + /*! + * This implements and provides an interface for WAV files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WAV files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v2 tags. + ID3v2 = 0x0001, + //! Matches INFO tags. + Info = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a WAV file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a WAV file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the ID3v2 Tag for this file. + * + * \note This method does not return all the tags for this file for + * backward compatibility. Will be fixed in TagLib 2.0. + */ + ID3v2::Tag *tag() const; + + /*! + * Returns the ID3v2 Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the + * file on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag() const; + + /*! + * Returns the RIFF INFO Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has a RIFF INFO tag. Use hasInfoTag() to check if the + * file on disk actually has a RIFF INFO tag. + * + * \see hasInfoTag() + */ + Info::Tag *InfoTag() const; + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * \note This will update the file immediately. + */ + void strip(TagTypes tags = AllTags); + + /*! + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the WAV::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED bool save(TagTypes tags, bool stripOthers, int id3v2Version = 4); + + /*! + * Save the file. If \a strip is specified, it is possible to choose if + * tags not specified in \a tags should be stripped from the file or + * retained. With \a version, it is possible to specify whether ID3v2.4 + * or ID3v2.3 should be used. + */ + bool save(TagTypes tags, StripTags strip = StripOthers, + ID3v2::Version version = ID3v2::v4); + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the file on disk actually has a RIFF INFO tag. + * + * \see InfoTag() + */ + bool hasInfoTag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a WAV + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + void removeTagChunks(TagTypes tags); + + friend class Properties; + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/wavpackfile.h b/external/taglib/include/wavpackfile.h new file mode 100644 index 0000000..ccc4ef6 --- /dev/null +++ b/external/taglib/include/wavpackfile.h @@ -0,0 +1,223 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVFILE_H +#define TAGLIB_WVFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "wavpackproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of WavPack metadata + + /*! + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace WavPack { + + //! An implementation of TagLib::File with WavPack specific methods + + /*! + * This implements and provides an interface for WavPack files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WavPack files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a WavPack file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an WavPack file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only APE + * will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Creates an APE tag if it does not exists and calls setProperties() on + * that. Any existing ID3v1 tag will be updated as well. + */ + PropertyMap setProperties(const PropertyMap&); + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Check if the given \a stream can be opened as a WavPack file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/wavpackproperties.h b/external/taglib/include/wavpackproperties.h new file mode 100644 index 0000000..e6acdcc --- /dev/null +++ b/external/taglib/include/wavpackproperties.h @@ -0,0 +1,149 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVPROPERTIES_H +#define TAGLIB_WVPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace WavPack { + + class File; + + static const unsigned int HeaderSize = 32; + + //! An implementation of audio property reading for WavPack + + /*! + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WavPack::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, long streamLength, + ReadStyle style = Average); + + /*! + * Create an instance of WavPack::Properties. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this WavPack::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. 0 means unknown or custom. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns whether or not the file is lossless encoded. + */ + bool isLossless() const; + + /*! + * Returns the total number of audio samples in file. + */ + unsigned int sampleFrames() const; + + /*! + * Returns WavPack version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file, long streamLength); + unsigned int seekFinalIndex(File *file, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/wavproperties.h b/external/taglib/include/wavproperties.h new file mode 100644 index 0000000..1ca7310 --- /dev/null +++ b/external/taglib/include/wavproperties.h @@ -0,0 +1,163 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPROPERTIES_H +#define TAGLIB_WAVPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + + class ByteVector; + + namespace RIFF { + + namespace WAV { + + class File; + + //! An implementation of audio property reading for WAV + + /*! + * This reads the data from an WAV stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); + + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data and the length calculated using \a streamLength. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, unsigned int streamLength, ReadStyle style); + + /*! + * Create an instance of WAV::Properties with the data read from the + * WAV::File \a file. + */ + Properties(File *file, ReadStyle style); + + /*! + * Destroys this WAV::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the number of bits per audio sample. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Returns the number of sample frames. + */ + unsigned int sampleFrames() const; + + /*! + * Returns the format ID of the file. + * 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and + * so forth. + * + * \note For further information, refer to the WAVE Form Registration + * Numbers in RFC 2361. + */ + int format() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/include/xingheader.h b/external/taglib/include/xingheader.h new file mode 100644 index 0000000..ce75619 --- /dev/null +++ b/external/taglib/include/xingheader.h @@ -0,0 +1,129 @@ +/*************************************************************************** + copyright : (C) 2003 by Ismael Orenstein + email : orenstein@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XINGHEADER_H +#define TAGLIB_XINGHEADER_H + +#include "mpegheader.h" +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + + namespace MPEG { + + class File; + + //! An implementation of the Xing/VBRI headers + + /*! + * This is a minimalistic implementation of the Xing/VBRI VBR headers. + * Xing/VBRI headers are often added to VBR (variable bit rate) MP3 streams + * to make it easy to compute the length and quality of a VBR stream. Our + * implementation is only concerned with the total size of the stream (so + * that we can calculate the total playing time and the average bitrate). + * It uses + * this text and the XMMS sources as references. + */ + + class TAGLIB_EXPORT XingHeader + { + public: + /*! + * The type of the VBR header. + */ + enum HeaderType + { + /*! + * Invalid header or no VBR header found. + */ + Invalid = 0, + + /*! + * Xing header. + */ + Xing = 1, + + /*! + * VBRI header. + */ + VBRI = 2, + }; + + /*! + * Parses an Xing/VBRI header based on \a data which contains the entire + * first MPEG frame. + */ + XingHeader(const ByteVector &data); + + /*! + * Destroy this XingHeader instance. + */ + virtual ~XingHeader(); + + /*! + * Returns true if the data was parsed properly and if there is a valid + * Xing/VBRI header present. + */ + bool isValid() const; + + /*! + * Returns the total number of frames. + */ + unsigned int totalFrames() const; + + /*! + * Returns the total size of stream in bytes. + */ + unsigned int totalSize() const; + + /*! + * Returns the type of the VBR header. + */ + HeaderType type() const; + + /*! + * Returns the offset for the start of this Xing header, given the + * version and channels of the frame + * + * \deprecated Always returns 0. + */ + TAGLIB_DEPRECATED static int xingHeaderOffset(TagLib::MPEG::Header::Version v, + TagLib::MPEG::Header::ChannelMode c); + + private: + XingHeader(const XingHeader &); + XingHeader &operator=(const XingHeader &); + + void parse(const ByteVector &data); + + class XingHeaderPrivate; + XingHeaderPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/xiphcomment.h b/external/taglib/include/xiphcomment.h new file mode 100644 index 0000000..7925fa0 --- /dev/null +++ b/external/taglib/include/xiphcomment.h @@ -0,0 +1,280 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISCOMMENT_H +#define TAGLIB_VORBISCOMMENT_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "tstring.h" +#include "tstringlist.h" +#include "tbytevector.h" +#include "flacpicture.h" +#include "taglib_export.h" + +#ifdef _MSC_VER +// Explained at end of tpropertymap.cpp +extern template class TAGLIB_EXPORT TagLib::Map; +#endif + +namespace TagLib { + + namespace Ogg { + + /*! + * A mapping between a list of field names, or keys, and a list of values + * associated with that field. + * + * \see XiphComment::fieldListMap() + */ + typedef Map FieldListMap; + + //! Ogg Vorbis comment implementation + + /*! + * This class is an implementation of the Ogg Vorbis comment specification, + * to be found in section 5 of the Ogg Vorbis specification. Because this + * format is also used in other (currently unsupported) Xiph.org formats, it + * has been made part of a generic implementation rather than being limited + * to strictly Vorbis. + * + * Vorbis comments are a simple vector of keys and values, called fields. + * Multiple values for a given key are supported. + * + * \see fieldListMap() + */ + + class TAGLIB_EXPORT XiphComment : public TagLib::Tag + { + public: + /*! + * Constructs an empty Vorbis comment. + */ + XiphComment(); + + /*! + * Constructs a Vorbis comment from \a data. + */ + XiphComment(const ByteVector &data); + + /*! + * Destroys this instance of the XiphComment. + */ + virtual ~XiphComment(); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns the number of fields present in the comment. + */ + unsigned int fieldCount() const; + + /*! + * Returns a reference to the map of field lists. Because Xiph comments + * support multiple fields with the same key, a pure Map would not work. + * As such this is a Map of string lists, keyed on the comment field name. + * + * The standard set of Xiph/Vorbis fields (which may or may not be + * contained in any specific comment) is: + * + *
    + *
  • TITLE
  • + *
  • VERSION
  • + *
  • ALBUM
  • + *
  • ARTIST
  • + *
  • PERFORMER
  • + *
  • COPYRIGHT
  • + *
  • ORGANIZATION
  • + *
  • DESCRIPTION
  • + *
  • GENRE
  • + *
  • DATE
  • + *
  • LOCATION
  • + *
  • CONTACT
  • + *
  • ISRC
  • + *
+ * + * For a more detailed description of these fields, please see the Ogg + * Vorbis specification, section 5.2.2.1. + * + * \note The Ogg Vorbis comment specification does allow these key values + * to be either upper or lower case. However, it is conventional for them + * to be upper case. As such, TagLib, when parsing a Xiph/Vorbis comment, + * converts all fields to uppercase. When you are using this data + * structure, you will need to specify the field name in upper case. + * + * \warning You should not modify this data structure directly, instead + * use addField() and removeField(). + */ + const FieldListMap &fieldListMap() const; + + /*! + * Implements the unified property interface -- export function. + * The result is a one-to-one match of the Xiph comment, since it is + * completely compatible with the property interface (in fact, a Xiph + * comment is nothing more than a map from tag names to list of values, + * as is the dict interface). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * The tags from the given map will be stored one-to-one in the file, + * except for invalid keys (less than one character, non-ASCII, or + * containing '=' or '~') in which case the according values will + * be contained in the returned PropertyMap. + */ + PropertyMap setProperties(const PropertyMap&); + + /*! + * Check if the given String is a valid Xiph comment key. + */ + static bool checkKey(const String&); + + /*! + * Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the + * most common case always returns "Xiph.Org libVorbis I 20020717". + */ + String vendorID() const; + + /*! + * Add the field specified by \a key with the data \a value. If \a replace + * is true, then all of the other fields with the same key will be removed + * first. + * + * If the field value is empty, the field will be removed. + */ + void addField(const String &key, const String &value, bool replace = true); + + /*! + * Remove the field specified by \a key with the data \a value. If + * \a value is null, all of the fields with the given key will be removed. + * + * \deprecated Using this method may lead to a linkage error. + */ + // BIC: remove and merge with below + TAGLIB_DEPRECATED void removeField(const String &key, const String &value = String()); + + /*! + * Remove all the fields specified by \a key. + * + * \see removeAllFields() + */ + void removeFields(const String &key); + + /*! + * Remove all the fields specified by \a key with the data \a value. + * + * \see removeAllFields() + */ + void removeFields(const String &key, const String &value); + + /*! + * Remove all the fields in the comment. + * + * \see removeFields() + */ + void removeAllFields(); + + /*! + * Returns true if the field is contained within the comment. + * + * \note This is safer than checking for membership in the FieldListMap. + */ + bool contains(const String &key) const; + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + */ + ByteVector render() const; // BIC: remove and merge with below + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + * + * If \a addFramingBit is true the standard Vorbis comment framing bit will + * be appended. However some formats (notably FLAC) do not work with this + * in place. + */ + ByteVector render(bool addFramingBit) const; + + + /*! + * Returns a list of pictures attached to the xiph comment. + */ + List pictureList(); + + /*! + * Removes an picture. If \a del is true the picture's memory + * will be freed; if it is false, it must be deleted by the user. + */ + void removePicture(FLAC::Picture *picture, bool del = true); + + /*! + * Remove all pictures. + */ + void removeAllPictures(); + + /*! + * Add a new picture to the comment block. The comment block takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(FLAC::Picture *picture); + + protected: + /*! + * Reads the tag from the file specified in the constructor and fills the + * FieldListMap. + */ + void parse(const ByteVector &data); + + private: + XiphComment(const XiphComment &); + XiphComment &operator=(const XiphComment &); + + class XiphCommentPrivate; + XiphCommentPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/xmfile.h b/external/taglib/include/xmfile.h new file mode 100644 index 0000000..9211078 --- /dev/null +++ b/external/taglib/include/xmfile.h @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XMFILE_H +#define TAGLIB_XMFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "xmproperties.h" + +namespace TagLib { + + namespace XM { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs an Extended Module file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs an Extended Module file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the XM::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + XM::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Extended Module tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/include/xmproperties.h b/external/taglib/include/xmproperties.h new file mode 100644 index 0000000..24a5221 --- /dev/null +++ b/external/taglib/include/xmproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XMPROPERTIES_H +#define TAGLIB_XMPROPERTIES_H + +#include "taglib.h" +#include "tstring.h" +#include "audioproperties.h" + +namespace TagLib { + namespace XM { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + LinearFreqTable = 1 // otherwise its the amiga freq. table + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + unsigned short version() const; + unsigned short restartPosition() const; + unsigned short patternCount() const; + unsigned short instrumentCount() const; + unsigned int sampleCount() const; + unsigned short flags() const; + unsigned short tempo() const; + unsigned short bpmSpeed() const; + + void setChannels(int channels); + + void setLengthInPatterns(unsigned short lengthInPatterns); + void setVersion(unsigned short version); + void setRestartPosition(unsigned short restartPosition); + void setPatternCount(unsigned short patternCount); + void setInstrumentCount(unsigned short instrumentCount); + void setSampleCount(unsigned int sampleCount); + void setFlags(unsigned short flags); + void setTempo(unsigned short tempo); + void setBpmSpeed(unsigned short bpmSpeed); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/ape/ape-tag-format.txt b/external/taglib/source/ape/ape-tag-format.txt new file mode 100644 index 0000000..cb6f46f --- /dev/null +++ b/external/taglib/source/ape/ape-tag-format.txt @@ -0,0 +1,170 @@ +================================================================================ += APE Tag Specification, Version 2.000 +================================================================================ + +Original Content (C) 2004, Frank Klemm +Formatting / Editing (C) 2004, Scott Wheeler + +================================================================================ += Contents +================================================================================ + +1 - APE Tag General Structure +2 - APE Tag Header / Footer Format +3 - APE Tag Flags +4 - APE Tag Item Format +5 - APE Tag Item Supported Keys +6 - APE Tag Item Content +7 - Data Types +7.1 - Data Types / UTF-8 +7.2 - Data Types / Dates +7.3 - Data Types / Timestamps + +================================================================================ += 1 - APE Tag General Structure +================================================================================ + +Member of Basic Components of SV8 Stream Note: + +It is strongly recommended that the data size be stored in the tags. The size +should normally be in the roughly one kilobyte, never more than 8 kilobytes. + +Larger data should be stored externally using link entries. Linked data is much +easier to process by normal programs, so for instance JPEG data should not be +included inside the audio file. + +APE Tag Version 2.000 (with header, recommended): + +/================================\ +| APE Tag Header | 32 bytes | +|-------------------|------------| +| APE Tag Item 1 | > 10 bytes | +| APE Tag Item 2 | > 10 bytes | +| APE Tag Item n-1 | > 10 bytes | +| APE Tag Item n | > 10 bytes | +|-------------------|------------| +| APE Tag Footer | 32 bytes | +\================================/ + + +APE tag items should be sorted ascending by size. When streaming, parts of the +APE tag may be dropped to reduce the danger of drop outs between tracks. This +is not required, but is strongly recommended. It would be desirable for the +items to be sorted by importance / size, but this is not feasible. This +convention should only be broken when adding less important small items and it +is not desirable to rewrite the entire tag. An APE tag at the end of a file +(the recommended location) must have at least a footer; an APE tag at the +beginning of a file (strongly discouraged) must have at least a header. + +APE Tag Version 1.000 (without header, deprecated) + +/================================\ +| APE Tag Item 1 | > 10 bytes | +| APE Tag Item 2 | > 10 bytes | +| APE Tag Item n-1 | > 10 bytes | +| APE Tag Item n | > 10 bytes | +|-------------------|------------| +| APE Tag Footer | 32 bytes | +\================================/ + +================================================================================ += 2 - APE Tag Header / Footer Format +================================================================================ + +Contains number, length and attributes of all tag items + +Header and Footer are different in 1 bit in the Tags Flags to distinguish +between them. + +Member of APE Tag 2.0 + +/===========================================================================\ +| Preamble | 8 bytes | { 'A', 'P', 'E', 'T', 'A', 'G', 'E', 'X' } | +|----------------|---------|------------------------------------------------| +| Version Number | 4 bytes | 1000 = Version 1.000, 2000 = Version 2.000 | +|----------------|---------|------------------------------------------------| +| Tag Size | 4 bytes | Tag size in bytes including footer and all tag | +| | | items excluding the header (for 1.000 | +| | | compatibility) | +|----------------|---------|------------------------------------------------| +| Item Count | 4 bytes | Number of items in the tag | +|----------------|---------|------------------------------------------------| +| Tag Flags | 4 bytes | Global flags | +|----------------|---------|------------------------------------------------| +| Reserved | 8 bytes | Must be zeroed | +\===========================================================================/ + +================================================================================ += 3 - APE Tag Flags +================================================================================ + +The general flag structure for either items or headers / footers is the same. +Bits 31, 30 and 29 are specific to headers / footers, whereas 2 through 0 are +item specific. + +Note: APE Tags from Version 1.0 do not use any of the following. All flags in +that version are zeroed and ignored when reading. + +/=================================================================\ +| Contains Header | Bit 31 | 1 - has header | 0 - no header | +|-----------------|-------------|---------------------------------| +| Contains Footer | Bit 30 | 1 - has footer | 0 - no footer | +|-----------------|-------------|---------------------------------| +| Is Header | Bit 29 | 1 - is header | 0 - is footer | +|-----------------|-------------|---------------------------------| +| Undefined | Bits 28 - 3 | Undefined, must be zeroed | +|-----------------|-------------|---------------------------------| +| Encoding | Bits 2 - 1 | 00 - UTF-8 | +| | | 01 - Binary Data * | +| | | 10 - External Reference ** | +| | | 11 - Reserved | +|-----------------|-------------|---------------------------------| +| Read Only | Bit 0 | 1 - read only | 0 - read/write | +\=================================================================/ + + (*) Should be ignored by tools for editing text values +(**) Allowed external reference formats: + - http://host/directory/filename.ext + - ftp://host/directory/filename.ext + - filename.ext + - /directory/filename.ext + - DRIVE:/directory/filename.ext + + Note: External references are also UTF-8 encoded. + +================================================================================ += 4 - APE Tag Item Format +================================================================================ + +APE Tag Items are stored as key-value pairs. APE Tags Item Key are case +sensitive, however it is illegal to use keys which only differ in case and +it is recommended that tag reading not be case sensitive. + +Every key can only occur (at most) once. It is not possible to repeat a key +to signify updated contents. + +Tags can be partially or completely repeated in the streaming format. This +makes it possible to display an artist and / or title if it was missed at the +beginning of the stream. It is recommended that the important information like +artist, album and title should occur approximately every 2 minutes in the +stream and again 5 to 10 seconds before the end. However, care should be tak +en not to replicate this information too often or during passages with high +bitrate demands to avoid unnecessary drop-outs. + +/==============================================================================\ +| Content Size | 4 bytes | Length of the value in bytes | +|----------------|---------------|---------------------------------------------| +| Flags | 4 bytes | Item flags | +|----------------|---------------|---------------------------------------------| +| Key | 2 - 255 bytes | Item key | +|----------------|---------------|---------------------------------------------| +| Key Terminator | 1 byte | Null byte that indicates the end of the key | +|----------------|---------------|---------------------------------------------| +| Value | variable | Content (formatted according to the flags) | +\==============================================================================/ + +================================================================================ + +Sections 5 - 7 haven't yet been converted from: + +http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html diff --git a/external/taglib/source/ape/apefile.cpp b/external/taglib/source/ape/apefile.cpp new file mode 100644 index 0000000..a10c1f6 --- /dev/null +++ b/external/taglib/source/ape/apefile.cpp @@ -0,0 +1,314 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "apefile.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { ApeAPEIndex = 0, ApeID3v1Index = 1 }; +} + +class APE::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + ID3v2Header(0), + ID3v2Location(-1), + ID3v2Size(0), + properties(0) {} + + ~FilePrivate() + { + delete ID3v2Header; + delete properties; + } + + long APELocation; + long APESize; + + long ID3v1Location; + + ID3v2::Header *ID3v2Header; + long ID3v2Location; + long ID3v2Size; + + TagUnion tag; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool APE::File::isSupported(IOStream *stream) +{ + // An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true); + return (buffer.find("MAC ") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +APE::File::~File() +{ + delete d; +} + +TagLib::Tag *APE::File::tag() const +{ + return &d->tag; +} + +PropertyMap APE::File::properties() const +{ + return d->tag.properties(); +} + +void APE::File::removeUnsupportedProperties(const StringList &properties) +{ + d->tag.removeUnsupportedProperties(properties); +} + +PropertyMap APE::File::setProperties(const PropertyMap &properties) +{ + if(ID3v1Tag()) + ID3v1Tag()->setProperties(properties); + + return APETag(true)->setProperties(properties); +} + +APE::Properties *APE::File::audioProperties() const +{ + return d->properties; +} + +bool APE::File::save() +{ + if(readOnly()) { + debug("APE::File::save() -- File is read only."); + return false; + } + + // Update ID3v1 tag + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + if(d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + } + } + + // Update APE tag + + if(APETag() && !APETag()->isEmpty()) { + + // APE tag is not empty. Update the old one or create a new one. + + if(d->APELocation < 0) { + if(d->ID3v1Location >= 0) + d->APELocation = d->ID3v1Location; + else + d->APELocation = length(); + } + + const ByteVector data = APETag()->render(); + insert(data, d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->APESize); + + d->APESize = data.size(); + } + else { + + // APE tag is empty. Remove the old one. + + if(d->APELocation >= 0) { + removeBlock(d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->APESize; + + d->APELocation = -1; + d->APESize = 0; + } + } + + return true; +} + +ID3v1::Tag *APE::File::ID3v1Tag(bool create) +{ + return d->tag.access(ApeID3v1Index, create); +} + +APE::Tag *APE::File::APETag(bool create) +{ + return d->tag.access(ApeAPEIndex, create); +} + +void APE::File::strip(int tags) +{ + if(tags & ID3v1) + d->tag.set(ApeID3v1Index, 0); + + if(tags & APE) + d->tag.set(ApeAPEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); +} + +bool APE::File::hasAPETag() const +{ + return (d->APELocation >= 0); +} + +bool APE::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void APE::File::read(bool readProperties) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = Utils::findID3v2(this); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location); + d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size())); + d->ID3v2Size = d->ID3v2Header->completeTagSize(); + } + + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + // Look for an APE tag + + d->APELocation = Utils::findAPE(this, d->ID3v1Location); + + if(d->APELocation >= 0) { + d->tag.set(ApeAPEIndex, new APE::Tag(this, d->APELocation)); + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APE::Footer::size() - d->APESize; + } + + if(d->ID3v1Location < 0) + APETag(true); + + // Look for APE audio properties + + if(readProperties) { + + long streamLength; + + if(d->APELocation >= 0) + streamLength = d->APELocation; + else if(d->ID3v1Location >= 0) + streamLength = d->ID3v1Location; + else + streamLength = length(); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location + d->ID3v2Size); + streamLength -= (d->ID3v2Location + d->ID3v2Size); + } + else { + seek(0); + } + + d->properties = new Properties(this, streamLength); + } +} diff --git a/external/taglib/source/ape/apefile.h b/external/taglib/source/ape/apefile.h new file mode 100644 index 0000000..267778b --- /dev/null +++ b/external/taglib/source/ape/apefile.h @@ -0,0 +1,235 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFILE_H +#define TAGLIB_APEFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "apeproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of APE metadata + + /*! + * This is implementation of APE metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace APE { + + //! An implementation of TagLib::File with APE specific methods + + /*! + * This implements and provides an interface for APE files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to APE files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an APE file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an APE file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only APE + * will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Creates an APEv2 tag if necessary. A potentially existing ID3v1 + * tag will be updated as well. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the APE::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * \note According to the official Monkey's Audio SDK, an APE file + * can only have either ID3V1 or APE tags, so a parameter is used here. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an APE + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/ape/apefooter.cpp b/external/taglib/source/ape/apefooter.cpp new file mode 100644 index 0000000..e9aefee --- /dev/null +++ b/external/taglib/source/ape/apefooter.cpp @@ -0,0 +1,232 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + (C) 2002 - 2008 by Scott Wheeler (id3v2header.cpp) + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include + +#include "apefooter.h" + +using namespace TagLib; +using namespace APE; + +class APE::Footer::FooterPrivate +{ +public: + FooterPrivate() : + version(0), + footerPresent(true), + headerPresent(false), + isHeader(false), + itemCount(0), + tagSize(0) {} + + unsigned int version; + + bool footerPresent; + bool headerPresent; + + bool isHeader; + + unsigned int itemCount; + unsigned int tagSize; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +unsigned int APE::Footer::size() +{ + return 32; +} + +ByteVector APE::Footer::fileIdentifier() +{ + return ByteVector("APETAGEX"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::Footer::Footer() : + d(new FooterPrivate()) +{ +} + +APE::Footer::Footer(const ByteVector &data) : + d(new FooterPrivate()) +{ + parse(data); +} + +APE::Footer::~Footer() +{ + delete d; +} + +unsigned int APE::Footer::version() const +{ + return d->version; +} + +bool APE::Footer::headerPresent() const +{ + return d->headerPresent; +} + +bool APE::Footer::footerPresent() const +{ + return d->footerPresent; +} + +bool APE::Footer::isHeader() const +{ + return d->isHeader; +} + +void APE::Footer::setHeaderPresent(bool b) const +{ + d->headerPresent = b; +} + +unsigned int APE::Footer::itemCount() const +{ + return d->itemCount; +} + +void APE::Footer::setItemCount(unsigned int s) +{ + d->itemCount = s; +} + +unsigned int APE::Footer::tagSize() const +{ + return d->tagSize; +} + +unsigned int APE::Footer::completeTagSize() const +{ + if(d->headerPresent) + return d->tagSize + size(); + return d->tagSize; +} + +void APE::Footer::setTagSize(unsigned int s) +{ + d->tagSize = s; +} + +void APE::Footer::setData(const ByteVector &data) +{ + parse(data); +} + +ByteVector APE::Footer::renderFooter() const +{ + return render(false); +} + +ByteVector APE::Footer::renderHeader() const +{ + if(!d->headerPresent) + return ByteVector(); + return render(true); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void APE::Footer::parse(const ByteVector &data) +{ + if(data.size() < size()) + return; + + // The first eight bytes, data[0..7], are the File Identifier, "APETAGEX". + + // Read the version number + + d->version = data.toUInt(8, false); + + // Read the tag size + + d->tagSize = data.toUInt(12, false); + + // Read the item count + + d->itemCount = data.toUInt(16, false); + + // Read the flags + + std::bitset<32> flags(TAGLIB_CONSTRUCT_BITSET(data.toUInt(20, false))); + + d->headerPresent = flags[31]; + d->footerPresent = !flags[30]; + d->isHeader = flags[29]; + +} + +ByteVector APE::Footer::render(bool isHeader) const +{ + ByteVector v; + + // add the file identifier -- "APETAGEX" + + v.append(fileIdentifier()); + + // add the version number -- we always render a 2.000 tag regardless of what + // the tag originally was. + + v.append(ByteVector::fromUInt(2000, false)); + + // add the tag size + + v.append(ByteVector::fromUInt(d->tagSize, false)); + + // add the item count + + v.append(ByteVector::fromUInt(d->itemCount, false)); + + // render and add the flags + + std::bitset<32> flags; + + flags[31] = d->headerPresent; + flags[30] = false; // footer is always present + flags[29] = isHeader; + + v.append(ByteVector::fromUInt(flags.to_ulong(), false)); + + // add the reserved 64bit + + v.append(ByteVector::fromLongLong(0)); + + return v; +} diff --git a/external/taglib/source/ape/apefooter.h b/external/taglib/source/ape/apefooter.h new file mode 100644 index 0000000..47741d0 --- /dev/null +++ b/external/taglib/source/ape/apefooter.h @@ -0,0 +1,173 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEFOOTER_H +#define TAGLIB_APEFOOTER_H + +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE footers + + /*! + * This class implements APE footers (and headers). It attempts to follow, both + * semantically and programmatically, the structure specified in + * the APE v2.0 standard. The API is based on the properties of APE footer and + * headers specified there. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty APE footer. + */ + Footer(); + + /*! + * Constructs an APE footer based on \a data. parse() is called + * immediately. + */ + Footer(const ByteVector &data); + + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the version number. (Note: This is the 1000 or 2000.) + */ + unsigned int version() const; + + /*! + * Returns true if a header is present in the tag. + */ + bool headerPresent() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + + /*! + * Returns true this is actually the header. + */ + bool isHeader() const; + + /*! + * Sets whether the header should be rendered or not + */ + void setHeaderPresent(bool b) const; + + /*! + * Returns the number of items in the tag. + */ + unsigned int itemCount() const; + + /*! + * Set the item count to \a s. + * \see itemCount() + */ + void setItemCount(unsigned int s); + + /*! + * Returns the tag size in bytes. This is the size of the frame content and footer. + * The size of the \e entire tag will be this plus the header size, if present. + * + * \see completeTagSize() + */ + unsigned int tagSize() const; + + /*! + * Returns the tag size, including if present, the header + * size. + * + * \see tagSize() + */ + unsigned int completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(unsigned int s); + + /*! + * Returns the size of the footer. Presently this is always 32 bytes. + */ + static unsigned int size(); + + /*! + * Returns the string used to identify an APE tag inside of a file. + * Presently this is always "APETAGEX". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the footer. 32 bytes, + * starting from \a data will be used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the footer back to binary format. + */ + ByteVector renderFooter() const; + + /*! + * Renders the header corresponding to the footer. If headerPresent is + * set to false, it returns an empty ByteVector. + */ + ByteVector renderHeader() const; + + protected: + /*! + * Called by setData() to parse the footer data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by renderFooter and renderHeader + */ + ByteVector render(bool isHeader) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/ape/apeitem.cpp b/external/taglib/source/ape/apeitem.cpp new file mode 100644 index 0000000..bbf463a --- /dev/null +++ b/external/taglib/source/ape/apeitem.cpp @@ -0,0 +1,298 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "apeitem.h" + +using namespace TagLib; +using namespace APE; + +class APE::Item::ItemPrivate +{ +public: + ItemPrivate() : + type(Text), + readOnly(false) {} + + Item::ItemTypes type; + String key; + ByteVector value; + StringList text; + bool readOnly; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::Item::Item() : + d(new ItemPrivate()) +{ +} + +APE::Item::Item(const String &key, const String &value) : + d(new ItemPrivate()) +{ + d->key = key; + d->text.append(value); +} + +APE::Item::Item(const String &key, const StringList &values) : + d(new ItemPrivate()) +{ + d->key = key; + d->text = values; +} + +APE::Item::Item(const String &key, const ByteVector &value, bool binary) : + d(new ItemPrivate()) +{ + d->key = key; + if(binary) { + d->type = Binary; + d->value = value; + } + else { + d->text.append(value); + } +} + +APE::Item::Item(const Item &item) : + d(new ItemPrivate(*item.d)) +{ +} + +APE::Item::~Item() +{ + delete d; +} + +Item &APE::Item::operator=(const Item &item) +{ + Item(item).swap(*this); + return *this; +} + +void APE::Item::swap(Item &item) +{ + using std::swap; + + swap(d, item.d); +} + +void APE::Item::setReadOnly(bool readOnly) +{ + d->readOnly = readOnly; +} + +bool APE::Item::isReadOnly() const +{ + return d->readOnly; +} + +void APE::Item::setType(APE::Item::ItemTypes val) +{ + d->type = val; +} + +APE::Item::ItemTypes APE::Item::type() const +{ + return d->type; +} + +String APE::Item::key() const +{ + return d->key; +} + +ByteVector APE::Item::binaryData() const +{ + return d->value; +} + +void APE::Item::setBinaryData(const ByteVector &value) +{ + d->type = Binary; + d->value = value; + d->text.clear(); +} + +ByteVector APE::Item::value() const +{ + // This seems incorrect as it won't be actually rendering the value to keep it + // up to date. + + return d->value; +} + +void APE::Item::setKey(const String &key) +{ + d->key = key; +} + +void APE::Item::setValue(const String &value) +{ + d->type = Text; + d->text = value; + d->value.clear(); +} + +void APE::Item::setValues(const StringList &value) +{ + d->type = Text; + d->text = value; + d->value.clear(); +} + +void APE::Item::appendValue(const String &value) +{ + d->type = Text; + d->text.append(value); + d->value.clear(); +} + +void APE::Item::appendValues(const StringList &values) +{ + d->type = Text; + d->text.append(values); + d->value.clear(); +} + +int APE::Item::size() const +{ + int result = 8 + d->key.size() + 1; + switch(d->type) { + case Text: + if(!d->text.isEmpty()) { + StringList::ConstIterator it = d->text.begin(); + + result += it->data(String::UTF8).size(); + it++; + for(; it != d->text.end(); ++it) + result += 1 + it->data(String::UTF8).size(); + } + break; + + case Binary: + case Locator: + result += d->value.size(); + break; + } + return result; +} + +StringList APE::Item::toStringList() const +{ + return d->text; +} + +StringList APE::Item::values() const +{ + return d->text; +} + +String APE::Item::toString() const +{ + if(d->type == Text && !isEmpty()) + return d->text.front(); + return String(); +} + +bool APE::Item::isEmpty() const +{ + switch(d->type) { + case Text: + if(d->text.isEmpty()) + return true; + return d->text.size() == 1 && d->text.front().isEmpty(); + case Binary: + case Locator: + return d->value.isEmpty(); + default: + return false; + } +} + +void APE::Item::parse(const ByteVector &data) +{ + // 11 bytes is the minimum size for an APE item + + if(data.size() < 11) { + debug("APE::Item::parse() -- no data in item"); + return; + } + + const unsigned int valueLength = data.toUInt(0, false); + const unsigned int flags = data.toUInt(4, false); + + // An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8. + // We assume that the validity of the given key has been checked. + + d->key = String(&data[8], String::Latin1); + + const ByteVector value = data.mid(8 + d->key.size() + 1, valueLength); + + setReadOnly(flags & 1); + setType(ItemTypes((flags >> 1) & 3)); + + if(Text == d->type) + d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8); + else + d->value = value; +} + +ByteVector APE::Item::render() const +{ + ByteVector data; + unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1); + ByteVector value; + + if(isEmpty()) + return data; + + if(d->type == Text) { + StringList::ConstIterator it = d->text.begin(); + + value.append(it->data(String::UTF8)); + it++; + for(; it != d->text.end(); ++it) { + value.append('\0'); + value.append(it->data(String::UTF8)); + } + d->value = value; + } + else + value.append(d->value); + + data.append(ByteVector::fromUInt(value.size(), false)); + data.append(ByteVector::fromUInt(flags, false)); + data.append(d->key.data(String::Latin1)); + data.append(ByteVector('\0')); + data.append(value); + + return data; +} diff --git a/external/taglib/source/ape/apeitem.h b/external/taglib/source/ape/apeitem.h new file mode 100644 index 0000000..cfd157c --- /dev/null +++ b/external/taglib/source/ape/apeitem.h @@ -0,0 +1,224 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEITEM_H +#define TAGLIB_APEITEM_H + +#include "tbytevector.h" +#include "tstring.h" +#include "tstringlist.h" + +namespace TagLib { + + namespace APE { + + //! An implementation of APE-items + + /*! + * This class provides the features of items in the APEv2 standard. + */ + class TAGLIB_EXPORT Item + { + public: + /*! + * Enum of types an Item can have. The value of 3 is reserved. + */ + enum ItemTypes { + //! Item contains text information coded in UTF-8 + Text = 0, + //! Item contains binary information + Binary = 1, + //! Item is a locator of external stored information + Locator = 2 + }; + /*! + * Constructs an empty item. + */ + Item(); + + /*! + * Constructs a text item with \a key and \a value. + */ + // BIC: Remove this, StringList has a constructor from a single string + Item(const String &key, const String &value); + + /*! + * Constructs a text item with \a key and \a values. + */ + Item(const String &key, const StringList &values); + + /*! + * Constructs an item with \a key and \a value. + * If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text + */ + Item(const String &key, const ByteVector &value, bool binary); + + /*! + * Construct an item as a copy of \a item. + */ + Item(const Item &item); + + /*! + * Destroys the item. + */ + virtual ~Item(); + + /*! + * Copies the contents of \a item into this item. + */ + Item &operator=(const Item &item); + + /*! + * Exchanges the content of this item by the content of \a item. + */ + void swap(Item &item); + + /*! + * Returns the key. + */ + String key() const; + + /*! + * Returns the binary value. + * If the item type is not \a Binary, always returns an empty ByteVector. + */ + ByteVector binaryData() const; + + /*! + * Set the binary value to \a value + * The item's type will also be set to \a Binary + */ + void setBinaryData(const ByteVector &value); + +#ifndef DO_NOT_DOCUMENT + /* Remove in next binary incompatible release */ + ByteVector value() const; +#endif + + /*! + * Sets the key for the item to \a key. + */ + void setKey(const String &key); + + /*! + * Sets the text value of the item to \a value and clears any previous contents. + * + * \see toString() + */ + void setValue(const String &value); + + /*! + * Sets the text value of the item to the list of values in \a value and clears + * any previous contents. + * + * \see toStringList() + */ + void setValues(const StringList &values); + + /*! + * Appends \a value to create (or extend) the current list of text values. + * + * \see toString() + */ + void appendValue(const String &value); + + /*! + * Appends \a values to extend the current list of text values. + * + * \see toStringList() + */ + void appendValues(const StringList &values); + + /*! + * Returns the size of the full item. + */ + int size() const; + + /*! + * Returns the value as a single string. In case of multiple strings, + * the first is returned. If the data type is not \a Text, always returns + * an empty String. + */ + String toString() const; + +#ifndef DO_NOT_DOCUMENT + /* Remove in next binary incompatible release */ + StringList toStringList() const; +#endif + + /*! + * Returns the list of text values. If the data type is not \a Text, always + * returns an empty StringList. + */ + StringList values() const; + + /*! + * Render the item to a ByteVector. + */ + ByteVector render() const; + + /*! + * Parse the item from the ByteVector \a data. + */ + void parse(const ByteVector& data); + + /*! + * Set the item to read-only. + */ + void setReadOnly(bool readOnly); + + /*! + * Return true if the item is read-only. + */ + bool isReadOnly() const; + + /*! + * Sets the type of the item to \a type. + * + * \see ItemTypes + */ + void setType(ItemTypes type); + + /*! + * Returns the type of the item. + */ + ItemTypes type() const; + + /*! + * Returns if the item has any real content. + */ + bool isEmpty() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + } + +} + +#endif + + diff --git a/external/taglib/source/ape/apeproperties.cpp b/external/taglib/source/ape/apeproperties.cpp new file mode 100644 index 0000000..dee7e8c --- /dev/null +++ b/external/taglib/source/ape/apeproperties.cpp @@ -0,0 +1,252 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include "id3v2tag.h" +#include "apeproperties.h" +#include "apefile.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +class APE::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0), + sampleFrames(0) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; + unsigned int sampleFrames; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +APE::Properties::Properties(File *, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("APE::Properties::Properties() -- This constructor is no longer used."); +} + +APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file, streamLength); +} + +APE::Properties::~Properties() +{ + delete d; +} + +int APE::Properties::length() const +{ + return lengthInSeconds(); +} + +int APE::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int APE::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int APE::Properties::bitrate() const +{ + return d->bitrate; +} + +int APE::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int APE::Properties::channels() const +{ + return d->channels; +} + +int APE::Properties::version() const +{ + return d->version; +} + +int APE::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +unsigned int APE::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +namespace +{ + int headerVersion(const ByteVector &header) + { + if(header.size() < 6 || !header.startsWith("MAC ")) + return -1; + + return header.toUShort(4, false); + } +} + +void APE::Properties::read(File *file, long streamLength) +{ + // First, we assume that the file pointer is set at the first descriptor. + long offset = file->tell(); + int version = headerVersion(file->readBlock(6)); + + // Next, we look for the descriptor. + if(version < 0) { + offset = file->find("MAC ", offset); + file->seek(offset); + version = headerVersion(file->readBlock(6)); + } + + if(version < 0) { + debug("APE::Properties::read() -- APE descriptor not found"); + return; + } + + d->version = version; + + if(d->version >= 3980) + analyzeCurrent(file); + else + analyzeOld(file); + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } +} + +void APE::Properties::analyzeCurrent(File *file) +{ + // Read the descriptor + file->seek(2, File::Current); + const ByteVector descriptor = file->readBlock(44); + if(descriptor.size() < 44) { + debug("APE::Properties::analyzeCurrent() -- descriptor is too short."); + return; + } + + const unsigned int descriptorBytes = descriptor.toUInt(0, false); + + if((descriptorBytes - 52) > 0) + file->seek(descriptorBytes - 52, File::Current); + + // Read the header + const ByteVector header = file->readBlock(24); + if(header.size() < 24) { + debug("APE::Properties::analyzeCurrent() -- MAC header is too short."); + return; + } + + // Get the APE info + d->channels = header.toShort(18, false); + d->sampleRate = header.toUInt(20, false); + d->bitsPerSample = header.toShort(16, false); + + const unsigned int totalFrames = header.toUInt(12, false); + if(totalFrames == 0) + return; + + const unsigned int blocksPerFrame = header.toUInt(4, false); + const unsigned int finalFrameBlocks = header.toUInt(8, false); + d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks; +} + +void APE::Properties::analyzeOld(File *file) +{ + const ByteVector header = file->readBlock(26); + if(header.size() < 26) { + debug("APE::Properties::analyzeOld() -- MAC header is too short."); + return; + } + + const unsigned int totalFrames = header.toUInt(18, false); + + // Fail on 0 length APE files (catches non-finalized APE files) + if(totalFrames == 0) + return; + + const short compressionLevel = header.toShort(0, false); + unsigned int blocksPerFrame; + if(d->version >= 3950) + blocksPerFrame = 73728 * 4; + else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000)) + blocksPerFrame = 73728; + else + blocksPerFrame = 9216; + + // Get the APE info + d->channels = header.toShort(4, false); + d->sampleRate = header.toUInt(6, false); + + const unsigned int finalFrameBlocks = header.toUInt(22, false); + d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks; + + // Get the bit depth from the RIFF-fmt chunk. + file->seek(16, File::Current); + const ByteVector fmt = file->readBlock(28); + if(fmt.size() < 28 || !fmt.startsWith("WAVEfmt ")) { + debug("APE::Properties::analyzeOld() -- fmt header is too short."); + return; + } + + d->bitsPerSample = fmt.toShort(26, false); +} diff --git a/external/taglib/source/ape/apeproperties.h b/external/taglib/source/ape/apeproperties.h new file mode 100644 index 0000000..ebbf949 --- /dev/null +++ b/external/taglib/source/ape/apeproperties.h @@ -0,0 +1,143 @@ +/*************************************************************************** + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + (original WavPack implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APEPROPERTIES_H +#define TAGLIB_APEPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace APE { + + class File; + + //! An implementation of audio property reading for APE + + /*! + * This reads the data from an APE stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of APE::Properties with the data read from the + * APE::File \a file. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average); + + /*! + * Create an instance of APE::Properties with the data read from the + * APE::File \a file. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this APE::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the total number of audio samples in file. + */ + unsigned int sampleFrames() const; + + /*! + * Returns APE version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file, long streamLength); + + void analyzeCurrent(File *file); + void analyzeOld(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/ape/apetag.cpp b/external/taglib/source/ape/apetag.cpp new file mode 100644 index 0000000..4235f73 --- /dev/null +++ b/external/taglib/source/ape/apetag.cpp @@ -0,0 +1,437 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#if defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x5130) +// Sun Studio finds multiple specializations of Map because +// it considers specializations with and without class types +// to be different; this define forces Map to use only the +// specialization with the class keyword. +#define WANT_CLASS_INSTANTIATION_OF_MAP (1) +#endif + +#include +#include +#include +#include +#include +#include + +#include "apetag.h" +#include "apefooter.h" +#include "apeitem.h" + +using namespace TagLib; +using namespace APE; + +namespace +{ + const unsigned int MinKeyLength = 2; + const unsigned int MaxKeyLength = 255; + + bool isKeyValid(const ByteVector &key) + { + const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 }; + + // only allow printable ASCII including space (32..126) + + for(ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) { + const int c = static_cast(*it); + if(c < 32 || c > 126) + return false; + } + + const String upperKey = String(key).upper(); + for(size_t i = 0; invalidKeys[i] != 0; ++i) { + if(upperKey == invalidKeys[i]) + return false; + } + + return true; + } +} // namespace + +class APE::Tag::TagPrivate +{ +public: + TagPrivate() : + file(0), + footerLocation(0) {} + + File *file; + long footerLocation; + + Footer footer; + ItemListMap itemListMap; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +APE::Tag::Tag() : + d(new TagPrivate()) +{ +} + +APE::Tag::Tag(TagLib::File *file, long footerLocation) : + d(new TagPrivate()) +{ + d->file = file; + d->footerLocation = footerLocation; + + read(); +} + +APE::Tag::~Tag() +{ + delete d; +} + +ByteVector APE::Tag::fileIdentifier() +{ + return ByteVector::fromCString("APETAGEX"); +} + +String APE::Tag::title() const +{ + Item value = d->itemListMap.value("TITLE"); + return value.isEmpty() ? String() : value.values().toString(); +} + +String APE::Tag::artist() const +{ + Item value = d->itemListMap.value("ARTIST"); + return value.isEmpty() ? String() : value.values().toString(); +} + +String APE::Tag::album() const +{ + Item value = d->itemListMap.value("ALBUM"); + return value.isEmpty() ? String() : value.values().toString(); +} + +String APE::Tag::comment() const +{ + Item value = d->itemListMap.value("COMMENT"); + return value.isEmpty() ? String() : value.values().toString(); +} + +String APE::Tag::genre() const +{ + Item value = d->itemListMap.value("GENRE"); + return value.isEmpty() ? String() : value.values().toString(); +} + +unsigned int APE::Tag::year() const +{ + Item value = d->itemListMap.value("YEAR"); + return value.isEmpty() ? 0 : value.toString().toInt(); +} + +unsigned int APE::Tag::track() const +{ + Item value = d->itemListMap.value("TRACK"); + return value.isEmpty() ? 0 : value.toString().toInt(); +} + +void APE::Tag::setTitle(const String &s) +{ + addValue("TITLE", s, true); +} + +void APE::Tag::setArtist(const String &s) +{ + addValue("ARTIST", s, true); +} + +void APE::Tag::setAlbum(const String &s) +{ + addValue("ALBUM", s, true); +} + +void APE::Tag::setComment(const String &s) +{ + addValue("COMMENT", s, true); +} + +void APE::Tag::setGenre(const String &s) +{ + addValue("GENRE", s, true); +} + +void APE::Tag::setYear(unsigned int i) +{ + if(i == 0) + removeItem("YEAR"); + else + addValue("YEAR", String::number(i), true); +} + +void APE::Tag::setTrack(unsigned int i) +{ + if(i == 0) + removeItem("TRACK"); + else + addValue("TRACK", String::number(i), true); +} + +namespace +{ + // conversions of tag keys between what we use in PropertyMap and what's usual + // for APE tags + // usual, APE + const std::pair keyConversions[] = { + std::make_pair("TRACKNUMBER", "TRACK"), + std::make_pair("DATE", "YEAR"), + std::make_pair("ALBUMARTIST", "ALBUM ARTIST"), + std::make_pair("DISCNUMBER", "DISC"), + std::make_pair("REMIXER", "MIXARTIST"), + std::make_pair("RELEASESTATUS", "MUSICBRAINZ_ALBUMSTATUS"), + std::make_pair("RELEASETYPE", "MUSICBRAINZ_ALBUMTYPE"), + }; + const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]); +} // namespace + +PropertyMap APE::Tag::properties() const +{ + PropertyMap properties; + ItemListMap::ConstIterator it = itemListMap().begin(); + for(; it != itemListMap().end(); ++it) { + String tagName = it->first.upper(); + // if the item is Binary or Locator, or if the key is an invalid string, + // add to unsupportedData + if(it->second.type() != Item::Text || tagName.isEmpty()) { + properties.unsupportedData().append(it->first); + } + else { + // Some tags need to be handled specially + for(size_t i = 0; i < keyConversionsSize; ++i) { + if(tagName == keyConversions[i].second) + tagName = keyConversions[i].first; + } + properties[tagName].append(it->second.toStringList()); + } + } + return properties; +} + +void APE::Tag::removeUnsupportedProperties(const StringList &properties) +{ + StringList::ConstIterator it = properties.begin(); + for(; it != properties.end(); ++it) + removeItem(*it); +} + +PropertyMap APE::Tag::setProperties(const PropertyMap &origProps) +{ + PropertyMap properties(origProps); // make a local copy that can be modified + + // see comment in properties() + for(size_t i = 0; i < keyConversionsSize; ++i) + if(properties.contains(keyConversions[i].first)) { + properties.insert(keyConversions[i].second, properties[keyConversions[i].first]); + properties.erase(keyConversions[i].first); + } + + // first check if tags need to be removed completely + StringList toRemove; + ItemListMap::ConstIterator remIt = itemListMap().begin(); + for(; remIt != itemListMap().end(); ++remIt) { + String key = remIt->first.upper(); + // only remove if a) key is valid, b) type is text, c) key not contained in new properties + if(!key.isEmpty() && remIt->second.type() == APE::Item::Text && !properties.contains(key)) + toRemove.append(remIt->first); + } + + for(StringList::ConstIterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++) + removeItem(*removeIt); + + // now sync in the "forward direction" + PropertyMap::ConstIterator it = properties.begin(); + PropertyMap invalid; + for(; it != properties.end(); ++it) { + const String &tagName = it->first; + if(!checkKey(tagName)) + invalid.insert(it->first, it->second); + else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) { + if(it->second.isEmpty()) + removeItem(tagName); + else { + StringList::ConstIterator valueIt = it->second.begin(); + addValue(tagName, *valueIt, true); + ++valueIt; + for(; valueIt != it->second.end(); ++valueIt) + addValue(tagName, *valueIt, false); + } + } + } + return invalid; +} + +bool APE::Tag::checkKey(const String &key) +{ + if(key.size() < MinKeyLength || key.size() > MaxKeyLength) + return false; + + return isKeyValid(key.data(String::UTF8)); +} + +APE::Footer *APE::Tag::footer() const +{ + return &d->footer; +} + +const APE::ItemListMap& APE::Tag::itemListMap() const +{ + return d->itemListMap; +} + +void APE::Tag::removeItem(const String &key) +{ + d->itemListMap.erase(key.upper()); +} + +void APE::Tag::addValue(const String &key, const String &value, bool replace) +{ + if(replace) + removeItem(key); + + if(value.isEmpty()) + return; + + // Text items may contain more than one value. + // Binary or locator items may have only one value, hence always replaced. + + ItemListMap::Iterator it = d->itemListMap.find(key.upper()); + + if(it != d->itemListMap.end() && it->second.type() == Item::Text) + it->second.appendValue(value); + else + setItem(key, Item(key, value)); +} + +void APE::Tag::setData(const String &key, const ByteVector &value) +{ + removeItem(key); + + if(value.isEmpty()) + return; + + setItem(key, Item(key, value, true)); +} + +void APE::Tag::setItem(const String &key, const Item &item) +{ + if(!checkKey(key)) { + debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key."); + return; + } + + d->itemListMap[key.upper()] = item; +} + +bool APE::Tag::isEmpty() const +{ + return d->itemListMap.isEmpty(); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +void APE::Tag::read() +{ + if(d->file && d->file->isValid()) { + + d->file->seek(d->footerLocation); + d->footer.setData(d->file->readBlock(Footer::size())); + + if(d->footer.tagSize() <= Footer::size() || + d->footer.tagSize() > static_cast(d->file->length())) + return; + + d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize()); + parse(d->file->readBlock(d->footer.tagSize() - Footer::size())); + } +} + +ByteVector APE::Tag::render() const +{ + ByteVector data; + unsigned int itemCount = 0; + + for(ItemListMap::ConstIterator it = d->itemListMap.begin(); it != d->itemListMap.end(); ++it) { + data.append(it->second.render()); + itemCount++; + } + + d->footer.setItemCount(itemCount); + d->footer.setTagSize(data.size() + Footer::size()); + d->footer.setHeaderPresent(true); + + return d->footer.renderHeader() + data + d->footer.renderFooter(); +} + +void APE::Tag::parse(const ByteVector &data) +{ + // 11 bytes is the minimum size for an APE item + + if(data.size() < 11) + return; + + unsigned int pos = 0; + + for(unsigned int i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) { + + const int nullPos = data.find('\0', pos + 8); + if(nullPos < 0) { + debug("APE::Tag::parse() - Couldn't find a key/value separator. Stopped parsing."); + return; + } + + const unsigned int keyLength = nullPos - pos - 8; + const unsigned int valLength = data.toUInt(pos, false); + + if(valLength >= data.size() || pos > data.size() - valLength) { + debug("APE::Tag::parse() - Invalid val length. Stopped parsing."); + return; + } + + if(keyLength >= MinKeyLength + && keyLength <= MaxKeyLength + && isKeyValid(data.mid(pos + 8, keyLength))) + { + APE::Item item; + item.parse(data.mid(pos)); + + d->itemListMap.insert(item.key().upper(), item); + } + else { + debug("APE::Tag::parse() - Skipped an item due to an invalid key."); + } + + pos += keyLength + valLength + 9; + } +} diff --git a/external/taglib/source/ape/apetag.h b/external/taglib/source/ape/apetag.h new file mode 100644 index 0000000..f4d4fba --- /dev/null +++ b/external/taglib/source/ape/apetag.h @@ -0,0 +1,208 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_APETAG_H +#define TAGLIB_APETAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tmap.h" +#include "tstring.h" +#include "taglib_export.h" + +#include "apeitem.h" + +namespace TagLib { + + class File; + + //! An implementation of the APE tagging format + + namespace APE { + + class Footer; + + /*! + * A mapping between a list of item names, or keys, and the associated item. + * + * \see APE::Tag::itemListMap() + */ + typedef Map ItemListMap; + + + //! An APE tag implementation + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an APE tag with default values. + */ + Tag(); + + /*! + * Create an APE tag and parse the data in \a file with APE footer at + * \a tagOffset. + */ + Tag(TagLib::File *file, long footerLocation); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "APETAGEX" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + /*! + * Implements the unified tag dictionary interface -- export function. + * APE tags are perfectly compatible with the dictionary interface because they + * support both arbitrary tag names and multiple values. Currently only + * APE items of type *Text* are handled by the dictionary interface; all *Binary* + * and *Locator* items will be put into the unsupportedData list and can be + * deleted on request using removeUnsupportedProperties(). The same happens + * to Text items if their key is invalid for PropertyMap (which should actually + * never happen). + * + * The only conversion done by this export function is to rename the APE tags + * TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively, + * in order to be compliant with the names used in other formats. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified tag dictionary interface -- import function. The same + * comments as for the export function apply; additionally note that the APE tag + * specification requires keys to have between 2 and 16 printable ASCII characters + * with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+". + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Check if the given String is a valid APE tag key. + */ + static bool checkKey(const String&); + + /*! + * Returns a pointer to the tag's footer. + */ + Footer *footer() const; + + /*! + * Returns a reference to the item list map. This is an ItemListMap of + * all of the items in the tag. + * + * This is the most powerful structure for accessing the items of the tag. + * + * APE tags are case-insensitive, all keys in this map have been converted + * to upper case. + * + * \warning You should not modify this data structure directly, instead + * use setItem() and removeItem(). + */ + const ItemListMap &itemListMap() const; + + /*! + * Removes the \a key item from the tag + */ + void removeItem(const String &key); + + /*! + * Adds to the text item specified by \a key the data \a value. If \a replace + * is true, then all of the other values on the same key will be removed + * first. If a binary item exists for \a key it will be removed first. + */ + void addValue(const String &key, const String &value, bool replace = true); + + /*! + * Set the binary data for the key specified by \a item to \a value + * This will convert the item to type \a Binary if it isn't already and + * all of the other values on the same key will be removed. + */ + void setData(const String &key, const ByteVector &value); + + /*! + * Sets the \a key item to the value of \a item. If an item with the \a key is already + * present, it will be replaced. + */ + void setItem(const String &key, const Item &item); + + /*! + * Returns true if the tag does not contain any data. + */ + bool isEmpty() const; + + protected: + + /*! + * Reads from the file specified in the constructor. + */ + void read(); + + /*! + * Parses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/asf/asfattribute.cpp b/external/taglib/source/asf/asfattribute.cpp new file mode 100644 index 0000000..1aa8e6f --- /dev/null +++ b/external/taglib/source/asf/asfattribute.cpp @@ -0,0 +1,351 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "asfattribute.h" +#include "asffile.h" +#include "asfutils.h" + +using namespace TagLib; + +class ASF::Attribute::AttributePrivate : public RefCounter +{ +public: + AttributePrivate() : + pictureValue(ASF::Picture::fromInvalid()), + numericValue(0), + stream(0), + language(0) {} + AttributeTypes type; + String stringValue; + ByteVector byteVectorValue; + ASF::Picture pictureValue; + unsigned long long numericValue; + int stream; + int language; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Attribute::Attribute() : + d(new AttributePrivate()) +{ + d->type = UnicodeType; +} + +ASF::Attribute::Attribute(const ASF::Attribute &other) : + d(other.d) +{ + d->ref(); +} + +ASF::Attribute::Attribute(const String &value) : + d(new AttributePrivate()) +{ + d->type = UnicodeType; + d->stringValue = value; +} + +ASF::Attribute::Attribute(const ByteVector &value) : + d(new AttributePrivate()) +{ + d->type = BytesType; + d->byteVectorValue = value; +} + +ASF::Attribute::Attribute(const ASF::Picture &value) : + d(new AttributePrivate()) +{ + d->type = BytesType; + d->pictureValue = value; +} + +ASF::Attribute::Attribute(unsigned int value) : + d(new AttributePrivate()) +{ + d->type = DWordType; + d->numericValue = value; +} + +ASF::Attribute::Attribute(unsigned long long value) : + d(new AttributePrivate()) +{ + d->type = QWordType; + d->numericValue = value; +} + +ASF::Attribute::Attribute(unsigned short value) : + d(new AttributePrivate()) +{ + d->type = WordType; + d->numericValue = value; +} + +ASF::Attribute::Attribute(bool value) : + d(new AttributePrivate()) +{ + d->type = BoolType; + d->numericValue = value; +} + +ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other) +{ + Attribute(other).swap(*this); + return *this; +} + +void ASF::Attribute::swap(Attribute &other) +{ + using std::swap; + + swap(d, other.d); +} + +ASF::Attribute::~Attribute() +{ + if(d->deref()) + delete d; +} + +ASF::Attribute::AttributeTypes ASF::Attribute::type() const +{ + return d->type; +} + +String ASF::Attribute::toString() const +{ + return d->stringValue; +} + +ByteVector ASF::Attribute::toByteVector() const +{ + if(d->pictureValue.isValid()) + return d->pictureValue.render(); + return d->byteVectorValue; +} + +unsigned short ASF::Attribute::toBool() const +{ + return d->numericValue ? 1 : 0; +} + +unsigned short ASF::Attribute::toUShort() const +{ + return static_cast(d->numericValue); +} + +unsigned int ASF::Attribute::toUInt() const +{ + return static_cast(d->numericValue); +} + +unsigned long long ASF::Attribute::toULongLong() const +{ + return static_cast(d->numericValue); +} + +ASF::Picture ASF::Attribute::toPicture() const +{ + return d->pictureValue; +} + +String ASF::Attribute::parse(ASF::File &f, int kind) +{ + unsigned int size, nameLength; + String name; + d->pictureValue = Picture::fromInvalid(); + // extended content descriptor + if(kind == 0) { + nameLength = readWORD(&f); + name = readString(&f, nameLength); + d->type = ASF::Attribute::AttributeTypes(readWORD(&f)); + size = readWORD(&f); + } + // metadata & metadata library + else { + int temp = readWORD(&f); + // metadata library + if(kind == 2) { + d->language = temp; + } + d->stream = readWORD(&f); + nameLength = readWORD(&f); + d->type = ASF::Attribute::AttributeTypes(readWORD(&f)); + size = readDWORD(&f); + name = readString(&f, nameLength); + } + + if(kind != 2 && size > 65535) { + debug("ASF::Attribute::parse() -- Value larger than 64kB"); + } + + switch(d->type) { + case WordType: + d->numericValue = readWORD(&f); + break; + + case BoolType: + if(kind == 0) { + d->numericValue = (readDWORD(&f) != 0); + } + else { + d->numericValue = (readWORD(&f) != 0); + } + break; + + case DWordType: + d->numericValue = readDWORD(&f); + break; + + case QWordType: + d->numericValue = readQWORD(&f); + break; + + case UnicodeType: + d->stringValue = readString(&f, size); + break; + + case BytesType: + case GuidType: + d->byteVectorValue = f.readBlock(size); + break; + } + + if(d->type == BytesType && name == "WM/Picture") { + d->pictureValue.parse(d->byteVectorValue); + if(d->pictureValue.isValid()) { + d->byteVectorValue.clear(); + } + } + + return name; +} + +int ASF::Attribute::dataSize() const +{ + switch (d->type) { + case WordType: + return 2; + case BoolType: + return 4; + case DWordType: + return 4; + case QWordType: + return 5; + case UnicodeType: + return d->stringValue.size() * 2 + 2; + case BytesType: + if(d->pictureValue.isValid()) + return d->pictureValue.dataSize(); + case GuidType: + return d->byteVectorValue.size(); + } + return 0; +} + +ByteVector ASF::Attribute::render(const String &name, int kind) const +{ + ByteVector data; + + switch (d->type) { + case WordType: + data.append(ByteVector::fromShort(toUShort(), false)); + break; + + case BoolType: + if(kind == 0) { + data.append(ByteVector::fromUInt(toBool(), false)); + } + else { + data.append(ByteVector::fromShort(toBool(), false)); + } + break; + + case DWordType: + data.append(ByteVector::fromUInt(toUInt(), false)); + break; + + case QWordType: + data.append(ByteVector::fromLongLong(toULongLong(), false)); + break; + + case UnicodeType: + data.append(renderString(d->stringValue)); + break; + + case BytesType: + if(d->pictureValue.isValid()) { + data.append(d->pictureValue.render()); + break; + } + case GuidType: + data.append(d->byteVectorValue); + break; + } + + if(kind == 0) { + data = renderString(name, true) + + ByteVector::fromShort(static_cast(d->type), false) + + ByteVector::fromShort(data.size(), false) + + data; + } + else { + ByteVector nameData = renderString(name); + data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) + + ByteVector::fromShort(d->stream, false) + + ByteVector::fromShort(nameData.size(), false) + + ByteVector::fromShort(static_cast(d->type), false) + + ByteVector::fromUInt(data.size(), false) + + nameData + + data; + } + + return data; +} + +int ASF::Attribute::language() const +{ + return d->language; +} + +void ASF::Attribute::setLanguage(int value) +{ + d->language = value; +} + +int ASF::Attribute::stream() const +{ + return d->stream; +} + +void ASF::Attribute::setStream(int value) +{ + d->stream = value; +} diff --git a/external/taglib/source/asf/asfattribute.h b/external/taglib/source/asf/asfattribute.h new file mode 100644 index 0000000..1738eb4 --- /dev/null +++ b/external/taglib/source/asf/asfattribute.h @@ -0,0 +1,208 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFATTRIBUTE_H +#define TAGLIB_ASFATTRIBUTE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "asfpicture.h" + +namespace TagLib +{ + + namespace ASF + { + + class File; + class Picture; + + class TAGLIB_EXPORT Attribute + { + public: + + /*! + * Enum of types an Attribute can have. + */ + enum AttributeTypes { + UnicodeType = 0, + BytesType = 1, + BoolType = 2, + DWordType = 3, + QWordType = 4, + WordType = 5, + GuidType = 6 + }; + + /*! + * Constructs an empty attribute. + */ + Attribute(); + + /*! + * Constructs an attribute with \a key and a UnicodeType \a value. + */ + Attribute(const String &value); + + /*! + * Constructs an attribute with \a key and a BytesType \a value. + */ + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ + Attribute(const Picture &value); + + /*! + * Constructs an attribute with \a key and a DWordType \a value. + */ + Attribute(unsigned int value); + + /*! + * Constructs an attribute with \a key and a QWordType \a value. + */ + Attribute(unsigned long long value); + + /*! + * Constructs an attribute with \a key and a WordType \a value. + */ + Attribute(unsigned short value); + + /*! + * Constructs an attribute with \a key and a BoolType \a value. + */ + Attribute(bool value); + + /*! + * Construct an attribute as a copy of \a other. + */ + Attribute(const Attribute &item); + + /*! + * Copies the contents of \a other into this item. + */ + Attribute &operator=(const Attribute &other); + + /*! + * Exchanges the content of the Attribute by the content of \a other. + */ + void swap(Attribute &other); + + /*! + * Destroys the attribute. + */ + virtual ~Attribute(); + + /*! + * Returns type of the value. + */ + AttributeTypes type() const; + + /*! + * Returns the BoolType \a value. + */ + unsigned short toBool() const; + + /*! + * Returns the WordType \a value. + */ + unsigned short toUShort() const; + + /*! + * Returns the DWordType \a value. + */ + unsigned int toUInt() const; + + /*! + * Returns the QWordType \a value. + */ + unsigned long long toULongLong() const; + + /*! + * Returns the UnicodeType \a value. + */ + String toString() const; + + /*! + * Returns the BytesType \a value. + */ + ByteVector toByteVector() const; + + /*! + * Returns the Picture \a value. + */ + Picture toPicture() const; + + /*! + * Returns the language number, or 0 is no stream number was set. + */ + int language() const; + + /*! + * Sets the language number. + */ + void setLanguage(int value); + + /*! + * Returns the stream number, or 0 is no stream number was set. + */ + int stream() const; + + /*! + * Sets the stream number. + */ + void setStream(int value); + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + String parse(ASF::File &file, int kind = 0); +#endif + + //! Returns the size of the stored data + int dataSize() const; + + private: + friend class File; + + ByteVector render(const String &name, int kind = 0) const; + + class AttributePrivate; + AttributePrivate *d; + }; + } + +} + +#endif diff --git a/external/taglib/source/asf/asffile.cpp b/external/taglib/source/asf/asffile.cpp new file mode 100644 index 0000000..fabb7e6 --- /dev/null +++ b/external/taglib/source/asf/asffile.cpp @@ -0,0 +1,705 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "asffile.h" +#include "asftag.h" +#include "asfproperties.h" +#include "asfutils.h" + +using namespace TagLib; + +class ASF::File::FilePrivate +{ +public: + class BaseObject; + class UnknownObject; + class FilePropertiesObject; + class StreamPropertiesObject; + class ContentDescriptionObject; + class ExtendedContentDescriptionObject; + class HeaderExtensionObject; + class CodecListObject; + class MetadataObject; + class MetadataLibraryObject; + + FilePrivate(): + headerSize(0), + tag(0), + properties(0), + contentDescriptionObject(0), + extendedContentDescriptionObject(0), + headerExtensionObject(0), + metadataObject(0), + metadataLibraryObject(0) + { + objects.setAutoDelete(true); + } + + ~FilePrivate() + { + delete tag; + delete properties; + } + + unsigned long long headerSize; + + ASF::Tag *tag; + ASF::Properties *properties; + + List objects; + + ContentDescriptionObject *contentDescriptionObject; + ExtendedContentDescriptionObject *extendedContentDescriptionObject; + HeaderExtensionObject *headerExtensionObject; + MetadataObject *metadataObject; + MetadataLibraryObject *metadataLibraryObject; +}; + +namespace +{ + const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); + const ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16); + const ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16); + const ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); + const ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16); + const ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16); + const ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16); + const ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16); + const ByteVector codecListGuid("\x40\x52\xd1\x86\x1d\x31\xd0\x11\xa3\xa4\x00\xa0\xc9\x03\x48\xf6", 16); + const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16); + const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16); + const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16); +} // namespace + +class ASF::File::FilePrivate::BaseObject +{ +public: + ByteVector data; + virtual ~BaseObject() {} + virtual ByteVector guid() const = 0; + virtual void parse(ASF::File *file, unsigned int size); + virtual ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::BaseObject +{ + ByteVector myGuid; +public: + UnknownObject(const ByteVector &guid); + ByteVector guid() const; +}; + +class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); +}; + +class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); +}; + +class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject +{ +public: + List objects; + HeaderExtensionObject(); + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject +{ +public: + ByteVector guid() const; + void parse(ASF::File *file, unsigned int size); + +private: + enum CodecType + { + Video = 0x0001, + Audio = 0x0002, + Unknown = 0xFFFF + }; +}; + +void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size) +{ + data.clear(); + if(size > 24 && size <= static_cast(file->length())) + data = file->readBlock(size - 24); + else + data = ByteVector(); +} + +ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/) +{ + return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data; +} + +ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) +{ +} + +ByteVector ASF::File::FilePrivate::UnknownObject::guid() const +{ + return myGuid; +} + +ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const +{ + return filePropertiesGuid; +} + +void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsigned int size) +{ + BaseObject::parse(file, size); + if(data.size() < 64) { + debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short."); + return; + } + + const long long duration = data.toLongLong(40, false); + const long long preroll = data.toLongLong(56, false); + file->d->properties->setLengthInMilliseconds(static_cast(duration / 10000.0 - preroll + 0.5)); +} + +ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const +{ + return streamPropertiesGuid; +} + +void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsigned int size) +{ + BaseObject::parse(file, size); + if(data.size() < 70) { + debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short."); + return; + } + + file->d->properties->setCodec(data.toUShort(54, false)); + file->d->properties->setChannels(data.toUShort(56, false)); + file->d->properties->setSampleRate(data.toUInt(58, false)); + file->d->properties->setBitrate(static_cast(data.toUInt(62, false) * 8.0 / 1000.0 + 0.5)); + file->d->properties->setBitsPerSample(data.toUShort(68, false)); +} + +ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const +{ + return contentDescriptionGuid; +} + +void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) +{ + const int titleLength = readWORD(file); + const int artistLength = readWORD(file); + const int copyrightLength = readWORD(file); + const int commentLength = readWORD(file); + const int ratingLength = readWORD(file); + file->d->tag->setTitle(readString(file,titleLength)); + file->d->tag->setArtist(readString(file,artistLength)); + file->d->tag->setCopyright(readString(file,copyrightLength)); + file->d->tag->setComment(readString(file,commentLength)); + file->d->tag->setRating(readString(file,ratingLength)); +} + +ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *file) +{ + const ByteVector v1 = renderString(file->d->tag->title()); + const ByteVector v2 = renderString(file->d->tag->artist()); + const ByteVector v3 = renderString(file->d->tag->copyright()); + const ByteVector v4 = renderString(file->d->tag->comment()); + const ByteVector v5 = renderString(file->d->tag->rating()); + data.clear(); + data.append(ByteVector::fromShort(v1.size(), false)); + data.append(ByteVector::fromShort(v2.size(), false)); + data.append(ByteVector::fromShort(v3.size(), false)); + data.append(ByteVector::fromShort(v4.size(), false)); + data.append(ByteVector::fromShort(v5.size(), false)); + data.append(v1); + data.append(v2); + data.append(v3); + data.append(v4); + data.append(v5); + return BaseObject::render(file); +} + +ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const +{ + return extendedContentDescriptionGuid; +} + +void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) +{ + int count = readWORD(file); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector("")); + return BaseObject::render(file); +} + +ByteVector ASF::File::FilePrivate::MetadataObject::guid() const +{ + return metadataGuid; +} + +void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/) +{ + int count = readWORD(file); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 1); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector("")); + return BaseObject::render(file); +} + +ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const +{ + return metadataLibraryGuid; +} + +void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/) +{ + int count = readWORD(file); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 2); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector("")); + return BaseObject::render(file); +} + +ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject() +{ + objects.setAutoDelete(true); +} + +ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const +{ + return headerExtensionGuid; +} + +void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/) +{ + file->seek(18, File::Current); + long long dataSize = readDWORD(file); + long long dataPos = 0; + while(dataPos < dataSize) { + ByteVector guid = file->readBlock(16); + if(guid.size() != 16) { + file->setValid(false); + break; + } + bool ok; + long long size = readQWORD(file, &ok); + if(!ok || size < 0 || size > dataSize - dataPos) { + file->setValid(false); + break; + } + BaseObject *obj; + if(guid == metadataGuid) { + file->d->metadataObject = new MetadataObject(); + obj = file->d->metadataObject; + } + else if(guid == metadataLibraryGuid) { + file->d->metadataLibraryObject = new MetadataLibraryObject(); + obj = file->d->metadataLibraryObject; + } + else { + obj = new UnknownObject(guid); + } + obj->parse(file, static_cast(size)); + objects.append(obj); + dataPos += size; + } +} + +ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file) +{ + data.clear(); + for(List::ConstIterator it = objects.begin(); it != objects.end(); ++it) { + data.append((*it)->render(file)); + } + data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data; + return BaseObject::render(file); +} + +ByteVector ASF::File::FilePrivate::CodecListObject::guid() const +{ + return codecListGuid; +} + +void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned int size) +{ + BaseObject::parse(file, size); + if(data.size() <= 20) { + debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short."); + return; + } + + unsigned int pos = 16; + + const int count = data.toUInt(pos, false); + pos += 4; + + for(int i = 0; i < count; ++i) { + + if(pos >= data.size()) + break; + + const CodecType type = static_cast(data.toUShort(pos, false)); + pos += 2; + + int nameLength = data.toUShort(pos, false); + pos += 2; + + const unsigned int namePos = pos; + pos += nameLength * 2; + + const int descLength = data.toUShort(pos, false); + pos += 2; + + const unsigned int descPos = pos; + pos += descLength * 2; + + const int infoLength = data.toUShort(pos, false); + pos += 2 + infoLength * 2; + + if(type == CodecListObject::Audio) { + // First audio codec found. + + const String name(data.mid(namePos, nameLength * 2), String::UTF16LE); + file->d->properties->setCodecName(name.stripWhiteSpace()); + + const String desc(data.mid(descPos, descLength * 2), String::UTF16LE); + file->d->properties->setCodecDescription(desc.stripWhiteSpace()); + + break; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool ASF::File::isSupported(IOStream *stream) +{ + // An ASF file has to start with the designated GUID. + + const ByteVector id = Utils::readHeader(stream, 16, false); + return (id == headerGuid); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::File::File(FileName file, bool, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(); +} + +ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(); +} + +ASF::File::~File() +{ + delete d; +} + +ASF::Tag *ASF::File::tag() const +{ + return d->tag; +} + +PropertyMap ASF::File::properties() const +{ + return d->tag->properties(); +} + +void ASF::File::removeUnsupportedProperties(const StringList &properties) +{ + d->tag->removeUnsupportedProperties(properties); +} + +PropertyMap ASF::File::setProperties(const PropertyMap &properties) +{ + return d->tag->setProperties(properties); +} + +ASF::Properties *ASF::File::audioProperties() const +{ + return d->properties; +} + +bool ASF::File::save() +{ + if(readOnly()) { + debug("ASF::File::save() -- File is read only."); + return false; + } + + if(!isValid()) { + debug("ASF::File::save() -- Trying to save invalid file."); + return false; + } + + if(!d->contentDescriptionObject) { + d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject(); + d->objects.append(d->contentDescriptionObject); + } + if(!d->extendedContentDescriptionObject) { + d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject(); + d->objects.append(d->extendedContentDescriptionObject); + } + if(!d->headerExtensionObject) { + d->headerExtensionObject = new FilePrivate::HeaderExtensionObject(); + d->objects.append(d->headerExtensionObject); + } + if(!d->metadataObject) { + d->metadataObject = new FilePrivate::MetadataObject(); + d->headerExtensionObject->objects.append(d->metadataObject); + } + if(!d->metadataLibraryObject) { + d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject(); + d->headerExtensionObject->objects.append(d->metadataLibraryObject); + } + + d->extendedContentDescriptionObject->attributeData.clear(); + d->metadataObject->attributeData.clear(); + d->metadataLibraryObject->attributeData.clear(); + + const AttributeListMap allAttributes = d->tag->attributeListMap(); + + for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) { + + const String &name = it->first; + const AttributeList &attributes = it->second; + + bool inExtendedContentDescriptionObject = false; + bool inMetadataObject = false; + + for(AttributeList::ConstIterator jt = attributes.begin(); jt != attributes.end(); ++jt) { + + const Attribute &attribute = *jt; + const bool largeValue = (attribute.dataSize() > 65535); + const bool guid = (attribute.type() == Attribute::GuidType); + + if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) { + d->extendedContentDescriptionObject->attributeData.append(attribute.render(name)); + inExtendedContentDescriptionObject = true; + } + else if(!inMetadataObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() != 0) { + d->metadataObject->attributeData.append(attribute.render(name, 1)); + inMetadataObject = true; + } + else { + d->metadataLibraryObject->attributeData.append(attribute.render(name, 2)); + } + } + } + + ByteVector data; + for(List::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) { + data.append((*it)->render(this)); + } + + seek(16); + writeBlock(ByteVector::fromLongLong(data.size() + 30, false)); + writeBlock(ByteVector::fromUInt(d->objects.size(), false)); + writeBlock(ByteVector("\x01\x02", 2)); + + insert(data, 30, static_cast(d->headerSize - 30)); + + d->headerSize = data.size() + 30; + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void ASF::File::read() +{ + if(!isValid()) + return; + + if(readBlock(16) != headerGuid) { + debug("ASF::File::read(): Not an ASF file."); + setValid(false); + return; + } + + d->tag = new ASF::Tag(); + d->properties = new ASF::Properties(); + + bool ok; + d->headerSize = readQWORD(this, &ok); + if(!ok) { + setValid(false); + return; + } + int numObjects = readDWORD(this, &ok); + if(!ok) { + setValid(false); + return; + } + seek(2, Current); + + FilePrivate::FilePropertiesObject *filePropertiesObject = 0; + FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0; + for(int i = 0; i < numObjects; i++) { + const ByteVector guid = readBlock(16); + if(guid.size() != 16) { + setValid(false); + break; + } + long size = static_cast(readQWORD(this, &ok)); + if(!ok) { + setValid(false); + break; + } + FilePrivate::BaseObject *obj; + if(guid == filePropertiesGuid) { + filePropertiesObject = new FilePrivate::FilePropertiesObject(); + obj = filePropertiesObject; + } + else if(guid == streamPropertiesGuid) { + streamPropertiesObject = new FilePrivate::StreamPropertiesObject(); + obj = streamPropertiesObject; + } + else if(guid == contentDescriptionGuid) { + d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject(); + obj = d->contentDescriptionObject; + } + else if(guid == extendedContentDescriptionGuid) { + d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject(); + obj = d->extendedContentDescriptionObject; + } + else if(guid == headerExtensionGuid) { + d->headerExtensionObject = new FilePrivate::HeaderExtensionObject(); + obj = d->headerExtensionObject; + } + else if(guid == codecListGuid) { + obj = new FilePrivate::CodecListObject(); + } + else { + if(guid == contentEncryptionGuid || + guid == extendedContentEncryptionGuid || + guid == advancedContentEncryptionGuid) { + d->properties->setEncrypted(true); + } + obj = new FilePrivate::UnknownObject(guid); + } + obj->parse(this, size); + d->objects.append(obj); + } + + if(!filePropertiesObject || !streamPropertiesObject) { + debug("ASF::File::read(): Missing mandatory header objects."); + setValid(false); + return; + } +} diff --git a/external/taglib/source/asf/asffile.h b/external/taglib/source/asf/asffile.h new file mode 100644 index 0000000..05cf4ee --- /dev/null +++ b/external/taglib/source/asf/asffile.h @@ -0,0 +1,138 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFFILE_H +#define TAGLIB_ASFFILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "asfproperties.h" +#include "asftag.h" + +namespace TagLib { + + //! An implementation of ASF (WMA) metadata + namespace ASF { + + /*! + * This implements and provides an interface for ASF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to ASF files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + + /*! + * Constructs an ASF file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an ASF file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + virtual Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the ASF audio properties for this file. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as an ASF + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + void read(); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/asf/asfpicture.cpp b/external/taglib/source/asf/asfpicture.cpp new file mode 100644 index 0000000..d856258 --- /dev/null +++ b/external/taglib/source/asf/asfpicture.cpp @@ -0,0 +1,183 @@ +/************************************************************************** + copyright : (C) 2010 by Anton Sergunov + email : setosha@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "asfattribute.h" +#include "asffile.h" +#include "asfpicture.h" +#include "asfutils.h" + +using namespace TagLib; + +class ASF::Picture::PicturePrivate : public RefCounter +{ +public: + bool valid; + Type type; + String mimeType; + String description; + ByteVector picture; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Picture class members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Picture::Picture() : + d(new PicturePrivate()) +{ + d->valid = true; +} + +ASF::Picture::Picture(const Picture& other) : + d(other.d) +{ + d->ref(); +} + +ASF::Picture::~Picture() +{ + if(d->deref()) + delete d; +} + +bool ASF::Picture::isValid() const +{ + return d->valid; +} + +String ASF::Picture::mimeType() const +{ + return d->mimeType; +} + +void ASF::Picture::setMimeType(const String &value) +{ + d->mimeType = value; +} + +ASF::Picture::Type ASF::Picture::type() const +{ + return d->type; +} + +void ASF::Picture::setType(const ASF::Picture::Type& t) +{ + d->type = t; +} + +String ASF::Picture::description() const +{ + return d->description; +} + +void ASF::Picture::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector ASF::Picture::picture() const +{ + return d->picture; +} + +void ASF::Picture::setPicture(const ByteVector &p) +{ + d->picture = p; +} + +int ASF::Picture::dataSize() const +{ + return + 9 + (d->mimeType.length() + d->description.length()) * 2 + + d->picture.size(); +} + +ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other) +{ + Picture(other).swap(*this); + return *this; +} + +void ASF::Picture::swap(Picture &other) +{ + using std::swap; + + swap(d, other.d); +} + +ByteVector ASF::Picture::render() const +{ + if(!isValid()) + return ByteVector(); + + return + ByteVector(static_cast(d->type)) + + ByteVector::fromUInt(d->picture.size(), false) + + renderString(d->mimeType) + + renderString(d->description) + + d->picture; +} + +void ASF::Picture::parse(const ByteVector& bytes) +{ + d->valid = false; + if(bytes.size() < 9) + return; + int pos = 0; + d->type = static_cast(bytes[0]); ++pos; + const unsigned int dataLen = bytes.toUInt(pos, false); pos+=4; + + const ByteVector nullStringTerminator(2, 0); + + int endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + endPos = bytes.find(nullStringTerminator, pos, 2); + if(endPos < 0) + return; + d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE); + pos = endPos+2; + + if(dataLen + pos != bytes.size()) + return; + + d->picture = bytes.mid(pos, dataLen); + d->valid = true; + return; +} + +ASF::Picture ASF::Picture::fromInvalid() +{ + Picture ret; + ret.d->valid = false; + return ret; +} diff --git a/external/taglib/source/asf/asfpicture.h b/external/taglib/source/asf/asfpicture.h new file mode 100644 index 0000000..17233ba --- /dev/null +++ b/external/taglib/source/asf/asfpicture.h @@ -0,0 +1,222 @@ +/************************************************************************** + copyright : (C) 2010 by Anton Sergunov + email : setosha@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef ASFPICTURE_H +#define ASFPICTURE_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "attachedpictureframe.h" + +namespace TagLib +{ + namespace ASF + { + + //! An ASF attached picture interface implementation + + /*! + * This is an implementation of ASF attached pictures interface. Pictures may be + * included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture + * attribute in a single tag). These pictures are usually in either JPEG or + * PNG format. + * \see Attribute::toPicture() + * \see Attribute::Attribute(const Picture& picture) + */ + class TAGLIB_EXPORT Picture { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture. + */ + Picture(); + + /*! + * Construct an picture as a copy of \a other. + */ + Picture(const Picture& other); + + /*! + * Destroys the picture. + */ + virtual ~Picture(); + + /*! + * Copies the contents of \a other into this picture. + */ + Picture& operator=(const Picture& other); + + /*! + * Exchanges the content of the Picture by the content of \a other. + */ + void swap(Picture &other); + + /*! + * Returns true if Picture stores valid picture + */ + bool isValid() const; + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + * \see setMimeType(const String &) + * \see picture() + * \see setPicture(const ByteArray&) + */ + void setMimeType(const String &value); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(const ASF::Picture::Type& t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + */ + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + */ + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + /*! + * Returns picture as binary raw data \a value + */ + ByteVector render() const; + + /*! + * Returns picture as binary raw data \a value + */ + int dataSize() const; + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + void parse(const ByteVector& ); + static Picture fromInvalid(); +#endif + + private: + class PicturePrivate; + PicturePrivate *d; + }; + } +} + +#endif // ASFPICTURE_H diff --git a/external/taglib/source/asf/asfproperties.cpp b/external/taglib/source/asf/asfproperties.cpp new file mode 100644 index 0000000..a836da3 --- /dev/null +++ b/external/taglib/source/asf/asfproperties.cpp @@ -0,0 +1,194 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0), + codec(ASF::Properties::Unknown), + encrypted(false) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; + ASF::Properties::Codec codec; + String codecName; + String codecDescription; + bool encrypted; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Properties::Properties() : + AudioProperties(AudioProperties::Average), + d(new PropertiesPrivate()) +{ +} + +ASF::Properties::~Properties() +{ + delete d; +} + +int ASF::Properties::length() const +{ + return lengthInSeconds(); +} + +int ASF::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int ASF::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int ASF::Properties::bitrate() const +{ + return d->bitrate; +} + +int ASF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int ASF::Properties::channels() const +{ + return d->channels; +} + +int ASF::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +ASF::Properties::Codec ASF::Properties::codec() const +{ + return d->codec; +} + +String ASF::Properties::codecName() const +{ + return d->codecName; +} + +String ASF::Properties::codecDescription() const +{ + return d->codecDescription; +} + +bool ASF::Properties::isEncrypted() const +{ + return d->encrypted; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void ASF::Properties::setLength(int /*length*/) +{ + debug("ASF::Properties::setLength() -- This method is deprecated. Do not use."); +} + +void ASF::Properties::setLengthInMilliseconds(int value) +{ + d->length = value; +} + +void ASF::Properties::setBitrate(int value) +{ + d->bitrate = value; +} + +void ASF::Properties::setSampleRate(int value) +{ + d->sampleRate = value; +} + +void ASF::Properties::setChannels(int value) +{ + d->channels = value; +} + +void ASF::Properties::setBitsPerSample(int value) +{ + d->bitsPerSample = value; +} + +void ASF::Properties::setCodec(int value) +{ + switch(value) + { + case 0x0160: + d->codec = WMA1; + break; + case 0x0161: + d->codec = WMA2; + break; + case 0x0162: + d->codec = WMA9Pro; + break; + case 0x0163: + d->codec = WMA9Lossless; + break; + default: + d->codec = Unknown; + break; + } +} + +void ASF::Properties::setCodecName(const String &value) +{ + d->codecName = value; +} + +void ASF::Properties::setCodecDescription(const String &value) +{ + d->codecDescription = value; +} + +void ASF::Properties::setEncrypted(bool value) +{ + d->encrypted = value; +} diff --git a/external/taglib/source/asf/asfproperties.h b/external/taglib/source/asf/asfproperties.h new file mode 100644 index 0000000..317bf10 --- /dev/null +++ b/external/taglib/source/asf/asfproperties.h @@ -0,0 +1,186 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFPROPERTIES_H +#define TAGLIB_ASFPROPERTIES_H + +#include "audioproperties.h" +#include "tstring.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ASF { + + //! An implementation of ASF audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + + /*! + * Audio codec types can be used in ASF file. + */ + enum Codec + { + /*! + * Couldn't detect the codec. + */ + Unknown = 0, + + /*! + * Windows Media Audio 1 + */ + WMA1, + + /*! + * Windows Media Audio 2 or above + */ + WMA2, + + /*! + * Windows Media Audio 9 Professional + */ + WMA9Pro, + + /*! + * Windows Media Audio 9 Lossless + */ + WMA9Lossless, + }; + + /*! + * Creates an instance of ASF::Properties. + */ + Properties(); + + /*! + * Destroys this ASF::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the codec used in the file. + * + * \see codecName() + * \see codecDescription() + */ + Codec codec() const; + + /*! + * Returns the concrete codec name, for example "Windows Media Audio 9.1" + * used in the file if available, otherwise an empty string. + * + * \see codec() + * \see codecDescription() + */ + String codecName() const; + + /*! + * Returns the codec description, typically contains the encoder settings, + * for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available, + * otherwise an empty string. + * + * \see codec() + * \see codecName() + */ + String codecDescription() const; + + /*! + * Returns whether or not the file is encrypted. + */ + bool isEncrypted() const; + +#ifndef DO_NOT_DOCUMENT + // deprecated + void setLength(int value); + + void setLengthInMilliseconds(int value); + void setBitrate(int value); + void setSampleRate(int value); + void setChannels(int value); + void setBitsPerSample(int value); + void setCodec(int value); + void setCodecName(const String &value); + void setCodecDescription(const String &value); + void setEncrypted(bool value); +#endif + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/asf/asftag.cpp b/external/taglib/source/asf/asftag.cpp new file mode 100644 index 0000000..e2a9ed8 --- /dev/null +++ b/external/taglib/source/asf/asftag.cpp @@ -0,0 +1,381 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include "asftag.h" + +using namespace TagLib; + +class ASF::Tag::TagPrivate +{ +public: + String title; + String artist; + String copyright; + String comment; + String rating; + AttributeListMap attributeListMap; +}; + +ASF::Tag::Tag() : + d(new TagPrivate()) +{ +} + +ASF::Tag::~Tag() +{ + delete d; +} + +String ASF::Tag::title() const +{ + return d->title; +} + +String ASF::Tag::artist() const +{ + return d->artist; +} + +String ASF::Tag::album() const +{ + if(d->attributeListMap.contains("WM/AlbumTitle")) + return d->attributeListMap["WM/AlbumTitle"][0].toString(); + return String(); +} + +String ASF::Tag::copyright() const +{ + return d->copyright; +} + +String ASF::Tag::comment() const +{ + return d->comment; +} + +String ASF::Tag::rating() const +{ + return d->rating; +} + +unsigned int ASF::Tag::year() const +{ + if(d->attributeListMap.contains("WM/Year")) + return d->attributeListMap["WM/Year"][0].toString().toInt(); + return 0; +} + +unsigned int ASF::Tag::track() const +{ + if(d->attributeListMap.contains("WM/TrackNumber")) { + const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0]; + if(attr.type() == ASF::Attribute::DWordType) + return attr.toUInt(); + return attr.toString().toInt(); + } + if(d->attributeListMap.contains("WM/Track")) + return d->attributeListMap["WM/Track"][0].toUInt(); + return 0; +} + +String ASF::Tag::genre() const +{ + if(d->attributeListMap.contains("WM/Genre")) + return d->attributeListMap["WM/Genre"][0].toString(); + return String(); +} + +void ASF::Tag::setTitle(const String &value) +{ + d->title = value; +} + +void ASF::Tag::setArtist(const String &value) +{ + d->artist = value; +} + +void ASF::Tag::setCopyright(const String &value) +{ + d->copyright = value; +} + +void ASF::Tag::setComment(const String &value) +{ + d->comment = value; +} + +void ASF::Tag::setRating(const String &value) +{ + d->rating = value; +} + +void ASF::Tag::setAlbum(const String &value) +{ + setAttribute("WM/AlbumTitle", value); +} + +void ASF::Tag::setGenre(const String &value) +{ + setAttribute("WM/Genre", value); +} + +void ASF::Tag::setYear(unsigned int value) +{ + setAttribute("WM/Year", String::number(value)); +} + +void ASF::Tag::setTrack(unsigned int value) +{ + setAttribute("WM/TrackNumber", String::number(value)); +} + +ASF::AttributeListMap& ASF::Tag::attributeListMap() +{ + return d->attributeListMap; +} + +const ASF::AttributeListMap &ASF::Tag::attributeListMap() const +{ + return d->attributeListMap; +} + +bool ASF::Tag::contains(const String &key) const +{ + return d->attributeListMap.contains(key); +} + +void ASF::Tag::removeItem(const String &key) +{ + d->attributeListMap.erase(key); +} + +ASF::AttributeList ASF::Tag::attribute(const String &name) const +{ + return d->attributeListMap[name]; +} + +void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) +{ + AttributeList value; + value.append(attribute); + d->attributeListMap.insert(name, value); +} + +void ASF::Tag::setAttribute(const String &name, const AttributeList &values) +{ + d->attributeListMap.insert(name, values); +} + +void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) +{ + if(d->attributeListMap.contains(name)) { + d->attributeListMap[name].append(attribute); + } + else { + setAttribute(name, attribute); + } +} + +bool ASF::Tag::isEmpty() const +{ + return TagLib::Tag::isEmpty() && + copyright().isEmpty() && + rating().isEmpty() && + d->attributeListMap.isEmpty(); +} + +namespace +{ + const std::pair keyTranslation[] = { + std::make_pair("WM/AlbumTitle", "ALBUM"), + std::make_pair("WM/AlbumArtist", "ALBUMARTIST"), + std::make_pair("WM/Composer", "COMPOSER"), + std::make_pair("WM/Writer", "LYRICIST"), + std::make_pair("WM/Conductor", "CONDUCTOR"), + std::make_pair("WM/ModifiedBy", "REMIXER"), + std::make_pair("WM/Year", "DATE"), + std::make_pair("WM/OriginalReleaseYear", "ORIGINALDATE"), + std::make_pair("WM/Producer", "PRODUCER"), + std::make_pair("WM/ContentGroupDescription", "WORK"), + std::make_pair("WM/SubTitle", "SUBTITLE"), + std::make_pair("WM/SetSubTitle", "DISCSUBTITLE"), + std::make_pair("WM/TrackNumber", "TRACKNUMBER"), + std::make_pair("WM/PartOfSet", "DISCNUMBER"), + std::make_pair("WM/Genre", "GENRE"), + std::make_pair("WM/BeatsPerMinute", "BPM"), + std::make_pair("WM/Mood", "MOOD"), + std::make_pair("WM/ISRC", "ISRC"), + std::make_pair("WM/Lyrics", "LYRICS"), + std::make_pair("WM/Media", "MEDIA"), + std::make_pair("WM/Publisher", "LABEL"), + std::make_pair("WM/CatalogNo", "CATALOGNUMBER"), + std::make_pair("WM/Barcode", "BARCODE"), + std::make_pair("WM/EncodedBy", "ENCODEDBY"), + std::make_pair("WM/AlbumSortOrder", "ALBUMSORT"), + std::make_pair("WM/AlbumArtistSortOrder", "ALBUMARTISTSORT"), + std::make_pair("WM/ArtistSortOrder", "ARTISTSORT"), + std::make_pair("WM/TitleSortOrder", "TITLESORT"), + std::make_pair("WM/Script", "SCRIPT"), + std::make_pair("WM/Language", "LANGUAGE"), + std::make_pair("WM/ARTISTS", "ARTISTS"), + std::make_pair("ASIN", "ASIN"), + std::make_pair("MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID"), + std::make_pair("MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID"), + std::make_pair("MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID"), + std::make_pair("MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"), + std::make_pair("MusicBrainz/Album Release Country", "RELEASECOUNTRY"), + std::make_pair("MusicBrainz/Album Status", "RELEASESTATUS"), + std::make_pair("MusicBrainz/Album Type", "RELEASETYPE"), + std::make_pair("MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID"), + std::make_pair("MusicBrainz/Release Track Id", "MUSICBRAINZ_RELEASETRACKID"), + std::make_pair("MusicBrainz/Work Id", "MUSICBRAINZ_WORKID"), + std::make_pair("MusicIP/PUID", "MUSICIP_PUID"), + std::make_pair("Acoustid/Id", "ACOUSTID_ID"), + std::make_pair("Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT"), + }; + const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]); + + String translateKey(const String &key) + { + for(size_t i = 0; i < keyTranslationSize; ++i) { + if(key == keyTranslation[i].first) + return keyTranslation[i].second; + } + + return String(); + } +} // namespace + +PropertyMap ASF::Tag::properties() const +{ + PropertyMap props; + + if(!d->title.isEmpty()) { + props["TITLE"] = d->title; + } + if(!d->artist.isEmpty()) { + props["ARTIST"] = d->artist; + } + if(!d->copyright.isEmpty()) { + props["COPYRIGHT"] = d->copyright; + } + if(!d->comment.isEmpty()) { + props["COMMENT"] = d->comment; + } + + ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin(); + for(; it != d->attributeListMap.end(); ++it) { + const String key = translateKey(it->first); + if(!key.isEmpty()) { + AttributeList::ConstIterator it2 = it->second.begin(); + for(; it2 != it->second.end(); ++it2) { + if(key == "TRACKNUMBER") { + if(it2->type() == ASF::Attribute::DWordType) + props.insert(key, String::number(it2->toUInt())); + else + props.insert(key, it2->toString()); + } + else { + props.insert(key, it2->toString()); + } + } + } + else { + props.unsupportedData().append(it->first); + } + } + return props; +} + +void ASF::Tag::removeUnsupportedProperties(const StringList &props) +{ + StringList::ConstIterator it = props.begin(); + for(; it != props.end(); ++it) + d->attributeListMap.erase(*it); +} + +PropertyMap ASF::Tag::setProperties(const PropertyMap &props) +{ + static Map reverseKeyMap; + if(reverseKeyMap.isEmpty()) { + for(size_t i = 0; i < keyTranslationSize; i++) { + reverseKeyMap[keyTranslation[i].second] = keyTranslation[i].first; + } + } + + PropertyMap origProps = properties(); + PropertyMap::ConstIterator it = origProps.begin(); + for(; it != origProps.end(); ++it) { + if(!props.contains(it->first) || props[it->first].isEmpty()) { + if(it->first == "TITLE") { + d->title.clear(); + } + else if(it->first == "ARTIST") { + d->artist.clear(); + } + else if(it->first == "COMMENT") { + d->comment.clear(); + } + else if(it->first == "COPYRIGHT") { + d->copyright.clear(); + } + else { + d->attributeListMap.erase(reverseKeyMap[it->first]); + } + } + } + + PropertyMap ignoredProps; + it = props.begin(); + for(; it != props.end(); ++it) { + if(reverseKeyMap.contains(it->first)) { + String name = reverseKeyMap[it->first]; + removeItem(name); + StringList::ConstIterator it2 = it->second.begin(); + for(; it2 != it->second.end(); ++it2) { + addAttribute(name, *it2); + } + } + else if(it->first == "TITLE") { + d->title = it->second.toString(); + } + else if(it->first == "ARTIST") { + d->artist = it->second.toString(); + } + else if(it->first == "COMMENT") { + d->comment = it->second.toString(); + } + else if(it->first == "COPYRIGHT") { + d->copyright = it->second.toString(); + } + else { + ignoredProps.insert(it->first, it->second); + } + } + + return ignoredProps; +} diff --git a/external/taglib/source/asf/asftag.h b/external/taglib/source/asf/asftag.h new file mode 100644 index 0000000..bbd9821 --- /dev/null +++ b/external/taglib/source/asf/asftag.h @@ -0,0 +1,210 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFTAG_H +#define TAGLIB_ASFTAG_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" +#include "asfattribute.h" + +namespace TagLib { + + namespace ASF { + + typedef List AttributeList; + typedef Map AttributeListMap; + + class TAGLIB_EXPORT Tag : public TagLib::Tag { + + friend class File; + + public: + + Tag(); + + virtual ~Tag(); + + /*! + * Returns the track name. + */ + virtual String title() const; + + /*! + * Returns the artist name. + */ + virtual String artist() const; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const; + + /*! + * Returns the track comment. + */ + virtual String comment() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const; + + /*! + * Returns the rating. + */ + virtual String rating() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String copyright() const; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual unsigned int year() const; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual unsigned int track() const; + + /*! + * Sets the title to \a s. + */ + virtual void setTitle(const String &s); + + /*! + * Sets the artist to \a s. + */ + virtual void setArtist(const String &s); + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s); + + /*! + * Sets the comment to \a s. + */ + virtual void setComment(const String &s); + + /*! + * Sets the rating to \a s. + */ + virtual void setRating(const String &s); + + /*! + * Sets the copyright to \a s. + */ + virtual void setCopyright(const String &s); + + /*! + * Sets the genre to \a s. + */ + virtual void setGenre(const String &s); + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(unsigned int i); + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(unsigned int i); + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * \deprecated + */ + AttributeListMap &attributeListMap(); + + /*! + * Returns a reference to the item list map. This is an AttributeListMap of + * all of the items in the tag. + */ + // BIC: return by value + const AttributeListMap &attributeListMap() const; + + /*! + * \return True if a value for \a attribute is currently set. + */ + bool contains(const String &name) const; + + /*! + * Removes the \a key attribute from the tag + */ + void removeItem(const String &name); + + /*! + * \return The list of values for the key \a name, or an empty list if no + * values have been set. + */ + AttributeList attribute(const String &name) const; + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be replaced. + */ + void setAttribute(const String &name, const Attribute &attribute); + + /*! + * Sets multiple \a values to the key \a name. + */ + void setAttribute(const String &name, const AttributeList &values); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ + void addAttribute(const String &name, const Attribute &attribute); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList& properties); + PropertyMap setProperties(const PropertyMap &properties); + + private: + + class TagPrivate; + TagPrivate *d; + }; + } +} +#endif diff --git a/external/taglib/source/asf/asfutils.h b/external/taglib/source/asf/asfutils.h new file mode 100644 index 0000000..a8ecd70 --- /dev/null +++ b/external/taglib/source/asf/asfutils.h @@ -0,0 +1,104 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ASFUTILS_H +#define TAGLIB_ASFUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace ASF + { + namespace + { + + inline unsigned short readWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(2); + if(v.size() != 2) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toUShort(false); + } + + inline unsigned int readDWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(4); + if(v.size() != 4) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toUInt(false); + } + + inline long long readQWORD(File *file, bool *ok = 0) + { + const ByteVector v = file->readBlock(8); + if(v.size() != 8) { + if(ok) *ok = false; + return 0; + } + if(ok) *ok = true; + return v.toLongLong(false); + } + + inline String readString(File *file, int length) + { + ByteVector data = file->readBlock(length); + unsigned int size = data.size(); + while (size >= 2) { + if(data[size - 1] != '\0' || data[size - 2] != '\0') { + break; + } + size -= 2; + } + if(size != data.size()) { + data.resize(size); + } + return String(data, String::UTF16LE); + } + + inline ByteVector renderString(const String &str, bool includeLength = false) + { + ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false); + if(includeLength) { + data = ByteVector::fromShort(data.size(), false) + data; + } + return data; + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/source/audioproperties.cpp b/external/taglib/source/audioproperties.cpp new file mode 100644 index 0000000..421785e --- /dev/null +++ b/external/taglib/source/audioproperties.cpp @@ -0,0 +1,110 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "aiffproperties.h" +#include "apeproperties.h" +#include "asfproperties.h" +#include "flacproperties.h" +#include "mp4properties.h" +#include "mpcproperties.h" +#include "mpegproperties.h" +#include "opusproperties.h" +#include "speexproperties.h" +#include "trueaudioproperties.h" +#include "vorbisproperties.h" +#include "wavproperties.h" +#include "wavpackproperties.h" + +#include "audioproperties.h" + +using namespace TagLib; + +// This macro is a workaround for the fact that we can't add virtual functions. +// Should be true virtual functions in taglib2. + +#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + if(dynamic_cast(this)) \ + return dynamic_cast(this)->function_name(); \ + return (default_value); + +class AudioProperties::AudioPropertiesPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +AudioProperties::~AudioProperties() +{ + +} + +int AudioProperties::lengthInSeconds() const +{ + VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0) +} + +int AudioProperties::lengthInMilliseconds() const +{ + VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0) +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +AudioProperties::AudioProperties(ReadStyle) : + d(0) +{ + +} diff --git a/external/taglib/source/audioproperties.h b/external/taglib/source/audioproperties.h new file mode 100644 index 0000000..f27aefc --- /dev/null +++ b/external/taglib/source/audioproperties.h @@ -0,0 +1,127 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIOPROPERTIES_H +#define TAGLIB_AUDIOPROPERTIES_H + +#include "taglib_export.h" + +namespace TagLib { + + //! A simple, abstract interface to common audio properties + + /*! + * The values here are common to most audio formats. For more specific, codec + * dependent values, please see see the subclasses APIs. This is meant to + * compliment the TagLib::File and TagLib::Tag APIs in providing a simple + * interface that is sufficient for most applications. + */ + + class TAGLIB_EXPORT AudioProperties + { + public: + + /*! + * Reading audio properties from a file can sometimes be very time consuming + * and for the most accurate results can often involve reading the entire + * file. Because in many situations speed is critical or the accuracy of the + * values is not particularly important this allows the level of desired + * accuracy to be set. + */ + enum ReadStyle { + //! Read as little of the file as possible + Fast, + //! Read more of the file and make better values guesses + Average, + //! Read as much of the file as needed to report accurate values + Accurate + }; + + /*! + * Destroys this AudioProperties instance. + */ + virtual ~AudioProperties(); + + /*! + * Returns the length of the file in seconds. + */ + virtual int length() const = 0; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the most appropriate bit rate for the file in kb/s. For constant + * bitrate formats this is simply the bitrate of the file. For variable + * bitrate formats this is either the average or nominal bitrate. + */ + virtual int bitrate() const = 0; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const = 0; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const = 0; + + protected: + + /*! + * Construct an audio properties instance. This is protected as this class + * should not be instantiated directly, but should be instantiated via its + * subclasses and can be fetched from the FileRef or File APIs. + * + * \see ReadStyle + */ + AudioProperties(ReadStyle style); + + private: + AudioProperties(const AudioProperties &); + AudioProperties &operator=(const AudioProperties &); + + class AudioPropertiesPrivate; + AudioPropertiesPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/source/fileref.cpp b/external/taglib/source/fileref.cpp new file mode 100644 index 0000000..b71d657 --- /dev/null +++ b/external/taglib/source/fileref.cpp @@ -0,0 +1,520 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2010 by Alex Novichkov + email : novichko@atnet.ru + (added APE file support) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "fileref.h" +#include "asffile.h" +#include "mpegfile.h" +#include "vorbisfile.h" +#include "flacfile.h" +#include "oggflacfile.h" +#include "mpcfile.h" +#include "mp4file.h" +#include "wavpackfile.h" +#include "speexfile.h" +#include "opusfile.h" +#include "trueaudiofile.h" +#include "aifffile.h" +#include "wavfile.h" +#include "apefile.h" +#include "modfile.h" +#include "s3mfile.h" +#include "itfile.h" +#include "xmfile.h" + +using namespace TagLib; + +namespace +{ + typedef List ResolverList; + ResolverList fileTypeResolvers; + + // Detect the file type by user-defined resolvers. + + File *detectByResolvers(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { +#ifdef _WIN32 + if(::strlen(fileName) == 0 && ::wcslen(fileName) == 0) + return 0; +#else + if(::strlen(fileName) == 0) + return 0; +#endif + ResolverList::ConstIterator it = fileTypeResolvers.begin(); + for(; it != fileTypeResolvers.end(); ++it) { + File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle); + if(file) + return file; + } + + return 0; + } + + File *detectByResolvers(IOStream* stream, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { + for(ResolverList::ConstIterator it = fileTypeResolvers.begin(); + it != fileTypeResolvers.end(); ++it) { + if(const FileRef::StreamTypeResolver *streamResolver = + dynamic_cast(*it)) { + if(File *file = streamResolver->createFileFromStream( + stream, readAudioProperties, audioPropertiesStyle)) + return file; + } + } + + return 0; + } + + // Detect the file type based on the file extension. + + File* detectByExtension(IOStream *stream, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { +#ifdef _WIN32 + const String s = stream->name().toString(); +#else + const String s(stream->name()); +#endif + + String ext; + const int pos = s.rfind("."); + if(pos != -1) + ext = s.substr(pos + 1).upper(); + + // If this list is updated, the method defaultFileExtensions() should also be + // updated. However at some point that list should be created at the same time + // that a default file type resolver is created. + + if(ext.isEmpty()) + return 0; + + // .oga can be any audio in the Ogg container. So leave it to content-based detection. + + File *file = 0; + + if(ext == "MP3") + file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + else if(ext == "OGG") + file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "FLAC") + file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + else if(ext == "MPC") + file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "WV") + file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "SPX") + file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "OPUS") + file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "TTA") + file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V") + file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "WMA" || ext == "ASF") + file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC") + file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "WAV") + file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "APE") + file = new APE::File(stream, readAudioProperties, audioPropertiesStyle); + // module, nst and wow are possible but uncommon extensions + else if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW") + file = new Mod::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "S3M") + file = new S3M::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "IT") + file = new IT::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ext == "XM") + file = new XM::File(stream, readAudioProperties, audioPropertiesStyle); + + // if file is not valid, leave it to content-based detection. + + if(file) { + if(file->isValid()) + return file; + delete file; + } + + return 0; + } + + // Detect the file type based on the actual content of the stream. + + File *detectByContent(IOStream *stream, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { + File *file = 0; + + if(MPEG::File::isSupported(stream)) + file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + else if(Ogg::Vorbis::File::isSupported(stream)) + file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle); + else if(Ogg::FLAC::File::isSupported(stream)) + file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle); + else if(FLAC::File::isSupported(stream)) + file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + else if(MPC::File::isSupported(stream)) + file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle); + else if(WavPack::File::isSupported(stream)) + file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle); + else if(Ogg::Speex::File::isSupported(stream)) + file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle); + else if(Ogg::Opus::File::isSupported(stream)) + file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle); + else if(TrueAudio::File::isSupported(stream)) + file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle); + else if(MP4::File::isSupported(stream)) + file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle); + else if(ASF::File::isSupported(stream)) + file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle); + else if(RIFF::AIFF::File::isSupported(stream)) + file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle); + else if(RIFF::WAV::File::isSupported(stream)) + file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle); + else if(APE::File::isSupported(stream)) + file = new APE::File(stream, readAudioProperties, audioPropertiesStyle); + + // isSupported() only does a quick check, so double check the file here. + + if(file) { + if(file->isValid()) + return file; + delete file; + } + + return 0; + } + + // Internal function that supports FileRef::create(). + // This looks redundant, but necessary in order not to change the previous + // behavior of FileRef::create(). + + File* createInternal(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) + { + File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle); + if(file) + return file; + +#ifdef _WIN32 + const String s = fileName.toString(); +#else + const String s(fileName); +#endif + + String ext; + const int pos = s.rfind("."); + if(pos != -1) + ext = s.substr(pos + 1).upper(); + + if(ext.isEmpty()) + return 0; + + if(ext == "MP3") + return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + if(ext == "OGG") + return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "OGA") { + /* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */ + File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle); + if(file->isValid()) + return file; + delete file; + return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle); + } + if(ext == "FLAC") + return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle); + if(ext == "MPC") + return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "WV") + return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "SPX") + return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "OPUS") + return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "TTA") + return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V") + return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "WMA" || ext == "ASF") + return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC") + return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "WAV") + return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "APE") + return new APE::File(fileName, readAudioProperties, audioPropertiesStyle); + // module, nst and wow are possible but uncommon extensions + if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW") + return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "S3M") + return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "IT") + return new IT::File(fileName, readAudioProperties, audioPropertiesStyle); + if(ext == "XM") + return new XM::File(fileName, readAudioProperties, audioPropertiesStyle); + + return 0; + } +} // namespace + +class FileRef::FileRefPrivate : public RefCounter +{ +public: + FileRefPrivate() : + file(0), + stream(0) {} + + ~FileRefPrivate() { + delete file; + delete stream; + } + + File *file; + IOStream *stream; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FileRef::FileRef() : + d(new FileRefPrivate()) +{ +} + +FileRef::FileRef(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) : + d(new FileRefPrivate()) +{ + parse(fileName, readAudioProperties, audioPropertiesStyle); +} + +FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) : + d(new FileRefPrivate()) +{ + parse(stream, readAudioProperties, audioPropertiesStyle); +} + +FileRef::FileRef(File *file) : + d(new FileRefPrivate()) +{ + d->file = file; +} + +FileRef::FileRef(const FileRef &ref) : + d(ref.d) +{ + d->ref(); +} + +FileRef::~FileRef() +{ + if(d->deref()) + delete d; +} + +Tag *FileRef::tag() const +{ + if(isNull()) { + debug("FileRef::tag() - Called without a valid file."); + return 0; + } + return d->file->tag(); +} + +AudioProperties *FileRef::audioProperties() const +{ + if(isNull()) { + debug("FileRef::audioProperties() - Called without a valid file."); + return 0; + } + return d->file->audioProperties(); +} + +File *FileRef::file() const +{ + return d->file; +} + +bool FileRef::save() +{ + if(isNull()) { + debug("FileRef::save() - Called without a valid file."); + return false; + } + return d->file->save(); +} + +const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static +{ + fileTypeResolvers.prepend(resolver); + return resolver; +} + +StringList FileRef::defaultFileExtensions() +{ + StringList l; + + l.append("ogg"); + l.append("flac"); + l.append("oga"); + l.append("opus"); + l.append("mp3"); + l.append("mpc"); + l.append("wv"); + l.append("spx"); + l.append("tta"); + l.append("m4a"); + l.append("m4r"); + l.append("m4b"); + l.append("m4p"); + l.append("3g2"); + l.append("mp4"); + l.append("m4v"); + l.append("wma"); + l.append("asf"); + l.append("aif"); + l.append("aiff"); + l.append("afc"); + l.append("aifc"); + l.append("wav"); + l.append("ape"); + l.append("mod"); + l.append("module"); // alias for "mod" + l.append("nst"); // alias for "mod" + l.append("wow"); // alias for "mod" + l.append("s3m"); + l.append("it"); + l.append("xm"); + + return l; +} + +bool FileRef::isNull() const +{ + return (!d->file || !d->file->isValid()); +} + +FileRef &FileRef::operator=(const FileRef &ref) +{ + FileRef(ref).swap(*this); + return *this; +} + +void FileRef::swap(FileRef &ref) +{ + using std::swap; + + swap(d, ref.d); +} + +bool FileRef::operator==(const FileRef &ref) const +{ + return (ref.d->file == d->file); +} + +bool FileRef::operator!=(const FileRef &ref) const +{ + return (ref.d->file != d->file); +} + +File *FileRef::create(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) // static +{ + return createInternal(fileName, readAudioProperties, audioPropertiesStyle); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FileRef::parse(FileName fileName, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) +{ + // Try user-defined resolvers. + + d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // Try to resolve file types based on the file extension. + + d->stream = new FileStream(fileName); + d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // At last, try to resolve file types based on the actual content. + + d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // Stream have to be closed here if failed to resolve file types. + + delete d->stream; + d->stream = 0; +} + +void FileRef::parse(IOStream *stream, bool readAudioProperties, + AudioProperties::ReadStyle audioPropertiesStyle) +{ + // Try user-defined stream resolvers. + + d->file = detectByResolvers(stream, readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // Try user-defined resolvers. + + d->file = detectByResolvers(stream->name(), readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // Try to resolve file types based on the file extension. + + d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle); + if(d->file) + return; + + // At last, try to resolve file types based on the actual content of the file. + + d->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle); +} diff --git a/external/taglib/source/fileref.h b/external/taglib/source/fileref.h new file mode 100644 index 0000000..75d1492 --- /dev/null +++ b/external/taglib/source/fileref.h @@ -0,0 +1,297 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILEREF_H +#define TAGLIB_FILEREF_H + +#include "tfile.h" +#include "tstringlist.h" + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + class Tag; + + //! This class provides a simple abstraction for creating and handling files + + /*! + * FileRef exists to provide a minimal, generic and value-based wrapper around + * a File. It is lightweight and implicitly shared, and as such suitable for + * pass-by-value use. This hides some of the uglier details of TagLib::File + * and the non-generic portions of the concrete file implementations. + * + * This class is useful in a "simple usage" situation where it is desirable + * to be able to get and set some of the tag information that is similar + * across file types. + * + * Also note that it is probably a good idea to plug this into your mime + * type system rather than using the constructor that accepts a file name using + * the FileTypeResolver. + * + * \see FileTypeResolver + * \see addFileTypeResolver() + */ + + class TAGLIB_EXPORT FileRef + { + public: + + //! A class for pluggable file type resolution. + + /*! + * This class is used to add extend TagLib's very basic file name based file + * type resolution. + * + * This can be accomplished with: + * + * \code + * + * class MyFileTypeResolver : FileTypeResolver + * { + * TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const + * { + * if(someCheckForAnMP3File(fileName)) + * return new TagLib::MPEG::File(fileName); + * return 0; + * } + * } + * + * FileRef::addFileTypeResolver(new MyFileTypeResolver); + * + * \endcode + * + * Naturally a less contrived example would be slightly more complex. This + * can be used to plug in mime-type detection systems or to add new file types + * to TagLib. + */ + + class TAGLIB_EXPORT FileTypeResolver + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + /*! + * This method must be overridden to provide an additional file type + * resolver. If the resolver is able to determine the file type it should + * return a valid File object; if not it should return 0. + * + * \note The created file is then owned by the FileRef and should not be + * deleted. Deletion will happen automatically when the FileRef passes + * out of scope. + */ + virtual File *createFile(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average) const = 0; + }; + + class TAGLIB_EXPORT StreamTypeResolver : public FileTypeResolver + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + virtual File *createFileFromStream(IOStream *stream, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average) const = 0; + }; + + /*! + * Creates a null FileRef. + */ + FileRef(); + + /*! + * Create a FileRef from \a fileName. If \a readAudioProperties is true then + * the audio properties will be read using \a audioPropertiesStyle. If + * \a readAudioProperties is false then \a audioPropertiesStyle will be + * ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + */ + explicit FileRef(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average); + + /*! + * Construct a FileRef from an opened \a IOStream. If \a readAudioProperties + * is true then the audio properties will be read using \a audioPropertiesStyle. + * If \a readAudioProperties is false then \a audioPropertiesStyle will be + * ignored. + * + * Also see the note in the class documentation about why you may not want to + * use this method in your application. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + explicit FileRef(IOStream* stream, + bool readAudioProperties = true, + AudioProperties::ReadStyle + audioPropertiesStyle = AudioProperties::Average); + + /*! + * Construct a FileRef using \a file. The FileRef now takes ownership of the + * pointer and will delete the File when it passes out of scope. + */ + explicit FileRef(File *file); + + /*! + * Make a copy of \a ref. + */ + FileRef(const FileRef &ref); + + /*! + * Destroys this FileRef instance. + */ + virtual ~FileRef(); + + /*! + * Returns a pointer to represented file's tag. + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + * + * \warning Do not cast it to any subclasses of Tag. + * Use tag returning methods of appropriate subclasses of File instead. + * + * \see File::tag() + */ + Tag *tag() const; + + /*! + * Returns the audio properties for this FileRef. If no audio properties + * were read then this will returns a null pointer. + */ + AudioProperties *audioProperties() const; + + /*! + * Returns a pointer to the file represented by this handler class. + * + * As a general rule this call should be avoided since if you need to work + * with file objects directly, you are probably better served instantiating + * the File subclasses (i.e. MPEG::File) manually and working with their APIs. + * + * This handle exists to provide a minimal, generic and value-based + * wrapper around a File. Accessing the file directly generally indicates + * a moving away from this simplicity (and into things beyond the scope of + * FileRef). + * + * \warning This pointer will become invalid when this FileRef and all + * copies pass out of scope. + */ + File *file() const; + + /*! + * Saves the file. Returns true on success. + */ + bool save(); + + /*! + * Adds a FileTypeResolver to the list of those used by TagLib. Each + * additional FileTypeResolver is added to the front of a list of resolvers + * that are tried. If the FileTypeResolver returns zero the next resolver + * is tried. + * + * Returns a pointer to the added resolver (the same one that's passed in -- + * this is mostly so that static initializers have something to use for + * assignment). + * + * \see FileTypeResolver + */ + static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver); + + /*! + * As is mentioned elsewhere in this class's documentation, the default file + * type resolution code provided by TagLib only works by comparing file + * extensions. + * + * This method returns the list of file extensions that are used by default. + * + * The extensions are all returned in lowercase, though the comparison used + * by TagLib for resolution is case-insensitive. + * + * \note This does not account for any additional file type resolvers that + * are plugged in. Also note that this is not intended to replace a proper + * mime-type resolution system, but is just here for reference. + * + * \see FileTypeResolver + */ + static StringList defaultFileExtensions(); + + /*! + * Returns true if the file (and as such other pointers) are null. + */ + bool isNull() const; + + /*! + * Assign the file pointed to by \a ref to this FileRef. + */ + FileRef &operator=(const FileRef &ref); + + /*! + * Exchanges the content of the FileRef by the content of \a ref. + */ + void swap(FileRef &ref); + + /*! + * Returns true if this FileRef and \a ref point to the same File object. + */ + bool operator==(const FileRef &ref) const; + + /*! + * Returns true if this FileRef and \a ref do not point to the same File + * object. + */ + bool operator!=(const FileRef &ref) const; + + /*! + * A simple implementation of file type guessing. If \a readAudioProperties + * is true then the audio properties will be read using + * \a audioPropertiesStyle. If \a readAudioProperties is false then + * \a audioPropertiesStyle will be ignored. + * + * \note You generally shouldn't use this method, but instead the constructor + * directly. + * + * \deprecated + */ + static File *create(FileName fileName, + bool readAudioProperties = true, + AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average); + + private: + void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle); + void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle); + + class FileRefPrivate; + FileRefPrivate *d; + }; + +} // namespace TagLib + +#endif diff --git a/external/taglib/source/flac/flacfile.cpp b/external/taglib/source/flac/flacfile.cpp new file mode 100644 index 0000000..a71d688 --- /dev/null +++ b/external/taglib/source/flac/flacfile.cpp @@ -0,0 +1,588 @@ +/*************************************************************************** + copyright : (C) 2003-2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "flacpicture.h" +#include "flacfile.h" +#include "flacmetadatablock.h" +#include "flacunknownmetadatablock.h" + +using namespace TagLib; + +namespace +{ + typedef List BlockList; + typedef BlockList::Iterator BlockIterator; + typedef BlockList::Iterator BlockConstIterator; + + enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 }; + + const long MinPaddingLength = 4096; + const long MaxPaddingLegnth = 1024 * 1024; + + const char LastBlockFlag = '\x80'; +} // namespace + +class FLAC::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Location(-1), + properties(0), + flacStart(0), + streamStart(0), + scanned(false) + { + blocks.setAutoDelete(true); + } + + ~FilePrivate() + { + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + long ID3v2Location; + long ID3v2OriginalSize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; + ByteVector xiphCommentData; + BlockList blocks; + + long flacStart; + long streamStart; + bool scanned; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool FLAC::File::isSupported(IOStream *stream) +{ + // A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true); + return (buffer.find("fLaC") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +FLAC::File::~File() +{ + delete d; +} + +TagLib::Tag *FLAC::File::tag() const +{ + return &d->tag; +} + +PropertyMap FLAC::File::properties() const +{ + return d->tag.properties(); +} + +void FLAC::File::removeUnsupportedProperties(const StringList &unsupported) +{ + d->tag.removeUnsupportedProperties(unsupported); +} + +PropertyMap FLAC::File::setProperties(const PropertyMap &properties) +{ + return xiphComment(true)->setProperties(properties); +} + +FLAC::Properties *FLAC::File::audioProperties() const +{ + return d->properties; +} + +bool FLAC::File::save() +{ + if(readOnly()) { + debug("FLAC::File::save() - Cannot save to a read only file."); + return false; + } + + if(!isValid()) { + debug("FLAC::File::save() -- Trying to save invalid file."); + return false; + } + + // Create new vorbis comments + if(!hasXiphComment()) + Tag::duplicate(&d->tag, xiphComment(true), false); + + d->xiphCommentData = xiphComment()->render(false); + + // Replace metadata blocks + + MetadataBlock *commentBlock = + new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData); + for(BlockIterator it = d->blocks.begin(); it != d->blocks.end();) { + if((*it)->code() == MetadataBlock::VorbisComment) { + // Remove the old Vorbis Comment block + delete *it; + it = d->blocks.erase(it); + continue; + } + if(commentBlock && (*it)->code() == MetadataBlock::Picture) { + // Set the new Vorbis Comment block before the first picture block + d->blocks.insert(it, commentBlock); + commentBlock = 0; + } + ++it; + } + if(commentBlock) + d->blocks.append(commentBlock); + + // Render data for the metadata blocks + + ByteVector data; + for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) { + ByteVector blockData = (*it)->render(); + ByteVector blockHeader = ByteVector::fromUInt(blockData.size()); + blockHeader[0] = (*it)->code(); + data.append(blockHeader); + data.append(blockData); + } + + // Compute the amount of padding, and append that to data. + + long originalLength = d->streamStart - d->flacStart; + long paddingLength = originalLength - data.size() - 4; + + if(paddingLength <= 0) { + paddingLength = MinPaddingLength; + } + else { + // Padding won't increase beyond 1% of the file size or 1MB. + + long threshold = length() / 100; + threshold = std::max(threshold, MinPaddingLength); + threshold = std::min(threshold, MaxPaddingLegnth); + + if(paddingLength > threshold) + paddingLength = MinPaddingLength; + } + + ByteVector paddingHeader = ByteVector::fromUInt(paddingLength); + paddingHeader[0] = static_cast(MetadataBlock::Padding | LastBlockFlag); + data.append(paddingHeader); + data.resize(static_cast(data.size() + paddingLength)); + + // Write the data to the file + + insert(data, d->flacStart, originalLength); + + d->streamStart += (static_cast(data.size()) - originalLength); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - originalLength); + + // Update ID3 tags + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + + // ID3v2 tag is not empty. Update the old one or create a new one. + + if(d->ID3v2Location < 0) + d->ID3v2Location = 0; + + data = ID3v2Tag()->render(); + insert(data, d->ID3v2Location, d->ID3v2OriginalSize); + + d->flacStart += (static_cast(data.size()) - d->ID3v2OriginalSize); + d->streamStart += (static_cast(data.size()) - d->ID3v2OriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->ID3v2OriginalSize); + + d->ID3v2OriginalSize = data.size(); + } + else { + + // ID3v2 tag is empty. Remove the old one. + + if(d->ID3v2Location >= 0) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + + d->flacStart -= d->ID3v2OriginalSize; + d->streamStart -= d->ID3v2OriginalSize; + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->ID3v2OriginalSize; + + d->ID3v2Location = -1; + d->ID3v2OriginalSize = 0; + } + } + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + if(d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + } + } + + return true; +} + +ID3v2::Tag *FLAC::File::ID3v2Tag(bool create) +{ + return d->tag.access(FlacID3v2Index, create); +} + +ID3v1::Tag *FLAC::File::ID3v1Tag(bool create) +{ + return d->tag.access(FlacID3v1Index, create); +} + +Ogg::XiphComment *FLAC::File::xiphComment(bool create) +{ + return d->tag.access(FlacXiphIndex, create); +} + +void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +ByteVector FLAC::File::streamInfoData() +{ + debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector."); + return ByteVector(); +} + +long FLAC::File::streamLength() +{ + debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero."); + return 0; +} + +List FLAC::File::pictureList() +{ + List pictures; + for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) { + Picture *picture = dynamic_cast(*it); + if(picture) { + pictures.append(picture); + } + } + return pictures; +} + +void FLAC::File::addPicture(Picture *picture) +{ + d->blocks.append(picture); +} + +void FLAC::File::removePicture(Picture *picture, bool del) +{ + BlockIterator it = d->blocks.find(picture); + if(it != d->blocks.end()) + d->blocks.erase(it); + + if(del) + delete picture; +} + +void FLAC::File::removePictures() +{ + for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ) { + if(dynamic_cast(*it)) { + delete *it; + it = d->blocks.erase(it); + } + else { + ++it; + } + } +} + +void FLAC::File::strip(int tags) +{ + if(tags & ID3v1) + d->tag.set(FlacID3v1Index, 0); + + if(tags & ID3v2) + d->tag.set(FlacID3v2Index, 0); + + if(tags & XiphComment) { + xiphComment()->removeAllFields(); + xiphComment()->removeAllPictures(); + } +} + +bool FLAC::File::hasXiphComment() const +{ + return !d->xiphCommentData.isEmpty(); +} + +bool FLAC::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +bool FLAC::File::hasID3v2Tag() const +{ + return (d->ID3v2Location >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FLAC::File::read(bool readProperties) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = Utils::findID3v2(this); + + if(d->ID3v2Location >= 0) { + d->tag.set(FlacID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + } + + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + // Look for FLAC metadata, including vorbis comments + + scan(); + + if(!isValid()) + return; + + if(!d->xiphCommentData.isEmpty()) + d->tag.set(FlacXiphIndex, new Ogg::XiphComment(d->xiphCommentData)); + else + d->tag.set(FlacXiphIndex, new Ogg::XiphComment()); + + if(readProperties) { + + // First block should be the stream_info metadata + + const ByteVector infoData = d->blocks.front()->render(); + + long streamLength; + + if(d->ID3v1Location >= 0) + streamLength = d->ID3v1Location - d->streamStart; + else + streamLength = length() - d->streamStart; + + d->properties = new Properties(infoData, streamLength); + } +} + +void FLAC::File::scan() +{ + // Scan the metadata pages + + if(d->scanned) + return; + + if(!isValid()) + return; + + long nextBlockOffset; + + if(d->ID3v2Location >= 0) + nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize); + else + nextBlockOffset = find("fLaC"); + + if(nextBlockOffset < 0) { + debug("FLAC::File::scan() -- FLAC stream not found"); + setValid(false); + return; + } + + nextBlockOffset += 4; + d->flacStart = nextBlockOffset; + + while(true) { + + seek(nextBlockOffset); + const ByteVector header = readBlock(4); + if(header.size() != 4) { + debug("FLAC::File::scan() -- Failed to read a block header"); + setValid(false); + return; + } + + // Header format (from spec): + // <1> Last-metadata-block flag + // <7> BLOCK_TYPE + // 0 : STREAMINFO + // 1 : PADDING + // .. + // 4 : VORBIS_COMMENT + // .. + // 6 : PICTURE + // .. + // <24> Length of metadata to follow + + const char blockType = header[0] & ~LastBlockFlag; + const bool isLastBlock = (header[0] & LastBlockFlag) != 0; + const unsigned int blockLength = header.toUInt(1U, 3U); + + // First block should be the stream_info metadata + + if(d->blocks.isEmpty() && blockType != MetadataBlock::StreamInfo) { + debug("FLAC::File::scan() -- First block should be the stream_info metadata"); + setValid(false); + return; + } + + if(blockLength == 0 + && blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable) + { + debug("FLAC::File::scan() -- Zero-sized metadata block found"); + setValid(false); + return; + } + + const ByteVector data = readBlock(blockLength); + if(data.size() != blockLength) { + debug("FLAC::File::scan() -- Failed to read a metadata block"); + setValid(false); + return; + } + + MetadataBlock *block = 0; + + // Found the vorbis-comment + if(blockType == MetadataBlock::VorbisComment) { + if(d->xiphCommentData.isEmpty()) { + d->xiphCommentData = data; + block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, data); + } + else { + debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, discarding"); + } + } + else if(blockType == MetadataBlock::Picture) { + FLAC::Picture *picture = new FLAC::Picture(); + if(picture->parse(data)) { + block = picture; + } + else { + debug("FLAC::File::scan() -- invalid picture found, discarding"); + delete picture; + } + } + else if(blockType == MetadataBlock::Padding) { + // Skip all padding blocks. + } + else { + block = new UnknownMetadataBlock(blockType, data); + } + + if(block) + d->blocks.append(block); + + nextBlockOffset += blockLength + 4; + + if(isLastBlock) + break; + } + + // End of metadata, now comes the datastream + + d->streamStart = nextBlockOffset; + + d->scanned = true; +} diff --git a/external/taglib/source/flac/flacfile.h b/external/taglib/source/flac/flacfile.h new file mode 100644 index 0000000..1b8654e --- /dev/null +++ b/external/taglib/source/flac/flacfile.h @@ -0,0 +1,343 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACFILE_H +#define TAGLIB_FLACFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tlist.h" +#include "tag.h" + +#include "flacpicture.h" +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + namespace ID3v2 { class FrameFactory; class Tag; } + namespace ID3v1 { class Tag; } + namespace Ogg { class XiphComment; } + + //! An implementation of FLAC metadata + + /*! + * This is implementation of FLAC metadata for non-Ogg FLAC files. At some + * point when Ogg / FLAC is more common there will be a similar implementation + * under the Ogg hierarchy. + * + * This supports ID3v1, ID3v2 and Xiph style comments as well as reading stream + * properties from the file. + */ + + namespace FLAC { + + //! An implementation of TagLib::File with FLAC specific methods + + /*! + * This implements and provides an interface for FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to FLAC files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches Vorbis comments. + XiphComment = 0x0001, + //! Matches ID3v1 tags. + ID3v1 = 0x0002, + //! Matches ID3v2 tags. + ID3v2 = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a FLAC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an FLAC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a FLAC file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be a union of XiphComment, + * ID3v1 and ID3v2 tags. + * + * \see ID3v2Tag() + * \see ID3v1Tag() + * \see XiphComment() + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains more than one tag (e.g. XiphComment and ID3v1), + * only the first one (in the order XiphComment, ID3v2, ID3v1) will be + * converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &); + + /*! + * Implements the unified property interface -- import function. + * This always creates a Xiph comment, if none exists. The return value + * relates to the Xiph comment only. + * Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed + * in the FLAC specification. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. This will primarily save the XiphComment, but + * will also keep any old ID3-tags up to date. If the file + * has no XiphComment, one will be constructed from the ID3-tags. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the XiphComment for the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid XiphComment. If \a create is true it will create + * a XiphComment if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has a XiphComment. Use hasXiphComment() to check if the + * file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasXiphComment() + */ + Ogg::XiphComment *xiphComment(bool create = false); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. This + * can be used to specify the way that ID3v2 frames will be interpreted + * when + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the block of data used by FLAC::Properties for parsing the + * stream properties. + * + * \deprecated Always returns an empty vector. + */ + TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + * + * \deprecated Always returns zero. + */ + TAGLIB_DEPRECATED long streamLength(); // BIC: remove + + /*! + * Returns a list of pictures attached to the FLAC file. + */ + List pictureList(); + + /*! + * Removes an attached picture. If \a del is true the picture's memory + * will be freed; if it is false, it must be deleted by the user. + */ + void removePicture(Picture *picture, bool del = true); + + /*! + * Remove all attached images. + */ + void removePictures(); + + /*! + * Add a new picture to the file. The file takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(Picture *picture); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from + * the file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags as their memory + * will be freed. + * + * \note In order to make the removal permanent save() still needs to be + * called. + * + * \note This won't remove the Vorbis comment block completely. The + * vendor ID will be preserved. + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see xiphComment() + */ + bool hasXiphComment() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a FLAC + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + void scan(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/flac/flacmetadatablock.cpp b/external/taglib/source/flac/flacmetadatablock.cpp new file mode 100644 index 0000000..17ab05f --- /dev/null +++ b/external/taglib/source/flac/flacmetadatablock.cpp @@ -0,0 +1,47 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "flacmetadatablock.h" + +using namespace TagLib; + +class FLAC::MetadataBlock::MetadataBlockPrivate +{ +public: + MetadataBlockPrivate() {} + +}; + +FLAC::MetadataBlock::MetadataBlock() +{ + d = 0; +} + +FLAC::MetadataBlock::~MetadataBlock() +{ +} + diff --git a/external/taglib/source/flac/flacmetadatablock.h b/external/taglib/source/flac/flacmetadatablock.h new file mode 100644 index 0000000..41bca31 --- /dev/null +++ b/external/taglib/source/flac/flacmetadatablock.h @@ -0,0 +1,75 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACMETADATABLOCK_H +#define TAGLIB_FLACMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT MetadataBlock + { + public: + MetadataBlock(); + virtual ~MetadataBlock(); + + enum BlockType { + StreamInfo = 0, + Padding, + Application, + SeekTable, + VorbisComment, + CueSheet, + Picture + }; + + /*! + * Returns the FLAC metadata block type. + */ + virtual int code() const = 0; + + /*! + * Render the content of the block. + */ + virtual ByteVector render() const = 0; + + private: + MetadataBlock(const MetadataBlock &item); + MetadataBlock &operator=(const MetadataBlock &item); + + class MetadataBlockPrivate; + MetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/flac/flacpicture.cpp b/external/taglib/source/flac/flacpicture.cpp new file mode 100644 index 0000000..ec07ad1 --- /dev/null +++ b/external/taglib/source/flac/flacpicture.cpp @@ -0,0 +1,217 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "flacpicture.h" + +using namespace TagLib; + +class FLAC::Picture::PicturePrivate +{ +public: + PicturePrivate() : + type(FLAC::Picture::Other), + width(0), + height(0), + colorDepth(0), + numColors(0) + {} + + Type type; + String mimeType; + String description; + int width; + int height; + int colorDepth; + int numColors; + ByteVector data; +}; + +FLAC::Picture::Picture() : + d(new PicturePrivate()) +{ +} + +FLAC::Picture::Picture(const ByteVector &data) : + d(new PicturePrivate()) +{ + parse(data); +} + +FLAC::Picture::~Picture() +{ + delete d; +} + +int FLAC::Picture::code() const +{ + return FLAC::MetadataBlock::Picture; +} + +bool FLAC::Picture::parse(const ByteVector &data) +{ + if(data.size() < 32) { + debug("A picture block must contain at least 5 bytes."); + return false; + } + + unsigned int pos = 0; + d->type = FLAC::Picture::Type(data.toUInt(pos)); + pos += 4; + unsigned int mimeTypeLength = data.toUInt(pos); + pos += 4; + if(pos + mimeTypeLength + 24 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8); + pos += mimeTypeLength; + unsigned int descriptionLength = data.toUInt(pos); + pos += 4; + if(pos + descriptionLength + 20 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->description = String(data.mid(pos, descriptionLength), String::UTF8); + pos += descriptionLength; + d->width = data.toUInt(pos); + pos += 4; + d->height = data.toUInt(pos); + pos += 4; + d->colorDepth = data.toUInt(pos); + pos += 4; + d->numColors = data.toUInt(pos); + pos += 4; + unsigned int dataLength = data.toUInt(pos); + pos += 4; + if(pos + dataLength > data.size()) { + debug("Invalid picture block."); + return false; + } + d->data = data.mid(pos, dataLength); + + return true; +} + +ByteVector FLAC::Picture::render() const +{ + ByteVector result; + result.append(ByteVector::fromUInt(d->type)); + ByteVector mimeTypeData = d->mimeType.data(String::UTF8); + result.append(ByteVector::fromUInt(mimeTypeData.size())); + result.append(mimeTypeData); + ByteVector descriptionData = d->description.data(String::UTF8); + result.append(ByteVector::fromUInt(descriptionData.size())); + result.append(descriptionData); + result.append(ByteVector::fromUInt(d->width)); + result.append(ByteVector::fromUInt(d->height)); + result.append(ByteVector::fromUInt(d->colorDepth)); + result.append(ByteVector::fromUInt(d->numColors)); + result.append(ByteVector::fromUInt(d->data.size())); + result.append(d->data); + return result; +} + +FLAC::Picture::Type FLAC::Picture::type() const +{ + return d->type; +} + +void FLAC::Picture::setType(FLAC::Picture::Type type) +{ + d->type = type; +} + +String FLAC::Picture::mimeType() const +{ + return d->mimeType; +} + +void FLAC::Picture::setMimeType(const String &mimeType) +{ + d->mimeType = mimeType; +} + +String FLAC::Picture::description() const +{ + return d->description; +} + +void FLAC::Picture::setDescription(const String &description) +{ + d->description = description; +} + +int FLAC::Picture::width() const +{ + return d->width; +} + +void FLAC::Picture::setWidth(int width) +{ + d->width = width; +} + +int FLAC::Picture::height() const +{ + return d->height; +} + +void FLAC::Picture::setHeight(int height) +{ + d->height = height; +} + +int FLAC::Picture::colorDepth() const +{ + return d->colorDepth; +} + +void FLAC::Picture::setColorDepth(int colorDepth) +{ + d->colorDepth = colorDepth; +} + +int FLAC::Picture::numColors() const +{ + return d->numColors; +} + +void FLAC::Picture::setNumColors(int numColors) +{ + d->numColors = numColors; +} + +ByteVector FLAC::Picture::data() const +{ + return d->data; +} + +void FLAC::Picture::setData(const ByteVector &data) +{ + d->data = data; +} + diff --git a/external/taglib/source/flac/flacpicture.h b/external/taglib/source/flac/flacpicture.h new file mode 100644 index 0000000..b6def57 --- /dev/null +++ b/external/taglib/source/flac/flacpicture.h @@ -0,0 +1,208 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPICTURE_H +#define TAGLIB_FLACPICTURE_H + +#include "tlist.h" +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT Picture : public MetadataBlock + { + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + Picture(); + Picture(const ByteVector &data); + ~Picture(); + + /*! + * Returns the type of the image. + */ + Type type() const; + + /*! + * Sets the type of the image. + */ + void setType(Type type); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns a text description of the image. + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + */ + + void setDescription(const String &desc); + + /*! + * Returns the width of the image. + */ + int width() const; + + /*! + * Sets the width of the image. + */ + void setWidth(int w); + + /*! + * Returns the height of the image. + */ + int height() const; + + /*! + * Sets the height of the image. + */ + void setHeight(int h); + + /*! + * Returns the color depth (in bits-per-pixel) of the image. + */ + int colorDepth() const; + + /*! + * Sets the color depth (in bits-per-pixel) of the image. + */ + void setColorDepth(int depth); + + /*! + * Returns the number of colors used on the image.. + */ + int numColors() const; + + /*! + * Sets the number of colors used on the image (for indexed images). + */ + void setNumColors(int numColors); + + /*! + * Returns the image data. + */ + ByteVector data() const; + + /*! + * Sets the image data. + */ + void setData(const ByteVector &data); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Render the content to the FLAC picture block format. + */ + ByteVector render() const; + + /*! + * Parse the picture data in the FLAC picture block format. + */ + bool parse(const ByteVector &rawData); + + private: + Picture(const Picture &item); + Picture &operator=(const Picture &item); + + class PicturePrivate; + PicturePrivate *d; + }; + + typedef List PictureList; + + } + +} + +#endif diff --git a/external/taglib/source/flac/flacproperties.cpp b/external/taglib/source/flac/flacproperties.cpp new file mode 100644 index 0000000..b947f03 --- /dev/null +++ b/external/taglib/source/flac/flacproperties.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "flacproperties.h" +#include "flacfile.h" + +using namespace TagLib; + +class FLAC::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + bitsPerSample(0), + channels(0), + sampleFrames(0) {} + + int length; + int bitrate; + int sampleRate; + int bitsPerSample; + int channels; + unsigned long long sampleFrames; + ByteVector signature; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(data, streamLength); +} + +FLAC::Properties::Properties(File *, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("FLAC::Properties::Properties() - This constructor is no longer used."); +} + +FLAC::Properties::~Properties() +{ + delete d; +} + +int FLAC::Properties::length() const +{ + return lengthInSeconds(); +} + +int FLAC::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int FLAC::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int FLAC::Properties::bitrate() const +{ + return d->bitrate; +} + +int FLAC::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int FLAC::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int FLAC::Properties::sampleWidth() const +{ + return bitsPerSample(); +} + +int FLAC::Properties::channels() const +{ + return d->channels; +} + +unsigned long long FLAC::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +ByteVector FLAC::Properties::signature() const +{ + return d->signature; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void FLAC::Properties::read(const ByteVector &data, long streamLength) +{ + if(data.size() < 18) { + debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes."); + return; + } + + unsigned int pos = 0; + + // Minimum block size (in samples) + pos += 2; + + // Maximum block size (in samples) + pos += 2; + + // Minimum frame size (in bytes) + pos += 3; + + // Maximum frame size (in bytes) + pos += 3; + + const unsigned int flags = data.toUInt(pos, true); + pos += 4; + + d->sampleRate = flags >> 12; + d->channels = ((flags >> 9) & 7) + 1; + d->bitsPerSample = ((flags >> 4) & 31) + 1; + + // The last 4 bits are the most significant 4 bits for the 36 bit + // stream length in samples. (Audio files measured in days) + + const unsigned long long hi = flags & 0xf; + const unsigned long long lo = data.toUInt(pos, true); + pos += 4; + + d->sampleFrames = (hi << 32) | lo; + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } + + if(data.size() >= pos + 16) + d->signature = data.mid(pos, 16); +} diff --git a/external/taglib/source/flac/flacproperties.h b/external/taglib/source/flac/flacproperties.h new file mode 100644 index 0000000..743e587 --- /dev/null +++ b/external/taglib/source/flac/flacproperties.h @@ -0,0 +1,148 @@ +/*************************************************************************** + copyright : (C) 2003 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACPROPERTIES_H +#define TAGLIB_FLACPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace FLAC { + + class File; + + //! An implementation of audio property reading for FLAC + + /*! + * This reads the data from an FLAC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of FLAC::Properties with the data read from the + * ByteVector \a data. + */ + // BIC: switch to const reference + Properties(ByteVector data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of FLAC::Properties with the data read from the + * FLAC::File \a file. + */ + // BIC: remove + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this FLAC::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample as read from the FLAC + * identification header. + */ + int bitsPerSample() const; + + /*! + * Returns the sample width as read from the FLAC identification + * header. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Return the number of sample frames. + */ + unsigned long long sampleFrames() const; + + /*! + * Returns the MD5 signature of the uncompressed audio stream as read + * from the stream info header. + */ + ByteVector signature() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/flac/flacunknownmetadatablock.cpp b/external/taglib/source/flac/flacunknownmetadatablock.cpp new file mode 100644 index 0000000..f9cf6e6 --- /dev/null +++ b/external/taglib/source/flac/flacunknownmetadatablock.cpp @@ -0,0 +1,78 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include "flacunknownmetadatablock.h" + +using namespace TagLib; + +class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate +{ +public: + UnknownMetadataBlockPrivate() : code(0) {} + + int code; + ByteVector data; +}; + +FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) : + d(new UnknownMetadataBlockPrivate()) +{ + d->code = code; + d->data = data; +} + +FLAC::UnknownMetadataBlock::~UnknownMetadataBlock() +{ + delete d; +} + +int FLAC::UnknownMetadataBlock::code() const +{ + return d->code; +} + +void FLAC::UnknownMetadataBlock::setCode(int code) +{ + d->code = code; +} + +ByteVector FLAC::UnknownMetadataBlock::data() const +{ + return d->data; +} + +void FLAC::UnknownMetadataBlock::setData(const ByteVector &data) +{ + d->data = data; +} + +ByteVector FLAC::UnknownMetadataBlock::render() const +{ + return d->data; +} + diff --git a/external/taglib/source/flac/flacunknownmetadatablock.h b/external/taglib/source/flac/flacunknownmetadatablock.h new file mode 100644 index 0000000..3030254 --- /dev/null +++ b/external/taglib/source/flac/flacunknownmetadatablock.h @@ -0,0 +1,81 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FLACUNKNOWNMETADATABLOCK_H +#define TAGLIB_FLACUNKNOWNMETADATABLOCK_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "flacmetadatablock.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock + { + public: + UnknownMetadataBlock(int blockType, const ByteVector &data); + ~UnknownMetadataBlock(); + + /*! + * Returns the FLAC metadata block type. + */ + int code() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setCode(int code); + + /*! + * Returns the FLAC metadata block type. + */ + ByteVector data() const; + + /*! + * Sets the FLAC metadata block type. + */ + void setData(const ByteVector &data); + + /*! + * Render the content of the block. + */ + ByteVector render() const; + + private: + UnknownMetadataBlock(const MetadataBlock &item); + UnknownMetadataBlock &operator=(const MetadataBlock &item); + + class UnknownMetadataBlockPrivate; + UnknownMetadataBlockPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/it/itfile.cpp b/external/taglib/source/it/itfile.cpp new file mode 100644 index 0000000..c60d5fc --- /dev/null +++ b/external/taglib/source/it/itfile.cpp @@ -0,0 +1,335 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "tstringlist.h" +#include "itfile.h" +#include "tdebug.h" +#include "modfileprivate.h" +#include "tpropertymap.h" + +using namespace TagLib; +using namespace IT; + +class IT::File::FilePrivate +{ +public: + FilePrivate(AudioProperties::ReadStyle propertiesStyle) + : properties(propertiesStyle) + { + } + + Mod::Tag tag; + IT::Properties properties; +}; + +IT::File::File(FileName file, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(file), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +IT::File::File(IOStream *stream, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(stream), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +IT::File::~File() +{ + delete d; +} + +Mod::Tag *IT::File::tag() const +{ + return &d->tag; +} + +PropertyMap IT::File::properties() const +{ + return d->tag.properties(); +} + +PropertyMap IT::File::setProperties(const PropertyMap &properties) +{ + return d->tag.setProperties(properties); +} + +IT::Properties *IT::File::audioProperties() const +{ + return &d->properties; +} + +bool IT::File::save() +{ + if(readOnly()) + { + debug("IT::File::save() - Cannot save to a read only file."); + return false; + } + seek(4); + writeString(d->tag.title(), 25); + writeByte(0); + + seek(2, Current); + + unsigned short length = 0; + unsigned short instrumentCount = 0; + unsigned short sampleCount = 0; + + if(!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount)) + return false; + + seek(15, Current); + + // write comment as instrument and sample names: + StringList lines = d->tag.comment().split("\n"); + for(unsigned short i = 0; i < instrumentCount; ++ i) { + seek(192L + length + (static_cast(i) << 2)); + unsigned long instrumentOffset = 0; + if(!readU32L(instrumentOffset)) + return false; + + seek(instrumentOffset + 32); + + if(i < lines.size()) + writeString(lines[i], 25); + else + writeString(String(), 25); + writeByte(0); + } + + for(unsigned short i = 0; i < sampleCount; ++ i) { + seek(192L + length + (static_cast(instrumentCount) << 2) + (static_cast(i) << 2)); + unsigned long sampleOffset = 0; + if(!readU32L(sampleOffset)) + return false; + + seek(sampleOffset + 20); + + if(static_cast(i + instrumentCount) < lines.size()) + writeString(lines[i + instrumentCount], 25); + else + writeString(String(), 25); + writeByte(0); + } + + // write rest as message: + StringList messageLines; + for(unsigned int i = instrumentCount + sampleCount; i < lines.size(); ++ i) + messageLines.append(lines[i]); + ByteVector message = messageLines.toString("\r").data(String::Latin1); + + // it's actually not really stated if the message needs a + // terminating NUL but it does not hurt to add one: + if(message.size() > 7999) + message.resize(7999); + message.append(static_cast(0)); + + unsigned short special = 0; + unsigned short messageLength = 0; + unsigned long messageOffset = 0; + + seek(46); + if(!readU16L(special)) + return false; + + unsigned long fileSize = File::length(); + if(special & Properties::MessageAttached) { + seek(54); + if(!readU16L(messageLength) || !readU32L(messageOffset)) + return false; + + if(messageLength == 0) + messageOffset = fileSize; + } + else + { + messageOffset = fileSize; + seek(46); + writeU16L(special | 0x1); + } + + if(messageOffset + messageLength >= fileSize) { + // append new message + seek(54); + writeU16L(message.size()); + writeU32L(messageOffset); + seek(messageOffset); + writeBlock(message); + truncate(messageOffset + message.size()); + } + else { + // Only overwrite existing message. + // I'd need to parse (understand!) the whole file for more. + // Although I could just move the message to the end of file + // and let the existing one be, but that would waste space. + message.resize(messageLength, 0); + seek(messageOffset); + writeBlock(message); + } + return true; +} + +void IT::File::read(bool) +{ + if(!isOpen()) + return; + + seek(0); + READ_ASSERT(readBlock(4) == "IMPM"); + READ_STRING(d->tag.setTitle, 26); + + seek(2, Current); + + READ_U16L_AS(length); + READ_U16L_AS(instrumentCount); + READ_U16L_AS(sampleCount); + + d->properties.setInstrumentCount(instrumentCount); + d->properties.setSampleCount(sampleCount); + READ_U16L(d->properties.setPatternCount); + READ_U16L(d->properties.setVersion); + READ_U16L(d->properties.setCompatibleVersion); + READ_U16L(d->properties.setFlags); + READ_U16L_AS(special); + d->properties.setSpecial(special); + READ_BYTE(d->properties.setGlobalVolume); + READ_BYTE(d->properties.setMixVolume); + READ_BYTE(d->properties.setBpmSpeed); + READ_BYTE(d->properties.setTempo); + READ_BYTE(d->properties.setPanningSeparation); + READ_BYTE(d->properties.setPitchWheelDepth); + + // IT supports some kind of comment tag. Still, the + // sample/instrument names are abused as comments so + // I just add all together. + String message; + if(special & Properties::MessageAttached) { + READ_U16L_AS(messageLength); + READ_U32L_AS(messageOffset); + seek(messageOffset); + ByteVector messageBytes = readBlock(messageLength); + READ_ASSERT(messageBytes.size() == messageLength); + int index = messageBytes.find(static_cast(0)); + if(index > -1) + messageBytes.resize(index, 0); + messageBytes.replace('\r', '\n'); + message = messageBytes; + } + + seek(64); + + ByteVector pannings = readBlock(64); + ByteVector volumes = readBlock(64); + READ_ASSERT(pannings.size() == 64 && volumes.size() == 64); + int channels = 0; + for(int i = 0; i < 64; ++ i) { + // Strictly speaking an IT file has always 64 channels, but + // I don't count disabled and muted channels. + // But this always gives 64 channels for all my files anyway. + // Strangely VLC does report other values. I wonder how VLC + // gets it's values. + if(static_cast(pannings[i]) < 128 && volumes[i] > 0) + ++channels; + } + d->properties.setChannels(channels); + + // real length might be shorter because of skips and terminator + unsigned short realLength = 0; + for(unsigned short i = 0; i < length; ++ i) { + READ_BYTE_AS(order); + if(order == 255) break; + if(order != 254) ++ realLength; + } + d->properties.setLengthInPatterns(realLength); + + StringList comment; + // Note: I found files that have nil characters somewhere + // in the instrument/sample names and more characters + // afterwards. The spec does not mention such a case. + // Currently I just discard anything after a nil, but + // e.g. VLC seems to interpret a nil as a space. I + // don't know what is the proper behaviour. + for(unsigned short i = 0; i < instrumentCount; ++ i) { + seek(192L + length + (static_cast(i) << 2)); + READ_U32L_AS(instrumentOffset); + seek(instrumentOffset); + + ByteVector instrumentMagic = readBlock(4); + READ_ASSERT(instrumentMagic == "IMPI"); + + READ_STRING_AS(dosFileName, 13); + + seek(15, Current); + + READ_STRING_AS(instrumentName, 26); + comment.append(instrumentName); + } + + for(unsigned short i = 0; i < sampleCount; ++ i) { + seek(192L + length + (static_cast(instrumentCount) << 2) + (static_cast(i) << 2)); + READ_U32L_AS(sampleOffset); + + seek(sampleOffset); + + ByteVector sampleMagic = readBlock(4); + READ_ASSERT(sampleMagic == "IMPS"); + + READ_STRING_AS(dosFileName, 13); + READ_BYTE_AS(globalVolume); + READ_BYTE_AS(sampleFlags); + READ_BYTE_AS(sampleVolume); + READ_STRING_AS(sampleName, 26); + /* + READ_BYTE_AS(sampleCvt); + READ_BYTE_AS(samplePanning); + READ_U32L_AS(sampleLength); + READ_U32L_AS(loopStart); + READ_U32L_AS(loopStop); + READ_U32L_AS(c5speed); + READ_U32L_AS(sustainLoopStart); + READ_U32L_AS(sustainLoopEnd); + READ_U32L_AS(sampleDataOffset); + READ_BYTE_AS(vibratoSpeed); + READ_BYTE_AS(vibratoDepth); + READ_BYTE_AS(vibratoRate); + READ_BYTE_AS(vibratoType); + */ + + comment.append(sampleName); + } + + if(message.size() > 0) + comment.append(message); + d->tag.setComment(comment.toString("\n")); + d->tag.setTrackerName("Impulse Tracker"); +} diff --git a/external/taglib/source/it/itfile.h b/external/taglib/source/it/itfile.h new file mode 100644 index 0000000..19327dc --- /dev/null +++ b/external/taglib/source/it/itfile.h @@ -0,0 +1,109 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_ITFILE_H +#define TAGLIB_ITFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "itproperties.h" + +namespace TagLib { + + namespace IT { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs a Impulse Tracker file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a Impulse Tracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Forwards to Mod::Tag::properties(). + * BIC: will be removed once File::toDict() is made virtual + */ + PropertyMap properties() const; + + /*! + * Forwards to Mod::Tag::setProperties(). + * BIC: will be removed once File::setProperties() is made virtual + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the IT::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + IT::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Impulse Tracker tags is not supported. + */ + bool save(); + + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/it/itproperties.cpp b/external/taglib/source/it/itproperties.cpp new file mode 100644 index 0000000..c317b66 --- /dev/null +++ b/external/taglib/source/it/itproperties.cpp @@ -0,0 +1,260 @@ +/*************************************************************************** + copyright :(C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "itproperties.h" + +using namespace TagLib; +using namespace IT; + +class IT::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + channels(0), + lengthInPatterns(0), + instrumentCount(0), + sampleCount(0), + patternCount(0), + version(0), + compatibleVersion(0), + flags(0), + special(0), + globalVolume(0), + mixVolume(0), + tempo(0), + bpmSpeed(0), + panningSeparation(0), + pitchWheelDepth(0) + { + } + + int channels; + unsigned short lengthInPatterns; + unsigned short instrumentCount; + unsigned short sampleCount; + unsigned short patternCount; + unsigned short version; + unsigned short compatibleVersion; + unsigned short flags; + unsigned short special; + unsigned char globalVolume; + unsigned char mixVolume; + unsigned char tempo; + unsigned char bpmSpeed; + unsigned char panningSeparation; + unsigned char pitchWheelDepth; +}; + +IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : + AudioProperties(propertiesStyle), + d(new PropertiesPrivate()) +{ +} + +IT::Properties::~Properties() +{ + delete d; +} + +int IT::Properties::length() const +{ + return 0; +} + +int IT::Properties::lengthInSeconds() const +{ + return 0; +} + +int IT::Properties::lengthInMilliseconds() const +{ + return 0; +} + +int IT::Properties::bitrate() const +{ + return 0; +} + +int IT::Properties::sampleRate() const +{ + return 0; +} + +int IT::Properties::channels() const +{ + return d->channels; +} + +unsigned short IT::Properties::lengthInPatterns() const +{ + return d->lengthInPatterns; +} + +bool IT::Properties::stereo() const +{ + return d->flags & Stereo; +} + +unsigned short IT::Properties::instrumentCount() const +{ + return d->instrumentCount; +} + +unsigned short IT::Properties::sampleCount() const +{ + return d->sampleCount; +} + +unsigned short IT::Properties::patternCount() const +{ + return d->patternCount; +} + +unsigned short IT::Properties::version() const +{ + return d->version; +} + +unsigned short IT::Properties::compatibleVersion() const +{ + return d->compatibleVersion; +} + +unsigned short IT::Properties::flags() const +{ + return d->flags; +} + +unsigned short IT::Properties::special() const +{ + return d->special; +} + +unsigned char IT::Properties::globalVolume() const +{ + return d->globalVolume; +} + +unsigned char IT::Properties::mixVolume() const +{ + return d->mixVolume; +} + +unsigned char IT::Properties::tempo() const +{ + return d->tempo; +} + +unsigned char IT::Properties::bpmSpeed() const +{ + return d->bpmSpeed; +} + +unsigned char IT::Properties::panningSeparation() const +{ + return d->panningSeparation; +} + +unsigned char IT::Properties::pitchWheelDepth() const +{ + return d->pitchWheelDepth; +} + +void IT::Properties::setChannels(int channels) +{ + d->channels = channels; +} + +void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns) +{ + d->lengthInPatterns = lengthInPatterns; +} + +void IT::Properties::setInstrumentCount(unsigned short instrumentCount) +{ + d->instrumentCount = instrumentCount; +} + +void IT::Properties::setSampleCount(unsigned short sampleCount) +{ + d->sampleCount = sampleCount; +} + +void IT::Properties::setPatternCount(unsigned short patternCount) +{ + d->patternCount = patternCount; +} + +void IT::Properties::setFlags(unsigned short flags) +{ + d->flags = flags; +} + +void IT::Properties::setSpecial(unsigned short special) +{ + d->special = special; +} + +void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion) +{ + d->compatibleVersion = compatibleVersion; +} + +void IT::Properties::setVersion(unsigned short version) +{ + d->version = version; +} + +void IT::Properties::setGlobalVolume(unsigned char globalVolume) +{ + d->globalVolume = globalVolume; +} + +void IT::Properties::setMixVolume(unsigned char mixVolume) +{ + d->mixVolume = mixVolume; +} + +void IT::Properties::setTempo(unsigned char tempo) +{ + d->tempo = tempo; +} + +void IT::Properties::setBpmSpeed(unsigned char bpmSpeed) +{ + d->bpmSpeed = bpmSpeed; +} + +void IT::Properties::setPanningSeparation(unsigned char panningSeparation) +{ + d->panningSeparation = panningSeparation; +} + +void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth) +{ + d->pitchWheelDepth = pitchWheelDepth; +} diff --git a/external/taglib/source/it/itproperties.h b/external/taglib/source/it/itproperties.h new file mode 100644 index 0000000..be1c9d2 --- /dev/null +++ b/external/taglib/source/it/itproperties.h @@ -0,0 +1,107 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ITPROPERTIES_H +#define TAGLIB_ITPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + namespace IT { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + Stereo = 1, + Vol0MixOptimizations = 2, + UseInstruments = 4, + LinearSlides = 8, + OldEffects = 16, + LinkEffects = 32, + UseMidiPitchController = 64, + RequestEmbeddedMidiConf = 128 + }; + + /*! Special bits. */ + enum { + MessageAttached = 1, + MidiConfEmbedded = 8 + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + bool stereo() const; + unsigned short instrumentCount() const; + unsigned short sampleCount() const; + unsigned short patternCount() const; + unsigned short version() const; + unsigned short compatibleVersion() const; + unsigned short flags() const; + unsigned short special() const; + unsigned char globalVolume() const; + unsigned char mixVolume() const; + unsigned char tempo() const; + unsigned char bpmSpeed() const; + unsigned char panningSeparation() const; + unsigned char pitchWheelDepth() const; + + void setChannels(int channels); + void setLengthInPatterns(unsigned short lengthInPatterns); + void setInstrumentCount(unsigned short instrumentCount); + void setSampleCount (unsigned short sampleCount); + void setPatternCount(unsigned short patternCount); + void setVersion (unsigned short version); + void setCompatibleVersion(unsigned short compatibleVersion); + void setFlags (unsigned short flags); + void setSpecial (unsigned short special); + void setGlobalVolume(unsigned char globalVolume); + void setMixVolume (unsigned char mixVolume); + void setTempo (unsigned char tempo); + void setBpmSpeed (unsigned char bpmSpeed); + void setPanningSeparation(unsigned char panningSeparation); + void setPitchWheelDepth (unsigned char pitchWheelDepth); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mod/modfile.cpp b/external/taglib/source/mod/modfile.cpp new file mode 100644 index 0000000..00d330e --- /dev/null +++ b/external/taglib/source/mod/modfile.cpp @@ -0,0 +1,192 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "modfile.h" +#include "tstringlist.h" +#include "tdebug.h" +#include "modfileprivate.h" +#include "tpropertymap.h" + +using namespace TagLib; +using namespace Mod; + +class Mod::File::FilePrivate +{ +public: + FilePrivate(AudioProperties::ReadStyle propertiesStyle) + : properties(propertiesStyle) + { + } + + Mod::Tag tag; + Mod::Properties properties; +}; + +Mod::File::File(FileName file, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(file), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +Mod::File::File(IOStream *stream, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(stream), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +Mod::File::~File() +{ + delete d; +} + +Mod::Tag *Mod::File::tag() const +{ + return &d->tag; +} + +Mod::Properties *Mod::File::audioProperties() const +{ + return &d->properties; +} + +PropertyMap Mod::File::properties() const +{ + return d->tag.properties(); +} + +PropertyMap Mod::File::setProperties(const PropertyMap &properties) +{ + return d->tag.setProperties(properties); +} + +bool Mod::File::save() +{ + if(readOnly()) { + debug("Mod::File::save() - Cannot save to a read only file."); + return false; + } + seek(0); + writeString(d->tag.title(), 20); + StringList lines = d->tag.comment().split("\n"); + unsigned int n = std::min(lines.size(), d->properties.instrumentCount()); + for(unsigned int i = 0; i < n; ++ i) { + writeString(lines[i], 22); + seek(8, Current); + } + + for(unsigned int i = n; i < d->properties.instrumentCount(); ++ i) { + writeString(String(), 22); + seek(8, Current); + } + return true; +} + +void Mod::File::read(bool) +{ + if(!isOpen()) + return; + + seek(1080); + ByteVector modId = readBlock(4); + READ_ASSERT(modId.size() == 4); + + int channels = 4; + unsigned int instruments = 31; + if(modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.") { + d->tag.setTrackerName("ProTracker"); + channels = 4; + } + else if(modId.startsWith("FLT") || modId.startsWith("TDZ")) { + d->tag.setTrackerName("StarTrekker"); + char digit = modId[3]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = digit - '0'; + } + else if(modId.endsWith("CHN")) { + d->tag.setTrackerName("StarTrekker"); + char digit = modId[0]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = digit - '0'; + } + else if(modId == "CD81" || modId == "OKTA") { + d->tag.setTrackerName("Atari Oktalyzer"); + channels = 8; + } + else if(modId.endsWith("CH") || modId.endsWith("CN")) { + d->tag.setTrackerName("TakeTracker"); + char digit = modId[0]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels = (digit - '0') * 10; + digit = modId[1]; + READ_ASSERT(digit >= '0' && digit <= '9'); + channels += digit - '0'; + } + else { + // Not sure if this is correct. I'd need a file + // created with NoiseTracker to check this. + d->tag.setTrackerName("NoiseTracker"); // probably + channels = 4; + instruments = 15; + } + d->properties.setChannels(channels); + d->properties.setInstrumentCount(instruments); + + seek(0); + READ_STRING(d->tag.setTitle, 20); + + StringList comment; + for(unsigned int i = 0; i < instruments; ++ i) { + READ_STRING_AS(instrumentName, 22); + // value in words, * 2 (<< 1) for bytes: + READ_U16B_AS(sampleLength); + + READ_BYTE_AS(fineTuneByte); + int fineTune = fineTuneByte & 0xF; + // > 7 means negative value + if(fineTune > 7) fineTune -= 16; + + READ_BYTE_AS(volume); + if(volume > 64) volume = 64; + // volume in decibels: 20 * log10(volume / 64) + + // value in words, * 2 (<< 1) for bytes: + READ_U16B_AS(repeatStart); + // value in words, * 2 (<< 1) for bytes: + READ_U16B_AS(repatLength); + + comment.append(instrumentName); + } + + READ_BYTE(d->properties.setLengthInPatterns); + + d->tag.setComment(comment.toString("\n")); +} diff --git a/external/taglib/source/mod/modfile.h b/external/taglib/source/mod/modfile.h new file mode 100644 index 0000000..b66452d --- /dev/null +++ b/external/taglib/source/mod/modfile.h @@ -0,0 +1,114 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILE_H +#define TAGLIB_MODFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "modproperties.h" + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT File : public TagLib::Mod::FileBase + { + public: + /*! + * Constructs a Protracker file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a Protracker file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + /*! + * Returns the Mod::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + Mod::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Protracker tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mod/modfilebase.cpp b/external/taglib/source/mod/modfilebase.cpp new file mode 100644 index 0000000..46da18a --- /dev/null +++ b/external/taglib/source/mod/modfilebase.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "tdebug.h" +#include "modfilebase.h" + +using namespace TagLib; +using namespace Mod; + +Mod::FileBase::FileBase(FileName file) : TagLib::File(file) +{ +} + +Mod::FileBase::FileBase(IOStream *stream) : TagLib::File(stream) +{ +} + +void Mod::FileBase::writeString(const String &s, unsigned long size, char padding) +{ + ByteVector data(s.data(String::Latin1)); + data.resize(size, padding); + writeBlock(data); +} + +bool Mod::FileBase::readString(String &s, unsigned long size) +{ + ByteVector data(readBlock(size)); + if(data.size() < size) return false; + int index = data.find(static_cast(0)); + if(index > -1) + { + data.resize(index); + } + data.replace('\xff', ' '); + + s = data; + return true; +} + +void Mod::FileBase::writeByte(unsigned char byte) +{ + ByteVector data(1, byte); + writeBlock(data); +} + +void Mod::FileBase::writeU16L(unsigned short number) +{ + writeBlock(ByteVector::fromShort(number, false)); +} + +void Mod::FileBase::writeU32L(unsigned long number) +{ + writeBlock(ByteVector::fromUInt(number, false)); +} + +void Mod::FileBase::writeU16B(unsigned short number) +{ + writeBlock(ByteVector::fromShort(number, true)); +} + +void Mod::FileBase::writeU32B(unsigned long number) +{ + writeBlock(ByteVector::fromUInt(number, true)); +} + +bool Mod::FileBase::readByte(unsigned char &byte) +{ + ByteVector data(readBlock(1)); + if(data.size() < 1) return false; + byte = data[0]; + return true; +} + +bool Mod::FileBase::readU16L(unsigned short &number) +{ + ByteVector data(readBlock(2)); + if(data.size() < 2) return false; + number = data.toUShort(false); + return true; +} + +bool Mod::FileBase::readU32L(unsigned long &number) { + ByteVector data(readBlock(4)); + if(data.size() < 4) return false; + number = data.toUInt(false); + return true; +} + +bool Mod::FileBase::readU16B(unsigned short &number) +{ + ByteVector data(readBlock(2)); + if(data.size() < 2) return false; + number = data.toUShort(true); + return true; +} + +bool Mod::FileBase::readU32B(unsigned long &number) { + ByteVector data(readBlock(4)); + if(data.size() < 4) return false; + number = data.toUInt(true); + return true; +} diff --git a/external/taglib/source/mod/modfilebase.h b/external/taglib/source/mod/modfilebase.h new file mode 100644 index 0000000..bae9716 --- /dev/null +++ b/external/taglib/source/mod/modfilebase.h @@ -0,0 +1,66 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILEBASE_H +#define TAGLIB_MODFILEBASE_H + +#include "taglib.h" +#include "tfile.h" +#include "tstring.h" +#include "tlist.h" +#include "taglib_export.h" + +#include + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT FileBase : public TagLib::File + { + protected: + FileBase(FileName file); + FileBase(IOStream *stream); + + void writeString(const String &s, unsigned long size, char padding = 0); + void writeByte(unsigned char byte); + void writeU16L(unsigned short number); + void writeU32L(unsigned long number); + void writeU16B(unsigned short number); + void writeU32B(unsigned long number); + + bool readString(String &s, unsigned long size); + bool readByte(unsigned char &byte); + bool readU16L(unsigned short &number); + bool readU32L(unsigned long &number); + bool readU16B(unsigned short &number); + bool readU32B(unsigned long &number); + }; + + } + +} + +#endif diff --git a/external/taglib/source/mod/modfileprivate.h b/external/taglib/source/mod/modfileprivate.h new file mode 100644 index 0000000..781db74 --- /dev/null +++ b/external/taglib/source/mod/modfileprivate.h @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_MODFILEPRIVATE_H +#define TAGLIB_MODFILEPRIVATE_H + +// some helper-macros only used internally by (s3m|it|xm)file.cpp +#define READ_ASSERT(cond) \ + if(!(cond)) \ + { \ + setValid(false); \ + return; \ + } + +#define READ(setter,type,read) \ + { \ + type number; \ + READ_ASSERT(read(number)); \ + setter(number); \ + } + +#define READ_BYTE(setter) READ(setter,unsigned char,readByte) +#define READ_U16L(setter) READ(setter,unsigned short,readU16L) +#define READ_U32L(setter) READ(setter,unsigned long,readU32L) +#define READ_U16B(setter) READ(setter,unsigned short,readU16B) +#define READ_U32B(setter) READ(setter,unsigned long,readU32B) + +#define READ_STRING(setter,size) \ + { \ + String s; \ + READ_ASSERT(readString(s, size)); \ + setter(s); \ + } + +#define READ_AS(type,name,read) \ + type name = 0; \ + READ_ASSERT(read(name)); + +#define READ_BYTE_AS(name) READ_AS(unsigned char,name,readByte) +#define READ_U16L_AS(name) READ_AS(unsigned short,name,readU16L) +#define READ_U32L_AS(name) READ_AS(unsigned long,name,readU32L) +#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B) +#define READ_U32B_AS(name) READ_AS(unsigned long,name,readU32B) + +#define READ_STRING_AS(name,size) \ + String name; \ + READ_ASSERT(readString(name, size)); + +#endif diff --git a/external/taglib/source/mod/modproperties.cpp b/external/taglib/source/mod/modproperties.cpp new file mode 100644 index 0000000..c6bf394 --- /dev/null +++ b/external/taglib/source/mod/modproperties.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "modproperties.h" + +using namespace TagLib; +using namespace Mod; + +class Mod::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + channels(0), + instrumentCount(0), + lengthInPatterns(0) + { + } + + int channels; + unsigned int instrumentCount; + unsigned char lengthInPatterns; +}; + +Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : + AudioProperties(propertiesStyle), + d(new PropertiesPrivate()) +{ +} + +Mod::Properties::~Properties() +{ + delete d; +} + +int Mod::Properties::length() const +{ + return 0; +} + +int Mod::Properties::lengthInSeconds() const +{ + return 0; +} + +int Mod::Properties::lengthInMilliseconds() const +{ + return 0; +} + +int Mod::Properties::bitrate() const +{ + return 0; +} + +int Mod::Properties::sampleRate() const +{ + return 0; +} + +int Mod::Properties::channels() const +{ + return d->channels; +} + +unsigned int Mod::Properties::instrumentCount() const +{ + return d->instrumentCount; +} + +unsigned char Mod::Properties::lengthInPatterns() const +{ + return d->lengthInPatterns; +} + +void Mod::Properties::setChannels(int channels) +{ + d->channels = channels; +} + +void Mod::Properties::setInstrumentCount(unsigned int instrumentCount) +{ + d->instrumentCount = instrumentCount; +} + +void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns) +{ + d->lengthInPatterns = lengthInPatterns; +} diff --git a/external/taglib/source/mod/modproperties.h b/external/taglib/source/mod/modproperties.h new file mode 100644 index 0000000..4712294 --- /dev/null +++ b/external/taglib/source/mod/modproperties.h @@ -0,0 +1,71 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODPROPERTIES_H +#define TAGLIB_MODPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace Mod { + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned int instrumentCount() const; + unsigned char lengthInPatterns() const; + + void setChannels(int channels); + + void setInstrumentCount(unsigned int sampleCount); + void setLengthInPatterns(unsigned char lengthInPatterns); + + private: + friend class File; + + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mod/modtag.cpp b/external/taglib/source/mod/modtag.cpp new file mode 100644 index 0000000..0495045 --- /dev/null +++ b/external/taglib/source/mod/modtag.cpp @@ -0,0 +1,173 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "modtag.h" +#include "tstringlist.h" +#include "tpropertymap.h" + +using namespace TagLib; +using namespace Mod; + +class Mod::Tag::TagPrivate +{ +public: + TagPrivate() + { + } + + String title; + String comment; + String trackerName; +}; + +Mod::Tag::Tag() : + d(new TagPrivate()) +{ +} + +Mod::Tag::~Tag() +{ + delete d; +} + +String Mod::Tag::title() const +{ + return d->title; +} + +String Mod::Tag::artist() const +{ + return String(); +} + +String Mod::Tag::album() const +{ + return String(); +} + +String Mod::Tag::comment() const +{ + return d->comment; +} + +String Mod::Tag::genre() const +{ + return String(); +} + +unsigned int Mod::Tag::year() const +{ + return 0; +} + +unsigned int Mod::Tag::track() const +{ + return 0; +} + +String Mod::Tag::trackerName() const +{ + return d->trackerName; +} + +void Mod::Tag::setTitle(const String &title) +{ + d->title = title; +} + +void Mod::Tag::setArtist(const String &) +{ +} + +void Mod::Tag::setAlbum(const String &) +{ +} + +void Mod::Tag::setComment(const String &comment) +{ + d->comment = comment; +} + +void Mod::Tag::setGenre(const String &) +{ +} + +void Mod::Tag::setYear(unsigned int) +{ +} + +void Mod::Tag::setTrack(unsigned int) +{ +} + +void Mod::Tag::setTrackerName(const String &trackerName) +{ + d->trackerName = trackerName; +} + +PropertyMap Mod::Tag::properties() const +{ + PropertyMap properties; + properties["TITLE"] = d->title; + properties["COMMENT"] = d->comment; + if(!(d->trackerName.isEmpty())) + properties["TRACKERNAME"] = d->trackerName; + return properties; +} + +PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) +{ + PropertyMap properties(origProps); + properties.removeEmpty(); + StringList oneValueSet; + if(properties.contains("TITLE")) { + d->title = properties["TITLE"].front(); + oneValueSet.append("TITLE"); + } else + d->title.clear(); + + if(properties.contains("COMMENT")) { + d->comment = properties["COMMENT"].front(); + oneValueSet.append("COMMENT"); + } else + d->comment.clear(); + + if(properties.contains("TRACKERNAME")) { + d->trackerName = properties["TRACKERNAME"].front(); + oneValueSet.append("TRACKERNAME"); + } else + d->trackerName.clear(); + + // for each tag that has been set above, remove the first entry in the corresponding + // value list. The others will be returned as unsupported by this format. + for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { + if(properties[*it].size() == 1) + properties.erase(*it); + else + properties[*it].erase( properties[*it].begin() ); + } + return properties; +} diff --git a/external/taglib/source/mod/modtag.h b/external/taglib/source/mod/modtag.h new file mode 100644 index 0000000..dee0661 --- /dev/null +++ b/external/taglib/source/mod/modtag.h @@ -0,0 +1,194 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MODTAG_H +#define TAGLIB_MODTAG_H + +#include "tag.h" + +namespace TagLib { + + namespace Mod { + + /*! + * Tags for module files (Mod, S3M, IT, XM). + * + * Note that only the \a title is supported as such by most + * module file formats. Except for XM files the \a trackerName + * is derived from the file format or the flavour of the file + * format. For XM files it is stored in the file. + * + * The \a comment tag is not strictly supported by module files, + * but it is common practice to abuse instrument/sample/pattern + * names as multiline comments. TagLib does so as well. + */ + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + Tag(); + virtual ~Tag(); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String artist() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String album() const; + + /*! + * Returns the track comment derived from the instrument/sample/pattern + * names; if no comment is present in the tag String::null will be + * returned. + */ + virtual String comment() const; + + /*! + * Not supported by module files. Therefore always returns String::null. + */ + virtual String genre() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual unsigned int year() const; + + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual unsigned int track() const; + + /*! + * Returns the name of the tracker used to create/edit the module file. + * Only XM files store this tag to the file as such, for other formats + * (Mod, S3M, IT) this is derived from the file type or the flavour of + * the file type. Therefore only XM files might have an empty + * (String::null) tracker name. + */ + String trackerName() const; + + /*! + * Sets the title to \a title. If \a title is String::null then this + * value will be cleared. + * + * The length limits per file type are (1 character = 1 byte): + * Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20 + * characters. + */ + virtual void setTitle(const String &title); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setArtist(const String &artist); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setAlbum(const String &album); + + /*! + * Sets the comment to \a comment. If \a comment is String::null then + * this value will be cleared. + * + * Note that module file formats don't actually support a comment tag. + * Instead the names of instruments/patterns/samples are abused as + * a multiline comment. Because of this the number of lines in a + * module file is fixed to the number of instruments/patterns/samples. + * + * Also note that the instrument/pattern/sample name length is limited + * an thus the line length in comments are limited. Too big comments + * will be truncated. + * + * The line length limits per file type are (1 character = 1 byte): + * Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22 + * characters. + */ + virtual void setComment(const String &comment); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setGenre(const String &genre); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setYear(unsigned int year); + + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setTrack(unsigned int track); + + /*! + * Sets the tracker name to \a trackerName. If \a trackerName is + * String::null then this value will be cleared. + * + * Note that only XM files support this tag. Setting the + * tracker name for other module file formats will be ignored. + * + * The length of this tag is limited to 20 characters (1 character + * = 1 byte). + */ + void setTrackerName(const String &trackerName); + + /*! + * Implements the unified property interface -- export function. + * Since the module tag is very limited, the exported map is as well. + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Because of the limitations of the module file tag, any tags besides + * COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be + * returned. Additionally, if the map contains tags with multiple values, + * all but the first will be contained in the returned map of unsupported + * properties. + */ + PropertyMap setProperties(const PropertyMap &); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mp4/mp4atom.cpp b/external/taglib/source/mp4/mp4atom.cpp new file mode 100644 index 0000000..140ed12 --- /dev/null +++ b/external/taglib/source/mp4/mp4atom.cpp @@ -0,0 +1,215 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include "mp4atom.h" + +using namespace TagLib; + +const char *const MP4::Atom::containers[11] = { + "moov", "udta", "mdia", "meta", "ilst", + "stbl", "minf", "moof", "traf", "trak", + "stsd" +}; + +MP4::Atom::Atom(File *file) +{ + children.setAutoDelete(true); + + offset = file->tell(); + ByteVector header = file->readBlock(8); + if(header.size() != 8) { + // The atom header must be 8 bytes long, otherwise there is either + // trailing garbage or the file is truncated + debug("MP4: Couldn't read 8 bytes of data for atom header"); + length = 0; + file->seek(0, File::End); + return; + } + + length = header.toUInt(); + + if(length == 0) { + // The last atom which extends to the end of the file. + length = file->length() - offset; + } + else if(length == 1) { + // The atom has a 64-bit length. + const long long longLength = file->readBlock(8).toLongLong(); + if(longLength <= LONG_MAX) { + // The actual length fits in long. That's always the case if long is 64-bit. + length = static_cast(longLength); + } + else { + debug("MP4: 64-bit atoms are not supported"); + length = 0; + file->seek(0, File::End); + return; + } + } + + if(length < 8) { + debug("MP4: Invalid atom size"); + length = 0; + file->seek(0, File::End); + return; + } + + name = header.mid(4, 4); + + for(int i = 0; i < numContainers; i++) { + if(name == containers[i]) { + if(name == "meta") { + long posAfterMeta = file->tell(); + ByteVector nextSize = file->readBlock(8).mid(4, 4); + static const char *const metaChildrenNames[] = { + "hdlr", "ilst", "mhdr", "ctry", "lang" + }; + bool metaIsFullAtom = true; + for(size_t j = 0; + j < sizeof(metaChildrenNames) / sizeof(metaChildrenNames[0]); + ++j) { + if(nextSize == metaChildrenNames[j]) { + // meta is not a full atom (i.e. not followed by version, flags). It + // is followed by the size and type of the first child atom. + metaIsFullAtom = false; + break; + } + } + // Only skip next four bytes, which contain version and flags, if meta + // is a full atom. + file->seek(posAfterMeta + (metaIsFullAtom ? 4 : 0)); + } + else if(name == "stsd") { + file->seek(8, File::Current); + } + while(file->tell() < offset + length) { + MP4::Atom *child = new MP4::Atom(file); + children.append(child); + if(child->length == 0) + return; + } + return; + } + } + + file->seek(offset + length); +} + +MP4::Atom::~Atom() +{ +} + +MP4::Atom * +MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) +{ + if(name1 == 0) { + return this; + } + for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { + if((*it)->name == name1) { + return (*it)->find(name2, name3, name4); + } + } + return 0; +} + +MP4::AtomList +MP4::Atom::findall(const char *name, bool recursive) +{ + MP4::AtomList result; + for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { + if((*it)->name == name) { + result.append(*it); + } + if(recursive) { + result.append((*it)->findall(name, recursive)); + } + } + return result; +} + +bool +MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3) +{ + path.append(this); + if(name1 == 0) { + return true; + } + for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) { + if((*it)->name == name1) { + return (*it)->path(path, name2, name3); + } + } + return false; +} + +MP4::Atoms::Atoms(File *file) +{ + atoms.setAutoDelete(true); + + file->seek(0, File::End); + long end = file->tell(); + file->seek(0); + while(file->tell() + 8 <= end) { + MP4::Atom *atom = new MP4::Atom(file); + atoms.append(atom); + if (atom->length == 0) + break; + } +} + +MP4::Atoms::~Atoms() +{ +} + +MP4::Atom * +MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) +{ + for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) { + if((*it)->name == name1) { + return (*it)->find(name2, name3, name4); + } + } + return 0; +} + +MP4::AtomList +MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) +{ + MP4::AtomList path; + for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) { + if((*it)->name == name1) { + if(!(*it)->path(path, name2, name3, name4)) { + path.clear(); + } + return path; + } + } + return path; +} diff --git a/external/taglib/source/mp4/mp4atom.h b/external/taglib/source/mp4/mp4atom.h new file mode 100644 index 0000000..5e234cc --- /dev/null +++ b/external/taglib/source/mp4/mp4atom.h @@ -0,0 +1,111 @@ +/************************************************************************** + copyright : (C) 2007,2011 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +// This file is not part of the public API! + +#ifndef DO_NOT_DOCUMENT + +#ifndef TAGLIB_MP4ATOM_H +#define TAGLIB_MP4ATOM_H + +#include "tfile.h" +#include "tlist.h" + +namespace TagLib { + + namespace MP4 { + + class Atom; + typedef TagLib::List AtomList; + + enum AtomDataType + { + TypeImplicit = 0, // for use with tags for which no type needs to be indicated because only one type is allowed + TypeUTF8 = 1, // without any count or null terminator + TypeUTF16 = 2, // also known as UTF-16BE + TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters + TypeHTML = 6, // the HTML file header specifies which HTML version + TypeXML = 7, // the XML header must identify the DTD or schemas + TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID) + TypeISRC = 9, // stored as UTF-8 text (valid as an ID) + TypeMI3P = 10, // stored as UTF-8 text (valid as an ID) + TypeGIF = 12, // (deprecated) a GIF image + TypeJPEG = 13, // a JPEG image + TypePNG = 14, // a PNG image + TypeURL = 15, // absolute, in UTF-8 characters + TypeDuration = 16, // in milliseconds, 32-bit integer + TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits + TypeGenred = 18, // a list of enumerated values + TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes + TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer + TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID) + TypeBMP = 27, // Windows bitmap image + TypeUndefined = 255 // undefined + }; + + struct AtomData { + AtomData(AtomDataType type, ByteVector data) : type(type), locale(0), data(data) {} + AtomDataType type; + int locale; + ByteVector data; + }; + + typedef TagLib::List AtomDataList; + + class TAGLIB_EXPORT Atom + { + public: + Atom(File *file); + ~Atom(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0); + AtomList findall(const char *name, bool recursive = false); + long offset; + long length; + TagLib::ByteVector name; + AtomList children; + private: + static const int numContainers = 11; + static const char *const containers[11]; + }; + + //! Root-level atoms + class TAGLIB_EXPORT Atoms + { + public: + Atoms(File *file); + ~Atoms(); + Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0); + AtomList atoms; + }; + + } + +} + +#endif + +#endif diff --git a/external/taglib/source/mp4/mp4coverart.cpp b/external/taglib/source/mp4/mp4coverart.cpp new file mode 100644 index 0000000..b12392e --- /dev/null +++ b/external/taglib/source/mp4/mp4coverart.cpp @@ -0,0 +1,92 @@ +/************************************************************************** + copyright : (C) 2009 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "trefcounter.h" +#include "mp4coverart.h" + +using namespace TagLib; + +class MP4::CoverArt::CoverArtPrivate : public RefCounter +{ +public: + CoverArtPrivate() : + format(MP4::CoverArt::JPEG) {} + + Format format; + ByteVector data; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MP4::CoverArt::CoverArt(Format format, const ByteVector &data) : + d(new CoverArtPrivate()) +{ + d->format = format; + d->data = data; +} + +MP4::CoverArt::CoverArt(const CoverArt &item) : + d(item.d) +{ + d->ref(); +} + +MP4::CoverArt & +MP4::CoverArt::operator=(const CoverArt &item) +{ + CoverArt(item).swap(*this); + return *this; +} + +void +MP4::CoverArt::swap(CoverArt &item) +{ + using std::swap; + + swap(d, item.d); +} + +MP4::CoverArt::~CoverArt() +{ + if(d->deref()) { + delete d; + } +} + +MP4::CoverArt::Format +MP4::CoverArt::format() const +{ + return d->format; +} + +ByteVector +MP4::CoverArt::data() const +{ + return d->data; +} diff --git a/external/taglib/source/mp4/mp4coverart.h b/external/taglib/source/mp4/mp4coverart.h new file mode 100644 index 0000000..ebfb3f9 --- /dev/null +++ b/external/taglib/source/mp4/mp4coverart.h @@ -0,0 +1,84 @@ +/************************************************************************** + copyright : (C) 2009 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4COVERART_H +#define TAGLIB_MP4COVERART_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "mp4atom.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT CoverArt + { + public: + /*! + * This describes the image type. + */ + enum Format { + JPEG = TypeJPEG, + PNG = TypePNG, + BMP = TypeBMP, + GIF = TypeGIF, + Unknown = TypeImplicit, + }; + + CoverArt(Format format, const ByteVector &data); + ~CoverArt(); + + CoverArt(const CoverArt &item); + + /*! + * Copies the contents of \a item into this CoverArt. + */ + CoverArt &operator=(const CoverArt &item); + + /*! + * Exchanges the content of the CoverArt by the content of \a item. + */ + void swap(CoverArt &item); + + //! Format of the image + Format format() const; + + //! The image data + ByteVector data() const; + + private: + class CoverArtPrivate; + CoverArtPrivate *d; + }; + + typedef List CoverArtList; + + } + +} + +#endif diff --git a/external/taglib/source/mp4/mp4file.cpp b/external/taglib/source/mp4/mp4file.cpp new file mode 100644 index 0000000..1747d62 --- /dev/null +++ b/external/taglib/source/mp4/mp4file.cpp @@ -0,0 +1,202 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "mp4atom.h" +#include "mp4tag.h" +#include "mp4file.h" + +using namespace TagLib; + +namespace +{ + bool checkValid(const MP4::AtomList &list) + { + for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) { + + if((*it)->length == 0) + return false; + + if(!checkValid((*it)->children)) + return false; + } + + return true; + } +} // namespace + +class MP4::File::FilePrivate +{ +public: + FilePrivate() : + tag(0), + atoms(0), + properties(0) {} + + ~FilePrivate() + { + delete atoms; + delete tag; + delete properties; + } + + MP4::Tag *tag; + MP4::Atoms *atoms; + MP4::Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool MP4::File::isSupported(IOStream *stream) +{ + // An MP4 file has to have an "ftyp" box first. + + const ByteVector id = Utils::readHeader(stream, 8, false); + return id.containsAt("ftyp", 4); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +MP4::File::~File() +{ + delete d; +} + +MP4::Tag * +MP4::File::tag() const +{ + return d->tag; +} + +PropertyMap MP4::File::properties() const +{ + return d->tag->properties(); +} + +void MP4::File::removeUnsupportedProperties(const StringList &properties) +{ + d->tag->removeUnsupportedProperties(properties); +} + +PropertyMap MP4::File::setProperties(const PropertyMap &properties) +{ + return d->tag->setProperties(properties); +} + +MP4::Properties * +MP4::File::audioProperties() const +{ + return d->properties; +} + +void +MP4::File::read(bool readProperties) +{ + if(!isValid()) + return; + + d->atoms = new Atoms(this); + if(!checkValid(d->atoms->atoms)) { + setValid(false); + return; + } + + // must have a moov atom, otherwise consider it invalid + if(!d->atoms->find("moov")) { + setValid(false); + return; + } + + d->tag = new Tag(this, d->atoms); + if(readProperties) { + d->properties = new Properties(this, d->atoms); + } +} + +bool +MP4::File::save() +{ + if(readOnly()) { + debug("MP4::File::save() -- File is read only."); + return false; + } + + if(!isValid()) { + debug("MP4::File::save() -- Trying to save invalid file."); + return false; + } + + return d->tag->save(); +} + +bool +MP4::File::strip(int tags) +{ + if(readOnly()) { + debug("MP4::File::strip() - Cannot strip tags from a read only file."); + return false; + } + + if(!isValid()) { + debug("MP4::File::strip() -- Cannot strip tags from an invalid file."); + return false; + } + + if(tags & MP4) { + return d->tag->strip(); + } + + return true; +} + +bool +MP4::File::hasMP4Tag() const +{ + return (d->atoms->find("moov", "udta", "meta", "ilst") != 0); +} diff --git a/external/taglib/source/mp4/mp4file.h b/external/taglib/source/mp4/mp4file.h new file mode 100644 index 0000000..a8bb488 --- /dev/null +++ b/external/taglib/source/mp4/mp4file.h @@ -0,0 +1,165 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILE_H +#define TAGLIB_MP4FILE_H + +#include "tag.h" +#include "tfile.h" +#include "taglib_export.h" +#include "mp4properties.h" +#include "mp4tag.h" + +namespace TagLib { + + //! An implementation of MP4 (AAC, ALAC, ...) metadata + namespace MP4 { + + class Atoms; + + /*! + * This implements and provides an interface for MP4 files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MP4 files. + */ + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for strip() and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches MP4 tags. + MP4 = 0x0001, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MP4 file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle audioPropertiesStyle = Properties::Average); + + /*! + * Constructs an MP4 file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle audioPropertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the MP4 tag of the file. + * + * MP4::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the MP4::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties. Forwards to the actual Tag's + * removeUnsupportedProperties() function. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MP4 audio properties for this file. + */ + Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + bool save(); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * \note This will update the file immediately. + */ + bool strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an MP4 tag, or the + * file has a Metadata Item List (ilst) atom. + */ + bool hasMP4Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an ASF + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mp4/mp4item.cpp b/external/taglib/source/mp4/mp4item.cpp new file mode 100644 index 0000000..eee8480 --- /dev/null +++ b/external/taglib/source/mp4/mp4item.cpp @@ -0,0 +1,211 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "trefcounter.h" +#include "mp4item.h" + +using namespace TagLib; + +class MP4::Item::ItemPrivate : public RefCounter +{ +public: + ItemPrivate() : + valid(true), + atomDataType(TypeUndefined) {} + + bool valid; + AtomDataType atomDataType; + union { + bool m_bool; + int m_int; + IntPair m_intPair; + unsigned char m_byte; + unsigned int m_uint; + long long m_longlong; + }; + StringList m_stringList; + ByteVectorList m_byteVectorList; + MP4::CoverArtList m_coverArtList; +}; + +MP4::Item::Item() : + d(new ItemPrivate()) +{ + d->valid = false; +} + +MP4::Item::Item(const Item &item) : + d(item.d) +{ + d->ref(); +} + +MP4::Item & +MP4::Item::operator=(const Item &item) +{ + Item(item).swap(*this); + return *this; +} + +void +MP4::Item::swap(Item &item) +{ + using std::swap; + + swap(d, item.d); +} + +MP4::Item::~Item() +{ + if(d->deref()) + delete d; +} + +MP4::Item::Item(bool value) : + d(new ItemPrivate()) +{ + d->m_bool = value; +} + +MP4::Item::Item(int value) : + d(new ItemPrivate()) +{ + d->m_int = value; +} + +MP4::Item::Item(unsigned char value) : + d(new ItemPrivate()) +{ + d->m_byte = value; +} + +MP4::Item::Item(unsigned int value) : + d(new ItemPrivate()) +{ + d->m_uint = value; +} + +MP4::Item::Item(long long value) : + d(new ItemPrivate()) +{ + d->m_longlong = value; +} + +MP4::Item::Item(int value1, int value2) : + d(new ItemPrivate()) +{ + d->m_intPair.first = value1; + d->m_intPair.second = value2; +} + +MP4::Item::Item(const ByteVectorList &value) : + d(new ItemPrivate()) +{ + d->m_byteVectorList = value; +} + +MP4::Item::Item(const StringList &value) : + d(new ItemPrivate()) +{ + d->m_stringList = value; +} + +MP4::Item::Item(const MP4::CoverArtList &value) : + d(new ItemPrivate()) +{ + d->m_coverArtList = value; +} + +void MP4::Item::setAtomDataType(MP4::AtomDataType type) +{ + d->atomDataType = type; +} + +MP4::AtomDataType MP4::Item::atomDataType() const +{ + return d->atomDataType; +} + +bool +MP4::Item::toBool() const +{ + return d->m_bool; +} + +int +MP4::Item::toInt() const +{ + return d->m_int; +} + +unsigned char +MP4::Item::toByte() const +{ + return d->m_byte; +} + +unsigned int +MP4::Item::toUInt() const +{ + return d->m_uint; +} + +long long +MP4::Item::toLongLong() const +{ + return d->m_longlong; +} + +MP4::Item::IntPair +MP4::Item::toIntPair() const +{ + return d->m_intPair; +} + +StringList +MP4::Item::toStringList() const +{ + return d->m_stringList; +} + +ByteVectorList +MP4::Item::toByteVectorList() const +{ + return d->m_byteVectorList; +} + +MP4::CoverArtList +MP4::Item::toCoverArtList() const +{ + return d->m_coverArtList; +} + +bool +MP4::Item::isValid() const +{ + return d->valid; +} diff --git a/external/taglib/source/mp4/mp4item.h b/external/taglib/source/mp4/mp4item.h new file mode 100644 index 0000000..3821135 --- /dev/null +++ b/external/taglib/source/mp4/mp4item.h @@ -0,0 +1,93 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4ITEM_H +#define TAGLIB_MP4ITEM_H + +#include "tstringlist.h" +#include "mp4coverart.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace MP4 { + + class TAGLIB_EXPORT Item + { + public: + struct IntPair { + int first, second; + }; + + Item(); + Item(const Item &item); + + /*! + * Copies the contents of \a item into this Item. + */ + Item &operator=(const Item &item); + + /*! + * Exchanges the content of the Item by the content of \a item. + */ + void swap(Item &item); + + ~Item(); + + Item(int value); + Item(unsigned char value); + Item(unsigned int value); + Item(long long value); + Item(bool value); + Item(int first, int second); + Item(const StringList &value); + Item(const ByteVectorList &value); + Item(const CoverArtList &value); + + void setAtomDataType(AtomDataType type); + AtomDataType atomDataType() const; + + int toInt() const; + unsigned char toByte() const; + unsigned int toUInt() const; + long long toLongLong() const; + bool toBool() const; + IntPair toIntPair() const; + StringList toStringList() const; + ByteVectorList toByteVectorList() const; + CoverArtList toCoverArtList() const; + + bool isValid() const; + + private: + class ItemPrivate; + ItemPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mp4/mp4properties.cpp b/external/taglib/source/mp4/mp4properties.cpp new file mode 100644 index 0000000..df62880 --- /dev/null +++ b/external/taglib/source/mp4/mp4properties.cpp @@ -0,0 +1,269 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "mp4file.h" +#include "mp4atom.h" +#include "mp4properties.h" + +using namespace TagLib; + +namespace +{ + // Calculate the total bytes used by audio data, used to calculate the bitrate + long long calculateMdatLength(const MP4::AtomList &list) + { + long long totalLength = 0; + for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) { + long length = (*it)->length; + if(length == 0) + return 0; // for safety, see checkValid() in mp4file.cpp + + if((*it)->name == "mdat") + totalLength += length; + + totalLength += calculateMdatLength((*it)->children); + } + + return totalLength; + } +} // namespace + +class MP4::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0), + encrypted(false), + codec(MP4::Properties::Unknown) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; + bool encrypted; + Codec codec; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file, atoms); +} + +MP4::Properties::~Properties() +{ + delete d; +} + +int +MP4::Properties::channels() const +{ + return d->channels; +} + +int +MP4::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int +MP4::Properties::length() const +{ + return lengthInSeconds(); +} + +int +MP4::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int +MP4::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int +MP4::Properties::bitrate() const +{ + return d->bitrate; +} + +int +MP4::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +bool +MP4::Properties::isEncrypted() const +{ + return d->encrypted; +} + +MP4::Properties::Codec +MP4::Properties::codec() const +{ + return d->codec; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void +MP4::Properties::read(File *file, Atoms *atoms) +{ + MP4::Atom *moov = atoms->find("moov"); + if(!moov) { + debug("MP4: Atom 'moov' not found"); + return; + } + + MP4::Atom *trak = 0; + ByteVector data; + + const MP4::AtomList trakList = moov->findall("trak"); + for(MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) { + trak = *it; + MP4::Atom *hdlr = trak->find("mdia", "hdlr"); + if(!hdlr) { + debug("MP4: Atom 'trak.mdia.hdlr' not found"); + return; + } + file->seek(hdlr->offset); + data = file->readBlock(hdlr->length); + if(data.containsAt("soun", 16)) { + break; + } + trak = 0; + } + if(!trak) { + debug("MP4: No audio tracks"); + return; + } + + MP4::Atom *mdhd = trak->find("mdia", "mdhd"); + if(!mdhd) { + debug("MP4: Atom 'trak.mdia.mdhd' not found"); + return; + } + + file->seek(mdhd->offset); + data = file->readBlock(mdhd->length); + + const unsigned int version = data.at(8); + long long unit; + long long length; + if(version == 1) { + if(data.size() < 36 + 8) { + debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected"); + return; + } + unit = data.toUInt(28U); + length = data.toLongLong(32U); + } + else { + if(data.size() < 24 + 8) { + debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected"); + return; + } + unit = data.toUInt(20U); + length = data.toUInt(24U); + } + if(unit > 0 && length > 0) + d->length = static_cast(length * 1000.0 / unit + 0.5); + + MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd"); + if(!atom) { + return; + } + + file->seek(atom->offset); + data = file->readBlock(atom->length); + if(data.containsAt("mp4a", 20)) { + d->codec = AAC; + d->channels = data.toShort(40U); + d->bitsPerSample = data.toShort(42U); + d->sampleRate = data.toUInt(46U); + if(data.containsAt("esds", 56) && data.at(64) == 0x03) { + unsigned int pos = 65; + if(data.containsAt("\x80\x80\x80", pos)) { + pos += 3; + } + pos += 4; + if(data.at(pos) == 0x04) { + pos += 1; + if(data.containsAt("\x80\x80\x80", pos)) { + pos += 3; + } + pos += 10; + const unsigned int bitrateValue = data.toUInt(pos); + if(bitrateValue != 0 || d->length <= 0) { + d->bitrate = static_cast((bitrateValue + 500) / 1000.0 + 0.5); + } + else { + d->bitrate = static_cast( + (calculateMdatLength(atoms->atoms) * 8) / d->length); + } + } + } + } + else if(data.containsAt("alac", 20)) { + if(atom->length == 88 && data.containsAt("alac", 56)) { + d->codec = ALAC; + d->bitsPerSample = data.at(69); + d->channels = data.at(73); + d->bitrate = static_cast(data.toUInt(80U) / 1000.0 + 0.5); + d->sampleRate = data.toUInt(84U); + + if(d->bitrate == 0 && d->length > 0) { + // There are files which do not contain a nominal bitrate, e.g. those + // generated by refalac64.exe. Calculate the bitrate from the audio + // data size (mdat atoms) and the duration. + d->bitrate = (calculateMdatLength(atoms->atoms) * 8) / d->length; + } + } + } + + MP4::Atom *drms = atom->find("drms"); + if(drms) { + d->encrypted = true; + } +} diff --git a/external/taglib/source/mp4/mp4properties.h b/external/taglib/source/mp4/mp4properties.h new file mode 100644 index 0000000..492a48c --- /dev/null +++ b/external/taglib/source/mp4/mp4properties.h @@ -0,0 +1,120 @@ +/************************************************************************** + copyright : (C) 2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4PROPERTIES_H +#define TAGLIB_MP4PROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MP4 { + + class Atoms; + class File; + + //! An implementation of MP4 audio properties + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + enum Codec { + Unknown = 0, + AAC, + ALAC + }; + + Properties(File *file, Atoms *atoms, ReadStyle style = Average); + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + virtual int bitsPerSample() const; + + /*! + * Returns whether or not the file is encrypted. + */ + bool isEncrypted() const; + + /*! + * Returns the codec used in the file. + */ + Codec codec() const; + + private: + void read(File *file, Atoms *atoms); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mp4/mp4tag.cpp b/external/taglib/source/mp4/mp4tag.cpp new file mode 100644 index 0000000..758475b --- /dev/null +++ b/external/taglib/source/mp4/mp4tag.cpp @@ -0,0 +1,1093 @@ +/************************************************************************** + copyright : (C) 2007,2011 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include "mp4atom.h" +#include "mp4tag.h" +#include "id3v1genres.h" + +using namespace TagLib; + +class MP4::Tag::TagPrivate +{ +public: + TagPrivate() : + file(0), + atoms(0) {} + + TagLib::File *file; + Atoms *atoms; + ItemMap items; +}; + +MP4::Tag::Tag() : + d(new TagPrivate()) +{ +} + +MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms) : + d(new TagPrivate()) +{ + d->file = file; + d->atoms = atoms; + + MP4::Atom *ilst = atoms->find("moov", "udta", "meta", "ilst"); + if(!ilst) { + //debug("Atom moov.udta.meta.ilst not found."); + return; + } + + for(AtomList::ConstIterator it = ilst->children.begin(); it != ilst->children.end(); ++it) { + MP4::Atom *atom = *it; + file->seek(atom->offset + 8); + if(atom->name == "----") { + parseFreeForm(atom); + } + else if(atom->name == "trkn" || atom->name == "disk") { + parseIntPair(atom); + } + else if(atom->name == "cpil" || atom->name == "pgap" || atom->name == "pcst" || + atom->name == "hdvd" || atom->name == "shwm") { + parseBool(atom); + } + else if(atom->name == "tmpo" || atom->name == "\251mvi" || atom->name == "\251mvc") { + parseInt(atom); + } + else if(atom->name == "rate") { + AtomDataList data = parseData2(atom); + if(!data.isEmpty()) { + AtomData val = data[0]; + if (val.type == TypeUTF8) { + addItem(atom->name, StringList(String(val.data, String::UTF8))); + } else { + addItem(atom->name, static_cast(val.data.toShort())); + } + } + } + else if(atom->name == "tvsn" || atom->name == "tves" || atom->name == "cnID" || + atom->name == "sfID" || atom->name == "atID" || atom->name == "geID" || + atom->name == "cmID") { + parseUInt(atom); + } + else if(atom->name == "plID") { + parseLongLong(atom); + } + else if(atom->name == "stik" || atom->name == "rtng" || atom->name == "akID") { + parseByte(atom); + } + else if(atom->name == "gnre") { + parseGnre(atom); + } + else if(atom->name == "covr") { + parseCovr(atom); + } + else if(atom->name == "purl" || atom->name == "egid") { + parseText(atom, -1); + } + else { + parseText(atom); + } + } +} + +MP4::Tag::~Tag() +{ + delete d; +} + +MP4::AtomDataList +MP4::Tag::parseData2(const MP4::Atom *atom, int expectedFlags, bool freeForm) +{ + AtomDataList result; + ByteVector data = d->file->readBlock(atom->length - 8); + int i = 0; + unsigned int pos = 0; + while(pos < data.size()) { + const int length = static_cast(data.toUInt(pos)); + if(length < 12) { + debug("MP4: Too short atom"); + return result; + } + + const ByteVector name = data.mid(pos + 4, 4); + const int flags = static_cast(data.toUInt(pos + 8)); + if(freeForm && i < 2) { + if(i == 0 && name != "mean") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"mean\""); + return result; + } + if(i == 1 && name != "name") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"name\""); + return result; + } + result.append(AtomData(AtomDataType(flags), data.mid(pos + 12, length - 12))); + } + else { + if(name != "data") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\""); + return result; + } + if(expectedFlags == -1 || flags == expectedFlags) { + result.append(AtomData(AtomDataType(flags), data.mid(pos + 16, length - 16))); + } + } + pos += length; + i++; + } + return result; +} + +ByteVectorList +MP4::Tag::parseData(const MP4::Atom *atom, int expectedFlags, bool freeForm) +{ + AtomDataList data = parseData2(atom, expectedFlags, freeForm); + ByteVectorList result; + for(AtomDataList::ConstIterator it = data.begin(); it != data.end(); ++it) { + result.append(it->data); + } + return result; +} + +void +MP4::Tag::parseInt(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + addItem(atom->name, static_cast(data[0].toShort())); + } +} + +void +MP4::Tag::parseUInt(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + addItem(atom->name, data[0].toUInt()); + } +} + +void +MP4::Tag::parseLongLong(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + addItem(atom->name, data[0].toLongLong()); + } +} + +void +MP4::Tag::parseByte(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + addItem(atom->name, static_cast(data[0].at(0))); + } +} + +void +MP4::Tag::parseGnre(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + int idx = static_cast(data[0].toShort()); + if(idx > 0) { + addItem("\251gen", StringList(ID3v1::genre(idx - 1))); + } + } +} + +void +MP4::Tag::parseIntPair(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + const int a = data[0].toShort(2U); + const int b = data[0].toShort(4U); + addItem(atom->name, MP4::Item(a, b)); + } +} + +void +MP4::Tag::parseBool(const MP4::Atom *atom) +{ + ByteVectorList data = parseData(atom); + if(!data.isEmpty()) { + bool value = data[0].size() ? data[0][0] != '\0' : false; + addItem(atom->name, value); + } +} + +void +MP4::Tag::parseText(const MP4::Atom *atom, int expectedFlags) +{ + ByteVectorList data = parseData(atom, expectedFlags); + if(!data.isEmpty()) { + StringList value; + for(ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) { + value.append(String(*it, String::UTF8)); + } + addItem(atom->name, value); + } +} + +void +MP4::Tag::parseFreeForm(const MP4::Atom *atom) +{ + AtomDataList data = parseData2(atom, -1, true); + if(data.size() > 2) { + AtomDataList::ConstIterator itBegin = data.begin(); + + String name = "----:"; + name += String((itBegin++)->data, String::UTF8); // data[0].data + name += ':'; + name += String((itBegin++)->data, String::UTF8); // data[1].data + + AtomDataType type = itBegin->type; // data[2].type + + for(AtomDataList::ConstIterator it = itBegin; it != data.end(); ++it) { + if(it->type != type) { + debug("MP4: We currently don't support values with multiple types"); + break; + } + } + if(type == TypeUTF8) { + StringList value; + for(AtomDataList::ConstIterator it = itBegin; it != data.end(); ++it) { + value.append(String(it->data, String::UTF8)); + } + Item item(value); + item.setAtomDataType(type); + addItem(name, item); + } + else { + ByteVectorList value; + for(AtomDataList::ConstIterator it = itBegin; it != data.end(); ++it) { + value.append(it->data); + } + Item item(value); + item.setAtomDataType(type); + addItem(name, item); + } + } +} + +void +MP4::Tag::parseCovr(const MP4::Atom *atom) +{ + MP4::CoverArtList value; + ByteVector data = d->file->readBlock(atom->length - 8); + unsigned int pos = 0; + while(pos < data.size()) { + const int length = static_cast(data.toUInt(pos)); + if(length < 12) { + debug("MP4: Too short atom"); + break; + } + + const ByteVector name = data.mid(pos + 4, 4); + const int flags = static_cast(data.toUInt(pos + 8)); + if(name != "data") { + debug("MP4: Unexpected atom \"" + name + "\", expecting \"data\""); + break; + } + if(flags == TypeJPEG || flags == TypePNG || flags == TypeBMP || + flags == TypeGIF || flags == TypeImplicit) { + value.append(MP4::CoverArt(MP4::CoverArt::Format(flags), + data.mid(pos + 16, length - 16))); + } + else { + debug("MP4: Unknown covr format " + String::number(flags)); + } + pos += length; + } + if(!value.isEmpty()) + addItem(atom->name, value); +} + +ByteVector +MP4::Tag::padIlst(const ByteVector &data, int length) const +{ + if(length == -1) { + length = ((data.size() + 1023) & ~1023) - data.size(); + } + return renderAtom("free", ByteVector(length, '\1')); +} + +ByteVector +MP4::Tag::renderAtom(const ByteVector &name, const ByteVector &data) const +{ + return ByteVector::fromUInt(data.size() + 8) + name + data; +} + +ByteVector +MP4::Tag::renderData(const ByteVector &name, int flags, const ByteVectorList &data) const +{ + ByteVector result; + for(ByteVectorList::ConstIterator it = data.begin(); it != data.end(); ++it) { + result.append(renderAtom("data", ByteVector::fromUInt(flags) + ByteVector(4, '\0') + *it)); + } + return renderAtom(name, result); +} + +ByteVector +MP4::Tag::renderBool(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector(1, item.toBool() ? '\1' : '\0')); + return renderData(name, TypeInteger, data); +} + +ByteVector +MP4::Tag::renderInt(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector::fromShort(item.toInt())); + return renderData(name, TypeInteger, data); +} + +ByteVector +MP4::Tag::renderUInt(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector::fromUInt(item.toUInt())); + return renderData(name, TypeInteger, data); +} + +ByteVector +MP4::Tag::renderLongLong(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector::fromLongLong(item.toLongLong())); + return renderData(name, TypeInteger, data); +} + +ByteVector +MP4::Tag::renderByte(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector(1, item.toByte())); + return renderData(name, TypeInteger, data); +} + +ByteVector +MP4::Tag::renderIntPair(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector(2, '\0') + + ByteVector::fromShort(item.toIntPair().first) + + ByteVector::fromShort(item.toIntPair().second) + + ByteVector(2, '\0')); + return renderData(name, TypeImplicit, data); +} + +ByteVector +MP4::Tag::renderIntPairNoTrailing(const ByteVector &name, const MP4::Item &item) const +{ + ByteVectorList data; + data.append(ByteVector(2, '\0') + + ByteVector::fromShort(item.toIntPair().first) + + ByteVector::fromShort(item.toIntPair().second)); + return renderData(name, TypeImplicit, data); +} + +ByteVector +MP4::Tag::renderText(const ByteVector &name, const MP4::Item &item, int flags) const +{ + ByteVectorList data; + StringList value = item.toStringList(); + for(StringList::ConstIterator it = value.begin(); it != value.end(); ++it) { + data.append(it->data(String::UTF8)); + } + return renderData(name, flags, data); +} + +ByteVector +MP4::Tag::renderCovr(const ByteVector &name, const MP4::Item &item) const +{ + ByteVector data; + MP4::CoverArtList value = item.toCoverArtList(); + for(MP4::CoverArtList::ConstIterator it = value.begin(); it != value.end(); ++it) { + data.append(renderAtom("data", ByteVector::fromUInt(it->format()) + + ByteVector(4, '\0') + it->data())); + } + return renderAtom(name, data); +} + +ByteVector +MP4::Tag::renderFreeForm(const String &name, const MP4::Item &item) const +{ + StringList header = StringList::split(name, ":"); + if(header.size() != 3) { + debug("MP4: Invalid free-form item name \"" + name + "\""); + return ByteVector(); + } + ByteVector data; + data.append(renderAtom("mean", ByteVector::fromUInt(0) + header[1].data(String::UTF8))); + data.append(renderAtom("name", ByteVector::fromUInt(0) + header[2].data(String::UTF8))); + AtomDataType type = item.atomDataType(); + if(type == TypeUndefined) { + if(!item.toStringList().isEmpty()) { + type = TypeUTF8; + } + else { + type = TypeImplicit; + } + } + if(type == TypeUTF8) { + StringList value = item.toStringList(); + for(StringList::ConstIterator it = value.begin(); it != value.end(); ++it) { + data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + it->data(String::UTF8))); + } + } + else { + ByteVectorList value = item.toByteVectorList(); + for(ByteVectorList::ConstIterator it = value.begin(); it != value.end(); ++it) { + data.append(renderAtom("data", ByteVector::fromUInt(type) + ByteVector(4, '\0') + *it)); + } + } + return renderAtom("----", data); +} + +bool +MP4::Tag::save() +{ + ByteVector data; + for(MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) { + const String name = it->first; + if(name.startsWith("----")) { + data.append(renderFreeForm(name, it->second)); + } + else if(name == "trkn") { + data.append(renderIntPair(name.data(String::Latin1), it->second)); + } + else if(name == "disk") { + data.append(renderIntPairNoTrailing(name.data(String::Latin1), it->second)); + } + else if(name == "cpil" || name == "pgap" || name == "pcst" || name == "hdvd" || + name == "shwm") { + data.append(renderBool(name.data(String::Latin1), it->second)); + } + else if(name == "tmpo" || name == "\251mvi" || name == "\251mvc") { + data.append(renderInt(name.data(String::Latin1), it->second)); + } + else if (name == "rate") { + const MP4::Item& item = it->second; + StringList value = item.toStringList(); + if (value.isEmpty()) { + data.append(renderInt(name.data(String::Latin1), item)); + } + else { + data.append(renderText(name.data(String::Latin1), item)); + } + } + else if(name == "tvsn" || name == "tves" || name == "cnID" || + name == "sfID" || name == "atID" || name == "geID" || + name == "cmID") { + data.append(renderUInt(name.data(String::Latin1), it->second)); + } + else if(name == "plID") { + data.append(renderLongLong(name.data(String::Latin1), it->second)); + } + else if(name == "stik" || name == "rtng" || name == "akID") { + data.append(renderByte(name.data(String::Latin1), it->second)); + } + else if(name == "covr") { + data.append(renderCovr(name.data(String::Latin1), it->second)); + } + else if(name == "purl" || name == "egid") { + data.append(renderText(name.data(String::Latin1), it->second, TypeImplicit)); + } + else if(name.size() == 4){ + data.append(renderText(name.data(String::Latin1), it->second)); + } + else { + debug("MP4: Unknown item name \"" + name + "\""); + } + } + data = renderAtom("ilst", data); + + AtomList path = d->atoms->path("moov", "udta", "meta", "ilst"); + if(path.size() == 4) { + saveExisting(data, path); + } + else { + saveNew(data); + } + + return true; +} + +bool +MP4::Tag::strip() +{ + d->items.clear(); + + AtomList path = d->atoms->path("moov", "udta", "meta", "ilst"); + if(path.size() == 4) { + saveExisting(ByteVector(), path); + } + + return true; +} + +void +MP4::Tag::updateParents(const AtomList &path, long delta, int ignore) +{ + if(static_cast(path.size()) <= ignore) + return; + + AtomList::ConstIterator itEnd = path.end(); + std::advance(itEnd, 0 - ignore); + + for(AtomList::ConstIterator it = path.begin(); it != itEnd; ++it) { + d->file->seek((*it)->offset); + long size = d->file->readBlock(4).toUInt(); + // 64-bit + if (size == 1) { + d->file->seek(4, File::Current); // Skip name + long long longSize = d->file->readBlock(8).toLongLong(); + // Seek the offset of the 64-bit size + d->file->seek((*it)->offset + 8); + d->file->writeBlock(ByteVector::fromLongLong(longSize + delta)); + } + // 32-bit + else { + d->file->seek((*it)->offset); + d->file->writeBlock(ByteVector::fromUInt(size + delta)); + } + } +} + +void +MP4::Tag::updateOffsets(long delta, long offset) +{ + MP4::Atom *moov = d->atoms->find("moov"); + if(moov) { + MP4::AtomList stco = moov->findall("stco", true); + for(MP4::AtomList::ConstIterator it = stco.begin(); it != stco.end(); ++it) { + MP4::Atom *atom = *it; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 12); + ByteVector data = d->file->readBlock(atom->length - 12); + unsigned int count = data.toUInt(); + d->file->seek(atom->offset + 16); + unsigned int pos = 4; + while(count--) { + long o = static_cast(data.toUInt(pos)); + if(o > offset) { + o += delta; + } + d->file->writeBlock(ByteVector::fromUInt(o)); + pos += 4; + } + } + + MP4::AtomList co64 = moov->findall("co64", true); + for(MP4::AtomList::ConstIterator it = co64.begin(); it != co64.end(); ++it) { + MP4::Atom *atom = *it; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 12); + ByteVector data = d->file->readBlock(atom->length - 12); + unsigned int count = data.toUInt(); + d->file->seek(atom->offset + 16); + unsigned int pos = 4; + while(count--) { + long long o = data.toLongLong(pos); + if(o > offset) { + o += delta; + } + d->file->writeBlock(ByteVector::fromLongLong(o)); + pos += 8; + } + } + } + + MP4::Atom *moof = d->atoms->find("moof"); + if(moof) { + MP4::AtomList tfhd = moof->findall("tfhd", true); + for(MP4::AtomList::ConstIterator it = tfhd.begin(); it != tfhd.end(); ++it) { + MP4::Atom *atom = *it; + if(atom->offset > offset) { + atom->offset += delta; + } + d->file->seek(atom->offset + 9); + ByteVector data = d->file->readBlock(atom->length - 9); + const unsigned int flags = data.toUInt(0, 3, true); + if(flags & 1) { + long long o = data.toLongLong(7U); + if(o > offset) { + o += delta; + } + d->file->seek(atom->offset + 16); + d->file->writeBlock(ByteVector::fromLongLong(o)); + } + } + } +} + +void +MP4::Tag::saveNew(ByteVector data) +{ + data = renderAtom("meta", ByteVector(4, '\0') + + renderAtom("hdlr", ByteVector(8, '\0') + ByteVector("mdirappl") + + ByteVector(9, '\0')) + + data + padIlst(data)); + + AtomList path = d->atoms->path("moov", "udta"); + if(path.size() != 2) { + path = d->atoms->path("moov"); + data = renderAtom("udta", data); + } + + long offset = path.back()->offset + 8; + d->file->insert(data, offset, 0); + + updateParents(path, data.size()); + updateOffsets(data.size(), offset); + + // Insert the newly created atoms into the tree to keep it up-to-date. + + d->file->seek(offset); + path.back()->children.prepend(new Atom(d->file)); +} + +void +MP4::Tag::saveExisting(ByteVector data, const AtomList &path) +{ + AtomList::ConstIterator it = path.end(); + + MP4::Atom *ilst = *(--it); + long offset = ilst->offset; + long length = ilst->length; + + MP4::Atom *meta = *(--it); + AtomList::ConstIterator index = meta->children.find(ilst); + + // check if there is an atom before 'ilst', and possibly use it as padding + if(index != meta->children.begin()) { + AtomList::ConstIterator prevIndex = index; + prevIndex--; + MP4::Atom *prev = *prevIndex; + if(prev->name == "free") { + offset = prev->offset; + length += prev->length; + } + } + // check if there is an atom after 'ilst', and possibly use it as padding + AtomList::ConstIterator nextIndex = index; + nextIndex++; + if(nextIndex != meta->children.end()) { + MP4::Atom *next = *nextIndex; + if(next->name == "free") { + length += next->length; + } + } + + long delta = data.size() - length; + if(!data.isEmpty()) { + if(delta > 0 || (delta < 0 && delta > -8)) { + data.append(padIlst(data)); + delta = data.size() - length; + } + else if(delta < 0) { + data.append(padIlst(data, -delta - 8)); + delta = 0; + } + + d->file->insert(data, offset, length); + + if(delta) { + updateParents(path, delta, 1); + updateOffsets(delta, offset); + } + } + else { + // Strip meta if data is empty, only the case when called from strip(). + MP4::Atom *udta = *(--it); + AtomList &udtaChildren = udta->children; + AtomList::Iterator metaIt = udtaChildren.find(meta); + if(metaIt != udtaChildren.end()) { + offset = meta->offset; + delta = - meta->length; + udtaChildren.erase(metaIt); + d->file->removeBlock(meta->offset, meta->length); + delete meta; + + if(delta) { + updateParents(path, delta, 2); + updateOffsets(delta, offset); + } + } + } +} + +String +MP4::Tag::title() const +{ + if(d->items.contains("\251nam")) + return d->items["\251nam"].toStringList().toString(", "); + return String(); +} + +String +MP4::Tag::artist() const +{ + if(d->items.contains("\251ART")) + return d->items["\251ART"].toStringList().toString(", "); + return String(); +} + +String +MP4::Tag::album() const +{ + if(d->items.contains("\251alb")) + return d->items["\251alb"].toStringList().toString(", "); + return String(); +} + +String +MP4::Tag::comment() const +{ + if(d->items.contains("\251cmt")) + return d->items["\251cmt"].toStringList().toString(", "); + return String(); +} + +String +MP4::Tag::genre() const +{ + if(d->items.contains("\251gen")) + return d->items["\251gen"].toStringList().toString(", "); + return String(); +} + +unsigned int +MP4::Tag::year() const +{ + if(d->items.contains("\251day")) + return d->items["\251day"].toStringList().toString().toInt(); + return 0; +} + +unsigned int +MP4::Tag::track() const +{ + if(d->items.contains("trkn")) + return d->items["trkn"].toIntPair().first; + return 0; +} + +void +MP4::Tag::setTitle(const String &value) +{ + setTextItem("\251nam", value); +} + +void +MP4::Tag::setArtist(const String &value) +{ + setTextItem("\251ART", value); +} + +void +MP4::Tag::setAlbum(const String &value) +{ + setTextItem("\251alb", value); +} + +void +MP4::Tag::setComment(const String &value) +{ + setTextItem("\251cmt", value); +} + +void +MP4::Tag::setGenre(const String &value) +{ + setTextItem("\251gen", value); +} + +void +MP4::Tag::setTextItem(const String &key, const String &value) +{ + if (!value.isEmpty()) { + d->items[key] = StringList(value); + } else { + d->items.erase(key); + } +} + +void +MP4::Tag::setYear(unsigned int value) +{ + if (value == 0) { + d->items.erase("\251day"); + } + else { + d->items["\251day"] = StringList(String::number(value)); + } +} + +void +MP4::Tag::setTrack(unsigned int value) +{ + if (value == 0) { + d->items.erase("trkn"); + } + else { + d->items["trkn"] = MP4::Item(value, 0); + } +} + +bool MP4::Tag::isEmpty() const +{ + return d->items.isEmpty(); +} + +MP4::ItemMap &MP4::Tag::itemListMap() +{ + return d->items; +} + +const MP4::ItemMap &MP4::Tag::itemMap() const +{ + return d->items; +} + +MP4::Item MP4::Tag::item(const String &key) const +{ + return d->items[key]; +} + +void MP4::Tag::setItem(const String &key, const Item &value) +{ + d->items[key] = value; +} + +void MP4::Tag::removeItem(const String &key) +{ + d->items.erase(key); +} + +bool MP4::Tag::contains(const String &key) const +{ + return d->items.contains(key); +} + +namespace +{ + const std::pair keyTranslation[] = { + std::make_pair("\251nam", "TITLE"), + std::make_pair("\251ART", "ARTIST"), + std::make_pair("\251alb", "ALBUM"), + std::make_pair("\251cmt", "COMMENT"), + std::make_pair("\251gen", "GENRE"), + std::make_pair("\251day", "DATE"), + std::make_pair("\251wrt", "COMPOSER"), + std::make_pair("\251grp", "GROUPING"), + std::make_pair("aART", "ALBUMARTIST"), + std::make_pair("trkn", "TRACKNUMBER"), + std::make_pair("disk", "DISCNUMBER"), + std::make_pair("cpil", "COMPILATION"), + std::make_pair("tmpo", "BPM"), + std::make_pair("cprt", "COPYRIGHT"), + std::make_pair("\251lyr", "LYRICS"), + std::make_pair("\251too", "ENCODEDBY"), + std::make_pair("soal", "ALBUMSORT"), + std::make_pair("soaa", "ALBUMARTISTSORT"), + std::make_pair("soar", "ARTISTSORT"), + std::make_pair("sonm", "TITLESORT"), + std::make_pair("soco", "COMPOSERSORT"), + std::make_pair("sosn", "SHOWSORT"), + std::make_pair("shwm", "SHOWWORKMOVEMENT"), + std::make_pair("pgap", "GAPLESSPLAYBACK"), + std::make_pair("pcst", "PODCAST"), + std::make_pair("catg", "PODCASTCATEGORY"), + std::make_pair("desc", "PODCASTDESC"), + std::make_pair("egid", "PODCASTID"), + std::make_pair("purl", "PODCASTURL"), + std::make_pair("tves", "TVEPISODE"), + std::make_pair("tven", "TVEPISODEID"), + std::make_pair("tvnn", "TVNETWORK"), + std::make_pair("tvsn", "TVSEASON"), + std::make_pair("tvsh", "TVSHOW"), + std::make_pair("\251wrk", "WORK"), + std::make_pair("\251mvn", "MOVEMENTNAME"), + std::make_pair("\251mvi", "MOVEMENTNUMBER"), + std::make_pair("\251mvc", "MOVEMENTCOUNT"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Release Group Id", "MUSICBRAINZ_RELEASEGROUPID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Release Track Id", "MUSICBRAINZ_RELEASETRACKID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Work Id", "MUSICBRAINZ_WORKID"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Album Release Country", "RELEASECOUNTRY"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Album Status", "RELEASESTATUS"), + std::make_pair("----:com.apple.iTunes:MusicBrainz Album Type", "RELEASETYPE"), + std::make_pair("----:com.apple.iTunes:ARTISTS", "ARTISTS"), + std::make_pair("----:com.apple.iTunes:originaldate", "ORIGINALDATE"), + std::make_pair("----:com.apple.iTunes:ASIN", "ASIN"), + std::make_pair("----:com.apple.iTunes:LABEL", "LABEL"), + std::make_pair("----:com.apple.iTunes:LYRICIST", "LYRICIST"), + std::make_pair("----:com.apple.iTunes:CONDUCTOR", "CONDUCTOR"), + std::make_pair("----:com.apple.iTunes:REMIXER", "REMIXER"), + std::make_pair("----:com.apple.iTunes:ENGINEER", "ENGINEER"), + std::make_pair("----:com.apple.iTunes:PRODUCER", "PRODUCER"), + std::make_pair("----:com.apple.iTunes:DJMIXER", "DJMIXER"), + std::make_pair("----:com.apple.iTunes:MIXER", "MIXER"), + std::make_pair("----:com.apple.iTunes:SUBTITLE", "SUBTITLE"), + std::make_pair("----:com.apple.iTunes:DISCSUBTITLE", "DISCSUBTITLE"), + std::make_pair("----:com.apple.iTunes:MOOD", "MOOD"), + std::make_pair("----:com.apple.iTunes:ISRC", "ISRC"), + std::make_pair("----:com.apple.iTunes:CATALOGNUMBER", "CATALOGNUMBER"), + std::make_pair("----:com.apple.iTunes:BARCODE", "BARCODE"), + std::make_pair("----:com.apple.iTunes:SCRIPT", "SCRIPT"), + std::make_pair("----:com.apple.iTunes:LANGUAGE", "LANGUAGE"), + std::make_pair("----:com.apple.iTunes:LICENSE", "LICENSE"), + std::make_pair("----:com.apple.iTunes:MEDIA", "MEDIA"), + }; + const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]); + + String translateKey(const String &key) + { + for(size_t i = 0; i < keyTranslationSize; ++i) { + if(key == keyTranslation[i].first) + return keyTranslation[i].second; + } + + return String(); + } +} // namespace + +PropertyMap MP4::Tag::properties() const +{ + PropertyMap props; + for(MP4::ItemMap::ConstIterator it = d->items.begin(); it != d->items.end(); ++it) { + const String key = translateKey(it->first); + if(!key.isEmpty()) { + if(key == "TRACKNUMBER" || key == "DISCNUMBER") { + MP4::Item::IntPair ip = it->second.toIntPair(); + String value = String::number(ip.first); + if(ip.second) { + value += "/" + String::number(ip.second); + } + props[key] = value; + } + else if(key == "BPM" || key == "MOVEMENTNUMBER" || key == "MOVEMENTCOUNT" || + key == "TVEPISODE" || key == "TVSEASON") { + props[key] = String::number(it->second.toInt()); + } + else if(key == "COMPILATION" || key == "SHOWWORKMOVEMENT" || + key == "GAPLESSPLAYBACK" || key == "PODCAST") { + props[key] = String::number(it->second.toBool()); + } + else { + props[key] = it->second.toStringList(); + } + } + else { + props.unsupportedData().append(it->first); + } + } + return props; +} + +void MP4::Tag::removeUnsupportedProperties(const StringList &props) +{ + for(StringList::ConstIterator it = props.begin(); it != props.end(); ++it) + d->items.erase(*it); +} + +PropertyMap MP4::Tag::setProperties(const PropertyMap &props) +{ + static Map reverseKeyMap; + if(reverseKeyMap.isEmpty()) { + for(size_t i = 0; i < keyTranslationSize; i++) { + reverseKeyMap[keyTranslation[i].second] = keyTranslation[i].first; + } + } + + PropertyMap origProps = properties(); + for(PropertyMap::ConstIterator it = origProps.begin(); it != origProps.end(); ++it) { + if(!props.contains(it->first) || props[it->first].isEmpty()) { + d->items.erase(reverseKeyMap[it->first]); + } + } + + PropertyMap ignoredProps; + for(PropertyMap::ConstIterator it = props.begin(); it != props.end(); ++it) { + if(reverseKeyMap.contains(it->first)) { + String name = reverseKeyMap[it->first]; + if((it->first == "TRACKNUMBER" || it->first == "DISCNUMBER") && !it->second.isEmpty()) { + StringList parts = StringList::split(it->second.front(), "/"); + if(!parts.isEmpty()) { + int first = parts[0].toInt(); + int second = 0; + if(parts.size() > 1) { + second = parts[1].toInt(); + } + d->items[name] = MP4::Item(first, second); + } + } + else if((it->first == "BPM" || it->first == "MOVEMENTNUMBER" || + it->first == "MOVEMENTCOUNT" || it->first == "TVEPISODE" || + it->first == "TVSEASON") && !it->second.isEmpty()) { + int value = it->second.front().toInt(); + d->items[name] = MP4::Item(value); + } + else if((it->first == "COMPILATION" || it->first == "SHOWWORKMOVEMENT" || + it->first == "GAPLESSPLAYBACK" || it->first == "PODCAST") && + !it->second.isEmpty()) { + bool value = (it->second.front().toInt() != 0); + d->items[name] = MP4::Item(value); + } + else { + d->items[name] = it->second; + } + } + else { + ignoredProps.insert(it->first, it->second); + } + } + + return ignoredProps; +} + +void MP4::Tag::addItem(const String &name, const Item &value) +{ + if(!d->items.contains(name)) { + d->items.insert(name, value); + } + else { + debug("MP4: Ignoring duplicate atom \"" + name + "\""); + } +} diff --git a/external/taglib/source/mp4/mp4tag.h b/external/taglib/source/mp4/mp4tag.h new file mode 100644 index 0000000..2f55114 --- /dev/null +++ b/external/taglib/source/mp4/mp4tag.h @@ -0,0 +1,169 @@ +/************************************************************************** + copyright : (C) 2007,2011 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MP4TAG_H +#define TAGLIB_MP4TAG_H + +#include "tag.h" +#include "tbytevectorlist.h" +#include "tfile.h" +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" +#include "mp4atom.h" +#include "mp4item.h" + +namespace TagLib { + + namespace MP4 { + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED typedef TagLib::Map ItemListMap; + typedef TagLib::Map ItemMap; + + class TAGLIB_EXPORT Tag: public TagLib::Tag + { + public: + Tag(); + Tag(TagLib::File *file, Atoms *atoms); + virtual ~Tag(); + bool save(); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &value); + virtual void setArtist(const String &value); + virtual void setAlbum(const String &value); + virtual void setComment(const String &value); + virtual void setGenre(const String &value); + virtual void setYear(unsigned int value); + virtual void setTrack(unsigned int value); + + virtual bool isEmpty() const; + + /*! + * \deprecated Use the item() and setItem() API instead + */ + TAGLIB_DEPRECATED ItemMap &itemListMap(); + + /*! + * Returns a string-keyed map of the MP4::Items for this tag. + */ + const ItemMap &itemMap() const; + + /*! + * \return The item, if any, corresponding to \a key. + */ + Item item(const String &key) const; + + /*! + * Sets the value of \a key to \a value, overwriting any previous value. + */ + void setItem(const String &key, const Item &value); + + /*! + * Removes the entry with \a key from the tag, or does nothing if it does + * not exist. + */ + void removeItem(const String &key); + + /*! + * \return True if the tag contains an entry for \a key. + */ + bool contains(const String &key) const; + + /*! + * Saves the associated file with the tag stripped. + */ + bool strip(); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList& properties); + PropertyMap setProperties(const PropertyMap &properties); + + protected: + /*! + * Sets the value of \a key to \a value, overwriting any previous value. + * If \a value is empty, the item is removed. + */ + void setTextItem(const String &key, const String &value); + + private: + AtomDataList parseData2(const Atom *atom, int expectedFlags = -1, + bool freeForm = false); + ByteVectorList parseData(const Atom *atom, int expectedFlags = -1, + bool freeForm = false); + void parseText(const Atom *atom, int expectedFlags = 1); + void parseFreeForm(const Atom *atom); + void parseInt(const Atom *atom); + void parseByte(const Atom *atom); + void parseUInt(const Atom *atom); + void parseLongLong(const Atom *atom); + void parseGnre(const Atom *atom); + void parseIntPair(const Atom *atom); + void parseBool(const Atom *atom); + void parseCovr(const Atom *atom); + + ByteVector padIlst(const ByteVector &data, int length = -1) const; + ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const; + ByteVector renderData(const ByteVector &name, int flags, + const ByteVectorList &data) const; + ByteVector renderText(const ByteVector &name, const Item &item, + int flags = TypeUTF8) const; + ByteVector renderFreeForm(const String &name, const Item &item) const; + ByteVector renderBool(const ByteVector &name, const Item &item) const; + ByteVector renderInt(const ByteVector &name, const Item &item) const; + ByteVector renderByte(const ByteVector &name, const Item &item) const; + ByteVector renderUInt(const ByteVector &name, const Item &item) const; + ByteVector renderLongLong(const ByteVector &name, const Item &item) const; + ByteVector renderIntPair(const ByteVector &name, const Item &item) const; + ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const; + ByteVector renderCovr(const ByteVector &name, const Item &item) const; + + void updateParents(const AtomList &path, long delta, int ignore = 0); + void updateOffsets(long delta, long offset); + + void saveNew(ByteVector data); + void saveExisting(ByteVector data, const AtomList &path); + + void addItem(const String &name, const Item &value); + + class TagPrivate; + TagPrivate *d; + }; + + } + +} + +#endif diff --git a/external/taglib/source/mpc/mpcfile.cpp b/external/taglib/source/mpc/mpcfile.cpp new file mode 100644 index 0000000..0ffaf89 --- /dev/null +++ b/external/taglib/source/mpc/mpcfile.cpp @@ -0,0 +1,332 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "mpcfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { MPCAPEIndex = 0, MPCID3v1Index = 1 }; +} + +class MPC::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + ID3v2Header(0), + ID3v2Location(-1), + ID3v2Size(0), + properties(0) {} + + ~FilePrivate() + { + delete ID3v2Header; + delete properties; + } + + long APELocation; + long APESize; + + long ID3v1Location; + + ID3v2::Header *ID3v2Header; + long ID3v2Location; + long ID3v2Size; + + TagUnion tag; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool MPC::File::isSupported(IOStream *stream) +{ + // A newer MPC file has to start with "MPCK" or "MP+", but older files don't + // have keys to do a quick check. + + const ByteVector id = Utils::readHeader(stream, 4, false); + return (id == "MPCK" || id.startsWith("MP+")); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +MPC::File::~File() +{ + delete d; +} + +TagLib::Tag *MPC::File::tag() const +{ + return &d->tag; +} + +PropertyMap MPC::File::properties() const +{ + return d->tag.properties(); +} + +void MPC::File::removeUnsupportedProperties(const StringList &properties) +{ + d->tag.removeUnsupportedProperties(properties); +} + +PropertyMap MPC::File::setProperties(const PropertyMap &properties) +{ + if(ID3v1Tag()) + ID3v1Tag()->setProperties(properties); + + return APETag(true)->setProperties(properties); +} + +MPC::Properties *MPC::File::audioProperties() const +{ + return d->properties; +} + +bool MPC::File::save() +{ + if(readOnly()) { + debug("MPC::File::save() -- File is read only."); + return false; + } + + // Possibly strip ID3v2 tag + + if(!d->ID3v2Header && d->ID3v2Location >= 0) { + removeBlock(d->ID3v2Location, d->ID3v2Size); + + if(d->APELocation >= 0) + d->APELocation -= d->ID3v2Size; + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->ID3v2Size; + + d->ID3v2Location = -1; + d->ID3v2Size = 0; + } + + // Update ID3v1 tag + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + if(d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + } + } + + // Update APE tag + + if(APETag() && !APETag()->isEmpty()) { + + // APE tag is not empty. Update the old one or create a new one. + + if(d->APELocation < 0) { + if(d->ID3v1Location >= 0) + d->APELocation = d->ID3v1Location; + else + d->APELocation = length(); + } + + const ByteVector data = APETag()->render(); + insert(data, d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->APESize); + + d->APESize = data.size(); + } + else { + + // APE tag is empty. Remove the old one. + + if(d->APELocation >= 0) { + removeBlock(d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->APESize; + + d->APELocation = -1; + d->APESize = 0; + } + } + + return true; +} + +ID3v1::Tag *MPC::File::ID3v1Tag(bool create) +{ + return d->tag.access(MPCID3v1Index, create); +} + +APE::Tag *MPC::File::APETag(bool create) +{ + return d->tag.access(MPCAPEIndex, create); +} + +void MPC::File::strip(int tags) +{ + if(tags & ID3v1) + d->tag.set(MPCID3v1Index, 0); + + if(tags & APE) + d->tag.set(MPCAPEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); + + if(tags & ID3v2) { + delete d->ID3v2Header; + d->ID3v2Header = 0; + } +} + +void MPC::File::remove(int tags) +{ + strip(tags); +} + +bool MPC::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +bool MPC::File::hasAPETag() const +{ + return (d->APELocation >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPC::File::read(bool readProperties) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = Utils::findID3v2(this); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location); + d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size())); + d->ID3v2Size = d->ID3v2Header->completeTagSize(); + } + + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + // Look for an APE tag + + d->APELocation = Utils::findAPE(this, d->ID3v1Location); + + if(d->APELocation >= 0) { + d->tag.set(MPCAPEIndex, new APE::Tag(this, d->APELocation)); + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APE::Footer::size() - d->APESize; + } + + if(d->ID3v1Location < 0) + APETag(true); + + // Look for MPC metadata + + if(readProperties) { + + long streamLength; + + if(d->APELocation >= 0) + streamLength = d->APELocation; + else if(d->ID3v1Location >= 0) + streamLength = d->ID3v1Location; + else + streamLength = length(); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location + d->ID3v2Size); + streamLength -= (d->ID3v2Location + d->ID3v2Size); + } + else { + seek(0); + } + + d->properties = new Properties(this, streamLength); + } +} diff --git a/external/taglib/source/mpc/mpcfile.h b/external/taglib/source/mpc/mpcfile.h new file mode 100644 index 0000000..eb3ec54 --- /dev/null +++ b/external/taglib/source/mpc/mpcfile.h @@ -0,0 +1,238 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCFILE_H +#define TAGLIB_MPCFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tag.h" + +#include "mpcproperties.h" + +#include "tlist.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of MPC metadata + + /*! + * This is implementation of MPC metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. ID3v2 tags are invalid in MPC-files, but will be skipped + * and ignored. + */ + + namespace MPC { + + //! An implementation of TagLib::File with MPC specific methods + + /*! + * This implements and provides an interface for MPC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to MPC files. + * The only invalid tag combination supported is an ID3v1 tag after an APE tag. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MPC file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPC file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only the APE + * tag will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Affects only the APEv2 tag which will be created if necessary. + * If an ID3v1 tag exists, it will be updated as well. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this returns a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. If + * there already be an ID3v1 tag, the new APE tag will be placed before it. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \warning This will also invalidate pointers to the tags + * as their memory will be freed. + * + * \note In order to make the removal permanent save() still needs to be called. + */ + void strip(int tags = AllTags); + + /*! + * \deprecated + * \see strip + */ + TAGLIB_DEPRECATED void remove(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an MPC + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpc/mpcproperties.cpp b/external/taglib/source/mpc/mpcproperties.cpp new file mode 100644 index 0000000..effaabe --- /dev/null +++ b/external/taglib/source/mpc/mpcproperties.cpp @@ -0,0 +1,371 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "mpcproperties.h" +#include "mpcfile.h" + +using namespace TagLib; + +class MPC::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + totalFrames(0), + sampleFrames(0), + trackGain(0), + trackPeak(0), + albumGain(0), + albumPeak(0) {} + + int version; + int length; + int bitrate; + int sampleRate; + int channels; + unsigned int totalFrames; + unsigned int sampleFrames; + int trackGain; + int trackPeak; + int albumGain; + int albumPeak; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + readSV7(data, streamLength); +} + +MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + ByteVector magic = file->readBlock(4); + if(magic == "MPCK") { + // Musepack version 8 + readSV8(file, streamLength); + } + else { + // Musepack version 7 or older, fixed size header + readSV7(magic + file->readBlock(MPC::HeaderSize - 4), streamLength); + } +} + +MPC::Properties::~Properties() +{ + delete d; +} + +int MPC::Properties::length() const +{ + return lengthInSeconds(); +} + +int MPC::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int MPC::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int MPC::Properties::bitrate() const +{ + return d->bitrate; +} + +int MPC::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int MPC::Properties::channels() const +{ + return d->channels; +} + +int MPC::Properties::mpcVersion() const +{ + return d->version; +} + +unsigned int MPC::Properties::totalFrames() const +{ + return d->totalFrames; +} + +unsigned int MPC::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +int MPC::Properties::trackGain() const +{ + return d->trackGain; +} + +int MPC::Properties::trackPeak() const +{ + return d->trackPeak; +} + +int MPC::Properties::albumGain() const +{ + return d->albumGain; +} + +int MPC::Properties::albumPeak() const +{ + return d->albumPeak; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +namespace +{ + unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) + { + sizeLength = 0; + eof = false; + + unsigned char tmp; + unsigned long size = 0; + + do { + const ByteVector b = file->readBlock(1); + if(b.isEmpty()) { + eof = true; + break; + } + + tmp = b[0]; + size = (size << 7) | (tmp & 0x7F); + sizeLength++; + } while((tmp & 0x80)); + return size; + } + + unsigned long readSize(const ByteVector &data, unsigned int &pos) + { + unsigned char tmp; + unsigned long size = 0; + + do { + tmp = data[pos++]; + size = (size << 7) | (tmp & 0x7F); + } while((tmp & 0x80) && (pos < data.size())); + return size; + } + + // This array looks weird, but the same as original MusePack code found at: + // https://www.musepack.net/index.php?pg=src + const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 }; +} // namespace + +void MPC::Properties::readSV8(File *file, long streamLength) +{ + bool readSH = false, readRG = false; + + while(!readSH && !readRG) { + const ByteVector packetType = file->readBlock(2); + + unsigned int packetSizeLength; + bool eof; + const unsigned long packetSize = readSize(file, packetSizeLength, eof); + if(eof) { + debug("MPC::Properties::readSV8() - Reached to EOF."); + break; + } + + const unsigned long dataSize = packetSize - 2 - packetSizeLength; + + const ByteVector data = file->readBlock(dataSize); + if(data.size() != dataSize) { + debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size."); + break; + } + + if(packetType == "SH") { + // Stream Header + // http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket + + if(dataSize <= 5) { + debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse."); + break; + } + + readSH = true; + + unsigned int pos = 4; + d->version = data[pos]; + pos += 1; + d->sampleFrames = readSize(data, pos); + if(pos > dataSize - 3) { + debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); + break; + } + + const unsigned long begSilence = readSize(data, pos); + if(pos > dataSize - 2) { + debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt."); + break; + } + + const unsigned short flags = data.toUShort(pos, true); + pos += 2; + + d->sampleRate = sftable[(flags >> 13) & 0x07]; + d->channels = ((flags >> 4) & 0x0F) + 1; + + const unsigned int frameCount = d->sampleFrames - begSilence; + if(frameCount > 0 && d->sampleRate > 0) { + const double length = frameCount * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } + } + else if (packetType == "RG") { + // Replay Gain + // http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket + + if(dataSize <= 9) { + debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse."); + break; + } + + readRG = true; + + const int replayGainVersion = data[0]; + if(replayGainVersion == 1) { + d->trackGain = data.toShort(1, true); + d->trackPeak = data.toShort(3, true); + d->albumGain = data.toShort(5, true); + d->albumPeak = data.toShort(7, true); + } + } + + else if(packetType == "SE") { + break; + } + + else { + file->seek(dataSize, File::Current); + } + } +} + +void MPC::Properties::readSV7(const ByteVector &data, long streamLength) +{ + if(data.startsWith("MP+")) { + if(data.size() < 4) + return; + + d->version = data[3] & 15; + if(d->version < 7) + return; + + d->totalFrames = data.toUInt(4, false); + + const unsigned int flags = data.toUInt(8, false); + d->sampleRate = sftable[(flags >> 16) & 0x03]; + d->channels = 2; + + const unsigned int gapless = data.toUInt(5, false); + + d->trackGain = data.toShort(14, false); + d->trackPeak = data.toUShort(12, false); + d->albumGain = data.toShort(18, false); + d->albumPeak = data.toUShort(16, false); + + // convert gain info + if(d->trackGain != 0) { + int tmp = static_cast((64.82 - static_cast(d->trackGain) / 100.) * 256. + .5); + if(tmp >= (1 << 16) || tmp < 0) tmp = 0; + d->trackGain = tmp; + } + + if(d->albumGain != 0) { + int tmp = static_cast((64.82 - d->albumGain / 100.) * 256. + .5); + if(tmp >= (1 << 16) || tmp < 0) tmp = 0; + d->albumGain = tmp; + } + + if (d->trackPeak != 0) + d->trackPeak = static_cast(log10(static_cast(d->trackPeak)) * 20 * 256 + .5); + + if (d->albumPeak != 0) + d->albumPeak = static_cast(log10(static_cast(d->albumPeak)) * 20 * 256 + .5); + + bool trueGapless = (gapless >> 31) & 0x0001; + if(trueGapless) { + unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF; + d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples; + } + else + d->sampleFrames = d->totalFrames * 1152 - 576; + } + else { + const unsigned int headerData = data.toUInt(0, false); + + d->bitrate = (headerData >> 23) & 0x01ff; + d->version = (headerData >> 11) & 0x03ff; + d->sampleRate = 44100; + d->channels = 2; + + if(d->version >= 5) + d->totalFrames = data.toUInt(4, false); + else + d->totalFrames = data.toUShort(6, false); + + d->sampleFrames = d->totalFrames * 1152 - 576; + } + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + + if(d->bitrate == 0) + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } +} diff --git a/external/taglib/source/mpc/mpcproperties.h b/external/taglib/source/mpc/mpcproperties.h new file mode 100644 index 0000000..9a902dc --- /dev/null +++ b/external/taglib/source/mpc/mpcproperties.h @@ -0,0 +1,158 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPCPROPERTIES_H +#define TAGLIB_MPCPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace MPC { + + class File; + + static const unsigned int HeaderSize = 8 * 7; + + //! An implementation of audio property reading for MPC + + /*! + * This reads the data from an MPC stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPC::Properties with the data read from the + * ByteVector \a data. + * + * This constructor is deprecated. It only works for MPC version up to 7. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Create an instance of MPC::Properties with the data read directly + * from a MPC::File. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this MPC::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the version of the bitstream (SV4-SV8) + */ + int mpcVersion() const; + + unsigned int totalFrames() const; + unsigned int sampleFrames() const; + + /*! + * Returns the track gain as an integer value, + * to convert to dB: trackGain in dB = 64.82 - (trackGain / 256) + */ + int trackGain() const; + + /*! + * Returns the track peak as an integer value, + * to convert to dB: trackPeak in dB = trackPeak / 256 + * to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768 + */ + int trackPeak() const; + + /*! + * Returns the album gain as an integer value, + * to convert to dB: albumGain in dB = 64.82 - (albumGain / 256) + */ + int albumGain() const; + + /*! + * Returns the album peak as an integer value, + * to convert to dB: albumPeak in dB = albumPeak / 256 + * to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768 + */ + int albumPeak() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void readSV7(const ByteVector &data, long streamLength); + void readSV8(File *file, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v1/id3v1genres.cpp b/external/taglib/source/mpeg/id3v1/id3v1genres.cpp new file mode 100644 index 0000000..c8f089b --- /dev/null +++ b/external/taglib/source/mpeg/id3v1/id3v1genres.cpp @@ -0,0 +1,285 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "id3v1genres.h" + +using namespace TagLib; + +namespace +{ + const wchar_t *const genres[] = { + L"Blues", + L"Classic Rock", + L"Country", + L"Dance", + L"Disco", + L"Funk", + L"Grunge", + L"Hip-Hop", + L"Jazz", + L"Metal", + L"New Age", + L"Oldies", + L"Other", + L"Pop", + L"R&B", + L"Rap", + L"Reggae", + L"Rock", + L"Techno", + L"Industrial", + L"Alternative", + L"Ska", + L"Death Metal", + L"Pranks", + L"Soundtrack", + L"Euro-Techno", + L"Ambient", + L"Trip-Hop", + L"Vocal", + L"Jazz-Funk", + L"Fusion", + L"Trance", + L"Classical", + L"Instrumental", + L"Acid", + L"House", + L"Game", + L"Sound Clip", + L"Gospel", + L"Noise", + L"Alternative Rock", + L"Bass", + L"Soul", + L"Punk", + L"Space", + L"Meditative", + L"Instrumental Pop", + L"Instrumental Rock", + L"Ethnic", + L"Gothic", + L"Darkwave", + L"Techno-Industrial", + L"Electronic", + L"Pop-Folk", + L"Eurodance", + L"Dream", + L"Southern Rock", + L"Comedy", + L"Cult", + L"Gangsta", + L"Top 40", + L"Christian Rap", + L"Pop/Funk", + L"Jungle", + L"Native American", + L"Cabaret", + L"New Wave", + L"Psychedelic", + L"Rave", + L"Showtunes", + L"Trailer", + L"Lo-Fi", + L"Tribal", + L"Acid Punk", + L"Acid Jazz", + L"Polka", + L"Retro", + L"Musical", + L"Rock & Roll", + L"Hard Rock", + L"Folk", + L"Folk Rock", + L"National Folk", + L"Swing", + L"Fast Fusion", + L"Bebop", + L"Latin", + L"Revival", + L"Celtic", + L"Bluegrass", + L"Avant-garde", + L"Gothic Rock", + L"Progressive Rock", + L"Psychedelic Rock", + L"Symphonic Rock", + L"Slow Rock", + L"Big Band", + L"Chorus", + L"Easy Listening", + L"Acoustic", + L"Humour", + L"Speech", + L"Chanson", + L"Opera", + L"Chamber Music", + L"Sonata", + L"Symphony", + L"Booty Bass", + L"Primus", + L"Porn Groove", + L"Satire", + L"Slow Jam", + L"Club", + L"Tango", + L"Samba", + L"Folklore", + L"Ballad", + L"Power Ballad", + L"Rhythmic Soul", + L"Freestyle", + L"Duet", + L"Punk Rock", + L"Drum Solo", + L"A Cappella", + L"Euro-House", + L"Dancehall", + L"Goa", + L"Drum & Bass", + L"Club-House", + L"Hardcore Techno", + L"Terror", + L"Indie", + L"Britpop", + L"Worldbeat", + L"Polsk Punk", + L"Beat", + L"Christian Gangsta Rap", + L"Heavy Metal", + L"Black Metal", + L"Crossover", + L"Contemporary Christian", + L"Christian Rock", + L"Merengue", + L"Salsa", + L"Thrash Metal", + L"Anime", + L"Jpop", + L"Synthpop", + L"Abstract", + L"Art Rock", + L"Baroque", + L"Bhangra", + L"Big Beat", + L"Breakbeat", + L"Chillout", + L"Downtempo", + L"Dub", + L"EBM", + L"Eclectic", + L"Electro", + L"Electroclash", + L"Emo", + L"Experimental", + L"Garage", + L"Global", + L"IDM", + L"Illbient", + L"Industro-Goth", + L"Jam Band", + L"Krautrock", + L"Leftfield", + L"Lounge", + L"Math Rock", + L"New Romantic", + L"Nu-Breakz", + L"Post-Punk", + L"Post-Rock", + L"Psytrance", + L"Shoegaze", + L"Space Rock", + L"Trop Rock", + L"World Music", + L"Neoclassical", + L"Audiobook", + L"Audio Theatre", + L"Neue Deutsche Welle", + L"Podcast", + L"Indie Rock", + L"G-Funk", + L"Dubstep", + L"Garage Rock", + L"Psybient" + }; + const int genresSize = sizeof(genres) / sizeof(genres[0]); +} // namespace + +StringList ID3v1::genreList() +{ + StringList l; + for(int i = 0; i < genresSize; i++) { + l.append(genres[i]); + } + + return l; +} + +ID3v1::GenreMap ID3v1::genreMap() +{ + GenreMap m; + for(int i = 0; i < genresSize; i++) { + m.insert(genres[i], i); + } + + return m; +} + +String ID3v1::genre(int i) +{ + if(i >= 0 && i < genresSize) + return String(genres[i]); // always make a copy + return String(); +} + +int ID3v1::genreIndex(const String &name) +{ + for(int i = 0; i < genresSize; ++i) { + if(name == genres[i]) + return i; + } + + // If the name was not found, try the names which have been changed + static const struct { + const wchar_t *genre; + int code; + } fixUpGenres[] = { + { L"Jazz+Funk", 29 }, + { L"Folk/Rock", 81 }, + { L"Bebob", 85 }, + { L"Avantgarde", 90 }, + { L"Dance Hall", 125 }, + { L"Hardcore", 129 }, + { L"BritPop", 132 }, + { L"Negerpunk", 133 } + }; + static const int fixUpGenresSize = + sizeof(fixUpGenres) / sizeof(fixUpGenres[0]); + for(int i = 0; i < fixUpGenresSize; ++i) { + if(name == fixUpGenres[i].genre) + return fixUpGenres[i].code; + } + + return 255; +} diff --git a/external/taglib/source/mpeg/id3v1/id3v1genres.h b/external/taglib/source/mpeg/id3v1/id3v1genres.h new file mode 100644 index 0000000..0a0dd97 --- /dev/null +++ b/external/taglib/source/mpeg/id3v1/id3v1genres.h @@ -0,0 +1,66 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1GENRE_H +#define TAGLIB_ID3V1GENRE_H + +#include "tmap.h" +#include "tstringlist.h" +#include "taglib_export.h" + +namespace TagLib { + namespace ID3v1 { + + typedef Map GenreMap; + + /*! + * Returns the list of canonical ID3v1 genre names in the order that they + * are listed in the standard. + */ + StringList TAGLIB_EXPORT genreList(); + + /*! + * A "reverse mapping" that goes from the canonical ID3v1 genre name to the + * respective genre number. genreMap()["Rock"] == + */ + GenreMap TAGLIB_EXPORT genreMap(); + + /*! + * Returns the name of the genre at \a index in the ID3v1 genre list. If + * \a index is out of range -- less than zero or greater than 191 -- a null + * string will be returned. + */ + String TAGLIB_EXPORT genre(int index); + + /*! + * Returns the genre index for the (case sensitive) genre \a name. If the + * genre is not in the list 255 (which signifies an unknown genre in ID3v1) + * will be returned. + */ + int TAGLIB_EXPORT genreIndex(const String &name); + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v1/id3v1tag.cpp b/external/taglib/source/mpeg/id3v1/id3v1tag.cpp new file mode 100644 index 0000000..358a959 --- /dev/null +++ b/external/taglib/source/mpeg/id3v1/id3v1tag.cpp @@ -0,0 +1,267 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "id3v1tag.h" +#include "id3v1genres.h" + +using namespace TagLib; +using namespace ID3v1; + +namespace +{ + const ID3v1::StringHandler defaultStringHandler; + const ID3v1::StringHandler *stringHandler = &defaultStringHandler; +} + +class ID3v1::Tag::TagPrivate +{ +public: + TagPrivate() : + file(0), + tagOffset(0), + track(0), + genre(255) {} + + File *file; + long tagOffset; + + String title; + String artist; + String album; + String year; + String comment; + unsigned char track; + unsigned char genre; +}; + +//////////////////////////////////////////////////////////////////////////////// +// StringHandler implementation +//////////////////////////////////////////////////////////////////////////////// + +StringHandler::StringHandler() +{ +} + +String ID3v1::StringHandler::parse(const ByteVector &data) const +{ + return String(data, String::Latin1).stripWhiteSpace(); +} + +ByteVector ID3v1::StringHandler::render(const String &s) const +{ + if(s.isLatin1()) + return s.data(String::Latin1); + return ByteVector(); +} + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +ID3v1::Tag::Tag() : + d(new TagPrivate()) +{ +} + +ID3v1::Tag::Tag(File *file, long tagOffset) : + d(new TagPrivate()) +{ + d->file = file; + d->tagOffset = tagOffset; + + read(); +} + +ID3v1::Tag::~Tag() +{ + delete d; +} + +ByteVector ID3v1::Tag::render() const +{ + ByteVector data; + + data.append(fileIdentifier()); + data.append(stringHandler->render(d->title).resize(30)); + data.append(stringHandler->render(d->artist).resize(30)); + data.append(stringHandler->render(d->album).resize(30)); + data.append(stringHandler->render(d->year).resize(4)); + data.append(stringHandler->render(d->comment).resize(28)); + data.append(char(0)); + data.append(char(d->track)); + data.append(char(d->genre)); + + return data; +} + +ByteVector ID3v1::Tag::fileIdentifier() +{ + return ByteVector::fromCString("TAG"); +} + +String ID3v1::Tag::title() const +{ + return d->title; +} + +String ID3v1::Tag::artist() const +{ + return d->artist; +} + +String ID3v1::Tag::album() const +{ + return d->album; +} + +String ID3v1::Tag::comment() const +{ + return d->comment; +} + +String ID3v1::Tag::genre() const +{ + return ID3v1::genre(d->genre); +} + +unsigned int ID3v1::Tag::year() const +{ + return d->year.toInt(); +} + +unsigned int ID3v1::Tag::track() const +{ + return d->track; +} + +void ID3v1::Tag::setTitle(const String &s) +{ + d->title = s; +} + +void ID3v1::Tag::setArtist(const String &s) +{ + d->artist = s; +} + +void ID3v1::Tag::setAlbum(const String &s) +{ + d->album = s; +} + +void ID3v1::Tag::setComment(const String &s) +{ + d->comment = s; +} + +void ID3v1::Tag::setGenre(const String &s) +{ + d->genre = ID3v1::genreIndex(s); +} + +void ID3v1::Tag::setYear(unsigned int i) +{ + d->year = i > 0 ? String::number(i) : String(); +} + +void ID3v1::Tag::setTrack(unsigned int i) +{ + d->track = i < 256 ? i : 0; +} + +unsigned int ID3v1::Tag::genreNumber() const +{ + return d->genre; +} + +void ID3v1::Tag::setGenreNumber(unsigned int i) +{ + d->genre = i < 256 ? i : 255; +} + +void ID3v1::Tag::setStringHandler(const StringHandler *handler) +{ + if(handler) + stringHandler = handler; + else + stringHandler = &defaultStringHandler; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected methods +//////////////////////////////////////////////////////////////////////////////// + +void ID3v1::Tag::read() +{ + if(d->file && d->file->isValid()) { + d->file->seek(d->tagOffset); + // read the tag -- always 128 bytes + const ByteVector data = d->file->readBlock(128); + + // some initial sanity checking + if(data.size() == 128 && data.startsWith("TAG")) + parse(data); + else + debug("ID3v1 tag is not valid or could not be read at the specified offset."); + } +} + +void ID3v1::Tag::parse(const ByteVector &data) +{ + int offset = 3; + + d->title = stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->artist = stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->album = stringHandler->parse(data.mid(offset, 30)); + offset += 30; + + d->year = stringHandler->parse(data.mid(offset, 4)); + offset += 4; + + // Check for ID3v1.1 -- Note that ID3v1 *does not* support "track zero" -- this + // is not a bug in TagLib. Since a zeroed byte is what we would expect to + // indicate the end of a C-String, specifically the comment string, a value of + // zero must be assumed to be just that. + + if(data[offset + 28] == 0 && data[offset + 29] != 0) { + // ID3v1.1 detected + + d->comment = stringHandler->parse(data.mid(offset, 28)); + d->track = static_cast(data[offset + 29]); + } + else + d->comment = data.mid(offset, 30); + + offset += 30; + + d->genre = static_cast(data[offset]); +} diff --git a/external/taglib/source/mpeg/id3v1/id3v1tag.h b/external/taglib/source/mpeg/id3v1/id3v1tag.h new file mode 100644 index 0000000..b61f06a --- /dev/null +++ b/external/taglib/source/mpeg/id3v1/id3v1tag.h @@ -0,0 +1,202 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V1TAG_H +#define TAGLIB_ID3V1TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class File; + + //! An ID3v1 implementation + + namespace ID3v1 { + + //! A abstraction for the string to data encoding in ID3v1 tags. + + /*! + * ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In + * practice it does not. TagLib by default only supports ISO-8859-1 data + * in ID3v1 tags. + * + * However by subclassing this class and reimplementing parse() and render() + * and setting your reimplementation as the default with + * ID3v1::Tag::setStringHandler() you can define how you would like these + * transformations to be done. + * + * \warning It is advisable not to write non-ISO-8859-1 data to ID3v1 + * tags. Please consider disabling the writing of ID3v1 tags in the case + * that the data is not ISO-8859-1. + * + * \see ID3v1::Tag::setStringHandler() + */ + + class TAGLIB_EXPORT StringHandler + { + TAGLIB_IGNORE_MISSING_DESTRUCTOR + public: + // BIC: Add virtual destructor. + StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ + virtual String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation + * assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is + * does not conform to ISO-8859-1, no value is written. + * + * \warning It is recommended that you not override this method, but + * instead do not write an ID3v1 tag in the case that the data is not + * ISO-8859-1. + */ + virtual ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v1 implementation + + /*! + * This is an implementation of the ID3v1 format. ID3v1 is both the simplest + * and most common of tag formats but is rather limited. Because of its + * pervasiveness and the way that applications have been written around the + * fields that it provides, the generic TagLib::Tag API is a mirror of what is + * provided by ID3v1. + * + * ID3v1 tags should generally only contain Latin1 information. However because + * many applications do not follow this rule there is now support for overriding + * the ID3v1 string handling using the ID3v1::StringHandler class. Please see + * the documentation for that class for more information. + * + * \see StringHandler + * + * \note Most fields are truncated to a maximum of 28-30 bytes. The + * truncation happens automatically when the tag is rendered. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Create an ID3v1 tag with default values. + */ + Tag(); + + /*! + * Create an ID3v1 tag and parse the data in \a file starting at + * \a tagOffset. + */ + Tag(File *file, long tagOffset); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Renders the in memory values to a ByteVector suitable for writing to + * the file. + */ + ByteVector render() const; + + /*! + * Returns the string "TAG" suitable for usage in locating the tag in a + * file. + */ + static ByteVector fileIdentifier(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + /*! + * Returns the genre in number. + * + * \note Normally 255 indicates that this tag contains no genre. + */ + unsigned int genreNumber() const; + + /*! + * Sets the genre in number to \a i. + * + * \note Valid value is from 0 up to 255. Normally 255 indicates that + * this tag contains no genre. + */ + void setGenreNumber(unsigned int i); + + /*! + * Sets the string handler that decides how the ID3v1 data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see StringHandler + */ + static void setStringHandler(const StringHandler *handler); + + protected: + /*! + * Reads from the file specified in the constructor. + */ + void read(); + /*! + * Pareses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.cpp b/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.cpp new file mode 100644 index 0000000..914a8f7 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.cpp @@ -0,0 +1,225 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "attachedpictureframe.h" + +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class AttachedPictureFrame::AttachedPictureFramePrivate +{ +public: + AttachedPictureFramePrivate() : textEncoding(String::Latin1), + type(AttachedPictureFrame::Other) {} + + String::Type textEncoding; + String mimeType; + AttachedPictureFrame::Type type; + String description; + ByteVector data; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +AttachedPictureFrame::AttachedPictureFrame() : + Frame("APIC"), + d(new AttachedPictureFramePrivate()) +{ +} + +AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : + Frame(data), + d(new AttachedPictureFramePrivate()) +{ + setData(data); +} + +AttachedPictureFrame::~AttachedPictureFrame() +{ + delete d; +} + +String AttachedPictureFrame::toString() const +{ + String s = "[" + d->mimeType + "]"; + return d->description.isEmpty() ? s : d->description + " " + s; +} + +String::Type AttachedPictureFrame::textEncoding() const +{ + return d->textEncoding; +} + +void AttachedPictureFrame::setTextEncoding(String::Type t) +{ + d->textEncoding = t; +} + +String AttachedPictureFrame::mimeType() const +{ + return d->mimeType; +} + +void AttachedPictureFrame::setMimeType(const String &m) +{ + d->mimeType = m; +} + +AttachedPictureFrame::Type AttachedPictureFrame::type() const +{ + return d->type; +} + +void AttachedPictureFrame::setType(Type t) +{ + d->type = t; +} + +String AttachedPictureFrame::description() const +{ + return d->description; +} + +void AttachedPictureFrame::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector AttachedPictureFrame::picture() const +{ + return d->data; +} + +void AttachedPictureFrame::setPicture(const ByteVector &p) +{ + d->data = p; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void AttachedPictureFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A picture frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + d->mimeType = readStringField(data, String::Latin1, &pos); + /* Now we need at least two more bytes available */ + if(static_cast(pos) + 1 >= data.size()) { + debug("Truncated picture frame."); + return; + } + + d->type = static_cast(data[pos++]); + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +ByteVector AttachedPictureFrame::renderFields() const +{ + ByteVector data; + + String::Type encoding = checkTextEncoding(d->description, d->textEncoding); + + data.append(char(encoding)); + data.append(d->mimeType.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(char(d->type)); + data.append(d->description.data(encoding)); + data.append(textDelimiter(encoding)); + data.append(d->data); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new AttachedPictureFramePrivate()) +{ + parseFields(fieldData(data)); +} + +//////////////////////////////////////////////////////////////////////////////// +// support for ID3v2.2 PIC frames +//////////////////////////////////////////////////////////////////////////////// + +void AttachedPictureFrameV22::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A picture frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + String fixedString = String(data.mid(pos, 3), String::Latin1); + pos += 3; + // convert fixed string image type to mime string + if (fixedString.upper() == "JPG") { + d->mimeType = "image/jpeg"; + } else if (fixedString.upper() == "PNG") { + d->mimeType = "image/png"; + } else { + debug("probably unsupported image type"); + d->mimeType = "image/" + fixedString; + } + + d->type = static_cast(data[pos++]); + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) +{ + // set v2.2 header to make fieldData work correctly + setHeader(h, true); + + parseFields(fieldData(data)); + + // now set the v2.4 header + Frame::Header *newHeader = new Frame::Header("APIC"); + newHeader->setFrameSize(h->frameSize()); + setHeader(newHeader, true); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.h b/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.h new file mode 100644 index 0000000..55067bd --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/attachedpictureframe.h @@ -0,0 +1,230 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ATTACHEDPICTUREFRAME_H +#define TAGLIB_ATTACHEDPICTUREFRAME_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 attached picture frame implementation + + /*! + * This is an implementation of ID3v2 attached pictures. Pictures may be + * included in tags, one per APIC frame (but there may be multiple APIC + * frames in a single tag). These pictures are usually in either JPEG or + * PNG format. + */ + + class TAGLIB_EXPORT AttachedPictureFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This describes the function or content of the picture. + */ + enum Type { + //! A type not enumerated below + Other = 0x00, + //! 32x32 PNG image that should be used as the file icon + FileIcon = 0x01, + //! File icon of a different size or format + OtherFileIcon = 0x02, + //! Front cover image of the album + FrontCover = 0x03, + //! Back cover image of the album + BackCover = 0x04, + //! Inside leaflet page of the album + LeafletPage = 0x05, + //! Image from the album itself + Media = 0x06, + //! Picture of the lead artist or soloist + LeadArtist = 0x07, + //! Picture of the artist or performer + Artist = 0x08, + //! Picture of the conductor + Conductor = 0x09, + //! Picture of the band or orchestra + Band = 0x0A, + //! Picture of the composer + Composer = 0x0B, + //! Picture of the lyricist or text writer + Lyricist = 0x0C, + //! Picture of the recording location or studio + RecordingLocation = 0x0D, + //! Picture of the artists during recording + DuringRecording = 0x0E, + //! Picture of the artists during performance + DuringPerformance = 0x0F, + //! Picture from a movie or video related to the track + MovieScreenCapture = 0x10, + //! Picture of a large, coloured fish + ColouredFish = 0x11, + //! Illustration related to the track + Illustration = 0x12, + //! Logo of the band or performer + BandLogo = 0x13, + //! Logo of the publisher (record company) + PublisherLogo = 0x14 + }; + + /*! + * Constructs an empty picture frame. The description, content and text + * encoding should be set manually. + */ + AttachedPictureFrame(); + + /*! + * Constructs an AttachedPicture frame based on \a data. + */ + explicit AttachedPictureFrame(const ByteVector &data); + + /*! + * Destroys the AttahcedPictureFrame instance. + */ + virtual ~AttachedPictureFrame(); + + /*! + * Returns a string containing the description and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description. + * + * \see setTextEncoding() + * \see description() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description. + * + * \see description() + */ + void setTextEncoding(String::Type t); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns the type of the image. + * + * \see Type + * \see setType() + */ + Type type() const; + + /*! + * Sets the type for the image. + * + * \see Type + * \see type() + */ + void setType(Type t); + + /*! + * Returns a text description of the image. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the image data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setPicture() + * \see mimeType() + */ + ByteVector picture() const; + + /*! + * Sets the image data to \a p. \a p should be of the type specified in + * this frame's mime-type specification. + * + * \see picture() + * \see mimeType() + * \see setMimeType() + */ + void setPicture(const ByteVector &p); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + class AttachedPictureFramePrivate; + AttachedPictureFramePrivate *d; + + private: + AttachedPictureFrame(const AttachedPictureFrame &); + AttachedPictureFrame &operator=(const AttachedPictureFrame &); + AttachedPictureFrame(const ByteVector &data, Header *h); + + }; + + //! support for ID3v2.2 PIC frames + class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame + { + protected: + virtual void parseFields(const ByteVector &data); + private: + AttachedPictureFrameV22(const ByteVector &data, Header *h); + friend class FrameFactory; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/chapterframe.cpp b/external/taglib/source/mpeg/id3v2/frames/chapterframe.cpp new file mode 100644 index 0000000..c839f58 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/chapterframe.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "chapterframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class ChapterFrame::ChapterFramePrivate +{ +public: + ChapterFramePrivate() : + tagHeader(0), + startTime(0), + endTime(0), + startOffset(0), + endOffset(0) + { + embeddedFrameList.setAutoDelete(true); + } + + const ID3v2::Header *tagHeader; + ByteVector elementID; + unsigned int startTime; + unsigned int endTime; + unsigned int startOffset; + unsigned int endOffset; + FrameListMap embeddedFrameListMap; + FrameList embeddedFrameList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : + ID3v2::Frame(data), + d(new ChapterFramePrivate()) +{ + d->tagHeader = tagHeader; + setData(data); +} + +ChapterFrame::ChapterFrame(const ByteVector &elementID, + unsigned int startTime, unsigned int endTime, + unsigned int startOffset, unsigned int endOffset, + const FrameList &embeddedFrames) : + ID3v2::Frame("CHAP"), + d(new ChapterFramePrivate()) +{ + // setElementID has a workaround for a previously silly API where you had to + // specifically include the null byte. + + setElementID(elementID); + + d->startTime = startTime; + d->endTime = endTime; + d->startOffset = startOffset; + d->endOffset = endOffset; + + for(FrameList::ConstIterator it = embeddedFrames.begin(); + it != embeddedFrames.end(); ++it) + addEmbeddedFrame(*it); +} + +ChapterFrame::~ChapterFrame() +{ + delete d; +} + +ByteVector ChapterFrame::elementID() const +{ + return d->elementID; +} + +unsigned int ChapterFrame::startTime() const +{ + return d->startTime; +} + +unsigned int ChapterFrame::endTime() const +{ + return d->endTime; +} + +unsigned int ChapterFrame::startOffset() const +{ + return d->startOffset; +} + +unsigned int ChapterFrame::endOffset() const +{ + return d->endOffset; +} + +void ChapterFrame::setElementID(const ByteVector &eID) +{ + d->elementID = eID; + + if(d->elementID.endsWith(char(0))) + d->elementID = d->elementID.mid(0, d->elementID.size() - 1); +} + +void ChapterFrame::setStartTime(const unsigned int &sT) +{ + d->startTime = sT; +} + +void ChapterFrame::setEndTime(const unsigned int &eT) +{ + d->endTime = eT; +} + +void ChapterFrame::setStartOffset(const unsigned int &sO) +{ + d->startOffset = sO; +} + +void ChapterFrame::setEndOffset(const unsigned int &eO) +{ + d->endOffset = eO; +} + +const FrameListMap &ChapterFrame::embeddedFrameListMap() const +{ + return d->embeddedFrameListMap; +} + +const FrameList &ChapterFrame::embeddedFrameList() const +{ + return d->embeddedFrameList; +} + +const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const +{ + return d->embeddedFrameListMap[frameID]; +} + +void ChapterFrame::addEmbeddedFrame(Frame *frame) +{ + d->embeddedFrameList.append(frame); + d->embeddedFrameListMap[frame->frameID()].append(frame); +} + +void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) +{ + // remove the frame from the frame list + FrameList::Iterator it = d->embeddedFrameList.find(frame); + d->embeddedFrameList.erase(it); + + // ...and from the frame list map + it = d->embeddedFrameListMap[frame->frameID()].find(frame); + d->embeddedFrameListMap[frame->frameID()].erase(it); + + // ...and delete as desired + if(del) + delete frame; +} + +void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) +{ + FrameList l = d->embeddedFrameListMap[id]; + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) + removeEmbeddedFrame(*it, true); +} + +String ChapterFrame::toString() const +{ + String s = String(d->elementID) + + ": start time: " + String::number(d->startTime) + + ", end time: " + String::number(d->endTime); + + if(d->startOffset != 0xFFFFFFFF) + s += ", start offset: " + String::number(d->startOffset); + + if(d->endOffset != 0xFFFFFFFF) + s += ", end offset: " + String::number(d->endOffset); + + if(!d->embeddedFrameList.isEmpty()) { + StringList frameIDs; + for(FrameList::ConstIterator it = d->embeddedFrameList.begin(); + it != d->embeddedFrameList.end(); ++it) + frameIDs.append((*it)->frameID()); + s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]"; + } + + return s; +} + +PropertyMap ChapterFrame::asProperties() const +{ + PropertyMap map; + + map.unsupportedData().append(frameID() + String("/") + d->elementID); + + return map; +} + +ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static +{ + ID3v2::FrameList comments = tag->frameList("CHAP"); + + for(ID3v2::FrameList::ConstIterator it = comments.begin(); + it != comments.end(); + ++it) + { + ChapterFrame *frame = dynamic_cast(*it); + if(frame && frame->elementID() == eID) + return frame; + } + + return 0; +} + +void ChapterFrame::parseFields(const ByteVector &data) +{ + unsigned int size = data.size(); + if(size < 18) { + debug("A CHAP frame must contain at least 18 bytes (1 byte element ID " + "terminated by null and 4x4 bytes for start and end time and offset)."); + return; + } + + int pos = 0; + unsigned int embPos = 0; + d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1); + d->startTime = data.toUInt(pos, true); + pos += 4; + d->endTime = data.toUInt(pos, true); + pos += 4; + d->startOffset = data.toUInt(pos, true); + pos += 4; + d->endOffset = data.toUInt(pos, true); + pos += 4; + size -= pos; + + // Embedded frames are optional + + if(size < header()->size()) + return; + + while(embPos < size - header()->size()) { + Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader); + + if(!frame) + return; + + // Checks to make sure that frame parsed correctly. + if(frame->size() <= 0) { + delete frame; + return; + } + + embPos += frame->size() + header()->size(); + addEmbeddedFrame(frame); + } +} + +ByteVector ChapterFrame::renderFields() const +{ + ByteVector data; + + data.append(d->elementID); + data.append('\0'); + data.append(ByteVector::fromUInt(d->startTime, true)); + data.append(ByteVector::fromUInt(d->endTime, true)); + data.append(ByteVector::fromUInt(d->startOffset, true)); + data.append(ByteVector::fromUInt(d->endOffset, true)); + FrameList l = d->embeddedFrameList; + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { + (*it)->header()->setVersion(header()->version()); + data.append((*it)->render()); + } + + return data; +} + +ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : + Frame(h), + d(new ChapterFramePrivate()) +{ + d->tagHeader = tagHeader; + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/chapterframe.h b/external/taglib/source/mpeg/id3v2/frames/chapterframe.h new file mode 100644 index 0000000..0eaa140 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/chapterframe.h @@ -0,0 +1,249 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_CHAPTERFRAME +#define TAGLIB_CHAPTERFRAME + +#include "id3v2tag.h" +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 chapter frames. The purpose of this + * frame is to describe a single chapter within an audio file. + */ + + //! An implementation of ID3v2 chapter frames + + class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a chapter frame based on \a data. \a tagHeader is required as + * the internal frames are parsed based on the tag version. + */ + ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data); + + /*! + * Creates a chapter frame with the element ID \a elementID, start time + * \a startTime, end time \a endTime, start offset \a startOffset, + * end offset \a endOffset and optionally a list of embedded frames, + * whose ownership will then be taken over by this Frame, in + * \a embeddedFrames; + * + * All times are in milliseconds. + */ + ChapterFrame(const ByteVector &elementID, + unsigned int startTime, unsigned int endTime, + unsigned int startOffset, unsigned int endOffset, + const FrameList &embeddedFrames = FrameList()); + + /*! + * Destroys the frame. + */ + virtual ~ChapterFrame(); + + /*! + * Returns the element ID of the frame. Element ID + * is a null terminated string, however it's not human-readable. + * + * \see setElementID() + */ + ByteVector elementID() const; + + /*! + * Returns time of chapter's start (in milliseconds). + * + * \see setStartTime() + */ + unsigned int startTime() const; + + /*! + * Returns time of chapter's end (in milliseconds). + * + * \see setEndTime() + */ + unsigned int endTime() const; + + /*! + * Returns zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's start. + * + * \note If returned value is 0xFFFFFFFF, start time should be used instead. + * \see setStartOffset() + */ + unsigned int startOffset() const; + + /*! + * Returns zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's end. + * + * \note If returned value is 0xFFFFFFFF, end time should be used instead. + * \see setEndOffset() + */ + unsigned int endOffset() const; + + /*! + * Sets the element ID of the frame to \a eID. If \a eID isn't + * null terminated, a null char is appended automatically. + * + * \see elementID() + */ + void setElementID(const ByteVector &eID); + + /*! + * Sets time of chapter's start (in milliseconds) to \a sT. + * + * \see startTime() + */ + void setStartTime(const unsigned int &sT); + + /*! + * Sets time of chapter's end (in milliseconds) to \a eT. + * + * \see endTime() + */ + void setEndTime(const unsigned int &eT); + + /*! + * Sets zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's start to \a sO. + * + * \see startOffset() + */ + void setStartOffset(const unsigned int &sO); + + /*! + * Sets zero based byte offset (count of bytes from the beginning + * of the audio file) of chapter's end to \a eO. + * + * \see endOffset() + */ + void setEndOffset(const unsigned int &eO); + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames embedded in the CHAP frame. + * + * This is the most convenient structure for accessing the CHAP frame's + * embedded frames. Many frame types allow multiple instances of the same + * frame type so this is a map of lists. In most cases however there will + * only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ + const FrameListMap &embeddedFrameListMap() const; + + /*! + * Returns a reference to the embedded frame list. This is an FrameList + * of all of the frames embedded in the CHAP frame in the order that they + * were parsed. + * + * This can be useful if for example you want iterate over the CHAP frame's + * embedded frames in the order that they occur in the CHAP frame. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + */ + const FrameList &embeddedFrameList() const; + + /*! + * Returns the embedded frame list for frames with the id \a frameID + * or an empty list if there are no embedded frames of that type. This + * is just a convenience and is equivalent to: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ + const FrameList &embeddedFrameList(const ByteVector &frameID) const; + + /*! + * Add an embedded frame to the CHAP frame. At this point the CHAP frame + * takes ownership of the embedded frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void addEmbeddedFrame(Frame *frame); + + /*! + * Remove an embedded frame from the CHAP frame. If \a del is true the frame's + * memory will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrame(Frame *frame, bool del = true); + + /*! + * Remove all embedded frames of type \a id from the CHAP frame and free their + * memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrames(const ByteVector &id); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * CHAP frames each have a unique element ID. This searches for a CHAP + * frame with the element ID \a eID and returns a pointer to it. This + * can be used to link CTOC and CHAP frames together. + * + * \see elementID() + */ + static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h); + ChapterFrame(const ChapterFrame &); + ChapterFrame &operator=(const ChapterFrame &); + + class ChapterFramePrivate; + ChapterFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/commentsframe.cpp b/external/taglib/source/mpeg/id3v2/frames/commentsframe.cpp new file mode 100644 index 0000000..815e5e1 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/commentsframe.cpp @@ -0,0 +1,198 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "commentsframe.h" +#include "tpropertymap.h" + +using namespace TagLib; +using namespace ID3v2; + +class CommentsFrame::CommentsFramePrivate +{ +public: + CommentsFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + ByteVector language; + String description; + String text; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +CommentsFrame::CommentsFrame(String::Type encoding) : + Frame("COMM"), + d(new CommentsFramePrivate()) +{ + d->textEncoding = encoding; +} + +CommentsFrame::CommentsFrame(const ByteVector &data) : + Frame(data), + d(new CommentsFramePrivate()) +{ + setData(data); +} + +CommentsFrame::~CommentsFrame() +{ + delete d; +} + +String CommentsFrame::toString() const +{ + return d->text; +} + +ByteVector CommentsFrame::language() const +{ + return d->language; +} + +String CommentsFrame::description() const +{ + return d->description; +} + +String CommentsFrame::text() const +{ + return d->text; +} + +void CommentsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void CommentsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void CommentsFrame::setText(const String &s) +{ + d->text = s; +} + +String::Type CommentsFrame::textEncoding() const +{ + return d->textEncoding; +} + +void CommentsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +PropertyMap CommentsFrame::asProperties() const +{ + String key = description().upper(); + PropertyMap map; + if(key.isEmpty() || key == "COMMENT") + map.insert("COMMENT", text()); + else + map.insert("COMMENT:" + key, text()); + return map; +} + +CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static +{ + ID3v2::FrameList comments = tag->frameList("COMM"); + + for(ID3v2::FrameList::ConstIterator it = comments.begin(); + it != comments.end(); + ++it) + { + CommentsFrame *frame = dynamic_cast(*it); + if(frame && frame->description() == d) + return frame; + } + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void CommentsFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("A comment frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + d->language = data.mid(1, 3); + + int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + + if(l.size() == 2) { + if(d->textEncoding == String::Latin1) { + d->description = Tag::latin1StringHandler()->parse(l.front()); + d->text = Tag::latin1StringHandler()->parse(l.back()); + } else { + d->description = String(l.front(), d->textEncoding); + d->text = String(l.back(), d->textEncoding); + } + } +} + +ByteVector CommentsFrame::renderFields() const +{ + ByteVector v; + + String::Type encoding = d->textEncoding; + + encoding = checkTextEncoding(d->description, encoding); + encoding = checkTextEncoding(d->text, encoding); + + v.append(char(encoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(d->text.data(encoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new CommentsFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/commentsframe.h b/external/taglib/source/mpeg/id3v2/frames/commentsframe.h new file mode 100644 index 0000000..4da9d53 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/commentsframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_COMMENTSFRAME_H +#define TAGLIB_COMMENTSFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 comments + + /*! + * This implements the ID3v2 comment format. An ID3v2 comment consists of + * a language encoding, a description and a single text field. + */ + + class TAGLIB_EXPORT CommentsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty comment frame that will use the text encoding + * \a encoding. + */ + explicit CommentsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a comment based on the data in \a data. + */ + explicit CommentsFrame(const ByteVector &data); + + /*! + * Destroys this CommentFrame instance. + */ + virtual ~CommentsFrame(); + + /*! + * Returns the text of this comment. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this comment. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this comment. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the comment to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the comment to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Parses this frame as PropertyMap with a single key. + * - if description() is empty or "COMMENT", the key will be "COMMENT" + * - if description() is not a valid PropertyMap key, the frame will be + * marked unsupported by an entry "COMM/" in the unsupportedData() + * attribute of the returned map. + * - otherwise, the key will be "COMMENT:" + * - The single value will be the frame's text(). + */ + PropertyMap asProperties() const; + + /*! + * Comments each have a unique description. This searches for a comment + * frame with the description \a d and returns a pointer to it. If no + * frame is found that matches the given description null is returned. + * + * \see description() + */ + static CommentsFrame *findByDescription(const Tag *tag, const String &d); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + CommentsFrame(const ByteVector &data, Header *h); + CommentsFrame(const CommentsFrame &); + CommentsFrame &operator=(const CommentsFrame &); + + class CommentsFramePrivate; + CommentsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.cpp b/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.cpp new file mode 100644 index 0000000..9303181 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.cpp @@ -0,0 +1,144 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "eventtimingcodesframe.h" +#include +#include +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class EventTimingCodesFrame::EventTimingCodesFramePrivate +{ +public: + EventTimingCodesFramePrivate() : + timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {} + EventTimingCodesFrame::TimestampFormat timestampFormat; + EventTimingCodesFrame::SynchedEventList synchedEvents; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +EventTimingCodesFrame::EventTimingCodesFrame() : + Frame("ETCO"), + d(new EventTimingCodesFramePrivate()) +{ +} + +EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : + Frame(data), + d(new EventTimingCodesFramePrivate()) +{ + setData(data); +} + +EventTimingCodesFrame::~EventTimingCodesFrame() +{ + delete d; +} + +String EventTimingCodesFrame::toString() const +{ + return String(); +} + +EventTimingCodesFrame::TimestampFormat +EventTimingCodesFrame::timestampFormat() const +{ + return d->timestampFormat; +} + +EventTimingCodesFrame::SynchedEventList +EventTimingCodesFrame::synchedEvents() const +{ + return d->synchedEvents; +} + +void EventTimingCodesFrame::setTimestampFormat( + EventTimingCodesFrame::TimestampFormat f) +{ + d->timestampFormat = f; +} + +void EventTimingCodesFrame::setSynchedEvents( + const EventTimingCodesFrame::SynchedEventList &e) +{ + d->synchedEvents = e; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void EventTimingCodesFrame::parseFields(const ByteVector &data) +{ + const int end = data.size(); + if(end < 1) { + debug("An event timing codes frame must contain at least 1 byte."); + return; + } + + d->timestampFormat = TimestampFormat(data[0]); + + int pos = 1; + d->synchedEvents.clear(); + while(pos + 4 < end) { + EventType type = static_cast(static_cast(data[pos++])); + unsigned int time = data.toUInt(pos, true); + pos += 4; + d->synchedEvents.append(SynchedEvent(time, type)); + } +} + +ByteVector EventTimingCodesFrame::renderFields() const +{ + ByteVector v; + + v.append(char(d->timestampFormat)); + for(SynchedEventList::ConstIterator it = d->synchedEvents.begin(); + it != d->synchedEvents.end(); + ++it) { + const SynchedEvent &entry = *it; + v.append(char(entry.type)); + v.append(ByteVector::fromUInt(entry.time)); + } + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new EventTimingCodesFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.h b/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.h new file mode 100644 index 0000000..3dcedb9 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/eventtimingcodesframe.h @@ -0,0 +1,185 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_EVENTTIMINGCODESFRAME_H +#define TAGLIB_EVENTTIMINGCODESFRAME_H + +#include "id3v2frame.h" +#include "tlist.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 event timing codes frame + /*! + * An implementation of ID3v2 event timing codes. + */ + class TAGLIB_EXPORT EventTimingCodesFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Specifies the timestamp format used. + */ + enum TimestampFormat { + //! The timestamp is of unknown format. + Unknown = 0x00, + //! The timestamp represents the number of MPEG frames since + //! the beginning of the audio stream. + AbsoluteMpegFrames = 0x01, + //! The timestamp represents the number of milliseconds since + //! the beginning of the audio stream. + AbsoluteMilliseconds = 0x02 + }; + + /*! + * Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes. + */ + enum EventType { + Padding = 0x00, + EndOfInitialSilence = 0x01, + IntroStart = 0x02, + MainPartStart = 0x03, + OutroStart = 0x04, + OutroEnd = 0x05, + VerseStart = 0x06, + RefrainStart = 0x07, + InterludeStart = 0x08, + ThemeStart = 0x09, + VariationStart = 0x0a, + KeyChange = 0x0b, + TimeChange = 0x0c, + MomentaryUnwantedNoise = 0x0d, + SustainedNoise = 0x0e, + SustainedNoiseEnd = 0x0f, + IntroEnd = 0x10, + MainPartEnd = 0x11, + VerseEnd = 0x12, + RefrainEnd = 0x13, + ThemeEnd = 0x14, + Profanity = 0x15, + ProfanityEnd = 0x16, + NotPredefinedSynch0 = 0xe0, + NotPredefinedSynch1 = 0xe1, + NotPredefinedSynch2 = 0xe2, + NotPredefinedSynch3 = 0xe3, + NotPredefinedSynch4 = 0xe4, + NotPredefinedSynch5 = 0xe5, + NotPredefinedSynch6 = 0xe6, + NotPredefinedSynch7 = 0xe7, + NotPredefinedSynch8 = 0xe8, + NotPredefinedSynch9 = 0xe9, + NotPredefinedSynchA = 0xea, + NotPredefinedSynchB = 0xeb, + NotPredefinedSynchC = 0xec, + NotPredefinedSynchD = 0xed, + NotPredefinedSynchE = 0xee, + NotPredefinedSynchF = 0xef, + AudioEnd = 0xfd, + AudioFileEnds = 0xfe + }; + + /*! + * Single entry of time stamp and event. + */ + struct SynchedEvent { + SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {} + unsigned int time; + EventType type; + }; + + /*! + * List of synchronized events. + */ + typedef TagLib::List SynchedEventList; + + /*! + * Construct an empty event timing codes frame. + */ + explicit EventTimingCodesFrame(); + + /*! + * Construct a event timing codes frame based on the data in \a data. + */ + explicit EventTimingCodesFrame(const ByteVector &data); + + /*! + * Destroys this EventTimingCodesFrame instance. + */ + virtual ~EventTimingCodesFrame(); + + /*! + * Returns a null string. + */ + virtual String toString() const; + + /*! + * Returns the timestamp format. + */ + TimestampFormat timestampFormat() const; + + /*! + * Returns the events with the time stamps. + */ + SynchedEventList synchedEvents() const; + + /*! + * Set the timestamp format. + * + * \see timestampFormat() + */ + void setTimestampFormat(TimestampFormat f); + + /*! + * Sets the text with the time stamps. + * + * \see text() + */ + void setSynchedEvents(const SynchedEventList &e); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + EventTimingCodesFrame(const ByteVector &data, Header *h); + EventTimingCodesFrame(const EventTimingCodesFrame &); + EventTimingCodesFrame &operator=(const EventTimingCodesFrame &); + + class EventTimingCodesFramePrivate; + EventTimingCodesFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp b/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp new file mode 100644 index 0000000..c9b2f6d --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp @@ -0,0 +1,187 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Aaron VonderHaar + email : avh4@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "generalencapsulatedobjectframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate +{ +public: + GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {} + + String::Type textEncoding; + String mimeType; + String fileName; + String description; + ByteVector data; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : + Frame("GEOB"), + d(new GeneralEncapsulatedObjectFramePrivate()) +{ +} + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : + Frame(data), + d(new GeneralEncapsulatedObjectFramePrivate()) +{ + setData(data); +} + +GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() +{ + delete d; +} + +String GeneralEncapsulatedObjectFrame::toString() const +{ + String text = "[" + d->mimeType + "]"; + + if(!d->fileName.isEmpty()) + text += " " + d->fileName; + + if(!d->description.isEmpty()) + text += " \"" + d->description + "\""; + + return text; +} + +String::Type GeneralEncapsulatedObjectFrame::textEncoding() const +{ + return d->textEncoding; +} + +void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +String GeneralEncapsulatedObjectFrame::mimeType() const +{ + return d->mimeType; +} + +void GeneralEncapsulatedObjectFrame::setMimeType(const String &type) +{ + d->mimeType = type; +} + +String GeneralEncapsulatedObjectFrame::fileName() const +{ + return d->fileName; +} + +void GeneralEncapsulatedObjectFrame::setFileName(const String &name) +{ + d->fileName = name; +} + +String GeneralEncapsulatedObjectFrame::description() const +{ + return d->description; +} + +void GeneralEncapsulatedObjectFrame::setDescription(const String &desc) +{ + d->description = desc; +} + +ByteVector GeneralEncapsulatedObjectFrame::object() const +{ + return d->data; +} + +void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) +{ + d->data = data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 4) { + debug("An object frame must contain at least 4 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + + int pos = 1; + + d->mimeType = readStringField(data, String::Latin1, &pos); + d->fileName = readStringField(data, d->textEncoding, &pos); + d->description = readStringField(data, d->textEncoding, &pos); + + d->data = data.mid(pos); +} + +ByteVector GeneralEncapsulatedObjectFrame::renderFields() const +{ + StringList sl; + sl.append(d->fileName); + sl.append(d->description); + + const String::Type encoding = checkTextEncoding(sl, d->textEncoding); + + ByteVector data; + + data.append(char(encoding)); + data.append(d->mimeType.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(d->fileName.data(encoding)); + data.append(textDelimiter(encoding)); + data.append(d->description.data(encoding)); + data.append(textDelimiter(encoding)); + data.append(d->data); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new GeneralEncapsulatedObjectFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.h b/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.h new file mode 100644 index 0000000..769dfb0 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/generalencapsulatedobjectframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Aaron VonderHaar + email : avh4@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_GENERALENCAPSULATEDOBJECT_H +#define TAGLIB_GENERALENCAPSULATEDOBJECT_H + +#include "id3v2frame.h" +#include "id3v2header.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 general encapsulated object frame implementation + + /*! + * This is an implementation of ID3v2 general encapsulated objects. + * Arbitrary binary data may be included in tags, stored in GEOB frames. + * There may be multiple GEOB frames in a single tag. Each GEOB it + * labelled with a content description (which may be blank), a required + * mime-type, and a file name (may be blank). The content description + * uniquely identifies the GEOB frame in the tag. + */ + + class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Constructs an empty object frame. The description, file name and text + * encoding should be set manually. + */ + GeneralEncapsulatedObjectFrame(); + + /*! + * Constructs a GeneralEncapsulatedObjectFrame frame based on \a data. + * + * \warning This is \em not data for the encapsulated object, for that use + * setObject(). This constructor is used when reading the frame from the + * disk. + */ + explicit GeneralEncapsulatedObjectFrame(const ByteVector &data); + + /*! + * Destroys the GeneralEncapsulatedObjectFrame instance. + */ + virtual ~GeneralEncapsulatedObjectFrame(); + + /*! + * Returns a string containing the description, file name and mime-type + */ + virtual String toString() const; + + /*! + * Returns the text encoding used for the description and file name. + * + * \see setTextEncoding() + * \see description() + * \see fileName() + */ + String::Type textEncoding() const; + + /*! + * Set the text encoding used for the description and file name. + * + * \see description() + * \see fileName() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the mime type of the object. + */ + String mimeType() const; + + /*! + * Sets the mime type of the object. + */ + void setMimeType(const String &type); + + /*! + * Returns the file name of the object. + * + * \see setFileName() + */ + String fileName() const; + + /*! + * Sets the file name for the object. + * + * \see fileName() + */ + void setFileName(const String &name); + + /*! + * Returns the content description of the object. + * + * \see setDescription() + * \see textEncoding() + * \see setTextEncoding() + */ + + String description() const; + + /*! + * Sets the content description of the object to \a desc. + * + * \see description() + * \see textEncoding() + * \see setTextEncoding() + */ + + void setDescription(const String &desc); + + /*! + * Returns the object data as a ByteVector. + * + * \note ByteVector has a data() method that returns a const char * which + * should make it easy to export this data to external programs. + * + * \see setObject() + * \see mimeType() + */ + ByteVector object() const; + + /*! + * Sets the object data to \a data. \a data should be of the type specified in + * this frame's mime-type specification. + * + * \see object() + * \see mimeType() + * \see setMimeType() + */ + void setObject(const ByteVector &object); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h); + GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &); + GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &); + + class GeneralEncapsulatedObjectFramePrivate; + GeneralEncapsulatedObjectFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/ownershipframe.cpp b/external/taglib/source/mpeg/id3v2/frames/ownershipframe.cpp new file mode 100644 index 0000000..132f5f2 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/ownershipframe.cpp @@ -0,0 +1,176 @@ +/*************************************************************************** + copyright : (C) 2012 by Rupert Daniel + email : rupert@cancelmonday.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "ownershipframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class OwnershipFrame::OwnershipFramePrivate +{ +public: + String pricePaid; + String datePurchased; + String seller; + String::Type textEncoding; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +OwnershipFrame::OwnershipFrame(String::Type encoding) : + Frame("OWNE"), + d(new OwnershipFramePrivate()) +{ + d->textEncoding = encoding; +} + +OwnershipFrame::OwnershipFrame(const ByteVector &data) : + Frame(data), + d(new OwnershipFramePrivate()) +{ + setData(data); +} + +OwnershipFrame::~OwnershipFrame() +{ + delete d; +} + +String OwnershipFrame::toString() const +{ + return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller; +} + +String OwnershipFrame::pricePaid() const +{ + return d->pricePaid; +} + +void OwnershipFrame::setPricePaid(const String &s) +{ + d->pricePaid = s; +} + +String OwnershipFrame::datePurchased() const +{ + return d->datePurchased; +} + +void OwnershipFrame::setDatePurchased(const String &s) +{ + d->datePurchased = s; +} + +String OwnershipFrame::seller() const +{ + return d->seller; +} + +void OwnershipFrame::setSeller(const String &s) +{ + d->seller = s; +} + +String::Type OwnershipFrame::textEncoding() const +{ + return d->textEncoding; +} + +void OwnershipFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void OwnershipFrame::parseFields(const ByteVector &data) +{ + int pos = 0; + + // Need at least 1 byte for the encoding + if(data.isEmpty()) { + return; + } + + // Get the text encoding + d->textEncoding = String::Type(data[0]); + pos += 1; + + // Read the price paid this is a null terminate string + d->pricePaid = readStringField(data, String::Latin1, &pos); + + // If we don't have at least 8 bytes left then don't parse the rest of the + // data + if(data.size() - pos < 8) { + return; + } + + // Read the date purchased YYYYMMDD + d->datePurchased = String(data.mid(pos, 8)); + pos += 8; + + // Read the seller + if(d->textEncoding == String::Latin1) + d->seller = Tag::latin1StringHandler()->parse(data.mid(pos)); + else + d->seller = String(data.mid(pos), d->textEncoding); +} + +ByteVector OwnershipFrame::renderFields() const +{ + StringList sl; + sl.append(d->seller); + + const String::Type encoding = checkTextEncoding(sl, d->textEncoding); + + ByteVector v; + + v.append(char(encoding)); + v.append(d->pricePaid.data(String::Latin1)); + v.append(textDelimiter(String::Latin1)); + v.append(d->datePurchased.data(String::Latin1)); + v.append(d->seller.data(encoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new OwnershipFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/ownershipframe.h b/external/taglib/source/mpeg/id3v2/frames/ownershipframe.h new file mode 100644 index 0000000..06a1e23 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/ownershipframe.h @@ -0,0 +1,151 @@ +/*************************************************************************** + copyright : (C) 2012 by Rupert Daniel + email : rupert@cancelmonday.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OWNERSHIPFRAME_H +#define TAGLIB_OWNERSHIPFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 "ownership" + + /*! + * This implements the ID3v2 ownership (OWNE frame). It consists of + * a price paid, a date purchased (YYYYMMDD) and the name of the seller. + */ + + class TAGLIB_EXPORT OwnershipFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty ownership frame. + */ + explicit OwnershipFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a ownership based on the data in \a data. + */ + explicit OwnershipFrame(const ByteVector &data); + + /*! + * Destroys this OwnershipFrame instance. + */ + virtual ~OwnershipFrame(); + + /*! + * Returns the text of this popularimeter. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the date purchased. + * + * \see setDatePurchased() + */ + String datePurchased() const; + + /*! + * Set the date purchased. + * + * \see datePurchased() + */ + void setDatePurchased(const String &datePurchased); + + /*! + * Returns the price paid. + * + * \see setPricePaid() + */ + String pricePaid() const; + + /*! + * Set the price paid. + * + * \see pricePaid() + */ + void setPricePaid(const String &pricePaid); + + /*! + * Returns the seller. + * + * \see setSeller() + */ + String seller() const; + + /*! + * Set the seller. + * + * \see seller() + */ + void setSeller(const String &seller); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + OwnershipFrame(const ByteVector &data, Header *h); + OwnershipFrame(const OwnershipFrame &); + OwnershipFrame &operator=(const OwnershipFrame &); + + class OwnershipFramePrivate; + OwnershipFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/podcastframe.cpp b/external/taglib/source/mpeg/id3v2/frames/podcastframe.cpp new file mode 100644 index 0000000..7dfe471 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/podcastframe.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2015 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "podcastframe.h" +#include + +using namespace TagLib; +using namespace ID3v2; + +class PodcastFrame::PodcastFramePrivate +{ +public: + ByteVector fieldData; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +PodcastFrame::PodcastFrame() : + Frame("PCST"), + d(new PodcastFramePrivate()) +{ + d->fieldData = ByteVector(4, '\0'); +} + +PodcastFrame::~PodcastFrame() +{ + delete d; +} + +String PodcastFrame::toString() const +{ + return String(); +} + +PropertyMap PodcastFrame::asProperties() const +{ + PropertyMap map; + map.insert("PODCAST", StringList()); + return map; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void PodcastFrame::parseFields(const ByteVector &data) +{ + d->fieldData = data; +} + +ByteVector PodcastFrame::renderFields() const +{ + return d->fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new PodcastFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/podcastframe.h b/external/taglib/source/mpeg/id3v2/frames/podcastframe.h new file mode 100644 index 0000000..a71278c --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/podcastframe.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2015 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PODCASTFRAME_H +#define TAGLIB_PODCASTFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 podcast frame + /*! + * An implementation of ID3v2 podcast flag, a frame with four zero bytes. + */ + class TAGLIB_EXPORT PodcastFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct a podcast frame. + */ + PodcastFrame(); + + /*! + * Destroys this PodcastFrame instance. + */ + virtual ~PodcastFrame(); + + /*! + * Returns a null string. + */ + virtual String toString() const; + + PropertyMap asProperties() const; + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PodcastFrame(const ByteVector &data, Header *h); + PodcastFrame(const PodcastFrame &); + PodcastFrame &operator=(const PodcastFrame &); + + class PodcastFramePrivate; + PodcastFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.cpp b/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.cpp new file mode 100644 index 0000000..b33067d --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + copyright : (C) 2008 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "popularimeterframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class PopularimeterFrame::PopularimeterFramePrivate +{ +public: + PopularimeterFramePrivate() : rating(0), counter(0) {} + String email; + int rating; + unsigned int counter; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +PopularimeterFrame::PopularimeterFrame() : + Frame("POPM"), + d(new PopularimeterFramePrivate()) +{ +} + +PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : + Frame(data), + d(new PopularimeterFramePrivate()) +{ + setData(data); +} + +PopularimeterFrame::~PopularimeterFrame() +{ + delete d; +} + +String PopularimeterFrame::toString() const +{ + return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter); +} + +String PopularimeterFrame::email() const +{ + return d->email; +} + +void PopularimeterFrame::setEmail(const String &s) +{ + d->email = s; +} + +int PopularimeterFrame::rating() const +{ + return d->rating; +} + +void PopularimeterFrame::setRating(int s) +{ + d->rating = s; +} + +unsigned int PopularimeterFrame::counter() const +{ + return d->counter; +} + +void PopularimeterFrame::setCounter(unsigned int s) +{ + d->counter = s; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void PopularimeterFrame::parseFields(const ByteVector &data) +{ + int pos = 0, size = int(data.size()); + + d->email = readStringField(data, String::Latin1, &pos); + + d->rating = 0; + d->counter = 0; + if(pos < size) { + d->rating = static_cast(data[pos++]); + if(pos < size) { + d->counter = data.toUInt(static_cast(pos)); + } + } +} + +ByteVector PopularimeterFrame::renderFields() const +{ + ByteVector data; + + data.append(d->email.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + data.append(char(d->rating)); + data.append(ByteVector::fromUInt(d->counter)); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new PopularimeterFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.h b/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.h new file mode 100644 index 0000000..405ca69 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/popularimeterframe.h @@ -0,0 +1,132 @@ +/*************************************************************************** + copyright : (C) 2008 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_POPULARIMETERFRAME_H +#define TAGLIB_POPULARIMETERFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 "popularimeter" + + /*! + * This implements the ID3v2 popularimeter (POPM frame). It consists of + * an email, a rating and an optional counter. + */ + + class TAGLIB_EXPORT PopularimeterFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty popularimeter frame. + */ + explicit PopularimeterFrame(); + + /*! + * Construct a popularimeter based on the data in \a data. + */ + explicit PopularimeterFrame(const ByteVector &data); + + /*! + * Destroys this PopularimeterFrame instance. + */ + virtual ~PopularimeterFrame(); + + /*! + * Returns the text of this popularimeter. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the email. + * + * \see setEmail() + */ + String email() const; + + /*! + * Set the email. + * + * \see email() + */ + void setEmail(const String &email); + + /*! + * Returns the rating. + * + * \see setRating() + */ + int rating() const; + + /*! + * Set the rating. + * + * \see rating() + */ + void setRating(int rating); + + /*! + * Returns the counter. + * + * \see setCounter() + */ + unsigned int counter() const; + + /*! + * Set the counter. + * + * \see counter() + */ + void setCounter(unsigned int counter); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PopularimeterFrame(const ByteVector &data, Header *h); + PopularimeterFrame(const PopularimeterFrame &); + PopularimeterFrame &operator=(const PopularimeterFrame &); + + class PopularimeterFramePrivate; + PopularimeterFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/privateframe.cpp b/external/taglib/source/mpeg/id3v2/frames/privateframe.cpp new file mode 100644 index 0000000..4f55a3c --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/privateframe.cpp @@ -0,0 +1,131 @@ +/*************************************************************************** + copyright : (C) 2008 by Serkan Kalyoncu + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "privateframe.h" + +using namespace TagLib; +using namespace ID3v2; + + +class PrivateFrame::PrivateFramePrivate +{ +public: + ByteVector data; + String owner; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +PrivateFrame::PrivateFrame() : + Frame("PRIV"), + d(new PrivateFramePrivate()) +{ +} + +PrivateFrame::PrivateFrame(const ByteVector &data) : + Frame(data), + d(new PrivateFramePrivate()) +{ + Frame::setData(data); +} + +PrivateFrame::~PrivateFrame() +{ + delete d; +} + +String PrivateFrame::toString() const +{ + return d->owner; +} + +String PrivateFrame::owner() const +{ + return d->owner; +} + +ByteVector PrivateFrame::data() const +{ + return d->data; +} + +void PrivateFrame::setOwner(const String &s) +{ + d->owner = s; +} + +void PrivateFrame::setData(const ByteVector & data) +{ + d->data = data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void PrivateFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 2) { + debug("A private frame must contain at least 2 bytes."); + return; + } + + // Owner identifier is assumed to be Latin1 + + const int byteAlign = 1; + const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign); + + d->owner = String(data.mid(0, endOfOwner)); + d->data = data.mid(endOfOwner + 1); +} + +ByteVector PrivateFrame::renderFields() const +{ + ByteVector v; + + v.append(d->owner.data(String::Latin1)); + v.append(textDelimiter(String::Latin1)); + v.append(d->data); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new PrivateFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/privateframe.h b/external/taglib/source/mpeg/id3v2/frames/privateframe.h new file mode 100644 index 0000000..06f82f3 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/privateframe.h @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2008 by Serkan Kalyoncu + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PRIVATEFRAME_H +#define TAGLIB_PRIVATEFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 privateframe + + class TAGLIB_EXPORT PrivateFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty private frame. + */ + PrivateFrame(); + + /*! + * Construct a private frame based on the data in \a data. + * + * \note This is the constructor used when parsing the frame from a file. + */ + explicit PrivateFrame(const ByteVector &data); + + /*! + * Destroys this private frame instance. + */ + virtual ~PrivateFrame(); + + /*! + * Returns the text of this private frame, currently just the owner. + * + * \see text() + */ + virtual String toString() const; + + /*! + * \return The owner of the private frame. + * \note This should contain an email address or link to a website. + */ + String owner() const; + + /*! + * + */ + ByteVector data() const; + + /*! + * Sets the owner of the frame to \a s. + * \note This should contain an email address or link to a website. + */ + void setOwner(const String &s); + + /*! + * + */ + void setData(const ByteVector &v); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + PrivateFrame(const ByteVector &data, Header *h); + + PrivateFrame(const PrivateFrame &); + PrivateFrame &operator=(const PrivateFrame &); + + class PrivateFramePrivate; + PrivateFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.cpp b/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.cpp new file mode 100644 index 0000000..c0817cb --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.cpp @@ -0,0 +1,233 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "relativevolumeframe.h" + +using namespace TagLib; +using namespace ID3v2; + +struct ChannelData +{ + ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {} + + RelativeVolumeFrame::ChannelType channelType; + short volumeAdjustment; + RelativeVolumeFrame::PeakVolume peakVolume; +}; + +class RelativeVolumeFrame::RelativeVolumeFramePrivate +{ +public: + String identification; + Map channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RelativeVolumeFrame::RelativeVolumeFrame() : + Frame("RVA2"), + d(new RelativeVolumeFramePrivate()) +{ +} + +RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : + Frame(data), + d(new RelativeVolumeFramePrivate()) +{ + setData(data); +} + +RelativeVolumeFrame::~RelativeVolumeFrame() +{ + delete d; +} + +String RelativeVolumeFrame::toString() const +{ + return d->identification; +} + +List RelativeVolumeFrame::channels() const +{ + List l; + + Map::ConstIterator it = d->channels.begin(); + for(; it != d->channels.end(); ++it) + l.append((*it).first); + + return l; +} + +// deprecated + +RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const +{ + return MasterVolume; +} + +// deprecated + +void RelativeVolumeFrame::setChannelType(ChannelType) +{ + +} + +short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const +{ + return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0; +} + +short RelativeVolumeFrame::volumeAdjustmentIndex() const +{ + return volumeAdjustmentIndex(MasterVolume); +} + +void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type) +{ + d->channels[type].volumeAdjustment = index; +} + +void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index) +{ + setVolumeAdjustmentIndex(index, MasterVolume); +} + +float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const +{ + return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0; +} + +float RelativeVolumeFrame::volumeAdjustment() const +{ + return volumeAdjustment(MasterVolume); +} + +void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type) +{ + d->channels[type].volumeAdjustment = short(adjustment * float(512)); +} + +void RelativeVolumeFrame::setVolumeAdjustment(float adjustment) +{ + setVolumeAdjustment(adjustment, MasterVolume); +} + +RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const +{ + return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume(); +} + +RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const +{ + return peakVolume(MasterVolume); +} + +void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type) +{ + d->channels[type].peakVolume = peak; +} + +void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak) +{ + setPeakVolume(peak, MasterVolume); +} + +String RelativeVolumeFrame::identification() const +{ + return d->identification; +} + +void RelativeVolumeFrame::setIdentification(const String &s) +{ + d->identification = s; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void RelativeVolumeFrame::parseFields(const ByteVector &data) +{ + int pos = 0; + d->identification = readStringField(data, String::Latin1, &pos); + + // Each channel is at least 4 bytes. + + while(pos <= static_cast(data.size()) - 4) { + + ChannelType type = ChannelType(data[pos]); + pos += 1; + + ChannelData &channel = d->channels[type]; + + channel.volumeAdjustment = data.toShort(static_cast(pos)); + pos += 2; + + channel.peakVolume.bitsRepresentingPeak = data[pos]; + pos += 1; + + const int bytes = (channel.peakVolume.bitsRepresentingPeak + 7) / 8; + channel.peakVolume.peakVolume = data.mid(pos, bytes); + pos += bytes; + } +} + +ByteVector RelativeVolumeFrame::renderFields() const +{ + ByteVector data; + + data.append(d->identification.data(String::Latin1)); + data.append(textDelimiter(String::Latin1)); + + Map::ConstIterator it = d->channels.begin(); + + for(; it != d->channels.end(); ++it) { + ChannelType type = (*it).first; + const ChannelData &channel = (*it).second; + + data.append(char(type)); + data.append(ByteVector::fromShort(channel.volumeAdjustment)); + data.append(char(channel.peakVolume.bitsRepresentingPeak)); + data.append(channel.peakVolume.peakVolume); + } + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new RelativeVolumeFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.h b/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.h new file mode 100644 index 0000000..55f13fc --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/relativevolumeframe.h @@ -0,0 +1,274 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RELATIVEVOLUMEFRAME_H +#define TAGLIB_RELATIVEVOLUMEFRAME_H + +#include "tlist.h" +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An ID3v2 relative volume adjustment frame implementation + + /*! + * This is an implementation of ID3v2 relative volume adjustment. The + * presence of this frame makes it possible to specify an increase in volume + * for an audio file or specific audio tracks in that file. + * + * Multiple relative volume adjustment frames may be present in the tag + * each with a unique identification and describing volume adjustment for + * different channel types. + */ + + class TAGLIB_EXPORT RelativeVolumeFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * This indicates the type of volume adjustment that should be applied. + */ + enum ChannelType { + //! A type not enumerated below + Other = 0x00, + //! The master volume for the track + MasterVolume = 0x01, + //! The front right audio channel + FrontRight = 0x02, + //! The front left audio channel + FrontLeft = 0x03, + //! The back right audio channel + BackRight = 0x04, + //! The back left audio channel + BackLeft = 0x05, + //! The front center audio channel + FrontCentre = 0x06, + //! The back center audio channel + BackCentre = 0x07, + //! The subwoofer audio channel + Subwoofer = 0x08 + }; + + //! Struct that stores the relevant values for ID3v2 peak volume + + /*! + * The peak volume is described as a series of bits that is padded to fill + * a block of bytes. These two values should always be updated in tandem. + */ + struct PeakVolume + { + /*! + * Constructs an empty peak volume description. + */ + PeakVolume() : bitsRepresentingPeak(0) {} + /*! + * The number of bits (in the range of 0 to 255) used to describe the + * peak volume. + */ + unsigned char bitsRepresentingPeak; + /*! + * The array of bits (represented as a series of bytes) used to describe + * the peak volume. + */ + ByteVector peakVolume; + }; + + /*! + * Constructs a RelativeVolumeFrame. The relevant data should be set + * manually. + */ + RelativeVolumeFrame(); + + /*! + * Constructs a RelativeVolumeFrame based on the contents of \a data. + */ + RelativeVolumeFrame(const ByteVector &data); + + /*! + * Destroys the RelativeVolumeFrame instance. + */ + virtual ~RelativeVolumeFrame(); + + /*! + * Returns the frame's identification. + * + * \see identification() + */ + virtual String toString() const; + + /*! + * Returns a list of channels with information currently in the frame. + */ + List channels() const; + + /*! + * \deprecated Always returns master volume. + */ + TAGLIB_DEPRECATED ChannelType channelType() const; + + /*! + * \deprecated This method no longer has any effect. + */ + TAGLIB_DEPRECATED void setChannelType(ChannelType t); + + /* + * There was a terrible API goof here, and while this can't be changed to + * the way it appears below for binary compatibility reasons, let's at + * least pretend that it looks clean. + */ + +#ifdef DOXYGEN + + /*! + * Returns the relative volume adjustment "index". As indicated by the + * ID3v2 standard this is a 16-bit signed integer that reflects the + * decibels of adjustment when divided by 512. + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustmentIndex() + * \see volumeAdjustment() + */ + short volumeAdjustmentIndex(ChannelType type = MasterVolume) const; + + /*! + * Set the volume adjustment to \a index. As indicated by the ID3v2 + * standard this is a 16-bit signed integer that reflects the decibels of + * adjustment when divided by 512. + * + * By default this sets the value for the master volume. + * + * \see volumeAdjustmentIndex() + * \see setVolumeAdjustment() + */ + void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume); + + /*! + * Returns the relative volume adjustment in decibels. + * + * \note Because this is actually stored internally as an "index" to this + * value the value returned by this method may not be identical to the + * value set using setVolumeAdjustment(). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + float volumeAdjustment(ChannelType type = MasterVolume) const; + + /*! + * Set the relative volume adjustment in decibels to \a adjustment. + * + * By default this sets the value for the master volume. + * + * \note Because this is actually stored internally as an "index" to this + * value the value set by this method may not be identical to the one + * returned by volumeAdjustment(). + * + * \see setVolumeAdjustment() + * \see volumeAdjustmentIndex() + */ + void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume); + + /*! + * Returns the peak volume (represented as a length and a string of bits). + * + * This defaults to returning the value for the master volume channel if + * available and returns 0 if the specified channel does not exist. + * + * \see setPeakVolume() + */ + PeakVolume peakVolume(ChannelType type = MasterVolume) const; + + /*! + * Sets the peak volume to \a peak. + * + * By default this sets the value for the master volume. + * + * \see peakVolume() + */ + void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume); + +#else + + // BIC: Combine each of the following pairs of functions (or maybe just + // rework this junk altogether). + + short volumeAdjustmentIndex(ChannelType type) const; + short volumeAdjustmentIndex() const; + + void setVolumeAdjustmentIndex(short index, ChannelType type); + void setVolumeAdjustmentIndex(short index); + + float volumeAdjustment(ChannelType type) const; + float volumeAdjustment() const; + + void setVolumeAdjustment(float adjustment, ChannelType type); + void setVolumeAdjustment(float adjustment); + + PeakVolume peakVolume(ChannelType type) const; + PeakVolume peakVolume() const; + + void setPeakVolume(const PeakVolume &peak, ChannelType type); + void setPeakVolume(const PeakVolume &peak); + +#endif + + /*! + * Returns the identification for this frame. + */ + String identification() const; + + /*! + * Sets the identification of the frame to \a s. The string + * is used to identify the situation and/or device where this + * adjustment should apply. + */ + void setIdentification(const String &s); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + RelativeVolumeFrame(const ByteVector &data, Header *h); + RelativeVolumeFrame(const RelativeVolumeFrame &); + RelativeVolumeFrame &operator=(const RelativeVolumeFrame &); + + class RelativeVolumeFramePrivate; + RelativeVolumeFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.cpp b/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.cpp new file mode 100644 index 0000000..6a62bb4 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.cpp @@ -0,0 +1,242 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "synchronizedlyricsframe.h" +#include +#include +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate +{ +public: + SynchronizedLyricsFramePrivate() : + textEncoding(String::Latin1), + timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds), + type(SynchronizedLyricsFrame::Lyrics) {} + String::Type textEncoding; + ByteVector language; + SynchronizedLyricsFrame::TimestampFormat timestampFormat; + SynchronizedLyricsFrame::Type type; + String description; + SynchronizedLyricsFrame::SynchedTextList synchedText; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) : + Frame("SYLT"), + d(new SynchronizedLyricsFramePrivate()) +{ + d->textEncoding = encoding; +} + +SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) : + Frame(data), + d(new SynchronizedLyricsFramePrivate()) +{ + setData(data); +} + +SynchronizedLyricsFrame::~SynchronizedLyricsFrame() +{ + delete d; +} + +String SynchronizedLyricsFrame::toString() const +{ + return d->description; +} + +String::Type SynchronizedLyricsFrame::textEncoding() const +{ + return d->textEncoding; +} + +ByteVector SynchronizedLyricsFrame::language() const +{ + return d->language; +} + +SynchronizedLyricsFrame::TimestampFormat +SynchronizedLyricsFrame::timestampFormat() const +{ + return d->timestampFormat; +} + +SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const +{ + return d->type; +} + +String SynchronizedLyricsFrame::description() const +{ + return d->description; +} + +SynchronizedLyricsFrame::SynchedTextList +SynchronizedLyricsFrame::synchedText() const +{ + return d->synchedText; +} + +void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f) +{ + d->timestampFormat = f; +} + +void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t) +{ + d->type = t; +} + +void SynchronizedLyricsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void SynchronizedLyricsFrame::setSynchedText( + const SynchronizedLyricsFrame::SynchedTextList &t) +{ + d->synchedText = t; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void SynchronizedLyricsFrame::parseFields(const ByteVector &data) +{ + const int end = data.size(); + if(end < 7) { + debug("A synchronized lyrics frame must contain at least 7 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + d->language = data.mid(1, 3); + d->timestampFormat = TimestampFormat(data[4]); + d->type = Type(data[5]); + + int pos = 6; + + d->description = readStringField(data, d->textEncoding, &pos); + if(pos == 6) + return; + + /* + * If UTF16 strings are found in SYLT frames, a BOM may only be + * present in the first string (content descriptor), and the strings of + * the synchronized text have no BOM. Here the BOM is read from + * the first string to have a specific encoding with endianness for the + * case of strings without BOM so that readStringField() will work. + */ + String::Type encWithEndianness = d->textEncoding; + if(d->textEncoding == String::UTF16) { + unsigned short bom = data.toUShort(6, true); + if(bom == 0xfffe) { + encWithEndianness = String::UTF16LE; + } else if(bom == 0xfeff) { + encWithEndianness = String::UTF16BE; + } + } + + d->synchedText.clear(); + while(pos < end) { + String::Type enc = d->textEncoding; + // If a UTF16 string has no BOM, use the encoding found above. + if(enc == String::UTF16 && pos + 1 < end) { + unsigned short bom = data.toUShort(pos, true); + if(bom != 0xfffe && bom != 0xfeff) { + enc = encWithEndianness; + } + } + String text = readStringField(data, enc, &pos); + if(pos + 4 > end) + return; + + unsigned int time = data.toUInt(pos, true); + pos += 4; + + d->synchedText.append(SynchedText(time, text)); + } +} + +ByteVector SynchronizedLyricsFrame::renderFields() const +{ + ByteVector v; + + String::Type encoding = d->textEncoding; + + encoding = checkTextEncoding(d->description, encoding); + for(SynchedTextList::ConstIterator it = d->synchedText.begin(); + it != d->synchedText.end(); + ++it) { + encoding = checkTextEncoding(it->text, encoding); + } + + v.append(char(encoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(char(d->timestampFormat)); + v.append(char(d->type)); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + for(SynchedTextList::ConstIterator it = d->synchedText.begin(); + it != d->synchedText.end(); + ++it) { + const SynchedText &entry = *it; + v.append(entry.text.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(ByteVector::fromUInt(entry.time)); + } + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new SynchronizedLyricsFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.h b/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.h new file mode 100644 index 0000000..f520c59 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/synchronizedlyricsframe.h @@ -0,0 +1,231 @@ +/*************************************************************************** + copyright : (C) 2014 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_SYNCHRONIZEDLYRICSFRAME_H + +#include "id3v2frame.h" +#include "tlist.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 synchronized lyrics frame + /*! + * An implementation of ID3v2 synchronized lyrics. + */ + class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + + /*! + * Specifies the timestamp format used. + */ + enum TimestampFormat { + //! The timestamp is of unknown format. + Unknown = 0x00, + //! The timestamp represents the number of MPEG frames since + //! the beginning of the audio stream. + AbsoluteMpegFrames = 0x01, + //! The timestamp represents the number of milliseconds since + //! the beginning of the audio stream. + AbsoluteMilliseconds = 0x02 + }; + + /*! + * Specifies the type of text contained. + */ + enum Type { + //! The text is some other type of text. + Other = 0x00, + //! The text contains lyrical data. + Lyrics = 0x01, + //! The text contains a transcription. + TextTranscription = 0x02, + //! The text lists the movements in the piece. + Movement = 0x03, + //! The text describes events that occur. + Events = 0x04, + //! The text contains chord changes that occur in the music. + Chord = 0x05, + //! The text contains trivia or "pop up" information about the media. + Trivia = 0x06, + //! The text contains URLs for relevant webpages. + WebpageUrls = 0x07, + //! The text contains URLs for relevant images. + ImageUrls = 0x08 + }; + + /*! + * Single entry of time stamp and lyrics text. + */ + struct SynchedText { + SynchedText(unsigned int ms, String str) : time(ms), text(str) {} + unsigned int time; + String text; + }; + + /*! + * List of synchronized lyrics. + */ + typedef TagLib::List SynchedTextList; + + /*! + * Construct an empty synchronized lyrics frame that will use the text + * encoding \a encoding. + */ + explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a synchronized lyrics frame based on the data in \a data. + */ + explicit SynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this SynchronizedLyricsFrame instance. + */ + virtual ~SynchronizedLyricsFrame(); + + /*! + * Returns the description of this synchronized lyrics frame. + * + * \see description() + */ + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the timestamp format. + */ + TimestampFormat timestampFormat() const; + + /*! + * Returns the type of text contained. + */ + Type type() const; + + /*! + * Returns the description of this synchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text with the time stamps. + */ + SynchedTextList synchedText() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Set the timestamp format. + * + * \see timestampFormat() + */ + void setTimestampFormat(TimestampFormat f); + + /*! + * Set the type of text contained. + * + * \see type() + */ + void setType(Type t); + + /*! + * Sets the description of the synchronized lyrics frame to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text with the time stamps. + * + * \see text() + */ + void setSynchedText(const SynchedTextList &t); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + SynchronizedLyricsFrame(const ByteVector &data, Header *h); + SynchronizedLyricsFrame(const SynchronizedLyricsFrame &); + SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &); + + class SynchronizedLyricsFramePrivate; + SynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.cpp b/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.cpp new file mode 100644 index 0000000..9061a9b --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.cpp @@ -0,0 +1,362 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "tableofcontentsframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class TableOfContentsFrame::TableOfContentsFramePrivate +{ +public: + TableOfContentsFramePrivate() : + tagHeader(0), + isTopLevel(false), + isOrdered(false) + { + embeddedFrameList.setAutoDelete(true); + } + + const ID3v2::Header *tagHeader; + ByteVector elementID; + bool isTopLevel; + bool isOrdered; + ByteVectorList childElements; + FrameListMap embeddedFrameListMap; + FrameList embeddedFrameList; +}; + +namespace { + + // These functions are needed to try to aim for backward compatibility with + // an API that previously (unreasonably) required null bytes to be appended + // at the end of identifiers explicitly by the API user. + + // BIC: remove these + + ByteVector &strip(ByteVector &b) + { + if(b.endsWith('\0')) + b.resize(b.size() - 1); + return b; + } + + ByteVectorList &strip(ByteVectorList &l) + { + for(ByteVectorList::Iterator it = l.begin(); it != l.end(); ++it) + { + strip(*it); + } + return l; + } +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : + ID3v2::Frame(data), + d(new TableOfContentsFramePrivate()) +{ + d->tagHeader = tagHeader; + setData(data); +} + +TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID, + const ByteVectorList &children, + const FrameList &embeddedFrames) : + ID3v2::Frame("CTOC"), + d(new TableOfContentsFramePrivate()) +{ + d->elementID = elementID; + strip(d->elementID); + d->childElements = children; + + for(FrameList::ConstIterator it = embeddedFrames.begin(); it != embeddedFrames.end(); ++it) + addEmbeddedFrame(*it); +} + +TableOfContentsFrame::~TableOfContentsFrame() +{ + delete d; +} + +ByteVector TableOfContentsFrame::elementID() const +{ + return d->elementID; +} + +bool TableOfContentsFrame::isTopLevel() const +{ + return d->isTopLevel; +} + +bool TableOfContentsFrame::isOrdered() const +{ + return d->isOrdered; +} + +unsigned int TableOfContentsFrame::entryCount() const +{ + return d->childElements.size(); +} + +ByteVectorList TableOfContentsFrame::childElements() const +{ + return d->childElements; +} + +void TableOfContentsFrame::setElementID(const ByteVector &eID) +{ + d->elementID = eID; + strip(d->elementID); +} + +void TableOfContentsFrame::setIsTopLevel(const bool &t) +{ + d->isTopLevel = t; +} + +void TableOfContentsFrame::setIsOrdered(const bool &o) +{ + d->isOrdered = o; +} + +void TableOfContentsFrame::setChildElements(const ByteVectorList &l) +{ + d->childElements = l; + strip(d->childElements); +} + +void TableOfContentsFrame::addChildElement(const ByteVector &cE) +{ + d->childElements.append(cE); + strip(d->childElements); +} + +void TableOfContentsFrame::removeChildElement(const ByteVector &cE) +{ + ByteVectorList::Iterator it = d->childElements.find(cE); + + if(it == d->childElements.end()) + it = d->childElements.find(cE + ByteVector("\0")); + + if(it != d->childElements.end()) + d->childElements.erase(it); +} + +const FrameListMap &TableOfContentsFrame::embeddedFrameListMap() const +{ + return d->embeddedFrameListMap; +} + +const FrameList &TableOfContentsFrame::embeddedFrameList() const +{ + return d->embeddedFrameList; +} + +const FrameList &TableOfContentsFrame::embeddedFrameList(const ByteVector &frameID) const +{ + return d->embeddedFrameListMap[frameID]; +} + +void TableOfContentsFrame::addEmbeddedFrame(Frame *frame) +{ + d->embeddedFrameList.append(frame); + d->embeddedFrameListMap[frame->frameID()].append(frame); +} + +void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) +{ + // remove the frame from the frame list + FrameList::Iterator it = d->embeddedFrameList.find(frame); + if(it != d->embeddedFrameList.end()) + d->embeddedFrameList.erase(it); + + // ...and from the frame list map + FrameList &mappedList = d->embeddedFrameListMap[frame->frameID()]; + it = mappedList.find(frame); + if(it != mappedList.end()) + mappedList.erase(it); + + // ...and delete as desired + if(del) + delete frame; +} + +void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id) +{ + FrameList l = d->embeddedFrameListMap[id]; + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) + removeEmbeddedFrame(*it, true); +} + +String TableOfContentsFrame::toString() const +{ + String s = String(d->elementID) + + ": top level: " + (d->isTopLevel ? "true" : "false") + + ", ordered: " + (d->isOrdered ? "true" : "false"); + + if(!d->childElements.isEmpty()) { + s+= ", chapters: [ " + String(d->childElements.toByteVector(", ")) + " ]"; + } + + if(!d->embeddedFrameList.isEmpty()) { + StringList frameIDs; + for(FrameList::ConstIterator it = d->embeddedFrameList.begin(); + it != d->embeddedFrameList.end(); ++it) + frameIDs.append((*it)->frameID()); + s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]"; + } + + return s; +} + +PropertyMap TableOfContentsFrame::asProperties() const +{ + PropertyMap map; + + map.unsupportedData().append(frameID() + String("/") + d->elementID); + + return map; +} + +TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, + const ByteVector &eID) // static +{ + ID3v2::FrameList tablesOfContents = tag->frameList("CTOC"); + + for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin(); + it != tablesOfContents.end(); + ++it) + { + TableOfContentsFrame *frame = dynamic_cast(*it); + if(frame && frame->elementID() == eID) + return frame; + } + + return 0; +} + +TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) // static +{ + ID3v2::FrameList tablesOfContents = tag->frameList("CTOC"); + + for(ID3v2::FrameList::ConstIterator it = tablesOfContents.begin(); + it != tablesOfContents.end(); + ++it) + { + TableOfContentsFrame *frame = dynamic_cast(*it); + if(frame && frame->isTopLevel()) + return frame; + } + + return 0; +} + +void TableOfContentsFrame::parseFields(const ByteVector &data) +{ + unsigned int size = data.size(); + if(size < 6) { + debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by " + "null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated " + "by null."); + return; + } + + int pos = 0; + unsigned int embPos = 0; + d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1); + d->isTopLevel = (data.at(pos) & 2) != 0; + d->isOrdered = (data.at(pos++) & 1) != 0; + unsigned int entryCount = static_cast(data.at(pos++)); + for(unsigned int i = 0; i < entryCount; i++) { + ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1); + d->childElements.append(childElementID); + } + + size -= pos; + + if(size < header()->size()) + return; + + while(embPos < size - header()->size()) { + Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader); + + if(!frame) + return; + + // Checks to make sure that frame parsed correctly. + if(frame->size() <= 0) { + delete frame; + return; + } + + embPos += frame->size() + header()->size(); + addEmbeddedFrame(frame); + } +} + +ByteVector TableOfContentsFrame::renderFields() const +{ + ByteVector data; + + data.append(d->elementID); + data.append('\0'); + char flags = 0; + if(d->isTopLevel) + flags += 2; + if(d->isOrdered) + flags += 1; + data.append(flags); + data.append(static_cast(entryCount())); + ByteVectorList::ConstIterator it = d->childElements.begin(); + while(it != d->childElements.end()) { + data.append(*it); + data.append('\0'); + it++; + } + FrameList l = d->embeddedFrameList; + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { + (*it)->header()->setVersion(header()->version()); + data.append((*it)->render()); + } + + return data; +} + +TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, + const ByteVector &data, Header *h) : + Frame(h), + d(new TableOfContentsFramePrivate()) +{ + d->tagHeader = tagHeader; + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.h b/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.h new file mode 100644 index 0000000..2e5401e --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/tableofcontentsframe.h @@ -0,0 +1,260 @@ +/*************************************************************************** + copyright : (C) 2013 by Lukas Krejci + email : krejclu6@fel.cvut.cz + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TABLEOFCONTENTSFRAME +#define TAGLIB_TABLEOFCONTENTSFRAME + +#include "id3v2tag.h" +#include "id3v2frame.h" + +#include "tbytevectorlist.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 table of contents frames. Purpose + * of this frame is to allow a table of contents to be defined. + */ + + //! An implementation of ID3v2 table of contents frames + + class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a table of contents frame based on \a data. \a tagHeader is + * required as the internal frames are parsed based on the tag version. + */ + TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data); + + /*! + * Creates a table of contents frame with the element ID \a elementID, + * the child elements \a children and embedded frames, which become owned + * by this frame, in \a embeddedFrames. + */ + TableOfContentsFrame(const ByteVector &elementID, + const ByteVectorList &children = ByteVectorList(), + const FrameList &embeddedFrames = FrameList()); + + /*! + * Destroys the frame. + */ + ~TableOfContentsFrame(); + + /*! + * Returns the elementID of the frame. Element ID + * is a null terminated string, however it's not human-readable. + * + * \see setElementID() + */ + ByteVector elementID() const; + + /*! + * Returns true, if the frame is top-level (doesn't have + * any parent CTOC frame). + * + * \see setIsTopLevel() + */ + bool isTopLevel() const; + + /*! + * Returns true, if the child elements list entries + * are ordered. + * + * \see setIsOrdered() + */ + bool isOrdered() const; + + /*! + * Returns count of child elements of the frame. It always + * corresponds to size of child elements list. + * + * \see childElements() + */ + unsigned int entryCount() const; + + /*! + * Returns list of child elements of the frame. + * + * \see setChildElements() + */ + ByteVectorList childElements() const; + + /*! + * Sets the elementID of the frame to \a eID. If \a eID isn't + * null terminated, a null char is appended automatically. + * + * \see elementID() + */ + void setElementID(const ByteVector &eID); + + /*! + * Sets, if the frame is top-level (doesn't have + * any parent CTOC frame). + * + * \see isTopLevel() + */ + void setIsTopLevel(const bool &t); + + /*! + * Sets, if the child elements list entries + * are ordered. + * + * \see isOrdered() + */ + void setIsOrdered(const bool &o); + + /*! + * Sets list of child elements of the frame to \a l. + * + * \see childElements() + */ + void setChildElements(const ByteVectorList &l); + + /*! + * Adds \a cE to list of child elements of the frame. + * + * \see childElements() + */ + void addChildElement(const ByteVector &cE); + + /*! + * Removes \a cE to list of child elements of the frame. + * + * \see childElements() + */ + void removeChildElement(const ByteVector &cE); + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames embedded in the CTOC frame. + * + * This is the most convenient structure for accessing the CTOC frame's + * embedded frames. Many frame types allow multiple instances of the same + * frame type so this is a map of lists. In most cases however there will + * only be a single frame of a certain type. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + * + * \see embeddedFrameList() + */ + const FrameListMap &embeddedFrameListMap() const; + + /*! + * Returns a reference to the embedded frame list. This is an FrameList + * of all of the frames embedded in the CTOC frame in the order that they + * were parsed. + * + * This can be useful if for example you want iterate over the CTOC frame's + * embedded frames in the order that they occur in the CTOC frame. + * + * \warning You should not modify this data structure directly, instead + * use addEmbeddedFrame() and removeEmbeddedFrame(). + */ + const FrameList &embeddedFrameList() const; + + /*! + * Returns the embedded frame list for frames with the id \a frameID + * or an empty list if there are no embedded frames of that type. This + * is just a convenience and is equivalent to: + * + * \code + * embeddedFrameListMap()[frameID]; + * \endcode + * + * \see embeddedFrameListMap() + */ + const FrameList &embeddedFrameList(const ByteVector &frameID) const; + + /*! + * Add an embedded frame to the CTOC frame. At this point the CTOC frame + * takes ownership of the embedded frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void addEmbeddedFrame(Frame *frame); + + /*! + * Remove an embedded frame from the CTOC frame. If \a del is true the frame's + * memory will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrame(Frame *frame, bool del = true); + + /*! + * Remove all embedded frames of type \a id from the CTOC frame and free their + * memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by embeddedFrameList() + */ + void removeEmbeddedFrames(const ByteVector &id); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * CTOC frames each have a unique element ID. This searches for a CTOC + * frame with the element ID \a eID and returns a pointer to it. This + * can be used to link together parent and child CTOC frames. + * + * \see elementID() + */ + static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID); + + /*! + * CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't + * any frame, which contains this frame in its child elements list). Only a single frame + * within tag can be top-level. This searches for a top-level CTOC frame. + * + * \see isTopLevel() + */ + static TableOfContentsFrame *findTopLevel(const Tag *tag); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h); + TableOfContentsFrame(const TableOfContentsFrame &); + TableOfContentsFrame &operator=(const TableOfContentsFrame &); + + class TableOfContentsFramePrivate; + TableOfContentsFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.cpp b/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.cpp new file mode 100644 index 0000000..f468b48 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.cpp @@ -0,0 +1,457 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "textidentificationframe.h" +#include "tpropertymap.h" +#include "id3v1genres.h" + +using namespace TagLib; +using namespace ID3v2; + +class TextIdentificationFrame::TextIdentificationFramePrivate +{ +public: + TextIdentificationFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + StringList fieldList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame public members +//////////////////////////////////////////////////////////////////////////////// + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) : + Frame(type), + d(new TextIdentificationFramePrivate()) +{ + d->textEncoding = encoding; +} + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) : + Frame(data), + d(new TextIdentificationFramePrivate()) +{ + setData(data); +} + +TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static +{ + TextIdentificationFrame *frame = new TextIdentificationFrame("TIPL"); + StringList l; + for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){ + const String role = involvedPeopleMap()[it->first]; + if(role.isEmpty()) // should not happen + continue; + l.append(role); + l.append(it->second.toString(",")); // comma-separated list of names + } + frame->setText(l); + return frame; +} + +TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static +{ + TextIdentificationFrame *frame = new TextIdentificationFrame("TMCL"); + StringList l; + for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it){ + if(!it->first.startsWith(instrumentPrefix)) // should not happen + continue; + l.append(it->first.substr(instrumentPrefix.size())); + l.append(it->second.toString(",")); + } + frame->setText(l); + return frame; +} + +TextIdentificationFrame::~TextIdentificationFrame() +{ + delete d; +} + +void TextIdentificationFrame::setText(const StringList &l) +{ + d->fieldList = l; +} + +void TextIdentificationFrame::setText(const String &s) +{ + d->fieldList = s; +} + +String TextIdentificationFrame::toString() const +{ + return d->fieldList.toString(); +} + +StringList TextIdentificationFrame::fieldList() const +{ + return d->fieldList; +} + +String::Type TextIdentificationFrame::textEncoding() const +{ + return d->textEncoding; +} + +void TextIdentificationFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +namespace +{ + // array of allowed TIPL prefixes and their corresponding key value + const std::pair involvedPeople[] = { + std::make_pair("ARRANGER", "ARRANGER"), + std::make_pair("ENGINEER", "ENGINEER"), + std::make_pair("PRODUCER", "PRODUCER"), + std::make_pair("DJ-MIX", "DJMIXER"), + std::make_pair("MIX", "MIXER"), + }; + const size_t involvedPeopleSize = sizeof(involvedPeople) / sizeof(involvedPeople[0]); +} // namespace + +const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static +{ + static KeyConversionMap m; + if(m.isEmpty()) { + for(size_t i = 0; i < involvedPeopleSize; ++i) + m.insert(involvedPeople[i].second, involvedPeople[i].first); + } + return m; +} + +PropertyMap TextIdentificationFrame::asProperties() const +{ + if(frameID() == "TIPL") + return makeTIPLProperties(); + if(frameID() == "TMCL") + return makeTMCLProperties(); + PropertyMap map; + String tagName = frameIDToKey(frameID()); + if(tagName.isEmpty()) { + map.unsupportedData().append(frameID()); + return map; + } + StringList values = fieldList(); + if(tagName == "GENRE") { + // Special case: Support ID3v1-style genre numbers. They are not officially supported in + // ID3v2, however it seems that still a lot of programs use them. + for(StringList::Iterator it = values.begin(); it != values.end(); ++it) { + bool ok = false; + int test = it->toInt(&ok); // test if the genre value is an integer + if(ok) + *it = ID3v1::genre(test); + } + } else if(tagName == "DATE") { + for(StringList::Iterator it = values.begin(); it != values.end(); ++it) { + // ID3v2 specifies ISO8601 timestamps which contain a 'T' as separator between date and time. + // Since this is unusual in other formats, the T is removed. + int tpos = it->find("T"); + if(tpos != -1) + (*it)[tpos] = ' '; + } + } + PropertyMap ret; + ret.insert(tagName, values); + return ret; +} + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame protected members +//////////////////////////////////////////////////////////////////////////////// + +void TextIdentificationFrame::parseFields(const ByteVector &data) +{ + // Don't try to parse invalid frames + + if(data.size() < 2) + return; + + // read the string data type (the first byte of the field data) + + d->textEncoding = String::Type(data[0]); + + // split the byte array into chunks based on the string type (two byte delimiter + // for unicode encodings) + + int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + // build a small counter to strip nulls off the end of the field + + int dataLength = data.size() - 1; + + while(dataLength > 0 && data[dataLength] == 0) + dataLength--; + + while(dataLength % byteAlign != 0) + dataLength++; + + ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign); + + d->fieldList.clear(); + + // append those split values to the list and make sure that the new string's + // type is the same specified for this frame + + unsigned short firstBom = 0; + for(ByteVectorList::ConstIterator it = l.begin(); it != l.end(); it++) { + if(!(*it).isEmpty()) { + if(d->textEncoding == String::Latin1) { + d->fieldList.append(Tag::latin1StringHandler()->parse(*it)); + } + else { + String::Type textEncoding = d->textEncoding; + if(textEncoding == String::UTF16) { + if(it == l.begin()) { + firstBom = it->mid(0, 2).toUShort(); + } + else { + unsigned short subsequentBom = it->mid(0, 2).toUShort(); + if(subsequentBom != 0xfeff && subsequentBom != 0xfffe) { + if(firstBom == 0xfeff) { + textEncoding = String::UTF16BE; + } + else if(firstBom == 0xfffe) { + textEncoding = String::UTF16LE; + } + } + } + } + d->fieldList.append(String(*it, textEncoding)); + } + } + } +} + +ByteVector TextIdentificationFrame::renderFields() const +{ + String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding); + + ByteVector v; + + v.append(char(encoding)); + + for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) { + + // Since the field list is null delimited, if this is not the first + // element in the list, append the appropriate delimiter for this + // encoding. + + if(it != d->fieldList.begin()) + v.append(textDelimiter(encoding)); + + v.append((*it).data(encoding)); + } + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// TextIdentificationFrame private members +//////////////////////////////////////////////////////////////////////////////// + +TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new TextIdentificationFramePrivate()) +{ + parseFields(fieldData(data)); +} + +PropertyMap TextIdentificationFrame::makeTIPLProperties() const +{ + PropertyMap map; + if(fieldList().size() % 2 != 0){ + // according to the ID3 spec, TIPL must contain an even number of entries + map.unsupportedData().append(frameID()); + return map; + } + StringList l = fieldList(); + for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + bool found = false; + for(size_t i = 0; i < involvedPeopleSize; ++i) + if(*it == involvedPeople[i].first) { + map.insert(involvedPeople[i].second, (++it)->split(",")); + found = true; + break; + } + if(!found){ + // invalid involved role -> mark whole frame as unsupported in order to be consistent with writing + map.clear(); + map.unsupportedData().append(frameID()); + return map; + } + } + return map; +} + +PropertyMap TextIdentificationFrame::makeTMCLProperties() const +{ + PropertyMap map; + if(fieldList().size() % 2 != 0){ + // according to the ID3 spec, TMCL must contain an even number of entries + map.unsupportedData().append(frameID()); + return map; + } + StringList l = fieldList(); + for(StringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + String instrument = it->upper(); + if(instrument.isEmpty()) { + // instrument is not a valid key -> frame unsupported + map.clear(); + map.unsupportedData().append(frameID()); + return map; + } + map.insert(L"PERFORMER:" + instrument, (++it)->split(",")); + } + return map; +} + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame public members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : + TextIdentificationFrame("TXXX", encoding), + d(0) +{ + StringList l; + l.append(String()); + l.append(String()); + setText(l); +} + + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) : + TextIdentificationFrame(data) +{ + checkFields(); +} + +UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) : + TextIdentificationFrame("TXXX", encoding), + d(0) +{ + setDescription(description); + setText(values); +} + +String UserTextIdentificationFrame::toString() const +{ + // first entry is the description itself, drop from values list + StringList l = fieldList(); + for(StringList::Iterator it = l.begin(); it != l.end(); ++it) { + l.erase(it); + break; + } + return "[" + description() + "] " + l.toString(); +} + +String UserTextIdentificationFrame::description() const +{ + return !TextIdentificationFrame::fieldList().isEmpty() + ? TextIdentificationFrame::fieldList().front() + : String(); +} + +StringList UserTextIdentificationFrame::fieldList() const +{ + // TODO: remove this function + + return TextIdentificationFrame::fieldList(); +} + +void UserTextIdentificationFrame::setText(const String &text) +{ + if(description().isEmpty()) + setDescription(String()); + + TextIdentificationFrame::setText(StringList(description()).append(text)); +} + +void UserTextIdentificationFrame::setText(const StringList &fields) +{ + if(description().isEmpty()) + setDescription(String()); + + TextIdentificationFrame::setText(StringList(description()).append(fields)); +} + +void UserTextIdentificationFrame::setDescription(const String &s) +{ + StringList l = fieldList(); + + if(l.isEmpty()) + l.append(s); + else + l[0] = s; + + TextIdentificationFrame::setText(l); +} + +PropertyMap UserTextIdentificationFrame::asProperties() const +{ + PropertyMap map; + String tagName = txxxToKey(description()); + StringList v = fieldList(); + for(StringList::ConstIterator it = v.begin(); it != v.end(); ++it) + if(it != v.begin()) + map.insert(tagName, *it); + return map; +} + +UserTextIdentificationFrame *UserTextIdentificationFrame::find( + ID3v2::Tag *tag, const String &description) // static +{ + FrameList l = tag->frameList("TXXX"); + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { + UserTextIdentificationFrame *f = dynamic_cast(*it); + if(f && f->description() == description) + return f; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame private members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) : + TextIdentificationFrame(data, h) +{ + checkFields(); +} + +void UserTextIdentificationFrame::checkFields() +{ + int fields = fieldList().size(); + + if(fields == 0) + setDescription(String()); + if(fields <= 1) + setText(String()); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.h b/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.h new file mode 100644 index 0000000..e49aa89 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/textidentificationframe.h @@ -0,0 +1,313 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TEXTIDENTIFICATIONFRAME_H +#define TAGLIB_TEXTIDENTIFICATIONFRAME_H + +#include "tstringlist.h" +#include "tmap.h" +#include "taglib_export.h" + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + class Tag; + typedef Map KeyConversionMap; + + //! An ID3v2 text identification frame implementation + + /*! + * This is an implementation of the most common type of ID3v2 frame -- text + * identification frames. There are a number of variations on this. Those + * enumerated in the ID3v2.4 standard are: + * + *
    + *
  • TALB Album/Movie/Show title
  • + *
  • TBPM BPM (beats per minute)
  • + *
  • TCOM Composer
  • + *
  • TCON Content type
  • + *
  • TCOP Copyright message
  • + *
  • TDEN Encoding time
  • + *
  • TDLY Playlist delay
  • + *
  • TDOR Original release time
  • + *
  • TDRC Recording time
  • + *
  • TDRL Release time
  • + *
  • TDTG Tagging time
  • + *
  • TENC Encoded by
  • + *
  • TEXT Lyricist/Text writer
  • + *
  • TFLT File type
  • + *
  • TIPL Involved people list
  • + *
  • TIT1 Content group description
  • + *
  • TIT2 Title/songname/content description
  • + *
  • TIT3 Subtitle/Description refinement
  • + *
  • TKEY Initial key
  • + *
  • TLAN Language(s)
  • + *
  • TLEN Length
  • + *
  • TMCL Musician credits list
  • + *
  • TMED Media type
  • + *
  • TMOO Mood
  • + *
  • TOAL Original album/movie/show title
  • + *
  • TOFN Original filename
  • + *
  • TOLY Original lyricist(s)/text writer(s)
  • + *
  • TOPE Original artist(s)/performer(s)
  • + *
  • TOWN File owner/licensee
  • + *
  • TPE1 Lead performer(s)/Soloist(s)
  • + *
  • TPE2 Band/orchestra/accompaniment
  • + *
  • TPE3 Conductor/performer refinement
  • + *
  • TPE4 Interpreted, remixed, or otherwise modified by
  • + *
  • TPOS Part of a set
  • + *
  • TPRO Produced notice
  • + *
  • TPUB Publisher
  • + *
  • TRCK Track number/Position in set
  • + *
  • TRSN Internet radio station name
  • + *
  • TRSO Internet radio station owner
  • + *
  • TSOA Album sort order
  • + *
  • TSOP Performer sort order
  • + *
  • TSOT Title sort order
  • + *
  • TSRC ISRC (international standard recording code)
  • + *
  • TSSE Software/Hardware and settings used for encoding
  • + *
  • TSST Set subtitle
  • + *
+ * + * The ID3v2 Frames document gives a description of each of these formats + * and the expected order of strings in each. ID3v2::Header::frameID() can + * be used to determine the frame type. + * + * \note If non-Latin1 compatible strings are used with this class, even if + * the text encoding is set to Latin1, the frame will be written using UTF8 + * (with the encoding flag appropriately set in the output). + */ + + class TAGLIB_EXPORT TextIdentificationFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty frame of type \a type. Uses \a encoding as the + * default text encoding. + * + * \note In this case you must specify the text encoding as it + * resolves the ambiguity between constructors. + * + * \note Please see the note in the class description regarding Latin1. + */ + TextIdentificationFrame(const ByteVector &type, String::Type encoding); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit TextIdentificationFrame(const ByteVector &data); + + /*! + * This is a special factory method to create a TIPL (involved people list) + * frame from the given \a properties. Will parse key=[list of values] data + * into the TIPL format as specified in the ID3 standard. + */ + static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties); + + /*! + * This is a special factory method to create a TMCL (musician credits list) + * frame from the given \a properties. Will parse key=[list of values] data + * into the TMCL format as specified in the ID3 standard, where key should be + * of the form instrumentPrefix:instrument. + */ + static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties); + /*! + * Destroys this TextIdentificationFrame instance. + */ + virtual ~TextIdentificationFrame(); + + /*! + * Text identification frames are a list of string fields. + * + * This function will accept either a StringList or a String (using the + * StringList constructor that accepts a single String). + * + * \note This will not change the text encoding of the frame even if the + * strings passed in are not of the same encoding. Please use + * setEncoding(s.type()) if you wish to change the encoding of the frame. + */ + void setText(const StringList &l); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \note Please see the note in the class description regarding Latin1. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns a list of the strings in this frame. + */ + StringList fieldList() const; + + /*! + * Returns a KeyConversionMap mapping a role as it would be used in a PropertyMap + * to the corresponding key used in a TIPL ID3 frame to describe that role. + */ + static const KeyConversionMap &involvedPeopleMap(); + + PropertyMap asProperties() const; + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + TextIdentificationFrame(const ByteVector &data, Header *h); + + private: + TextIdentificationFrame(const TextIdentificationFrame &); + TextIdentificationFrame &operator=(const TextIdentificationFrame &); + + /*! + * Parses the special structure of a TIPL frame + * Only the whitelisted roles "ARRANGER", "ENGINEER", "PRODUCER", + * "DJMIXER" (ID3: "DJ-MIX") and "MIXER" (ID3: "MIX") are allowed. + */ + PropertyMap makeTIPLProperties() const; + /*! + * Parses the special structure of a TMCL frame. + */ + PropertyMap makeTMCLProperties() const; + class TextIdentificationFramePrivate; + TextIdentificationFramePrivate *d; + }; + + /*! + * This is a specialization of text identification frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a text identification frame has. + * + * This description identifies the frame and must be unique. + */ + + //! An ID3v2 custom text identification frame implementation + + class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined text identification frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1); + + /*! + * Creates a frame based on \a data. + */ + explicit UserTextIdentificationFrame(const ByteVector &data); + + /*! + * Creates a user defined text identification frame with the given \a description + * and \a values. + */ + UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8); + + virtual String toString() const; + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. You can + * check for the presence of another user defined text frame of the same type + * using find() and testing for null. + */ + void setDescription(const String &s); + + StringList fieldList() const; + void setText(const String &text); + void setText(const StringList &fields); + + /*! + * A UserTextIdentificationFrame is parsed into a PropertyMap as follows: + * - the key is the frame's description, uppercased + * - if the description contains '::', only the substring after that + * separator is considered as key (compatibility with exfalso) + * - if the above rules don't yield a valid key (e.g. containing non-ASCII + * characters), the returned map will contain an entry "TXXX/" + * in its unsupportedData() list. + * - The values will be copies of the fieldList(). + * - If the description() appears as value in fieldList(), it will be omitted + * in the value list, in order to be compatible with TagLib which copies + * the description() into the fieldList(). + */ + PropertyMap asProperties() const; + + /*! + * Searches for the user defined text frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserTextIdentificationFrame *find(Tag *tag, const String &description); + + private: + UserTextIdentificationFrame(const ByteVector &data, Header *h); + UserTextIdentificationFrame(const TextIdentificationFrame &); + UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &); + + void checkFields(); + + class UserTextIdentificationFramePrivate; + UserTextIdentificationFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.cpp b/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.cpp new file mode 100644 index 0000000..fcb855b --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.cpp @@ -0,0 +1,148 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "id3v2tag.h" +#include "uniquefileidentifierframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class UniqueFileIdentifierFrame::UniqueFileIdentifierFramePrivate +{ +public: + String owner; + ByteVector identifier; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public methods +//////////////////////////////////////////////////////////////////////////////// + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data) : + ID3v2::Frame(data), + d(new UniqueFileIdentifierFramePrivate()) +{ + setData(data); +} + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const String &owner, const ByteVector &id) : + ID3v2::Frame("UFID"), + d(new UniqueFileIdentifierFramePrivate()) +{ + d->owner = owner; + d->identifier = id; +} + +UniqueFileIdentifierFrame::~UniqueFileIdentifierFrame() +{ + delete d; +} + +String UniqueFileIdentifierFrame::owner() const +{ + return d->owner; +} + +ByteVector UniqueFileIdentifierFrame::identifier() const +{ + return d->identifier; +} + +void UniqueFileIdentifierFrame::setOwner(const String &s) +{ + d->owner = s; +} + +void UniqueFileIdentifierFrame::setIdentifier(const ByteVector &v) +{ + d->identifier = v; +} + +String UniqueFileIdentifierFrame::toString() const +{ + return String(); +} + +PropertyMap UniqueFileIdentifierFrame::asProperties() const +{ + PropertyMap map; + if(d->owner == "http://musicbrainz.org") { + map.insert("MUSICBRAINZ_TRACKID", String(d->identifier)); + } + else { + map.unsupportedData().append(frameID() + String("/") + d->owner); + } + return map; +} + +UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::Tag *tag, const String &o) // static +{ + ID3v2::FrameList comments = tag->frameList("UFID"); + + for(ID3v2::FrameList::ConstIterator it = comments.begin(); + it != comments.end(); + ++it) + { + UniqueFileIdentifierFrame *frame = dynamic_cast(*it); + if(frame && frame->owner() == o) + return frame; + } + + return 0; +} + +void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 1) { + debug("An UFID frame must contain at least 1 byte."); + return; + } + + int pos = 0; + d->owner = readStringField(data, String::Latin1, &pos); + d->identifier = data.mid(pos); +} + +ByteVector UniqueFileIdentifierFrame::renderFields() const +{ + ByteVector data; + + data.append(d->owner.data(String::Latin1)); + data.append(char(0)); + data.append(d->identifier); + + return data; +} + +UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new UniqueFileIdentifierFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.h b/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.h new file mode 100644 index 0000000..decf1b0 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/uniquefileidentifierframe.h @@ -0,0 +1,123 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNIQUEFILEIDENTIFIERFRAME +#define TAGLIB_UNIQUEFILEIDENTIFIERFRAME + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + /*! + * This is an implementation of ID3v2 unique file identifier frames. This + * frame is used to identify the file in an arbitrary database identified + * by the owner field. + */ + + //! An implementation of ID3v2 unique identifier frames + + class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame + { + friend class FrameFactory; + + public: + /*! + * Creates a unique file identifier frame based on \a data. + */ + UniqueFileIdentifierFrame(const ByteVector &data); + + /*! + * Creates a unique file identifier frame with the owner \a owner and + * the identification \a id. + */ + UniqueFileIdentifierFrame(const String &owner, const ByteVector &id); + + /*! + * Destroys the frame. + */ + ~UniqueFileIdentifierFrame(); + + /*! + * Returns the owner for the frame; essentially this is the key for + * determining which identification scheme this key belongs to. This + * will usually either be an email address or URL for the person or tool + * used to create the unique identifier. + * + * \see setOwner() + */ + String owner() const; + + /*! + * Returns the unique identifier. Though sometimes this is a text string + * it also may be binary data and as much should be assumed when handling + * it. + */ + ByteVector identifier() const; + + /*! + * Sets the owner of the identification scheme to \a s. + * + * \see owner() + */ + void setOwner(const String &s); + + /*! + * Sets the unique file identifier to \a v. + * + * \see identifier() + */ + void setIdentifier(const ByteVector &v); + + virtual String toString() const; + + PropertyMap asProperties() const; + + /*! + * UFID frames each have a unique owner. This searches for a UFID + * frame with the owner \a o and returns a pointer to it. + * + * \see owner() + */ + static UniqueFileIdentifierFrame *findByOwner(const Tag *tag, const String &o); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UniqueFileIdentifierFrame(const UniqueFileIdentifierFrame &); + UniqueFileIdentifierFrame &operator=(const UniqueFileIdentifierFrame &); + + UniqueFileIdentifierFrame(const ByteVector &data, Header *h); + + class UniqueFileIdentifierFramePrivate; + UniqueFileIdentifierFramePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/unknownframe.cpp b/external/taglib/source/mpeg/id3v2/frames/unknownframe.cpp new file mode 100644 index 0000000..edb3008 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/unknownframe.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "unknownframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class UnknownFrame::UnknownFramePrivate +{ +public: + ByteVector fieldData; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +UnknownFrame::UnknownFrame(const ByteVector &data) : + Frame(data), + d(new UnknownFramePrivate()) +{ + setData(data); +} + +UnknownFrame::~UnknownFrame() +{ + delete d; +} + +String UnknownFrame::toString() const +{ + return String(); +} + +ByteVector UnknownFrame::data() const +{ + return d->fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void UnknownFrame::parseFields(const ByteVector &data) +{ + d->fieldData = data; +} + +ByteVector UnknownFrame::renderFields() const +{ + return d->fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new UnknownFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/unknownframe.h b/external/taglib/source/mpeg/id3v2/frames/unknownframe.h new file mode 100644 index 0000000..6559f4e --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/unknownframe.h @@ -0,0 +1,79 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNKNOWNFRAME_H +#define TAGLIB_UNKNOWNFRAME_H + +#include "id3v2frame.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A frame type \e unknown to TagLib. + + /*! + * This class represents a frame type not known (or more often simply + * unimplemented) in TagLib. This is here provide a basic API for + * manipulating the binary data of unknown frames and to provide a means + * of rendering such \e unknown frames. + * + * Please note that a cleaner way of handling frame types that TagLib + * does not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory + * to have your frame type supported through the standard ID3v2 mechanism. + */ + + class TAGLIB_EXPORT UnknownFrame : public Frame + { + friend class FrameFactory; + + public: + UnknownFrame(const ByteVector &data); + virtual ~UnknownFrame(); + + virtual String toString() const; + + /*! + * Returns the field data (everything but the header) for this frame. + */ + ByteVector data() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + UnknownFrame(const ByteVector &data, Header *h); + UnknownFrame(const UnknownFrame &); + UnknownFrame &operator=(const UnknownFrame &); + + class UnknownFramePrivate; + UnknownFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp b/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp new file mode 100644 index 0000000..eafae17 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp @@ -0,0 +1,198 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "unsynchronizedlyricsframe.h" +#include +#include +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class UnsynchronizedLyricsFrame::UnsynchronizedLyricsFramePrivate +{ +public: + UnsynchronizedLyricsFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + ByteVector language; + String description; + String text; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) : + Frame("USLT"), + d(new UnsynchronizedLyricsFramePrivate()) +{ + d->textEncoding = encoding; +} + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) : + Frame(data), + d(new UnsynchronizedLyricsFramePrivate()) +{ + setData(data); +} + +UnsynchronizedLyricsFrame::~UnsynchronizedLyricsFrame() +{ + delete d; +} + +String UnsynchronizedLyricsFrame::toString() const +{ + return d->text; +} + +ByteVector UnsynchronizedLyricsFrame::language() const +{ + return d->language; +} + +String UnsynchronizedLyricsFrame::description() const +{ + return d->description; +} + +String UnsynchronizedLyricsFrame::text() const +{ + return d->text; +} + +void UnsynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void UnsynchronizedLyricsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void UnsynchronizedLyricsFrame::setText(const String &s) +{ + d->text = s; +} + + +String::Type UnsynchronizedLyricsFrame::textEncoding() const +{ + return d->textEncoding; +} + +void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +PropertyMap UnsynchronizedLyricsFrame::asProperties() const +{ + PropertyMap map; + String key = description().upper(); + if(key.isEmpty() || key == "LYRICS") + map.insert("LYRICS", text()); + else + map.insert("LYRICS:" + key, text()); + return map; +} + +UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static +{ + ID3v2::FrameList lyrics = tag->frameList("USLT"); + + for(ID3v2::FrameList::ConstIterator it = lyrics.begin(); it != lyrics.end(); ++it){ + UnsynchronizedLyricsFrame *frame = dynamic_cast(*it); + if(frame && frame->description() == d) + return frame; + } + return 0; +} +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("An unsynchronized lyrics frame must contain at least 5 bytes."); + return; + } + + d->textEncoding = String::Type(data[0]); + d->language = data.mid(1, 3); + + int byteAlign + = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2; + + ByteVectorList l = + ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2); + + if(l.size() == 2) { + if(d->textEncoding == String::Latin1) { + d->description = Tag::latin1StringHandler()->parse(l.front()); + d->text = Tag::latin1StringHandler()->parse(l.back()); + } else { + d->description = String(l.front(), d->textEncoding); + d->text = String(l.back(), d->textEncoding); + } + } +} + +ByteVector UnsynchronizedLyricsFrame::renderFields() const +{ + StringList sl; + sl.append(d->description); + sl.append(d->text); + + const String::Type encoding = checkTextEncoding(sl, d->textEncoding); + + ByteVector v; + + v.append(char(encoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(d->text.data(encoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new UnsynchronizedLyricsFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.h b/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.h new file mode 100644 index 0000000..dad67c7 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/unsynchronizedlyricsframe.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 unsynchronized lyrics frame + /*! + * An implementation of ID3v2 unsynchronized lyrics. + */ + class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty unsynchronized lyrics frame that will use the text encoding + * \a encoding. + */ + explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a unsynchronized lyrics frame based on the data in \a data. + */ + explicit UnsynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this UnsynchronizedLyricsFrame instance. + */ + virtual ~UnsynchronizedLyricsFrame(); + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this unsynchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the unsynchronized lyrics frame to \a s. + * + * \see description() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the unsynchronized lyrics frame to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + + /*! Parses this frame as PropertyMap with a single key. + * - if description() is empty or "LYRICS", the key will be "LYRICS" + * - if description() is not a valid PropertyMap key, the frame will be + * marked unsupported by an entry "USLT/" in the unsupportedData() + * attribute of the returned map. + * - otherwise, the key will be "LYRICS:" + * - The single value will be the frame's text(). + * Note that currently the language() field is not supported by the PropertyMap + * interface. + */ + PropertyMap asProperties() const; + + /*! + * LyricsFrames each have a unique description. This searches for a lyrics + * frame with the description \a d and returns a pointer to it. If no + * frame is found that matches the given description null is returned. + * + * \see description() + */ + static UnsynchronizedLyricsFrame *findByDescription(const Tag *tag, const String &d); + + protected: + // Reimplementations. + + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + private: + /*! + * The constructor used by the FrameFactory. + */ + UnsynchronizedLyricsFrame(const ByteVector &data, Header *h); + UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &); + UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &); + + class UnsynchronizedLyricsFramePrivate; + UnsynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/frames/urllinkframe.cpp b/external/taglib/source/mpeg/id3v2/frames/urllinkframe.cpp new file mode 100644 index 0000000..543b518 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/urllinkframe.cpp @@ -0,0 +1,246 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "urllinkframe.h" +#include "id3v2tag.h" +#include +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class UrlLinkFrame::UrlLinkFramePrivate +{ +public: + String url; +}; + +class UserUrlLinkFrame::UserUrlLinkFramePrivate +{ +public: + UserUrlLinkFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + String description; +}; + +//////////////////////////////////////////////////////////////////////////////// +// UrlLinkFrame public members +//////////////////////////////////////////////////////////////////////////////// + +UrlLinkFrame::UrlLinkFrame(const ByteVector &data) : + Frame(data), + d(new UrlLinkFramePrivate()) +{ + setData(data); +} + +UrlLinkFrame::~UrlLinkFrame() +{ + delete d; +} + +void UrlLinkFrame::setUrl(const String &s) +{ + d->url = s; +} + +String UrlLinkFrame::url() const +{ + return d->url; +} + +void UrlLinkFrame::setText(const String &s) +{ + setUrl(s); +} + +String UrlLinkFrame::toString() const +{ + return url(); +} + +PropertyMap UrlLinkFrame::asProperties() const +{ + String key = frameIDToKey(frameID()); + PropertyMap map; + if(key.isEmpty()) + // unknown W*** frame - this normally shouldn't happen + map.unsupportedData().append(frameID()); + else + map.insert(key, url()); + return map; +} + +//////////////////////////////////////////////////////////////////////////////// +// UrlLinkFrame protected members +//////////////////////////////////////////////////////////////////////////////// + +void UrlLinkFrame::parseFields(const ByteVector &data) +{ + d->url = String(data); +} + +ByteVector UrlLinkFrame::renderFields() const +{ + return d->url.data(String::Latin1); +} + +UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) : + Frame(h), + d(new UrlLinkFramePrivate()) +{ + parseFields(fieldData(data)); +} + +//////////////////////////////////////////////////////////////////////////////// +// UserUrlLinkFrame public members +//////////////////////////////////////////////////////////////////////////////// + +UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) : + UrlLinkFrame("WXXX"), + d(new UserUrlLinkFramePrivate()) +{ + d->textEncoding = encoding; +} + +UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) : + UrlLinkFrame(data), + d(new UserUrlLinkFramePrivate()) +{ + setData(data); +} + +UserUrlLinkFrame::~UserUrlLinkFrame() +{ + delete d; +} + +String UserUrlLinkFrame::toString() const +{ + return "[" + description() + "] " + url(); +} + +String::Type UserUrlLinkFrame::textEncoding() const +{ + return d->textEncoding; +} + +void UserUrlLinkFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +String UserUrlLinkFrame::description() const +{ + return d->description; +} + +void UserUrlLinkFrame::setDescription(const String &s) +{ + d->description = s; +} + +PropertyMap UserUrlLinkFrame::asProperties() const +{ + PropertyMap map; + String key = description().upper(); + if(key.isEmpty() || key == "URL") + map.insert("URL", url()); + else + map.insert("URL:" + key, url()); + return map; +} + +UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static +{ + FrameList l = tag->frameList("WXXX"); + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) { + UserUrlLinkFrame *f = dynamic_cast(*it); + if(f && f->description() == description) + return f; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// UserUrlLinkFrame protected members +//////////////////////////////////////////////////////////////////////////////// + +void UserUrlLinkFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 2) { + debug("A user URL link frame must contain at least 2 bytes."); + return; + } + + int pos = 0; + + d->textEncoding = String::Type(data[0]); + pos += 1; + + if(d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8) { + int offset = data.find(textDelimiter(d->textEncoding), pos); + if(offset < pos) + return; + + d->description = String(data.mid(pos, offset - pos), d->textEncoding); + pos = offset + 1; + } + else { + int len = data.mid(pos).find(textDelimiter(d->textEncoding), 0, 2); + if(len < 0) + return; + + d->description = String(data.mid(pos, len), d->textEncoding); + pos += len + 2; + } + + setUrl(String(data.mid(pos))); +} + +ByteVector UserUrlLinkFrame::renderFields() const +{ + ByteVector v; + + String::Type encoding = checkTextEncoding(d->description, d->textEncoding); + + v.append(char(encoding)); + v.append(d->description.data(encoding)); + v.append(textDelimiter(encoding)); + v.append(url().data(String::Latin1)); + + return v; +} + +UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : + UrlLinkFrame(data, h), + d(new UserUrlLinkFramePrivate()) +{ + parseFields(fieldData(data)); +} diff --git a/external/taglib/source/mpeg/id3v2/frames/urllinkframe.h b/external/taglib/source/mpeg/id3v2/frames/urllinkframe.h new file mode 100644 index 0000000..d9ac109 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/frames/urllinkframe.h @@ -0,0 +1,190 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + + copyright : (C) 2006 by Urs Fleisch + email : ufleisch@users.sourceforge.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_URLLINKFRAME_H +#define TAGLIB_URLLINKFRAME_H + +#include "id3v2frame.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 URL frame + /*! + * An implementation of ID3v2 URL link frames. + */ + class TAGLIB_EXPORT UrlLinkFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UrlLinkFrame instance. + */ + virtual ~UrlLinkFrame(); + + /*! + * Returns the URL. + */ + virtual String url() const; + + /*! + * Sets the URL to \a s. + */ + virtual void setUrl(const String &s); + + // Reimplementations. + + virtual void setText(const String &s); + virtual String toString() const; + PropertyMap asProperties() const; + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UrlLinkFrame(const ByteVector &data, Header *h); + + private: + UrlLinkFrame(const UrlLinkFrame &); + UrlLinkFrame &operator=(const UrlLinkFrame &); + + class UrlLinkFramePrivate; + UrlLinkFramePrivate *d; + }; + + //! ID3v2 User defined URL frame + + /*! + * This is a specialization of URL link frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a URL link frame has. + * + * This description identifies the frame and must be unique. + */ + class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined URL link frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserUrlLinkFrame(String::Type encoding = String::Latin1); + + /*! + * This is a dual purpose constructor. \a data can either be binary data + * that should be parsed or (at a minimum) the frame ID. + */ + explicit UserUrlLinkFrame(const ByteVector &data); + + /*! + * Destroys this UserUrlLinkFrame instance. + */ + virtual ~UserUrlLinkFrame(); + + // Reimplementations. + + virtual String toString() const; + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + String::Type textEncoding() const; + + /*! + * Sets the text encoding to be used when rendering this frame to + * \a encoding. + * + * \see textEncoding() + * \see render() + */ + void setTextEncoding(String::Type encoding); + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. + */ + void setDescription(const String &s); + + /*! + * Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key, + * and the URL as single value. + * - if description() is empty, the key will be "URL". + * - otherwise, if description() is not a valid key (e.g. containing non-ASCII + * characters), the returned map will contain an entry "WXXX/" + * in its unsupportedData() list. + */ + PropertyMap asProperties() const; + + /*! + * Searches for the user defined url frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserUrlLinkFrame *find(Tag *tag, const String &description); + + protected: + virtual void parseFields(const ByteVector &data); + virtual ByteVector renderFields() const; + + /*! + * The constructor used by the FrameFactory. + */ + UserUrlLinkFrame(const ByteVector &data, Header *h); + + private: + UserUrlLinkFrame(const UserUrlLinkFrame &); + UserUrlLinkFrame &operator=(const UserUrlLinkFrame &); + + class UserUrlLinkFramePrivate; + UserUrlLinkFramePrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2.2.0.txt b/external/taglib/source/mpeg/id3v2/id3v2.2.0.txt new file mode 100644 index 0000000..a69bddd --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2.2.0.txt @@ -0,0 +1,1660 @@ + +Informal standard M. Nilsson +Document: id3v2-00.txt 26th March 1998 + + + ID3 tag version 2 + +Status of this document + + This document is an Informal standard and is released so that + implementors could have a set standard before the formal standard is + set. The formal standard will use another version number if not + identical to what is described in this document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + The recent gain of popularity for MPEG layer III audio files on the + internet forced a standardised way of storing information about an + audio file within itself to determinate its origin and contents. + + Today the most accepted way to do this is with the so called ID3 tag, + which is simple but very limited and in some cases very unsuitable. + The ID3 tag has very limited space in every field, very limited + numbers of fields, not expandable or upgradeable and is placed at the + end of a the file, which is unsuitable for streaming audio. This draft + is an attempt to answer these issues with a new version of the ID3 + tag. + + +1. Table of contents + + 2. Conventions in this document + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 frames overview + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Text information frames - details + 4.2.2. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Involved people list + 4.5. Music CD Identifier + 4.6. Event timing codes + 4.7. MPEG location lookup table + 4.8. Synced tempo codes + 4.9. Unsychronised lyrics/text transcription + 4.10. Synchronised lyrics/text + 4.11. Comments + 4.12. Relative volume adjustment + 4.13. Equalisation + 4.14. Reverb + 4.15. Attached picture + 4.16. General encapsulated object + 4.17. Play counter + 4.18. Popularimeter + 4.19. Recommended buffer size + 4.20. Encrypted meta frame + 4.21. Audio encryption + 4.22. Linked information + 5. The 'unsynchronisation scheme' + 6. Copyright + 7. References + 8. Appendix + A. Appendix A - ID3-Tag Specification V1.1 + A.1. Overview + A.2. ID3v1 Implementation + A.3. Genre List + A.4. Track addition - ID3v1.1 + 9. Author's Address + + +2. Conventions in this document + + In the examples, text within "" is a text string exactly as it appears + in a file. Numbers preceded with $ are hexadecimal and numbers + preceded with % are binary. $xx is used to indicate a byte with + unknown content. %x is used to indicate a bit with unknown content. + The most significant bit (MSB) of a byte is called 'bit 7' and the + least significant bit (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters 0-9 only. + + +3. ID3v2 overview + + The two biggest design goals were to be able to implement ID3v2 + without disturbing old software too much and that ID3v2 should be + expandable. + + The first criterion is met by the simple fact that the MPEG [MPEG] + decoding software uses a syncsignal, embedded in the audiostream, to + 'lock on to' the audio. Since the ID3v2 tag doesn't contain a valid + syncsignal, no software will attempt to play the tag. If, for any + reason, coincidence make a syncsignal appear within the tag it will be + taken care of by the 'unsynchronisation scheme' described in section + 5. + + The second criterion has made a more noticeable impact on the design + of the ID3v2 tag. It is constructed as a container for several + information blocks, called frames, whose format need not be known to + the software that encounters them. At the start of every frame there + is an identifier that explains the frames's format and content, and a + size descriptor that allows software to skip unknown frames. + + If a total revision of the ID3v2 tag should be needed, there is a + version number and a size descriptor in the ID3v2 header. + + The ID3 tag described in this document is mainly targeted to files + encoded with MPEG-2 layer I, MPEG-2 layer II, MPEG-2 layer III and + MPEG-2.5, but may work with other types of encoded audio. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78). + + It is permitted to include padding after all the final frame (at the + end of the ID3 tag), making the size of all the frames together + smaller than the size given in the head of the tag. A possible purpose + of this padding is to allow for adding a few additional frames or + enlarge existing frames within the tag without having to rewrite the + entire file. The value of the padding bytes must be $00. + + +3.1. ID3v2 header + + The ID3v2 tag header, which should be the first information in the + file, is 10 bytes as follows: + + ID3/file identifier "ID3" + ID3 version $02 00 + ID3 flags %xx000000 + ID3 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3" to indicate that + this is an ID3 tag, directly followed by the two version bytes. The + first byte of ID3 version is it's major version, while the second byte + is its revision number. All revisions are backwards compatible while + major versions are not. If software with ID3v2 and below support + should encounter version three or higher it should simply ignore the + whole tag. Version and revision will never be $FF. + + The first bit (bit 7) in the 'ID3 flags' is indicating whether or not + unsynchronisation is used (see section 5 for details); a set bit + indicates usage. + + The second bit (bit 6) is indicating whether or not compression is + used; a set bit indicates usage. Since no compression scheme has been + decided yet, the ID3 decoder (for now) should just ignore the entire + tag if the compression bit is set. + + The ID3 tag size is encoded with four bytes where the first bit (bit + 7) is set to zero in every byte, making a total of 28 bits. The zeroed + bits are ignored, so a 257 bytes long tag is represented as $00 00 02 + 01. + + The ID3 tag size is the size of the complete tag after + unsychronisation, including padding, excluding the header (total tag + size - 10). The reason to use 28 bits (representing up to 256MB) for + size description is that we don't want to run out of space here. + + A ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. ID3v2 frames overview + + The headers of the frames are similar in their construction. They + consist of one three character identifier (capital A-Z and 0-9) and + one three byte size field, making a total of six bytes. The header is + excluded from the size. Identifiers beginning with "X", "Y" and "Z" + are for experimental use and free for everyone to use. Have in mind + that someone else might have used the same identifier as you. All + other identifiers are either used or reserved for future use. + + The three character frame identifier is followed by a three byte size + descriptor, making a total header size of six bytes in every frame. + The size is calculated as framesize excluding frame identifier and + size descriptor (frame size - 6). + + There is no fixed order of the frames' appearance in the tag, although + it is desired that the frames are arranged in order of significance + concerning the recognition of the file. An example of such order: + UFI, MCI, TT2 ... + + A tag must contain at least one frame. A frame must be at least 1 byte + big, excluding the 6-byte header. + + If nothing else is said a string is represented as ISO-8859-1 + [ISO-8859-1] characters in the range $20 - $FF. All unicode strings + [UNICODE] use 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). All + numeric strings are always encoded as ISO-8859-1. Terminated strings + are terminated with $00 if encoded with ISO-8859-1 and $00 00 if + encoded as unicode. If nothing else is said newline character is + forbidden. In ISO-8859-1 a new line is represented, when allowed, with + $0A only. Frames that allow different types of text encoding have a + text encoding description byte directly after the frame size. If + ISO-8859-1 is used this byte should be $00, if unicode is used it + should be $01. + + The three byte language field is used to describe the language of the + frame's content, according to ISO-639-2 [ISO-639-2]. + + All URLs [URL] may be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3 standard. This + is reflected by the revision number in the header of the tag. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.19 BUF Recommended buffer size + + 4.17 CNT Play counter + 4.11 COM Comments + 4.21 CRA Audio encryption + 4.20 CRM Encrypted meta frame + + 4.6 ETC Event timing codes + 4.13 EQU Equalization + + 4.16 GEO General encapsulated object + + 4.4 IPL Involved people list + + 4.22 LNK Linked information + + 4.5 MCI Music CD Identifier + 4.7 MLL MPEG location lookup table + + 4.15 PIC Attached picture + 4.18 POP Popularimeter + + 4.14 REV Reverb + 4.12 RVA Relative volume adjustment + + 4.10 SLT Synchronized lyric/text + 4.8 STC Synced tempo codes + + 4.2.1 TAL Album/Movie/Show title + 4.2.1 TBP BPM (Beats Per Minute) + 4.2.1 TCM Composer + 4.2.1 TCO Content type + 4.2.1 TCR Copyright message + 4.2.1 TDA Date + 4.2.1 TDY Playlist delay + 4.2.1 TEN Encoded by + 4.2.1 TFT File type + 4.2.1 TIM Time + 4.2.1 TKE Initial key + 4.2.1 TLA Language(s) + 4.2.1 TLE Length + 4.2.1 TMT Media type + 4.2.1 TOA Original artist(s)/performer(s) + 4.2.1 TOF Original filename + 4.2.1 TOL Original Lyricist(s)/text writer(s) + 4.2.1 TOR Original release year + 4.2.1 TOT Original album/Movie/Show title + 4.2.1 TP1 Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group + 4.2.1 TP2 Band/Orchestra/Accompaniment + 4.2.1 TP3 Conductor/Performer refinement + 4.2.1 TP4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPA Part of a set + 4.2.1 TPB Publisher + 4.2.1 TRC ISRC (International Standard Recording Code) + 4.2.1 TRD Recording dates + 4.2.1 TRK Track number/Position in set + 4.2.1 TSI Size + 4.2.1 TSS Software/hardware and settings used for encoding + 4.2.1 TT1 Content group description + 4.2.1 TT2 Title/Songname/Content description + 4.2.1 TT3 Subtitle/Description refinement + 4.2.1 TXT Lyricist/text writer + 4.2.2 TXX User defined text information frame + 4.2.1 TYE Year + + 4.1 UFI Unique file identifier + 4.9 ULT Unsychronized lyric/text transcription + + 4.3.1 WAF Official audio file webpage + 4.3.1 WAR Official artist/performer webpage + 4.3.1 WAS Official audio source webpage + 4.3.1 WCM Commercial information + 4.3.1 WCP Copyright/Legal information + 4.3.1 WPB Publishers official webpage + 4.3.2 WXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database that may contain more information relevant to the content. + Since standardisation of such a database is beyond this document, all + frames begin with a null-terminated string with a URL [URL] containing + an email address, or a link to a location where an email address can + be found, that belongs to the organisation responsible for this + specific database implementation. Questions regarding the database + should be sent to the indicated email address. The URL should not be + used for the actual database queries. If a $00 is found directly after + the 'Frame size' the whole frame should be ignored, and preferably be + removed. The 'Owner identifier' is then followed by the actual + identifier, which may be up to 64 bytes. There may be more than one + "UFI" frame in a tag, but only one with the same 'Owner identifier'. + + Unique file identifier "UFI" + Frame size $xx xx xx + Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are the most important frames, containing + information like artist, album and more. There may only be one text + information frame of its kind in an tag. If the textstring is followed + by a termination ($00 (00)) all the following information should be + ignored and not be displayed. All the text information frames have the + following format: + + Text information identifier "T00" - "TZZ" , excluding "TXX", + described in 4.2.2. + Frame size $xx xx xx + Text encoding $xx + Information + + +4.2.1. Text information frames - details + + TT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at wembley"). + + TP1 + The 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group' is + used for the main artist(s). They are seperated with the "/" + character. + + TP2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TP3 + The 'Conductor' frame is used for the name of the conductor. + + TP4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TCM + The 'Composer(s)' frame is intended for the name of the composer(s). + They are seperated with the "/" character. + + TXT + The 'Lyricist(s)/text writer(s)' frame is intended for the writer(s) + of the text or lyrics in the recording. They are seperated with the + "/" character. + + TLA + The 'Language(s)' frame should contain the languages of the text or + lyrics in the audio file. The language is represented with three + characters according to ISO-639-2. If more than one language is used + in the text their language codes should follow according to their + usage. + + TCO + The content type, which previously (in ID3v1.1, see appendix A) was + stored as a one byte numeric value only, is now a numeric string. You + may use one or several of the types as ID3v1.1 did or, since the + category list would be impossible to maintain with accurate and up to + date categories, define your own. + References to the ID3v1 genres can be made by, as first byte, enter + "(" followed by a number from the genres list (section A.3.) and + ended with a ")" character. This is optionally followed by a + refinement, e.g. "(21)" or "(4)Eurodisco". Several references can be + made in the same frame, e.g. "(51)(39)". If the refinement should + begin with a "(" character it should be replaced with "((", e.g. "((I + can figure out any genre)" or "(55)((I think...)". The following new + content types is defined in ID3v2 and is implemented in the same way + as the numerig content types, e.g. "(RX)". + + RX Remix + CR Cover + + TAL + The 'Album/Movie/Show title' frame is intended for the title of the + recording(/source of sound) which the audio in the file is taken from. + + TPA + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TAL" frame is divided into several mediums, e.g. a + double CD. The value may be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TRK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This may be extended with a "/" character and a numeric + string containing the total numer of tracks/elements on the original + recording. E.g. "4/9". + + TRC + The 'ISRC' frame should contian the International Standard Recording + Code [ISRC]. + + TYE + The 'Year' frame is a numeric string with a year of the recording. + This frames is always four characters long (until the year 10000). + + TDA + The 'Date' frame is a numeric string in the DDMM format containing + the date for the recording. This field is always four characters + long. + + TIM + The 'Time' frame is a numeric string in the HHMM format containing + the time for the recording. This field is always four characters + long. + + TRD + The 'Recording dates' frame is a intended to be used as complement to + the "TYE", "TDA" and "TIM" frames. E.g. "4th-7th June, 12th June" in + combination with the "TYE" frame. + + TMT + The 'Media type' frame describes from which media the sound + originated. This may be a textstring or a reference to the predefined + media types found in the list below. References are made within "(" + and ")" and are optionally followed by a text refinement, e.g. "(MC) + with four channels". If a text refinement should begin with a "(" + character it should be replaced with "((" in the same way as in the + "TCO" frame. Predefined refinements is appended after the media type, + e.g. "(CD/S)" or "(VID/PAL/VHS)". + + DIG Other digital media + /A Analog transfer from media + + ANA Other analog media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analog transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + /A Analog transfer from media + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analog transfer from media + + DAT DAT + /A Analog transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, nonlinear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analog transfer from media + + DVD DVD + /A Analog transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TFT + The 'File type' frame indicates which type of audio this tag defines. + The following type and refinements are defined: + + MPG MPEG Audio + /1 MPEG 2 layer I + /2 MPEG 2 layer II + /3 MPEG 2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + + but other types may be used, not for these types though. This is used + in a similar way to the predefined types in the "TMT" frame, but + without parenthesis. If this frame is not present audio type is + assumed to be "MPG". + + TBP + BPM is short for beats per minute, and is easily computed by + dividing the number of beats in a musical piece with its length. To + get a more accurate result, do the BPM calculation on the main-part + only. To acquire best result measure the time between each beat and + calculate individual BPM for each beat and use the median value as + result. BPM is an integer and represented as a numerical string. + + TCR + The 'Copyright message' frame, which must begin with a year and a + space character (making five characters), is intended for the + copyright holder of the original sound, not the audio file itself. The + absence of this frame means only that the copyright information is + unavailable or has been removed, and must not be interpreted to mean + that the sound is public domain. Every time this field is displayed + the field must be preceded with "Copyright " (C) " ", where (C) is one + character showing a C in a circle. + + TPB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TEN + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + TSS + The 'Software/hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TOF + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TLE + The 'Length' frame contains the length of the audiofile in + milliseconds, represented as a numeric string. + + TSI + The 'Size' frame contains the size of the audiofile in bytes + excluding the tag, represented as a numeric string. + + TDY + The 'Playlist delay' defines the numbers of milliseconds of silence + between every song in a playlist. The player should use the "ETC" + frame, if present, to skip initial silence and silence at the end of + the audio to match the 'Playlist delay' time. The time is represented + as a numeric string. + + TKE + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m". Example "Cbm". Off key is represented with an "o" + only. + + TOT + The 'Original album/Movie/Show title' frame is intended for the title + of the original recording(/source of sound), if for example the music + in the file should be a cover of a previously released song. + + TOA + The 'Original artist(s)/performer(s)' frame is intended for the + performer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The + performers are seperated with the "/" character. + + TOL + The 'Original Lyricist(s)/text writer(s)' frame is intended for the + text writer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The text + writers are seperated with the "/" character. + + TOR + The 'Original release year' frame is intended for the year when the + original recording, if for example the music in the file should be a + cover of a previously released song, was released. The field is + formatted as in the "TDY" frame. + + +4.2.2. User defined text information frame + + This frame is intended for one-string text information concerning the + audiofile in a similar way to the other "T"xx frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXX" frame in each tag, but only one with the same description. + + User defined... "TXX" + Frame size $xx xx xx + Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + textstring is followed by a termination ($00 (00)) all the following + information should be ignored and not be displayed. All URL link + frames have the following format: + + URL link frame "W00" - "WZZ" , excluding "WXX" + (described in 4.3.2.) + Frame size $xx xx xx + URL + + +4.3.1. URL link frames - details + + WAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WAR" frame + in a tag if the audio contains more than one performer. + + WAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WCM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCM" frame in a tag. + + WCP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is described. + + WPB + The 'Publishers official webpage' frame is a URL pointing at the + official wepage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audiofile in + a similar way to the other "W"xx frames. The frame body consists of a + description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXX" frame in each tag, but + only one with the same description. + + User defined... "WXX" + Frame size $xx xx xx + Text encoding $xx + Description $00 (00) + URL + + +4.4. Involved people list + + Since there might be a lot of people contributing to an audio file in + various ways, such as musicians and technicians, the 'Text + information frames' are often insufficient to list everyone involved + in a project. The 'Involved people list' is a frame containing the + names of those involved, and how they were involved. The body simply + contains a terminated string with the involvement directly followed by + a terminated string with the involvee followed by a new involvement + and so on. There may only be one "IPL" frame in each tag. + + Involved people list "IPL" + Frame size $xx xx xx + Text encoding $xx + People list strings + + +4.5. Music CD Identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD making a + maximum of 804 bytes. This frame requires a present and valid "TRK" + frame. There may only be one "MCI" frame in each tag. + + Music CD identifier "MCI" + Frame size $xx xx xx + CD TOC + + +4.6. Event timing codes + + This frame allows synchronisation with key events in a song or sound. + The head is: + + Event timing codes "ETC" + Frame size $xx xx xx + Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events should be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 mainpart start + $04 outro start + $05 outro end + $06 verse begins + $07 refrain begins + $08 interlude + $09 theme start + $0A variation + $0B key change + $0C time change + $0D unwanted noise (Snap, Crackle & Pop) + + $0E-$DF reserved for future use + + $E0-$EF not predefined sync 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + The 'Not predefined sync's ($E0-EF) are for user events. You might + want to synchronise your music to something, like setting of an + explosion on-stage, turning on your screensaver etc. + + There may only be one "ETC" frame in each tag. + + +4.7. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with timecodes in different locations in the file + might be useful. The ID3 frame includes references that the software + can use to calculate positions in the file. After the frame header is + a descriptor of how much the 'frame counter' should increase for every + reference. If this value is two then the first reference points out + the second frame, the 2nd reference the 4th frame, the 3rd reference + the 6th frame etc. In a similar way the 'bytes between reference' and + 'milliseconds between reference' points out bytes and milliseconds + respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only be + one "MLL" frame in each tag. + + Location lookup table "MLL" + ID3 frame size $xx xx xx + MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.8. Synced tempo codes + + For a more accurate description of the tempo of a musical piece this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more tempo + codes. Each tempo code consists of one tempo part and one time part. + The tempo is in BPM described with one or two bytes. If the first byte + has the value $FF, one more byte follows, which is added to the first + giving a range from 2 - 510 BPM, since $00 and $01 is reserved. $00 is + used to describe a beat-free time period, which is not the same as a + music-free time period. $01 is used to indicate one single beat-stroke + followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the tempo + in the music changes, a tempo descriptor may indicate this for the + player. All tempo descriptors should be sorted in chronological order. + The first beat-stroke in a time-period is at the same time as the beat + description occurs. There may only be one "STC" frame in each tag. + + Synced tempo codes "STC" + Frame size $xx xx xx + Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + +4.9. Unsychronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. Maximum length for the descriptor is 64 + bytes. There may be more than one lyrics/text frame in each tag, but + only one with the same language and content descriptor. + + Unsynced lyrics/text "ULT" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.10. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the audio. + It might also be used to describing events e.g. occurring on a stage + or on the screen in sync with the audio. The header includes a content + descriptor, represented with as terminated textstring. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + + Synced lyrics/text "SLT" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + + Encoding: $00 ISO-8859-1 [ISO-8859-1] character set is used => $00 + is sync identifier. + $01 Unicode [UNICODE] character set is used => $00 00 is + sync identifier. + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + + Time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps should + be sorted in chronological order. The sync can be considered as a + validator of the subsequent string. + + Newline characters are allowed in all "SLT" frames and should be used + after every entry (name, event etc.) in a frame with the content type + $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "ULT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SLT" frame in each tag, but only one with + the same language and content descriptor. + + +4.11. Comments + + This frame replaces the old 30-character comment field in ID3v1. It + consists of a frame head followed by encoding, language and content + descriptors and is ended with the actual comment as a text string. + Newline characters are allowed in the comment text string. There may + be more than one comment frame in each tag, but only one with the same + language and content descriptor. + + Comment "COM" + Frame size $xx xx xx + Text encoding $xx + Language $xx xx xx + Short content description $00 (00) + The actual text + + +4.12. Relative volume adjustment + + This is a more subjective function than the previous ones. It allows + the user to say how much he wants to increase/decrease the volume on + each channel while the file is played. The purpose is to be able to + align all files to a reference volume, so that you don't have to + change the volume constantly. This frame may also be used to balance + adjust the audio. If the volume peak levels are known then this could + be described with the 'Peak volume right' and 'Peak volume left' + field. If Peakvolume is not known these fields could be left zeroed + or completely omitted. There may only be one "RVA" frame in each + tag. + + Relative volume adjustment "RVA" + Frame size $xx xx xx + Increment/decrement %000000xx + Bits used for volume descr. $xx + Relative volume change, right $xx xx (xx ...) + Relative volume change, left $xx xx (xx ...) + Peak volume right $xx xx (xx ...) + Peak volume left $xx xx (xx ...) + + In the increment/decrement field bit 0 is used to indicate the right + channel and bit 1 is used to indicate the left channel. 1 is + increment and 0 is decrement. + + The 'bits used for volume description' field is normally $10 (16 bits) + for MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not + be $00. The volume is always represented with whole bytes, padded in + the beginning (highest bits) when 'bits used for volume description' + is not a multiple of eight. + + +4.13. Equalisation + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may only + be one "EQU" frame in each tag. + + Equalisation "EQU" + Frame size $xx xx xx + Adjustment bits $xx + + The 'adjustment bits' field defines the number of bits used for + representation of the adjustment. This is normally $10 (16 bits) for + MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not be + $00. + + This is followed by 2 bytes + ('adjustment bits' rounded up to the + nearest byte) for every equalisation band in the following format, + giving a frequency range of 0 - 32767Hz: + + Increment/decrement %x (MSB of the Frequency) + Frequency (lower 15 bits) + Adjustment $xx (xx ...) + + The increment/decrement bit is 1 for increment and 0 for decrement. + The equalisation bands should be ordered increasingly with reference + to frequency. All frequencies don't have to be declared. Adjustments + with the value $00 should be omitted. A frequency should only be + described once in the frame. + + +4.14. Reverb + + Yet another subjective one. You may here adjust echoes of different + kinds. Reverb left/right is the delay between every bounce in ms. + Reverb bounces left/right is the number of bounces that should be + made. $FF equals an infinite number of bounces. Feedback is the amount + of volume that should be returned to the next echo bounce. $00 is 0%, + $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, yet 50% on the second and so on. Left + to left means the sound from the left bounce to be played in the left + speaker, while left to right means sound from the left bounce to be + played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. Setting + both premix to $FF would result in a mono output (if the reverb is + applied symmetric). There may only be one "REV" frame in each tag. + + Reverb settings "REV" + Frame size $00 00 0C + Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.15. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is preferably "PNG" [PNG] or "JPG" [JFIF]. Description + is a short description of the picture, represented as a terminated + textstring. The description has a maximum length of 64 characters, + but may be empty. There may be several pictures attached to one file, + each in their individual "PIC" frame, but only one with the same + content descriptor. There may only be one picture with the picture + type declared as picture type $01 and $02 respectively. There is a + possibility to put only a link to the image file by using the 'image + format' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used restrictively since + there is the risk of separation of files. + + Attached picture "PIC" + Frame size $xx xx xx + Text encoding $xx + Image format $xx xx xx + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. lable side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.16. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] and 'Filename' + for the encapsulated object, both represented as terminated strings + encoded with ISO 8859-1 [ISO-8859-1]. The filename is case sensitive. + Then follows a content description as terminated string, encoded as + 'Encoding'. The last thing in the frame is the actual object. The + first two strings may be omitted, leaving only their terminations. + MIME type is always an ISO-8859-1 text string. There may be more than + one "GEO" frame in each tag, but only one with the same content + descriptor. + + General encapsulated object "GEO" + Frame size $xx xx xx + Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.17. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "CNT" frame in each tag. When the counter + reaches all one's, one byte is inserted in front of the counter thus + making the counter eight bits bigger. The counter must be at least + 32-bits long to begin with. + + Play counter "CNT" + Frame size $xx xx xx + Counter $xx xx xx xx (xx ...) + + +4.18. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audiofiles more often than others or it + could be used to profile a persons taste and find other 'good' files + by comparing people's profiles. The frame is very simple. It contains + the email address to the user, one rating byte and a four byte play + counter, intended to be increased with one for every time the file is + played. The email is a terminated string. The rating is 1-255 where + 1 is worst and 255 is best. 0 is unknown. If no personal counter is + wanted it may be omitted. When the counter reaches all one's, one + byte is inserted in front of the counter thus making the counter + eight bits bigger in the same away as the play counter ("CNT"). + There may be more than one "POP" frame in each tag, but only one with + the same email address. + + Popularimeter "POP" + Frame size $xx xx xx + Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.19. Recommended buffer size + + Sometimes the server from which a audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audiostream. + In such case the tag should reside between two MPEG [MPEG] frames, if + the audio is MPEG encoded. If the position of the next tag is known, + 'offset to next tag' may be used. The offset is calculated from the + end of tag in which this frame resides to the first byte of the header + in the next. This field may be omitted. Embedded tags is currently not + recommended since this could render unpredictable behaviour from + present software/hardware. The 'Buffer size' should be kept to a + minimum. There may only be one "BUF" frame in each tag. + + Recommended buffer size "BUF" + Frame size $xx xx xx + Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.20. Encrypted meta frame + + This frame contains one or more encrypted frames. This enables + protection of copyrighted information such as pictures and text, that + people might want to pay extra for. Since standardisation of such an + encryption scheme is beyond this document, all "CRM" frames begin with + a terminated string with a URL [URL] containing an email address, or a + link to a location where an email adress can be found, that belongs to + the organisation responsible for this specific encrypted meta frame. + + Questions regarding the encrypted frame should be sent to the + indicated email address. If a $00 is found directly after the 'Frame + size', the whole frame should be ignored, and preferably be removed. + The 'Owner identifier' is then followed by a short content description + and explanation as to why it's encrypted. After the + 'content/explanation' description, the actual encrypted block follows. + + When an ID3v2 decoder encounters a "CRM" frame, it should send the + datablock to the 'plugin' with the corresponding 'owner identifier' + and expect to receive either a datablock with one or several ID3v2 + frames after each other or an error. There may be more than one "CRM" + frames in a tag, but only one with the same 'owner identifier'. + + Encrypted meta frame "CRM" + Frame size $xx xx xx + Owner identifier $00 (00) + Content/explanation $00 (00) + Encrypted datablock + + +4.21. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encrypion scheme is beyond this + document, all "CRA" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audiofile indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should be + left zeroed. After the 'preview length' field follows optionally a + datablock required for decryption of the audio. There may be more than + one "CRA" frames in a tag, but only one with the same 'Owner + identifier'. + + Audio encryption "CRA" + Frame size $xx xx xx + Owner identifier $00 (00) + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.22. Linked information + + To keep space waste as low as possible this frame may be used to link + information from another ID3v2 tag that might reside in another audio + file or alone in a binary file. It is recommended that this method is + only used when the files are stored on a CD-ROM or other circumstances + when the risk of file seperation is low. The frame contains a frame + identifier, which is the frame that should be linked into this tag, a + URL [URL] field, where a reference to the file where the frame is + given, and additional ID data, if needed. Data should be retrieved + from the first tag found in the file to which this link points. There + may be more than one "LNK" frame in a tag, but only one with the same + contents. A linked frame is to be considered as part of the tag and + has the same restrictions as if it was a physical part of the tag + (i.e. only one "REV" frame allowed, whether it's linked or not). + + Linked information "LNK" + Frame size $xx xx xx + Frame identifier $xx xx xx + URL $00 (00) + Additional ID data + + Frames that may be linked and need no additional data are "IPL", + "MCI", "ETC", "LLT", "STC", "RVA", "EQU", "REV", "BUF", the text + information frames and the URL link frames. + + The "TXX", "PIC", "GEO", "CRM" and "CRA" frames may be linked with the + content descriptor as additional ID data. + + The "COM", "SLT" and "ULT" frames may be linked with three bytes of + language descriptor directly followed by a content descriptor as + additional ID data. + + +5. The 'unsynchronisation scheme' + + The only purpose of the 'unsychronisation scheme' is to make the ID3v2 + tag as compatible as possible with existing software. There is no use + in 'unsynchronising' tags if the file is only to be processed by new + software. Unsynchronisation may only be made with MPEG 2 layer I, II + and III and MPEG 2.5 files. + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of a correct sync that should be altered by ID3 encoders is as + follows: + + %11111111 111xxxxx + + And should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they won't be affected by the decoding process. Therefore + all the $FF 00 combinations have to be replaced with the $FF 00 00 + combination during the unsynchonisation. + + To indicate usage of the unsynchronisation, the first bit in 'ID3 + flags' should be set. This bit should only be set if the tag + contained a, now corrected, false synchronisation. The bit should + only be clear if the tag does not contain any false synchronisations. + + Do bear in mind, that if a compression scheme is used by the encoder, + the unsyncronisation scheme should be applied *afterwards*. When + decoding a compressed, 'unsyncronised' file, the 'unsyncronisation + scheme' should be parsed first, compression afterwards. + + +6. Copyright + + Copyright (C) Martin Nilsson 1998. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE + INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +7. References + + [CDDB] Compact Disc Data Base + + + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + + + [UNICODE] ISO/IEC 10646-1:1993. + Universal Multiple-Octet Coded Character Set (UCS), Part 1: + Architecture and Basic Multilingual Plane. Technical committee + / subcommittee: JTC 1 / SC 2 + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + + + +8. Appendix + + +A. Appendix A - ID3-Tag Specification V1.1 + + ID3-Tag Specification V1.1 (12 dec 1997) by Michael Mutschler + , edited for space and clarity + reasons. + + +A.1. Overview + + The ID3-Tag is an information field for MPEG Layer 3 audio files. + Since a standalone MP3 doesn't provide a method of storing other + information than those directly needed for replay reasons, the + ID3-tag was invented by Eric Kemp in 1996. + + A revision from ID3v1 to ID3v1.1 was made by Michael Mutschler to + support track number information is described in A.4. + + +A.2. ID3v1 Implementation + + The Information is stored in the last 128 bytes of an MP3. The Tag + has got the following fields, and the offsets given here, are from + 0-127. + + Field Length Offsets + Tag 3 0-2 + Songname 30 3-32 + Artist 30 33-62 + Album 30 63-92 + Year 4 93-96 + Comment 30 97-126 + Genre 1 127 + + + The string-fields contain ASCII-data, coded in ISO-Latin 1 codepage. + Strings which are smaller than the field length are padded with zero- + bytes. + + Tag: The tag is valid if this field contains the string "TAG". This + has to be uppercase! + + Songname: This field contains the title of the MP3 (string as + above). + + Artist: This field contains the artist of the MP3 (string as above). + + Album: this field contains the album where the MP3 comes from + (string as above). + + Year: this field contains the year when this song has originally + been released (string as above). + + Comment: this field contains a comment for the MP3 (string as + above). Revision to this field has been made in ID3v1.1. See + A.4. + + Genre: this byte contains the offset of a genre in a predefined + list the byte is treated as an unsigned byte. The offset is + starting from 0. See A.3. + + +A.3. Genre List + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + The following genres are Winamp extensions + + 80.Folk + 81.Folk-Rock + 82.National Folk + 83.Swing + 84.Fast Fusion + 85.Bebob + 86.Latin + 87.Revival + 88.Celtic + 89.Bluegrass + 90.Avantgarde + 91.Gothic Rock + 92.Progressive Rock + 93.Psychedelic Rock + 94.Symphonic Rock + 95.Slow Rock + 96.Big Band + 97.Chorus + 98.Easy Listening + 99.Acoustic + 100.Humour + 101.Speech + 102.Chanson + 103.Opera + 104.Chamber Music + 105.Sonata + 106.Symphony + 107.Booty Bass + 108.Primus + 109.Porn Groove + 110.Satire + 111.Slow Jam + 112.Club + 113.Tango + 114.Samba + 115.Folklore + 116.Ballad + 117.Power Ballad + 118.Rhythmic Soul + 119.Freestyle + 120.Duet + 121.Punk Rock + 122.Drum Solo + 123.A capella + 124.Euro-House + 125.Dance Hall + + +A.4. Track addition - ID3v1.1 + + In ID3v1.1, Michael Mutschler revised the specification of the + comment field in order to implement the track number. The new format + of the comment field is a 28 character string followed by a mandatory + null ($00) character and the original album tracknumber stored as an + unsigned byte-size integer. In such cases where the 29th byte is not + the null character or when the 30th is a null character, the + tracknumber is to be considered undefined. + + +9. Author's Address + + Martin Nilsson + Rydsvgen 246 C. 30 + S-584 34 Linkping + Sweden + + Email: nilsson@id3.org + + Co-authors: + + Johan Sundstrm Email: johan@id3.org + + diff --git a/external/taglib/source/mpeg/id3v2/id3v2.3.0.txt b/external/taglib/source/mpeg/id3v2/id3v2.3.0.txt new file mode 100644 index 0000000..b4ed763 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2.3.0.txt @@ -0,0 +1,2022 @@ +Informal standard M. Nilsson +Document: id3v2.3.0.txt 3rd February 1999 + + + ID3 tag version 2.3.0 + +Status of this document + + This document is an informal standard and replaces the ID3v2.2.0 + standard [ID3v2]. The informal standard is released so that + implementors could have a set standard before a formal standard is + set. The formal standard will use another version or revision number + if not identical to what is described in this document. The contents + in this document may change for clarifications but never for added or + altered functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the ID3v2.3.0, which is a more developed + version of the ID3v2 informal standard [ID3v2] (version 2.2.0), + evolved from the ID3 tagging system. The ID3v2 offers a flexible way + of storing information about an audio file within itself to determine + its origin and contents. The information may be technical + information, such as equalisation curves, as well as related meta + information, such as title, performer, copyright etc. + + +1. Table of contents + + 2. Conventions in this document + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 extended header + 3.3. ID3v2 frames overview + 3.3.1. Frame header flags + 3.3.2. Default flags + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Text information frames - details + 4.2.2. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Involved people list + 4.5. Music CD Identifier + 4.6. Event timing codes + 4.7. MPEG location lookup table + 4.8. Synced tempo codes + 4.9. Unsychronised lyrics/text transcription + 4.10. Synchronised lyrics/text + 4.11. Comments + 4.12. Relative volume adjustment + 4.13. Equalisation + 4.14. Reverb + 4.15. Attached picture + 4.16. General encapsulated object + 4.17. Play counter + 4.18. Popularimeter + 4.19. Recommended buffer size + 4.20. Audio encryption + 4.21. Linked information + 4.22. Position synchronisation frame + 4.23. Terms of use + 4.24. Ownership frame + 4.25. Commercial frame + 4.26. Encryption method registration + 4.27. Group identification registration + 4.28. Private frame + 5. The 'unsynchronisation scheme' + 6. Copyright + 7. References + 8. Appendix + A. Appendix A - Genre List from ID3v1 + 9. Author's Address + + +2. Conventions in this document + + In the examples, text within "" is a text string exactly as it + appears in a file. Numbers preceded with $ are hexadecimal and + numbers preceded with % are binary. $xx is used to indicate a byte + with unknown content. %x is used to indicate a bit with unknown + content. The most significant bit (MSB) of a byte is called 'bit 7' + and the least significant bit (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters 0-9 only. + + +3. ID3v2 overview + + The two biggest design goals were to be able to implement ID3v2 + without disturbing old software too much and that ID3v2 should be + as flexible and expandable as possible. + + The first criterion is met by the simple fact that the MPEG [MPEG] + decoding software uses a syncsignal, embedded in the audiostream, to + 'lock on to' the audio. Since the ID3v2 tag doesn't contain a valid + syncsignal, no software will attempt to play the tag. If, for any + reason, coincidence make a syncsignal appear within the tag it will + be taken care of by the 'unsynchronisation scheme' described in + section 5. + + The second criterion has made a more noticeable impact on the design + of the ID3v2 tag. It is constructed as a container for several + information blocks, called frames, whose format need not be known to + the software that encounters them. At the start of every frame there + is an identifier that explains the frames' format and content, and a + size descriptor that allows software to skip unknown frames. + + If a total revision of the ID3v2 tag should be needed, there is a + version number and a size descriptor in the ID3v2 header. + + The ID3 tag described in this document is mainly targeted at files + encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III + and MPEG-2.5, but may work with other types of encoded audio. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78). + + It is permitted to include padding after all the final frame (at the + end of the ID3 tag), making the size of all the frames together + smaller than the size given in the head of the tag. A possible + purpose of this padding is to allow for adding a few additional + frames or enlarge existing frames within the tag without having to + rewrite the entire file. The value of the padding bytes must be $00. + + +3.1. ID3v2 header + + The ID3v2 tag header, which should be the first information in the + file, is 10 bytes as follows: + + ID3v2/file identifier "ID3" + ID3v2 version $03 00 + ID3v2 flags %abc00000 + ID3v2 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3" to indicate that + this is an ID3v2 tag, directly followed by the two version bytes. The + first byte of ID3v2 version is it's major version, while the second + byte is its revision number. In this case this is ID3v2.3.0. All + revisions are backwards compatible while major versions are not. If + software with ID3v2.2.0 and below support should encounter version + three or higher it should simply ignore the whole tag. Version and + revision will never be $FF. + + The version is followed by one the ID3v2 flags field, of which + currently only three flags are used. + + + a - Unsynchronisation + + Bit 7 in the 'ID3v2 flags' indicates whether or not + unsynchronisation is used (see section 5 for details); a set bit + indicates usage. + + + b - Extended header + + The second bit (bit 6) indicates whether or not the header is + followed by an extended header. The extended header is described in + section 3.2. + + + c - Experimental indicator + + The third bit (bit 5) should be used as an 'experimental + indicator'. This flag should always be set when the tag is in an + experimental stage. + + All the other flags should be cleared. If one of these undefined + flags are set that might mean that the tag is not readable for a + parser that does not know the flags function. + + The ID3v2 tag size is encoded with four bytes where the most + significant bit (bit 7) is set to zero in every byte, making a total + of 28 bits. The zeroed bits are ignored, so a 257 bytes long tag is + represented as $00 00 02 01. + + The ID3v2 tag size is the size of the complete tag after + unsychronisation, including padding, excluding the header but not + excluding the extended header (total tag size - 10). Only 28 bits + (representing up to 256MB) are used in the size description to avoid + the introducuction of 'false syncsignals'. + + An ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. ID3v2 extended header + + The extended header contains information that is not vital to the + correct parsing of the tag information, hence the extended header is + optional. + + Extended header size $xx xx xx xx + Extended Flags $xx xx + Size of padding $xx xx xx xx + + Where the 'Extended header size', currently 6 or 10 bytes, excludes + itself. The 'Size of padding' is simply the total tag size excluding + the frames and the headers, in other words the padding. The extended + header is considered separate from the header proper, and as such is + subject to unsynchronisation. + + The extended flags are a secondary flag set which describes further + attributes of the tag. These attributes are currently defined as + follows + + %x0000000 00000000 + + + x - CRC data present + + If this flag is set four bytes of CRC-32 data is appended to the + extended header. The CRC should be calculated before + unsynchronisation on the data between the extended header and the + padding, i.e. the frames and only the frames. + + Total frame CRC $xx xx xx xx + + +3.3. ID3v2 frame overview + + As the tag consists of a tag header and a tag body with one or more + frames, all the frames consists of a frame header followed by one or + more fields containing the actual information. The layout of the + frame header: + + Frame ID $xx xx xx xx (four characters) + Size $xx xx xx xx + Flags $xx xx + + The frame ID made out of the characters capital A-Z and 0-9. + Identifiers beginning with "X", "Y" and "Z" are for experimental use + and free for everyone to use, without the need to set the + experimental bit in the tag header. Have in mind that someone else + might have used the same identifier as you. All other identifiers are + either used or reserved for future use. + + The frame ID is followed by a size descriptor, making a total header + size of ten bytes in every frame. The size is calculated as frame + size excluding frame header (frame size - 10). + + In the frame header the size descriptor is followed by two flags + bytes. These flags are described in section 3.3.1. + + There is no fixed order of the frames' appearance in the tag, + although it is desired that the frames are arranged in order of + significance concerning the recognition of the file. An example of + such order: UFID, TIT2, MCDI, TRCK ... + + A tag must contain at least one frame. A frame must be at least 1 + byte big, excluding the header. + + If nothing else is said a string is represented as ISO-8859-1 + [ISO-8859-1] characters in the range $20 - $FF. Such strings are + represented as , or if newlines are + allowed, in the frame descriptions. All Unicode strings [UNICODE] use + 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). Unicode strings + must begin with the Unicode BOM ($FF FE or $FE FF) to identify the + byte order. + + All numeric strings and URLs [URL] are always encoded as ISO-8859-1. + Terminated strings are terminated with $00 if encoded with ISO-8859-1 + and $00 00 if encoded as unicode. If nothing else is said newline + character is forbidden. In ISO-8859-1 a new line is represented, when + allowed, with $0A only. Frames that allow different types of text + encoding have a text encoding description byte directly after the + frame size. If ISO-8859-1 is used this byte should be $00, if Unicode + is used it should be $01. Strings dependent on encoding is + represented as , or if newlines are allowed. Any empty + Unicode strings which are NULL-terminated may have the Unicode BOM + followed by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00). + + The three byte language field is used to describe the language of the + frame's content, according to ISO-639-2 [ISO-639-2]. + + All URLs [URL] may be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3v2 standard. This + is reflected by the revision number in the header of the tag. + + +3.3.1. Frame header flags + + In the frame header the size descriptor is followed by two flags + bytes. All unused flags must be cleared. The first byte is for + 'status messages' and the second byte is for encoding purposes. If an + unknown flag is set in the first byte the frame may not be changed + without the bit cleared. If an unknown flag is set in the second byte + it is likely to not be readable. The flags field is defined as + follows. + + %abc00000 %ijk00000 + + + a - Tag alter preservation + + This flag tells the software what to do with this frame if it is + unknown and the tag is altered in any way. This applies to all + kinds of alterations, including adding more padding and reordering + the frames. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + b - File alter preservation + + This flag tells the software what to do with this frame if it is + unknown and the file, excluding the tag, is altered. This does not + apply when the audio is completely replaced with other audio data. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + c - Read only + + This flag, if set, tells the software that the contents of this + frame is intended to be read only. Changing the contents might + break something, e.g. a signature. If the contents are changed, + without knowledge in why the frame was flagged read only and + without taking the proper means to compensate, e.g. recalculating + the signature, the bit should be cleared. + + + i - Compression + + This flag indicates whether or not the frame is compressed. + + 0 Frame is not compressed. + 1 Frame is compressed using zlib [zlib] with 4 bytes for + 'decompressed size' appended to the frame header. + + + j - Encryption + + This flag indicates wether or not the frame is enrypted. If set + one byte indicating with which method it was encrypted will be + appended to the frame header. See section 4.26. for more + information about encryption method registration. + + 0 Frame is not encrypted. + 1 Frame is encrypted. + + + k - Grouping identity + + This flag indicates whether or not this frame belongs in a group + with other frames. If set a group identifier byte is added to the + frame header. Every frame with the same group identifier belongs + to the same group. + + 0 Frame does not contain group information + 1 Frame contains group information + + + Some flags indicates that the frame header is extended with + additional information. This information will be added to the frame + header in the same order as the flags indicating the additions. I.e. + the four bytes of decompressed size will preceed the encryption + method byte. These additions to the frame header, while not included + in the frame header size but are included in the 'frame size' field, + are not subject to encryption or compression. + + +3.3.2. Default flags + + The default settings for the frames described in this document can be + divided into the following classes. The flags may be set differently + if found more suitable by the software. + + 1. Discarded if tag is altered, discarded if file is altered. + + None. + + 2. Discarded if tag is altered, preserved if file is altered. + + None. + + 3. Preserved if tag is altered, discarded if file is altered. + + AENC, ETCO, EQUA, MLLT, POSS, SYLT, SYTC, RVAD, TENC, TLEN, TSIZ + + 4. Preserved if tag is altered, preserved if file is altered. + + The rest of the frames. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.21 AENC Audio encryption + 4.15 APIC Attached picture + + 4.11 COMM Comments + 4.25 COMR Commercial frame + + 4.26 ENCR Encryption method registration + 4.13 EQUA Equalization + 4.6 ETCO Event timing codes + + 4.16 GEOB General encapsulated object + 4.27 GRID Group identification registration + + 4.4 IPLS Involved people list + + 4.21 LINK Linked information + + 4.5 MCDI Music CD identifier + 4.7 MLLT MPEG location lookup table + + 4.24 OWNE Ownership frame + + 4.28. PRIV Private frame + 4.17 PCNT Play counter + 4.18 POPM Popularimeter + 4.22 POSS Position synchronisation frame + + 4.19 RBUF Recommended buffer size + 4.12 RVAD Relative volume adjustment + 4.14 RVRB Reverb + + 4.10 SYLT Synchronized lyric/text + 4.8 SYTC Synchronized tempo codes + + 4.2.1 TALB Album/Movie/Show title + 4.2.1 TBPM BPM (beats per minute) + 4.2.1 TCOM Composer + 4.2.1 TCON Content type + 4.2.1 TCOP Copyright message + 4.2.1 TDAT Date + 4.2.1 TDLY Playlist delay + 4.2.1 TENC Encoded by + 4.2.1 TEXT Lyricist/Text writer + 4.2.1 TFLT File type + 4.2.1 TIME Time + 4.2.1 TIT1 Content group description + 4.2.1 TIT2 Title/songname/content description + 4.2.1 TIT3 Subtitle/Description refinement + 4.2.1 TKEY Initial key + 4.2.1 TLAN Language(s) + 4.2.1 TLEN Length + 4.2.1 TMED Media type + 4.2.1 TOAL Original album/movie/show title + 4.2.1 TOFN Original filename + 4.2.1 TOLY Original lyricist(s)/text writer(s) + 4.2.1 TOPE Original artist(s)/performer(s) + 4.2.1 TORY Original release year + 4.2.1 TOWN File owner/licensee + 4.2.1 TPE1 Lead performer(s)/Soloist(s) + 4.2.1 TPE2 Band/orchestra/accompaniment + 4.2.1 TPE3 Conductor/performer refinement + 4.2.1 TPE4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPOS Part of a set + 4.2.1 TPUB Publisher + 4.2.1 TRCK Track number/Position in set + 4.2.1 TRDA Recording dates + 4.2.1 TRSN Internet radio station name + 4.2.1 TRSO Internet radio station owner + 4.2.1 TSIZ Size + 4.2.1 TSRC ISRC (international standard recording code) + 4.2.1 TSSE Software/Hardware and settings used for encoding + 4.2.1 TYER Year + 4.2.2 TXXX User defined text information frame + + 4.1 UFID Unique file identifier + 4.23 USER Terms of use + 4.9 USLT Unsychronized lyric/text transcription + + 4.3.1 WCOM Commercial information + 4.3.1 WCOP Copyright/Legal information + 4.3.1 WOAF Official audio file webpage + 4.3.1 WOAR Official artist/performer webpage + 4.3.1 WOAS Official audio source webpage + 4.3.1 WORS Official internet radio station homepage + 4.3.1 WPAY Payment + 4.3.1 WPUB Publishers official webpage + 4.3.2 WXXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database that may contain more information relevant to the content. + Since standardisation of such a database is beyond this document, all + frames begin with a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific database implementation. Questions regarding the + database should be sent to the indicated email address. The URL + should not be used for the actual database queries. The string + "http://www.id3.org/dummy/ufid.html" should be used for tests. + Software that isn't told otherwise may safely remove such frames. The + 'Owner identifier' must be non-empty (more than just a termination). + The 'Owner identifier' is then followed by the actual identifier, + which may be up to 64 bytes. There may be more than one "UFID" frame + in a tag, but only one with the same 'Owner identifier'. + +
+ Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are the most important frames, containing + information like artist, album and more. There may only be one text + information frame of its kind in an tag. If the textstring is + followed by a termination ($00 (00)) all the following information + should be ignored and not be displayed. All text frame identifiers + begin with "T". Only text frame identifiers begin with "T", with the + exception of the "TXXX" frame. All the text information frames have + the following format: + +
+ Text encoding $xx + Information + + +4.2.1. Text information frames - details + + TALB + The 'Album/Movie/Show title' frame is intended for the title of the + recording(/source of sound) which the audio in the file is taken + from. + + TBPM + The 'BPM' frame contains the number of beats per minute in the + mainpart of the audio. The BPM is an integer and represented as a + numerical string. + + TCOM + The 'Composer(s)' frame is intended for the name of the composer(s). + They are seperated with the "/" character. + + TCON + The 'Content type', which previously was stored as a one byte numeric + value only, is now a numeric string. You may use one or several of + the types as ID3v1.1 did or, since the category list would be + impossible to maintain with accurate and up to date categories, + define your own. + + References to the ID3v1 genres can be made by, as first byte, enter + "(" followed by a number from the genres list (appendix A.) and + ended with a ")" character. This is optionally followed by a + refinement, e.g. "(21)" or "(4)Eurodisco". Several references can be + made in the same frame, e.g. "(51)(39)". If the refinement should + begin with a "(" character it should be replaced with "((", e.g. "((I + can figure out any genre)" or "(55)((I think...)". The following new + content types is defined in ID3v2 and is implemented in the same way + as the numerig content types, e.g. "(RX)". + + RX Remix + CR Cover + + TCOP + The 'Copyright message' frame, which must begin with a year and a + space character (making five characters), is intended for the + copyright holder of the original sound, not the audio file itself. + The absence of this frame means only that the copyright information + is unavailable or has been removed, and must not be interpreted to + mean that the sound is public domain. Every time this field is + displayed the field must be preceded with "Copyright " (C) " ", where + (C) is one character showing a C in a circle. + + TDAT + The 'Date' frame is a numeric string in the DDMM format containing + the date for the recording. This field is always four characters + long. + + TDLY + The 'Playlist delay' defines the numbers of milliseconds of silence + between every song in a playlist. The player should use the "ETC" + frame, if present, to skip initial silence and silence at the end of + the audio to match the 'Playlist delay' time. The time is represented + as a numeric string. + + TENC + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + TEXT + The 'Lyricist(s)/Text writer(s)' frame is intended for the writer(s) + of the text or lyrics in the recording. They are seperated with the + "/" character. + + TFLT + The 'File type' frame indicates which type of audio this tag defines. + The following type and refinements are defined: + + MPG MPEG Audio + /1 MPEG 1/2 layer I + /2 MPEG 1/2 layer II + /3 MPEG 1/2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + VQF Transform-domain Weighted Interleave Vector Quantization + PCM Pulse Code Modulated audio + + but other types may be used, not for these types though. This is used + in a similar way to the predefined types in the "TMED" frame, but + without parentheses. If this frame is not present audio type is + assumed to be "MPG". + + TIME + The 'Time' frame is a numeric string in the HHMM format containing + the time for the recording. This field is always four characters + long. + + TIT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TIT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TIT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at Wembley"). + + TKEY + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m". Example "Cbm". Off key is represented with an "o" + only. + + TLAN + The 'Language(s)' frame should contain the languages of the text or + lyrics spoken or sung in the audio. The language is represented with + three characters according to ISO-639-2. If more than one language is + used in the text their language codes should follow according to + their usage. + + TLEN + The 'Length' frame contains the length of the audiofile in + milliseconds, represented as a numeric string. + + TMED + The 'Media type' frame describes from which media the sound + originated. This may be a text string or a reference to the + predefined media types found in the list below. References are made + within "(" and ")" and are optionally followed by a text refinement, + e.g. "(MC) with four channels". If a text refinement should begin + with a "(" character it should be replaced with "((" in the same way + as in the "TCO" frame. Predefined refinements is appended after the + media type, e.g. "(CD/A)" or "(VID/PAL/VHS)". + + DIG Other digital media + /A Analog transfer from media + + ANA Other analog media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analog transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + /A Analog transfer from media + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analog transfer from media + + DAT DAT + /A Analog transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, nonlinear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analog transfer from media + + DVD DVD + /A Analog transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TOAL + The 'Original album/movie/show title' frame is intended for the title + of the original recording (or source of sound), if for example the + music in the file should be a cover of a previously released song. + + TOFN + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TOLY + The 'Original lyricist(s)/text writer(s)' frame is intended for the + text writer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The text + writers are seperated with the "/" character. + + TOPE + The 'Original artist(s)/performer(s)' frame is intended for the + performer(s) of the original recording, if for example the music in + the file should be a cover of a previously released song. The + performers are seperated with the "/" character. + + TORY + The 'Original release year' frame is intended for the year when the + original recording, if for example the music in the file should be a + cover of a previously released song, was released. The field is + formatted as in the "TYER" frame. + + TOWN + The 'File owner/licensee' frame contains the name of the owner or + licensee of the file and it's contents. + + TPE1 + The 'Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group' is + used for the main artist(s). They are seperated with the "/" + character. + + TPE2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TPE3 + The 'Conductor' frame is used for the name of the conductor. + + TPE4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TPOS + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TALB" frame is divided into several mediums, e.g. a + double CD. The value may be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TPUB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TRCK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This may be extended with a "/" character and a numeric + string containing the total numer of tracks/elements on the original + recording. E.g. "4/9". + + TRDA + The 'Recording dates' frame is a intended to be used as complement to + the "TYER", "TDAT" and "TIME" frames. E.g. "4th-7th June, 12th June" + in combination with the "TYER" frame. + + TRSN + The 'Internet radio station name' frame contains the name of the + internet radio station from which the audio is streamed. + + TRSO + The 'Internet radio station owner' frame contains the name of the + owner of the internet radio station from which the audio is + streamed. + + TSIZ + The 'Size' frame contains the size of the audiofile in bytes, + excluding the ID3v2 tag, represented as a numeric string. + + TSRC + The 'ISRC' frame should contain the International Standard Recording + Code [ISRC] (12 characters). + + TSSE + The 'Software/Hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TYER + The 'Year' frame is a numeric string with a year of the recording. + This frames is always four characters long (until the year 10000). + + +4.2.2. User defined text information frame + + This frame is intended for one-string text information concerning the + audiofile in a similar way to the other "T"-frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXXX" frame in each tag, but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + textstring is followed by a termination ($00 (00)) all the following + information should be ignored and not be displayed. All URL link + frame identifiers begins with "W". Only URL link frame identifiers + begins with "W". All URL link frames have the following format: + +
+ URL + + +4.3.1. URL link frames - details + + WCOM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCOM" frame in a tag, but not with the same content. + + WCOP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is + described. + + WOAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WOAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WOAR" frame + in a tag if the audio contains more than one performer, but not with + the same content. + + WOAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WORS + The 'Official internet radio station homepage' contains a URL + pointing at the homepage of the internet radio station. + + WPAY + The 'Payment' frame is a URL pointing at a webpage that will handle + the process of paying for this file. + + WPUB + The 'Publishers official webpage' frame is a URL pointing at the + official wepage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audiofile + in a similar way to the other "W"-frames. The frame body consists + of a description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXXX" frame in each tag, + but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + URL + + +4.4. Involved people list + + Since there might be a lot of people contributing to an audio file in + various ways, such as musicians and technicians, the 'Text + information frames' are often insufficient to list everyone involved + in a project. The 'Involved people list' is a frame containing the + names of those involved, and how they were involved. The body simply + contains a terminated string with the involvement directly followed + by a terminated string with the involvee followed by a new + involvement and so on. There may only be one "IPLS" frame in each + tag. + +
+ Text encoding $xx + People list strings + + +4.5. Music CD identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD plus 8 + bytes for the 'lead out' making a maximum of 804 bytes. The offset to + the beginning of every track on the CD should be described with a + four bytes absolute CD-frame address per track, and not with absolute + time. This frame requires a present and valid "TRCK" frame, even if + the CD's only got one track. There may only be one "MCDI" frame in + each tag. + +
+ CD TOC + + +4.6. Event timing codes + + This frame allows synchronisation with key events in a song or sound. + The header is: + +
+ Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events should be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 mainpart start + $04 outro start + $05 outro end + $06 verse start + $07 refrain start + $08 interlude start + $09 theme start + $0A variation start + $0B key change + $0C time change + $0D momentary unwanted noise (Snap, Crackle & Pop) + $0E sustained noise + $0F sustained noise end + $10 intro end + $11 mainpart end + $12 verse end + $13 refrain end + $14 theme end + + $15-$DF reserved for future use + + $E0-$EF not predefined sync 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + Terminating the start events such as "intro start" is not required. + The 'Not predefined sync's ($E0-EF) are for user events. You might + want to synchronise your music to something, like setting of an + explosion on-stage, turning on your screensaver etc. + + There may only be one "ETCO" frame in each tag. + + +4.7. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with timecodes in different locations in the file + might be useful. The ID3v2 frame includes references that the + software can use to calculate positions in the file. After the frame + header is a descriptor of how much the 'frame counter' should + increase for every reference. If this value is two then the first + reference points out the second frame, the 2nd reference the 4th + frame, the 3rd reference the 6th frame etc. In a similar way the + 'bytes between reference' and 'milliseconds between reference' points + out bytes and milliseconds respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only + be one "MLLT" frame in each tag. + +
+ MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.8. Synchronised tempo codes + + For a more accurate description of the tempo of a musical piece this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more + tempo codes. Each tempo code consists of one tempo part and one time + part. The tempo is in BPM described with one or two bytes. If the + first byte has the value $FF, one more byte follows, which is added + to the first giving a range from 2 - 510 BPM, since $00 and $01 is + reserved. $00 is used to describe a beat-free time period, which is + not the same as a music-free time period. $01 is used to indicate one + single beat-stroke followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the + tempo in the music changes, a tempo descriptor may indicate this for + the player. All tempo descriptors should be sorted in chronological + order. The first beat-stroke in a time-period is at the same time as + the beat description occurs. There may only be one "SYTC" frame in + each tag. + +
+ Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + +4.9. Unsychronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. There may be more than one 'Unsynchronised + lyrics/text transcription' frame in each tag, but only one with the + same language and content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.10. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the + audio. It might also be used to describing events e.g. occurring on a + stage or on the screen in sync with the audio. The header includes a + content descriptor, represented with as terminated textstring. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + +
+ Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + + Encoding: $00 ISO-8859-1 [ISO-8859-1] character set is used => $00 + is sync identifier. + $01 Unicode [UNICODE] character set is used => $00 00 is + sync identifier. + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + $06 is trivia/'pop up' information + + Time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Abolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps + should be sorted in chronological order. The sync can be considered + as a validator of the subsequent string. + + Newline ($0A) characters are allowed in all "SYLT" frames and should + be used after every entry (name, event etc.) in a frame with the + content type $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "USLT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SYLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SYLT" frame in each tag, but only one + with the same language and content descriptor. + + +4.11. Comments + + This frame is indended for any kind of full text information that + does not fit in any other frame. It consists of a frame header + followed by encoding, language and content descriptors and is ended + with the actual comment as a text string. Newline characters are + allowed in the comment text string. There may be more than one + comment frame in each tag, but only one with the same language and + content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Short content descrip. $00 (00) + The actual text + + +4.12. Relative volume adjustment + + This is a more subjective function than the previous ones. It allows + the user to say how much he wants to increase/decrease the volume on + each channel while the file is played. The purpose is to be able to + align all files to a reference volume, so that you don't have to + change the volume constantly. This frame may also be used to balance + adjust the audio. If the volume peak levels are known then this could + be described with the 'Peak volume right' and 'Peak volume left' + field. If Peakvolume is not known these fields could be left zeroed + or, if no other data follows, be completely omitted. There may only + be one "RVAD" frame in each tag. + +
+ Increment/decrement %00xxxxxx + Bits used for volume descr. $xx + Relative volume change, right $xx xx (xx ...) + Relative volume change, left $xx xx (xx ...) + Peak volume right $xx xx (xx ...) + Peak volume left $xx xx (xx ...) + + In the increment/decrement field bit 0 is used to indicate the right + channel and bit 1 is used to indicate the left channel. 1 is + increment and 0 is decrement. + + The 'bits used for volume description' field is normally $10 (16 + bits) for MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value + may not be $00. The volume is always represented with whole bytes, + padded in the beginning (highest bits) when 'bits used for volume + description' is not a multiple of eight. + + This datablock is then optionally followed by a volume definition for + the left and right back channels. If this information is appended to + the frame the first two channels will be treated as front channels. + In the increment/decrement field bit 2 is used to indicate the right + back channel and bit 3 for the left back channel. + + Relative volume change, right back $xx xx (xx ...) + Relative volume change, left back $xx xx (xx ...) + Peak volume right back $xx xx (xx ...) + Peak volume left back $xx xx (xx ...) + + If the center channel adjustment is present the following is appended + to the existing frame, after the left and right back channels. The + center channel is represented by bit 4 in the increase/decrease + field. + + Relative volume change, center $xx xx (xx ...) + Peak volume center $xx xx (xx ...) + + If the bass channel adjustment is present the following is appended + to the existing frame, after the center channel. The bass channel is + represented by bit 5 in the increase/decrease field. + + Relative volume change, bass $xx xx (xx ...) + Peak volume bass $xx xx (xx ...) + + +4.13. Equalisation + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may only + be one "EQUA" frame in each tag. + +
+ Adjustment bits $xx + + The 'adjustment bits' field defines the number of bits used for + representation of the adjustment. This is normally $10 (16 bits) for + MPEG 2 layer I, II and III [MPEG] and MPEG 2.5. This value may not be + $00. + + This is followed by 2 bytes + ('adjustment bits' rounded up to the + nearest byte) for every equalisation band in the following format, + giving a frequency range of 0 - 32767Hz: + + Increment/decrement %x (MSB of the Frequency) + Frequency (lower 15 bits) + Adjustment $xx (xx ...) + + The increment/decrement bit is 1 for increment and 0 for decrement. + The equalisation bands should be ordered increasingly with reference + to frequency. All frequencies don't have to be declared. The + equalisation curve in the reading software should be interpolated + between the values in this frame. Three equal adjustments for three + subsequent frequencies. A frequency should only be described once in + the frame. + + +4.14. Reverb + + Yet another subjective one. You may here adjust echoes of different + kinds. Reverb left/right is the delay between every bounce in ms. + Reverb bounces left/right is the number of bounces that should be + made. $FF equals an infinite number of bounces. Feedback is the + amount of volume that should be returned to the next echo bounce. $00 + is 0%, $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, 50% of that on the second and so on. + Left to left means the sound from the left bounce to be played in the + left speaker, while left to right means sound from the left bounce to + be played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. + Setting both premix to $FF would result in a mono output (if the + reverb is applied symmetric). There may only be one "RVRB" frame in + each tag. + +
+ Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.15. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is the MIME type and subtype [MIME] for the image. In + the event that the MIME media type name is omitted, "image/" will be + implied. The "image/png" [PNG] or "image/jpeg" [JFIF] picture format + should be used when interoperability is wanted. Description is a + short description of the picture, represented as a terminated + textstring. The description has a maximum length of 64 characters, + but may be empty. There may be several pictures attached to one file, + each in their individual "APIC" frame, but only one with the same + content descriptor. There may only be one picture with the picture + type declared as picture type $01 and $02 respectively. There is the + possibility to put only a link to the image file by using the 'MIME + type' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used sparingly since there + is the risk of separation of files. + +
+ Text encoding $xx + MIME type $00 + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. lable side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.16. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] represented as + as a terminated string encoded with ISO 8859-1 [ISO-8859-1]. The + filename is case sensitive and is encoded as 'Encoding'. Then follows + a content description as terminated string, encoded as 'Encoding'. + The last thing in the frame is the actual object. The first two + strings may be omitted, leaving only their terminations. MIME type is + always an ISO-8859-1 text string. There may be more than one "GEOB" + frame in each tag, but only one with the same content descriptor. + +
+ Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.17. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "PCNT" frame in each tag. When the + counter reaches all one's, one byte is inserted in front of the + counter thus making the counter eight bits bigger. The counter must + be at least 32-bits long to begin with. + +
+ Counter $xx xx xx xx (xx ...) + + +4.18. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audiofiles more often than others or it + could be used to profile a person's taste and find other 'good' files + by comparing people's profiles. The frame is very simple. It contains + the email address to the user, one rating byte and a four byte play + counter, intended to be increased with one for every time the file is + played. The email is a terminated string. The rating is 1-255 where + 1 is worst and 255 is best. 0 is unknown. If no personal counter is + wanted it may be omitted. When the counter reaches all one's, one + byte is inserted in front of the counter thus making the counter + eight bits bigger in the same away as the play counter ("PCNT"). + There may be more than one "POPM" frame in each tag, but only one + with the same email address. + +
+ Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.19. Recommended buffer size + + Sometimes the server from which a audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audiostream. + In such case the tag should reside between two MPEG [MPEG] frames, if + the audio is MPEG encoded. If the position of the next tag is known, + 'offset to next tag' may be used. The offset is calculated from the + end of tag in which this frame resides to the first byte of the + header in the next. This field may be omitted. Embedded tags are + generally not recommended since this could render unpredictable + behaviour from present software/hardware. + + For applications like streaming audio it might be an idea to embed + tags into the audio stream though. If the clients connects to + individual connections like HTTP and there is a possibility to begin + every transmission with a tag, then this tag should include a + 'recommended buffer size' frame. If the client is connected to a + arbitrary point in the stream, such as radio or multicast, then the + 'recommended buffer size' frame should be included in every tag. + Every tag that is picked up after the initial/first tag is to be + considered as an update of the previous one. E.g. if there is a + "TIT2" frame in the first received tag and one in the second tag, + then the first should be 'replaced' with the second. + + The 'Buffer size' should be kept to a minimum. There may only be one + "RBUF" frame in each tag. + +
+ Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.20. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encrypion scheme is beyond this + document, all "AENC" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audiofile indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should + be left zeroed. After the 'preview length' field follows optionally a + datablock required for decryption of the audio. There may be more + than one "AENC" frames in a tag, but only one with the same 'Owner + identifier'. + +
+ Owner identifier $00 + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.21. Linked information + + To keep space waste as low as possible this frame may be used to link + information from another ID3v2 tag that might reside in another audio + file or alone in a binary file. It is recommended that this method is + only used when the files are stored on a CD-ROM or other + circumstances when the risk of file seperation is low. The frame + contains a frame identifier, which is the frame that should be linked + into this tag, a URL [URL] field, where a reference to the file where + the frame is given, and additional ID data, if needed. Data should be + retrieved from the first tag found in the file to which this link + points. There may be more than one "LINK" frame in a tag, but only + one with the same contents. A linked frame is to be considered as + part of the tag and has the same restrictions as if it was a physical + part of the tag (i.e. only one "RVRB" frame allowed, whether it's + linked or not). + +
+ Frame identifier $xx xx xx + URL $00 + ID and additional data + + Frames that may be linked and need no additional data are "IPLS", + "MCID", "ETCO", "MLLT", "SYTC", "RVAD", "EQUA", "RVRB", "RBUF", the + text information frames and the URL link frames. + + The "TXXX", "APIC", "GEOB" and "AENC" frames may be linked with + the content descriptor as additional ID data. + + The "COMM", "SYLT" and "USLT" frames may be linked with three bytes + of language descriptor directly followed by a content descriptor as + additional ID data. + + +4.22. Position synchronisation frame + + This frame delivers information to the listener of how far into the + audio stream he picked up; in effect, it states the time offset of + the first frame in the stream. The frame layout is: + + + Time stamp format $xx + Position $xx (xx ...) + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + and position is where in the audio the listener starts to receive, + i.e. the beginning of the next frame. If this frame is used in the + beginning of a file the value is always 0. There may only be one + "POSS" frame in each tag. + + +4.23. Terms of use frame + + This frame contains a brief description of the terms of use and + ownership of the file. More detailed information concerning the legal + terms might be available through the "WCOP" frame. Newlines are + allowed in the text. There may only be one "USER" frame in a tag. + +
+ Text encoding $xx + Language $xx xx xx + The actual text + + +4.24. Ownership frame + + The ownership frame might be used as a reminder of a made transaction + or, if signed, as proof. Note that the "USER" and "TOWN" frames are + good to use in conjunction with this one. The frame begins, after the + frame ID, size and encoding fields, with a 'price payed' field. The + first three characters of this field contains the currency used for + the transaction, encoded according to ISO 4217 [ISO-4217] alphabetic + currency code. Concatenated to this is the actual price payed, as a + numerical string using "." as the decimal separator. Next is an 8 + character date string (YYYYMMDD) followed by a string with the name + of the seller as the last field in the frame. There may only be one + "OWNE" frame in a tag. + +
+ Text encoding $xx + Price payed $00 + Date of purch. + Seller + + +4.25. Commercial frame + + This frame enables several competing offers in the same tag by + bundling all needed information. That makes this frame rather complex + but it's an easier solution than if one tries to achieve the same + result with several frames. The frame begins, after the frame ID, + size and encoding fields, with a price string field. A price is + constructed by one three character currency code, encoded according + to ISO 4217 [ISO-4217] alphabetic currency code, followed by a + numerical value where "." is used as decimal seperator. In the price + string several prices may be concatenated, seperated by a "/" + character, but there may only be one currency of each type. + + The price string is followed by an 8 character date string in the + format YYYYMMDD, describing for how long the price is valid. After + that is a contact URL, with which the user can contact the seller, + followed by a one byte 'received as' field. It describes how the + audio is delivered when bought according to the following list: + + $00 Other + $01 Standard CD album with other songs + $02 Compressed audio on CD + $03 File over the Internet + $04 Stream over the Internet + $05 As note sheets + $06 As note sheets in a book with other sheets + $07 Music on other media + $08 Non-musical merchandise + + Next follows a terminated string with the name of the seller followed + by a terminated string with a short description of the product. The + last thing is the ability to include a company logotype. The first of + them is the 'Picture MIME type' field containing information about + which picture format is used. In the event that the MIME media type + name is omitted, "image/" will be implied. Currently only "image/png" + and "image/jpeg" are allowed. This format string is followed by the + binary picture data. This two last fields may be omitted if no + picture is to attach. + +
+ Text encoding $xx + Price string $00 + Valid until + Contact URL $00 + Received as $xx + Name of seller $00 (00) + Description $00 (00) + Picture MIME type $00 + Seller logo + + +4.26. Encryption method registration + + To identify with which method a frame has been encrypted the + encryption method must be registered in the tag with this frame. The + 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific encryption method. Questions regarding the + encryption method should be sent to the indicated email address. The + 'Method symbol' contains a value that is associated with this method + throughout the whole tag. Values below $80 are reserved. The 'Method + symbol' may optionally be followed by encryption specific data. There + may be several "ENCR" frames in a tag but only one containing the + same symbol and only one containing the same owner identifier. The + method must be used somewhere in the tag. See section 3.3.1, flag j + for more information. + +
+ Owner identifier $00 + Method symbol $xx + Encryption data + + +4.27. Group identification registration + + This frame enables grouping of otherwise unrelated frames. This can + be used when some frames are to be signed. To identify which frames + belongs to a set of frames a group identifier must be registered in + the tag with this frame. The 'Owner identifier' is a null-terminated + string with a URL [URL] containing an email address, or a link to a + location where an email address can be found, that belongs to the + organisation responsible for this grouping. Questions regarding the + grouping should be sent to the indicated email address. The 'Group + symbol' contains a value that associates the frame with this group + throughout the whole tag. Values below $80 are reserved. The 'Group + symbol' may optionally be followed by some group specific data, e.g. + a digital signature. There may be several "GRID" frames in a tag but + only one containing the same symbol and only one containing the same + owner identifier. The group symbol must be used somewhere in the tag. + See section 3.3.1, flag j for more information. + +
+ Owner identifier $00 + Group symbol $xx + Group dependent data + + +4.28. Private frame + + This frame is used to contain information from a software producer + that its program uses and does not fit into the other frames. The + frame consists of an 'Owner identifier' string and the binary data. + The 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for the frame. Questions regarding the frame should be sent to the + indicated email address. The tag may contain more than one "PRIV" + frame but only with different contents. It is recommended to keep the + number of "PRIV" frames as low as possible. + +
+ Owner identifier $00 + The private data + + +5. The 'unsynchronisation scheme' + + The only purpose of the 'unsynchronisation scheme' is to make the + ID3v2 tag as compatible as possible with existing software. There is + no use in 'unsynchronising' tags if the file is only to be processed + by new software. Unsynchronisation may only be made with MPEG 2 layer + I, II and III and MPEG 2.5 files. + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of a correct sync that should be altered by ID3 encoders is as + follows: + + %11111111 111xxxxx + + And should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they won't be affected by the decoding process. Therefore + all the $FF 00 combinations have to be replaced with the $FF 00 00 + combination during the unsynchronisation. + + To indicate usage of the unsynchronisation, the first bit in 'ID3 + flags' should be set. This bit should only be set if the tag + contains a, now corrected, false synchronisation. The bit should + only be clear if the tag does not contain any false synchronisations. + + Do bear in mind, that if a compression scheme is used by the encoder, + the unsynchronisation scheme should be applied *afterwards*. When + decoding a compressed, 'unsynchronised' file, the 'unsynchronisation + scheme' should be parsed first, decompression afterwards. + + If the last byte in the tag is $FF, and there is a need to eliminate + false synchronisations in the tag, at least one byte of padding + should be added. + + +6. Copyright + + Copyright (C) Martin Nilsson 1998. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +7. References + + [CDDB] Compact Disc Data Base + + http://www.cddb.com + + [ID3v2] Martin Nilsson, "ID3v2 informal standard". + + http://www.id3lib.org/id3/id3v2-00.txt + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-4217] ISO 4217:1995. + Codes for the representation of currencies and funds. + Technical committee / subcommittee: TC 68 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + http://www.w3.org/Graphics/JPEG/jfif.txt">http://www.w3.org/Graphics/JPEG/jfif.txt + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + ftp://ftp.isi.edu/in-notes/rfc2045.txt">ftp://ftp.isi.edu/in-notes/rfc2045.txt + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + http://www.w3.org/TR/REC-png-multi.html + + [UNICODE] ISO/IEC 10646-1:1993. + Universal Multiple-Octet Coded Character Set (UCS), Part 1: + Architecture and Basic Multilingual Plane. + Technical committee / subcommittee: JTC 1 / SC 2 + + http://www.unicode.org/ + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + ftp://ftp.isi.edu/in-notes/rfc1738.txt + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, "ZLIB + Compressed + Data Format Specification version 3.3", RFC 1950, May 1996. + + ftp://ftp.isi.edu/in-notes/rfc1950.txt + + +8. Appendix + + +A. Appendix A - Genre List from ID3v1 + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + The following genres are Winamp extensions + + 80.Folk + 81.Folk-Rock + 82.National Folk + 83.Swing + 84.Fast Fusion + 85.Bebob + 86.Latin + 87.Revival + 88.Celtic + 89.Bluegrass + 90.Avantgarde + 91.Gothic Rock + 92.Progressive Rock + 93.Psychedelic Rock + 94.Symphonic Rock + 95.Slow Rock + 96.Big Band + 97.Chorus + 98.Easy Listening + 99.Acoustic + 100.Humour + 101.Speech + 102.Chanson + 103.Opera + 104.Chamber Music + 105.Sonata + 106.Symphony + 107.Booty Bass + 108.Primus + 109.Porn Groove + 110.Satire + 111.Slow Jam + 112.Club + 113.Tango + 114.Samba + 115.Folklore + 116.Ballad + 117.Power Ballad + 118.Rhythmic Soul + 119.Freestyle + 120.Duet + 121.Punk Rock + 122.Drum Solo + 123.Acapella + 124.Euro-House + 125.Dance Hall + + +9. Author's Address + + Written by + + Martin Nilsson + Rydsvgen 246 C. 30 + S-584 34 Linkping + Sweden + + Email: nilsson@id3.org + + + Edited by + + Dirk Mahoney + 57 Pechey Street + Chermside Q + Australia 4032 + + Email: dirk@id3.org + + + Johan Sundstrm + Alsttersgatan 5 A. 34 + S-584 35 Linkping + Sweden + + Email: johan@id3.org diff --git a/external/taglib/source/mpeg/id3v2/id3v2.4.0-frames.txt b/external/taglib/source/mpeg/id3v2/id3v2.4.0-frames.txt new file mode 100644 index 0000000..74a21be --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2.4.0-frames.txt @@ -0,0 +1,1734 @@ +$Id$ + +Informal standard M. Nilsson +Document: id3v2.4.0-frames.txt 1st November 2000 + + + ID3 tag version 2.4.0 - Native Frames + +Status of this document + + This document is an informal standard and replaces the ID3v2.3.0 + standard [ID3v2]. A formal standard will use another revision number + even if the content is identical to document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the frames natively supported by ID3v2.4.0, + which is a revised version of the ID3v2 informal standard [ID3v2.3.0] + version 2.3.0. The ID3v2 offers a flexible way of storing audio meta + information within audio file itself. The information may be + technical information, such as equalisation curves, as well as title, + performer, copyright etc. + + ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order + to allow for implementations to be revised as easily as possible. + + +1. Table of contents + + 2. Conventions in this document + 3. Default flags + 4. Declared ID3v2 frames + 4.1. Unique file identifier + 4.2. Text information frames + 4.2.1. Identification frames + 4.2.2. Involved persons frames + 4.2.3. Derived and subjective properties frames + 4.2.4. Rights and license frames + 4.2.5. Other text frames + 4.2.6. User defined text information frame + 4.3. URL link frames + 4.3.1. URL link frames - details + 4.3.2. User defined URL link frame + 4.4. Music CD Identifier + 4.5. Event timing codes + 4.6. MPEG location lookup table + 4.7. Synced tempo codes + 4.8. Unsynchronised lyrics/text transcription + 4.9. Synchronised lyrics/text + 4.10. Comments + 4.11. Relative volume adjustment (2) + 4.12. Equalisation (2) + 4.13. Reverb + 4.14. Attached picture + 4.15. General encapsulated object + 4.16. Play counter + 4.17. Popularimeter + 4.18. Recommended buffer size + 4.19. Audio encryption + 4.20. Linked information + 4.21. Position synchronisation frame + 4.22. Terms of use + 4.23. Ownership frame + 4.24. Commercial frame + 4.25. Encryption method registration + 4.26. Group identification registration + 4.27. Private frame + 4.28. Signature frame + 4.29. Seek frame + 4.30. Audio seek point index + 5. Copyright + 6. References + 7. Appendix + A. Appendix A - Genre List from ID3v1 + 8. Author's Address + + +2. Conventions in this document + + Text within "" is a text string exactly as it appears in a tag. + Numbers preceded with $ are hexadecimal and numbers preceded with % + are binary. $xx is used to indicate a byte with unknown content. %x + is used to indicate a bit with unknown content. The most significant + bit (MSB) of a byte is called 'bit 7' and the least significant bit + (LSB) is called 'bit 0'. + + A tag is the whole tag described the ID3v2 main structure document + [ID3v2-strct]. A frame is a block of information in the tag. The tag + consists of a header, frames and optional padding. A field is a piece + of information; one value, a string etc. A numeric string is a string + that consists of the characters "0123456789" only. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [KEYWORDS]. + + +3. Default flags + + The default settings for the frames described in this document can be + divided into the following classes. The flags may be set differently + if found more suitable by the software. + + 1. Discarded if tag is altered, discarded if file is altered. + + None. + + 2. Discarded if tag is altered, preserved if file is altered. + + None. + + 3. Preserved if tag is altered, discarded if file is altered. + + ASPI, AENC, ETCO, EQU2, MLLT, POSS, SEEK, SYLT, SYTC, RVA2, TENC, + TLEN + + 4. Preserved if tag is altered, preserved if file is altered. + + The rest of the frames. + + +4. Declared ID3v2 frames + + The following frames are declared in this draft. + + 4.19 AENC Audio encryption + 4.14 APIC Attached picture + 4.30 ASPI Audio seek point index + + 4.10 COMM Comments + 4.24 COMR Commercial frame + + 4.25 ENCR Encryption method registration + 4.12 EQU2 Equalisation (2) + 4.5 ETCO Event timing codes + + 4.15 GEOB General encapsulated object + 4.26 GRID Group identification registration + + 4.20 LINK Linked information + + 4.4 MCDI Music CD identifier + 4.6 MLLT MPEG location lookup table + + 4.23 OWNE Ownership frame + + 4.27 PRIV Private frame + 4.16 PCNT Play counter + 4.17 POPM Popularimeter + 4.21 POSS Position synchronisation frame + + 4.18 RBUF Recommended buffer size + 4.11 RVA2 Relative volume adjustment (2) + 4.13 RVRB Reverb + + 4.29 SEEK Seek frame + 4.28 SIGN Signature frame + 4.9 SYLT Synchronised lyric/text + 4.7 SYTC Synchronised tempo codes + + 4.2.1 TALB Album/Movie/Show title + 4.2.3 TBPM BPM (beats per minute) + 4.2.2 TCOM Composer + 4.2.3 TCON Content type + 4.2.4 TCOP Copyright message + 4.2.5 TDEN Encoding time + 4.2.5 TDLY Playlist delay + 4.2.5 TDOR Original release time + 4.2.5 TDRC Recording time + 4.2.5 TDRL Release time + 4.2.5 TDTG Tagging time + 4.2.2 TENC Encoded by + 4.2.2 TEXT Lyricist/Text writer + 4.2.3 TFLT File type + 4.2.2 TIPL Involved people list + 4.2.1 TIT1 Content group description + 4.2.1 TIT2 Title/songname/content description + 4.2.1 TIT3 Subtitle/Description refinement + 4.2.3 TKEY Initial key + 4.2.3 TLAN Language(s) + 4.2.3 TLEN Length + 4.2.2 TMCL Musician credits list + 4.2.3 TMED Media type + 4.2.3 TMOO Mood + 4.2.1 TOAL Original album/movie/show title + 4.2.5 TOFN Original filename + 4.2.2 TOLY Original lyricist(s)/text writer(s) + 4.2.2 TOPE Original artist(s)/performer(s) + 4.2.4 TOWN File owner/licensee + 4.2.2 TPE1 Lead performer(s)/Soloist(s) + 4.2.2 TPE2 Band/orchestra/accompaniment + 4.2.2 TPE3 Conductor/performer refinement + 4.2.2 TPE4 Interpreted, remixed, or otherwise modified by + 4.2.1 TPOS Part of a set + 4.2.4 TPRO Produced notice + 4.2.4 TPUB Publisher + 4.2.1 TRCK Track number/Position in set + 4.2.4 TRSN Internet radio station name + 4.2.4 TRSO Internet radio station owner + 4.2.5 TSOA Album sort order + 4.2.5 TSOP Performer sort order + 4.2.5 TSOT Title sort order + 4.2.1 TSRC ISRC (international standard recording code) + 4.2.5 TSSE Software/Hardware and settings used for encoding + 4.2.1 TSST Set subtitle + 4.2.2 TXXX User defined text information frame + + 4.1 UFID Unique file identifier + 4.22 USER Terms of use + 4.8 USLT Unsynchronised lyric/text transcription + + 4.3.1 WCOM Commercial information + 4.3.1 WCOP Copyright/Legal information + 4.3.1 WOAF Official audio file webpage + 4.3.1 WOAR Official artist/performer webpage + 4.3.1 WOAS Official audio source webpage + 4.3.1 WORS Official Internet radio station homepage + 4.3.1 WPAY Payment + 4.3.1 WPUB Publishers official webpage + 4.3.2 WXXX User defined URL link frame + + +4.1. Unique file identifier + + This frame's purpose is to be able to identify the audio file in a + database, that may provide more information relevant to the content. + Since standardisation of such a database is beyond this document, all + UFID frames begin with an 'owner identifier' field. It is a null- + terminated string with a URL [URL] containing an email address, or a + link to a location where an email address can be found, that belongs + to the organisation responsible for this specific database + implementation. Questions regarding the database should be sent to + the indicated email address. The URL should not be used for the + actual database queries. The string + "http://www.id3.org/dummy/ufid.html" should be used for tests. The + 'Owner identifier' must be non-empty (more than just a termination). + The 'Owner identifier' is then followed by the actual identifier, + which may be up to 64 bytes. There may be more than one "UFID" frame + in a tag, but only one with the same 'Owner identifier'. + +
+ Owner identifier $00 + Identifier + + +4.2. Text information frames + + The text information frames are often the most important frames, + containing information like artist, album and more. There may only be + one text information frame of its kind in an tag. All text + information frames supports multiple strings, stored as a null + separated list, where null is reperesented by the termination code + for the charater encoding. All text frame identifiers begin with "T". + Only text frame identifiers begin with "T", with the exception of the + "TXXX" frame. All the text information frames have the following + format: + +
+ Text encoding $xx + Information + + +4.2.1. Identification frames + + TIT1 + The 'Content group description' frame is used if the sound belongs to + a larger category of sounds/music. For example, classical music is + often sorted in different musical sections (e.g. "Piano Concerto", + "Weather - Hurricane"). + + TIT2 + The 'Title/Songname/Content description' frame is the actual name of + the piece (e.g. "Adagio", "Hurricane Donna"). + + TIT3 + The 'Subtitle/Description refinement' frame is used for information + directly related to the contents title (e.g. "Op. 16" or "Performed + live at Wembley"). + + TALB + The 'Album/Movie/Show title' frame is intended for the title of the + recording (or source of sound) from which the audio in the file is + taken. + + TOAL + The 'Original album/movie/show title' frame is intended for the title + of the original recording (or source of sound), if for example the + music in the file should be a cover of a previously released song. + + TRCK + The 'Track number/Position in set' frame is a numeric string + containing the order number of the audio-file on its original + recording. This MAY be extended with a "/" character and a numeric + string containing the total number of tracks/elements on the original + recording. E.g. "4/9". + + TPOS + The 'Part of a set' frame is a numeric string that describes which + part of a set the audio came from. This frame is used if the source + described in the "TALB" frame is divided into several mediums, e.g. a + double CD. The value MAY be extended with a "/" character and a + numeric string containing the total number of parts in the set. E.g. + "1/2". + + TSST + The 'Set subtitle' frame is intended for the subtitle of the part of + a set this track belongs to. + + TSRC + The 'ISRC' frame should contain the International Standard Recording + Code [ISRC] (12 characters). + + +4.2.2. Involved persons frames + + TPE1 + The 'Lead artist/Lead performer/Soloist/Performing group' is + used for the main artist. + + TPE2 + The 'Band/Orchestra/Accompaniment' frame is used for additional + information about the performers in the recording. + + TPE3 + The 'Conductor' frame is used for the name of the conductor. + + TPE4 + The 'Interpreted, remixed, or otherwise modified by' frame contains + more information about the people behind a remix and similar + interpretations of another existing piece. + + TOPE + The 'Original artist/performer' frame is intended for the performer + of the original recording, if for example the music in the file + should be a cover of a previously released song. + + TEXT + The 'Lyricist/Text writer' frame is intended for the writer of the + text or lyrics in the recording. + + TOLY + The 'Original lyricist/text writer' frame is intended for the + text writer of the original recording, if for example the music in + the file should be a cover of a previously released song. + + TCOM + The 'Composer' frame is intended for the name of the composer. + + TMCL + The 'Musician credits list' is intended as a mapping between + instruments and the musician that played it. Every odd field is an + instrument and every even is an artist or a comma delimited list of + artists. + + TIPL + The 'Involved people list' is very similar to the musician credits + list, but maps between functions, like producer, and names. + + TENC + The 'Encoded by' frame contains the name of the person or + organisation that encoded the audio file. This field may contain a + copyright message, if the audio file also is copyrighted by the + encoder. + + +4.2.3. Derived and subjective properties frames + + TBPM + The 'BPM' frame contains the number of beats per minute in the + main part of the audio. The BPM is an integer and represented as a + numerical string. + + TLEN + The 'Length' frame contains the length of the audio file in + milliseconds, represented as a numeric string. + + TKEY + The 'Initial key' frame contains the musical key in which the sound + starts. It is represented as a string with a maximum length of three + characters. The ground keys are represented with "A","B","C","D","E", + "F" and "G" and halfkeys represented with "b" and "#". Minor is + represented as "m", e.g. "Dbm" $00. Off key is represented with an + "o" only. + + TLAN + The 'Language' frame should contain the languages of the text or + lyrics spoken or sung in the audio. The language is represented with + three characters according to ISO-639-2 [ISO-639-2]. If more than one + language is used in the text their language codes should follow + according to the amount of their usage, e.g. "eng" $00 "sve" $00. + + TCON + The 'Content type', which ID3v1 was stored as a one byte numeric + value only, is now a string. You may use one or several of the ID3v1 + types as numerical strings, or, since the category list would be + impossible to maintain with accurate and up to date categories, + define your own. Example: "21" $00 "Eurodisco" $00 + + You may also use any of the following keywords: + + RX Remix + CR Cover + + TFLT + The 'File type' frame indicates which type of audio this tag defines. + The following types and refinements are defined: + + MIME MIME type follows + MPG MPEG Audio + /1 MPEG 1/2 layer I + /2 MPEG 1/2 layer II + /3 MPEG 1/2 layer III + /2.5 MPEG 2.5 + /AAC Advanced audio compression + VQF Transform-domain Weighted Interleave Vector Quantisation + PCM Pulse Code Modulated audio + + but other types may be used, but not for these types though. This is + used in a similar way to the predefined types in the "TMED" frame, + but without parentheses. If this frame is not present audio type is + assumed to be "MPG". + + TMED + The 'Media type' frame describes from which media the sound + originated. This may be a text string or a reference to the + predefined media types found in the list below. Example: + "VID/PAL/VHS" $00. + + DIG Other digital media + /A Analogue transfer from media + + ANA Other analogue media + /WAC Wax cylinder + /8CA 8-track tape cassette + + CD CD + /A Analogue transfer from media + /DD DDD + /AD ADD + /AA AAD + + LD Laserdisc + + TT Turntable records + /33 33.33 rpm + /45 45 rpm + /71 71.29 rpm + /76 76.59 rpm + /78 78.26 rpm + /80 80 rpm + + MD MiniDisc + /A Analogue transfer from media + + DAT DAT + /A Analogue transfer from media + /1 standard, 48 kHz/16 bits, linear + /2 mode 2, 32 kHz/16 bits, linear + /3 mode 3, 32 kHz/12 bits, non-linear, low speed + /4 mode 4, 32 kHz/12 bits, 4 channels + /5 mode 5, 44.1 kHz/16 bits, linear + /6 mode 6, 44.1 kHz/16 bits, 'wide track' play + + DCC DCC + /A Analogue transfer from media + + DVD DVD + /A Analogue transfer from media + + TV Television + /PAL PAL + /NTSC NTSC + /SECAM SECAM + + VID Video + /PAL PAL + /NTSC NTSC + /SECAM SECAM + /VHS VHS + /SVHS S-VHS + /BETA BETAMAX + + RAD Radio + /FM FM + /AM AM + /LW LW + /MW MW + + TEL Telephone + /I ISDN + + MC MC (normal cassette) + /4 4.75 cm/s (normal speed for a two sided cassette) + /9 9.5 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + REE Reel + /9 9.5 cm/s + /19 19 cm/s + /38 38 cm/s + /76 76 cm/s + /I Type I cassette (ferric/normal) + /II Type II cassette (chrome) + /III Type III cassette (ferric chrome) + /IV Type IV cassette (metal) + + TMOO + The 'Mood' frame is intended to reflect the mood of the audio with a + few keywords, e.g. "Romantic" or "Sad". + + +4.2.4. Rights and license frames + + TCOP + The 'Copyright message' frame, in which the string must begin with a + year and a space character (making five characters), is intended for + the copyright holder of the original sound, not the audio file + itself. The absence of this frame means only that the copyright + information is unavailable or has been removed, and must not be + interpreted to mean that the audio is public domain. Every time this + field is displayed the field must be preceded with "Copyright " (C) " + ", where (C) is one character showing a C in a circle. + + TPRO + The 'Produced notice' frame, in which the string must begin with a + year and a space character (making five characters), is intended for + the production copyright holder of the original sound, not the audio + file itself. The absence of this frame means only that the production + copyright information is unavailable or has been removed, and must + not be interpreted to mean that the audio is public domain. Every + time this field is displayed the field must be preceded with + "Produced " (P) " ", where (P) is one character showing a P in a + circle. + + TPUB + The 'Publisher' frame simply contains the name of the label or + publisher. + + TOWN + The 'File owner/licensee' frame contains the name of the owner or + licensee of the file and it's contents. + + TRSN + The 'Internet radio station name' frame contains the name of the + internet radio station from which the audio is streamed. + + TRSO + The 'Internet radio station owner' frame contains the name of the + owner of the internet radio station from which the audio is + streamed. + +4.2.5. Other text frames + + TOFN + The 'Original filename' frame contains the preferred filename for the + file, since some media doesn't allow the desired length of the + filename. The filename is case sensitive and includes its suffix. + + TDLY + The 'Playlist delay' defines the numbers of milliseconds of silence + that should be inserted before this audio. The value zero indicates + that this is a part of a multifile audio track that should be played + continuously. + + TDEN + The 'Encoding time' frame contains a timestamp describing when the + audio was encoded. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDOR + The 'Original release time' frame contains a timestamp describing + when the original recording of the audio was released. Timestamp + format is described in the ID3v2 structure document [ID3v2-strct]. + + TDRC + The 'Recording time' frame contains a timestamp describing when the + audio was recorded. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDRL + The 'Release time' frame contains a timestamp describing when the + audio was first released. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TDTG + The 'Tagging time' frame contains a timestamp describing then the + audio was tagged. Timestamp format is described in the ID3v2 + structure document [ID3v2-strct]. + + TSSE + The 'Software/Hardware and settings used for encoding' frame + includes the used audio encoder and its settings when the file was + encoded. Hardware refers to hardware encoders, not the computer on + which a program was run. + + TSOA + The 'Album sort order' frame defines a string which should be used + instead of the album name (TALB) for sorting purposes. E.g. an album + named "A Soundtrack" might preferably be sorted as "Soundtrack". + + TSOP + The 'Performer sort order' frame defines a string which should be + used instead of the performer (TPE2) for sorting purposes. + + TSOT + The 'Title sort order' frame defines a string which should be used + instead of the title (TIT2) for sorting purposes. + + +4.2.6. User defined text information frame + + This frame is intended for one-string text information concerning the + audio file in a similar way to the other "T"-frames. The frame body + consists of a description of the string, represented as a terminated + string, followed by the actual string. There may be more than one + "TXXX" frame in each tag, but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + Value + + +4.3. URL link frames + + With these frames dynamic data such as webpages with touring + information, price information or plain ordinary news can be added to + the tag. There may only be one URL [URL] link frame of its kind in an + tag, except when stated otherwise in the frame description. If the + text string is followed by a string termination, all the following + information should be ignored and not be displayed. All URL link + frame identifiers begins with "W". Only URL link frame identifiers + begins with "W", except for "WXXX". All URL link frames have the + following format: + +
+ URL + + +4.3.1. URL link frames - details + + WCOM + The 'Commercial information' frame is a URL pointing at a webpage + with information such as where the album can be bought. There may be + more than one "WCOM" frame in a tag, but not with the same content. + + WCOP + The 'Copyright/Legal information' frame is a URL pointing at a + webpage where the terms of use and ownership of the file is + described. + + WOAF + The 'Official audio file webpage' frame is a URL pointing at a file + specific webpage. + + WOAR + The 'Official artist/performer webpage' frame is a URL pointing at + the artists official webpage. There may be more than one "WOAR" frame + in a tag if the audio contains more than one performer, but not with + the same content. + + WOAS + The 'Official audio source webpage' frame is a URL pointing at the + official webpage for the source of the audio file, e.g. a movie. + + WORS + The 'Official Internet radio station homepage' contains a URL + pointing at the homepage of the internet radio station. + + WPAY + The 'Payment' frame is a URL pointing at a webpage that will handle + the process of paying for this file. + + WPUB + The 'Publishers official webpage' frame is a URL pointing at the + official webpage for the publisher. + + +4.3.2. User defined URL link frame + + This frame is intended for URL [URL] links concerning the audio file + in a similar way to the other "W"-frames. The frame body consists + of a description of the string, represented as a terminated string, + followed by the actual URL. The URL is always encoded with ISO-8859-1 + [ISO-8859-1]. There may be more than one "WXXX" frame in each tag, + but only one with the same description. + +
+ Text encoding $xx + Description $00 (00) + URL + + +4.4. Music CD identifier + + This frame is intended for music that comes from a CD, so that the CD + can be identified in databases such as the CDDB [CDDB]. The frame + consists of a binary dump of the Table Of Contents, TOC, from the CD, + which is a header of 4 bytes and then 8 bytes/track on the CD plus 8 + bytes for the 'lead out', making a maximum of 804 bytes. The offset + to the beginning of every track on the CD should be described with a + four bytes absolute CD-frame address per track, and not with absolute + time. When this frame is used the presence of a valid "TRCK" frame is + REQUIRED, even if the CD's only got one track. It is recommended that + this frame is always added to tags originating from CDs. There may + only be one "MCDI" frame in each tag. + +
+ CD TOC + + +4.5. Event timing codes + + This frame allows synchronisation with key events in the audio. The + header is: + +
+ Time stamp format $xx + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + Followed by a list of key events in the following format: + + Type of event $xx + Time stamp $xx (xx ...) + + The 'Time stamp' is set to zero if directly at the beginning of the + sound or after the previous event. All events MUST be sorted in + chronological order. The type of event is as follows: + + $00 padding (has no meaning) + $01 end of initial silence + $02 intro start + $03 main part start + $04 outro start + $05 outro end + $06 verse start + $07 refrain start + $08 interlude start + $09 theme start + $0A variation start + $0B key change + $0C time change + $0D momentary unwanted noise (Snap, Crackle & Pop) + $0E sustained noise + $0F sustained noise end + $10 intro end + $11 main part end + $12 verse end + $13 refrain end + $14 theme end + $15 profanity + $16 profanity end + + $17-$DF reserved for future use + + $E0-$EF not predefined synch 0-F + + $F0-$FC reserved for future use + + $FD audio end (start of silence) + $FE audio file ends + $FF one more byte of events follows (all the following bytes with + the value $FF have the same function) + + Terminating the start events such as "intro start" is OPTIONAL. The + 'Not predefined synch's ($E0-EF) are for user events. You might want + to synchronise your music to something, like setting off an explosion + on-stage, activating a screensaver etc. + + There may only be one "ETCO" frame in each tag. + + +4.6. MPEG location lookup table + + To increase performance and accuracy of jumps within a MPEG [MPEG] + audio file, frames with time codes in different locations in the file + might be useful. This ID3v2 frame includes references that the + software can use to calculate positions in the file. After the frame + header follows a descriptor of how much the 'frame counter' should be + increased for every reference. If this value is two then the first + reference points out the second frame, the 2nd reference the 4th + frame, the 3rd reference the 6th frame etc. In a similar way the + 'bytes between reference' and 'milliseconds between reference' points + out bytes and milliseconds respectively. + + Each reference consists of two parts; a certain number of bits, as + defined in 'bits for bytes deviation', that describes the difference + between what is said in 'bytes between reference' and the reality and + a certain number of bits, as defined in 'bits for milliseconds + deviation', that describes the difference between what is said in + 'milliseconds between reference' and the reality. The number of bits + in every reference, i.e. 'bits for bytes deviation'+'bits for + milliseconds deviation', must be a multiple of four. There may only + be one "MLLT" frame in each tag. + +
+ MPEG frames between reference $xx xx + Bytes between reference $xx xx xx + Milliseconds between reference $xx xx xx + Bits for bytes deviation $xx + Bits for milliseconds dev. $xx + + Then for every reference the following data is included; + + Deviation in bytes %xxx.... + Deviation in milliseconds %xxx.... + + +4.7. Synchronised tempo codes + + For a more accurate description of the tempo of a musical piece, this + frame might be used. After the header follows one byte describing + which time stamp format should be used. Then follows one or more + tempo codes. Each tempo code consists of one tempo part and one time + part. The tempo is in BPM described with one or two bytes. If the + first byte has the value $FF, one more byte follows, which is added + to the first giving a range from 2 - 510 BPM, since $00 and $01 is + reserved. $00 is used to describe a beat-free time period, which is + not the same as a music-free time period. $01 is used to indicate one + single beat-stroke followed by a beat-free period. + + The tempo descriptor is followed by a time stamp. Every time the + tempo in the music changes, a tempo descriptor may indicate this for + the player. All tempo descriptors MUST be sorted in chronological + order. The first beat-stroke in a time-period is at the same time as + the beat description occurs. There may only be one "SYTC" frame in + each tag. + +
+ Time stamp format $xx + Tempo data + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + +4.8. Unsynchronised lyrics/text transcription + + This frame contains the lyrics of the song or a text transcription of + other vocal activities. The head includes an encoding descriptor and + a content descriptor. The body consists of the actual text. The + 'Content descriptor' is a terminated string. If no descriptor is + entered, 'Content descriptor' is $00 (00) only. Newline characters + are allowed in the text. There may be more than one 'Unsynchronised + lyrics/text transcription' frame in each tag, but only one with the + same language and content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Content descriptor $00 (00) + Lyrics/text + + +4.9. Synchronised lyrics/text + + This is another way of incorporating the words, said or sung lyrics, + in the audio file as text, this time, however, in sync with the + audio. It might also be used to describing events e.g. occurring on a + stage or on the screen in sync with the audio. The header includes a + content descriptor, represented with as terminated text string. If no + descriptor is entered, 'Content descriptor' is $00 (00) only. + +
+ Text encoding $xx + Language $xx xx xx + Time stamp format $xx + Content type $xx + Content descriptor $00 (00) + + Content type: $00 is other + $01 is lyrics + $02 is text transcription + $03 is movement/part name (e.g. "Adagio") + $04 is events (e.g. "Don Quijote enters the stage") + $05 is chord (e.g. "Bb F Fsus") + $06 is trivia/'pop up' information + $07 is URLs to webpages + $08 is URLs to images + + Time stamp format: + + $01 Absolute time, 32 bit sized, using MPEG [MPEG] frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + Absolute time means that every stamp contains the time from the + beginning of the file. + + The text that follows the frame header differs from that of the + unsynchronised lyrics/text transcription in one major way. Each + syllable (or whatever size of text is considered to be convenient by + the encoder) is a null terminated string followed by a time stamp + denoting where in the sound file it belongs. Each sync thus has the + following structure: + + Terminated text to be synced (typically a syllable) + Sync identifier (terminator to above string) $00 (00) + Time stamp $xx (xx ...) + + The 'time stamp' is set to zero or the whole sync is omitted if + located directly at the beginning of the sound. All time stamps + should be sorted in chronological order. The sync can be considered + as a validator of the subsequent string. + + Newline characters are allowed in all "SYLT" frames and MUST be used + after every entry (name, event etc.) in a frame with the content type + $03 - $04. + + A few considerations regarding whitespace characters: Whitespace + separating words should mark the beginning of a new word, thus + occurring in front of the first syllable of a new word. This is also + valid for new line characters. A syllable followed by a comma should + not be broken apart with a sync (both the syllable and the comma + should be before the sync). + + An example: The "USLT" passage + + "Strangers in the night" $0A "Exchanging glances" + + would be "SYLT" encoded as: + + "Strang" $00 xx xx "ers" $00 xx xx " in" $00 xx xx " the" $00 xx xx + " night" $00 xx xx 0A "Ex" $00 xx xx "chang" $00 xx xx "ing" $00 xx + xx "glan" $00 xx xx "ces" $00 xx xx + + There may be more than one "SYLT" frame in each tag, but only one + with the same language and content descriptor. + + +4.10. Comments + + This frame is intended for any kind of full text information that + does not fit in any other frame. It consists of a frame header + followed by encoding, language and content descriptors and is ended + with the actual comment as a text string. Newline characters are + allowed in the comment text string. There may be more than one + comment frame in each tag, but only one with the same language and + content descriptor. + +
+ Text encoding $xx + Language $xx xx xx + Short content descrip. $00 (00) + The actual text + + +4.11. Relative volume adjustment (2) + + This is a more subjective frame than the previous ones. It allows the + user to say how much he wants to increase/decrease the volume on each + channel when the file is played. The purpose is to be able to align + all files to a reference volume, so that you don't have to change the + volume constantly. This frame may also be used to balance adjust the + audio. The volume adjustment is encoded as a fixed point decibel + value, 16 bit signed integer representing (adjustment*512), giving + +/- 64 dB with a precision of 0.001953125 dB. E.g. +2 dB is stored as + $04 00 and -2 dB is $FC 00. There may be more than one "RVA2" frame + in each tag, but only one with the same identification string. + +
+ Identification $00 + + The 'identification' string is used to identify the situation and/or + device where this adjustment should apply. The following is then + repeated for every channel + + Type of channel $xx + Volume adjustment $xx xx + Bits representing peak $xx + Peak volume $xx (xx ...) + + + Type of channel: $00 Other + $01 Master volume + $02 Front right + $03 Front left + $04 Back right + $05 Back left + $06 Front centre + $07 Back centre + $08 Subwoofer + + Bits representing peak can be any number between 0 and 255. 0 means + that there is no peak volume field. The peak volume field is always + padded to whole bytes, setting the most significant bits to zero. + + +4.12. Equalisation (2) + + This is another subjective, alignment frame. It allows the user to + predefine an equalisation curve within the audio file. There may be + more than one "EQU2" frame in each tag, but only one with the same + identification string. + +
+ Interpolation method $xx + Identification $00 + + The 'interpolation method' describes which method is preferred when + an interpolation between the adjustment point that follows. The + following methods are currently defined: + + $00 Band + No interpolation is made. A jump from one adjustment level to + another occurs in the middle between two adjustment points. + $01 Linear + Interpolation between adjustment points is linear. + + The 'identification' string is used to identify the situation and/or + device where this adjustment should apply. The following is then + repeated for every adjustment point + + Frequency $xx xx + Volume adjustment $xx xx + + The frequency is stored in units of 1/2 Hz, giving it a range from 0 + to 32767 Hz. + + The volume adjustment is encoded as a fixed point decibel value, 16 + bit signed integer representing (adjustment*512), giving +/- 64 dB + with a precision of 0.001953125 dB. E.g. +2 dB is stored as $04 00 + and -2 dB is $FC 00. + + Adjustment points should be ordered by frequency and one frequency + should only be described once in the frame. + + +4.13. Reverb + + Yet another subjective frame, with which you can adjust echoes of + different kinds. Reverb left/right is the delay between every bounce + in ms. Reverb bounces left/right is the number of bounces that should + be made. $FF equals an infinite number of bounces. Feedback is the + amount of volume that should be returned to the next echo bounce. $00 + is 0%, $FF is 100%. If this value were $7F, there would be 50% volume + reduction on the first bounce, 50% of that on the second and so on. + Left to left means the sound from the left bounce to be played in the + left speaker, while left to right means sound from the left bounce to + be played in the right speaker. + + 'Premix left to right' is the amount of left sound to be mixed in the + right before any reverb is applied, where $00 id 0% and $FF is 100%. + 'Premix right to left' does the same thing, but right to left. + Setting both premix to $FF would result in a mono output (if the + reverb is applied symmetric). There may only be one "RVRB" frame in + each tag. + +
+ Reverb left (ms) $xx xx + Reverb right (ms) $xx xx + Reverb bounces, left $xx + Reverb bounces, right $xx + Reverb feedback, left to left $xx + Reverb feedback, left to right $xx + Reverb feedback, right to right $xx + Reverb feedback, right to left $xx + Premix left to right $xx + Premix right to left $xx + + +4.14. Attached picture + + This frame contains a picture directly related to the audio file. + Image format is the MIME type and subtype [MIME] for the image. In + the event that the MIME media type name is omitted, "image/" will be + implied. The "image/png" [PNG] or "image/jpeg" [JFIF] picture format + should be used when interoperability is wanted. Description is a + short description of the picture, represented as a terminated + text string. There may be several pictures attached to one file, each + in their individual "APIC" frame, but only one with the same content + descriptor. There may only be one picture with the picture type + declared as picture type $01 and $02 respectively. There is the + possibility to put only a link to the image file by using the 'MIME + type' "-->" and having a complete URL [URL] instead of picture data. + The use of linked files should however be used sparingly since there + is the risk of separation of files. + +
+ Text encoding $xx + MIME type $00 + Picture type $xx + Description $00 (00) + Picture data + + + Picture type: $00 Other + $01 32x32 pixels 'file icon' (PNG only) + $02 Other file icon + $03 Cover (front) + $04 Cover (back) + $05 Leaflet page + $06 Media (e.g. label side of CD) + $07 Lead artist/lead performer/soloist + $08 Artist/performer + $09 Conductor + $0A Band/Orchestra + $0B Composer + $0C Lyricist/text writer + $0D Recording Location + $0E During recording + $0F During performance + $10 Movie/video screen capture + $11 A bright coloured fish + $12 Illustration + $13 Band/artist logotype + $14 Publisher/Studio logotype + + +4.15. General encapsulated object + + In this frame any type of file can be encapsulated. After the header, + 'Frame size' and 'Encoding' follows 'MIME type' [MIME] represented as + as a terminated string encoded with ISO 8859-1 [ISO-8859-1]. The + filename is case sensitive and is encoded as 'Encoding'. Then follows + a content description as terminated string, encoded as 'Encoding'. + The last thing in the frame is the actual object. The first two + strings may be omitted, leaving only their terminations. MIME type is + always an ISO-8859-1 text string. There may be more than one "GEOB" + frame in each tag, but only one with the same content descriptor. + +
+ Text encoding $xx + MIME type $00 + Filename $00 (00) + Content description $00 (00) + Encapsulated object + + +4.16. Play counter + + This is simply a counter of the number of times a file has been + played. The value is increased by one every time the file begins to + play. There may only be one "PCNT" frame in each tag. When the + counter reaches all one's, one byte is inserted in front of the + counter thus making the counter eight bits bigger. The counter must + be at least 32-bits long to begin with. + +
+ Counter $xx xx xx xx (xx ...) + + +4.17. Popularimeter + + The purpose of this frame is to specify how good an audio file is. + Many interesting applications could be found to this frame such as a + playlist that features better audio files more often than others or + it could be used to profile a person's taste and find other 'good' + files by comparing people's profiles. The frame contains the email + address to the user, one rating byte and a four byte play counter, + intended to be increased with one for every time the file is played. + The email is a terminated string. The rating is 1-255 where 1 is + worst and 255 is best. 0 is unknown. If no personal counter is wanted + it may be omitted. When the counter reaches all one's, one byte is + inserted in front of the counter thus making the counter eight bits + bigger in the same away as the play counter ("PCNT"). There may be + more than one "POPM" frame in each tag, but only one with the same + email address. + +
+ Email to user $00 + Rating $xx + Counter $xx xx xx xx (xx ...) + + +4.18. Recommended buffer size + + Sometimes the server from which an audio file is streamed is aware of + transmission or coding problems resulting in interruptions in the + audio stream. In these cases, the size of the buffer can be + recommended by the server using this frame. If the 'embedded info + flag' is true (1) then this indicates that an ID3 tag with the + maximum size described in 'Buffer size' may occur in the audio + stream. In such case the tag should reside between two MPEG [MPEG] + frames, if the audio is MPEG encoded. If the position of the next tag + is known, 'offset to next tag' may be used. The offset is calculated + from the end of tag in which this frame resides to the first byte of + the header in the next. This field may be omitted. Embedded tags are + generally not recommended since this could render unpredictable + behaviour from present software/hardware. + + For applications like streaming audio it might be an idea to embed + tags into the audio stream though. If the clients connects to + individual connections like HTTP and there is a possibility to begin + every transmission with a tag, then this tag should include a + 'recommended buffer size' frame. If the client is connected to a + arbitrary point in the stream, such as radio or multicast, then the + 'recommended buffer size' frame SHOULD be included in every tag. + + The 'Buffer size' should be kept to a minimum. There may only be one + "RBUF" frame in each tag. + +
+ Buffer size $xx xx xx + Embedded info flag %0000000x + Offset to next tag $xx xx xx xx + + +4.19. Audio encryption + + This frame indicates if the actual audio stream is encrypted, and by + whom. Since standardisation of such encryption scheme is beyond this + document, all "AENC" frames begin with a terminated string with a + URL containing an email address, or a link to a location where an + email address can be found, that belongs to the organisation + responsible for this specific encrypted audio file. Questions + regarding the encrypted audio should be sent to the email address + specified. If a $00 is found directly after the 'Frame size' and the + audio file indeed is encrypted, the whole file may be considered + useless. + + After the 'Owner identifier', a pointer to an unencrypted part of the + audio can be specified. The 'Preview start' and 'Preview length' is + described in frames. If no part is unencrypted, these fields should + be left zeroed. After the 'preview length' field follows optionally a + data block required for decryption of the audio. There may be more + than one "AENC" frames in a tag, but only one with the same 'Owner + identifier'. + +
+ Owner identifier $00 + Preview start $xx xx + Preview length $xx xx + Encryption info + + +4.20. Linked information + + To keep information duplication as low as possible this frame may be + used to link information from another ID3v2 tag that might reside in + another audio file or alone in a binary file. It is RECOMMENDED that + this method is only used when the files are stored on a CD-ROM or + other circumstances when the risk of file separation is low. The + frame contains a frame identifier, which is the frame that should be + linked into this tag, a URL [URL] field, where a reference to the + file where the frame is given, and additional ID data, if needed. + Data should be retrieved from the first tag found in the file to + which this link points. There may be more than one "LINK" frame in a + tag, but only one with the same contents. A linked frame is to be + considered as part of the tag and has the same restrictions as if it + was a physical part of the tag (i.e. only one "RVRB" frame allowed, + whether it's linked or not). + +
+ Frame identifier $xx xx xx xx + URL $00 + ID and additional data + + Frames that may be linked and need no additional data are "ASPI", + "ETCO", "EQU2", "MCID", "MLLT", "OWNE", "RVA2", "RVRB", "SYTC", the + text information frames and the URL link frames. + + The "AENC", "APIC", "GEOB" and "TXXX" frames may be linked with + the content descriptor as additional ID data. + + The "USER" frame may be linked with the language field as additional + ID data. + + The "PRIV" frame may be linked with the owner identifier as + additional ID data. + + The "COMM", "SYLT" and "USLT" frames may be linked with three bytes + of language descriptor directly followed by a content descriptor as + additional ID data. + + +4.21. Position synchronisation frame + + This frame delivers information to the listener of how far into the + audio stream he picked up; in effect, it states the time offset from + the first frame in the stream. The frame layout is: + + + Time stamp format $xx + Position $xx (xx ...) + + Where time stamp format is: + + $01 Absolute time, 32 bit sized, using MPEG frames as unit + $02 Absolute time, 32 bit sized, using milliseconds as unit + + and position is where in the audio the listener starts to receive, + i.e. the beginning of the next frame. If this frame is used in the + beginning of a file the value is always 0. There may only be one + "POSS" frame in each tag. + + +4.22. Terms of use frame + + This frame contains a brief description of the terms of use and + ownership of the file. More detailed information concerning the legal + terms might be available through the "WCOP" frame. Newlines are + allowed in the text. There may be more than one 'Terms of use' frame + in a tag, but only one with the same 'Language'. + +
+ Text encoding $xx + Language $xx xx xx + The actual text + + +4.23. Ownership frame + + The ownership frame might be used as a reminder of a made transaction + or, if signed, as proof. Note that the "USER" and "TOWN" frames are + good to use in conjunction with this one. The frame begins, after the + frame ID, size and encoding fields, with a 'price paid' field. The + first three characters of this field contains the currency used for + the transaction, encoded according to ISO 4217 [ISO-4217] alphabetic + currency code. Concatenated to this is the actual price paid, as a + numerical string using "." as the decimal separator. Next is an 8 + character date string (YYYYMMDD) followed by a string with the name + of the seller as the last field in the frame. There may only be one + "OWNE" frame in a tag. + +
+ Text encoding $xx + Price paid $00 + Date of purch. + Seller + + +4.24. Commercial frame + + This frame enables several competing offers in the same tag by + bundling all needed information. That makes this frame rather complex + but it's an easier solution than if one tries to achieve the same + result with several frames. The frame begins, after the frame ID, + size and encoding fields, with a price string field. A price is + constructed by one three character currency code, encoded according + to ISO 4217 [ISO-4217] alphabetic currency code, followed by a + numerical value where "." is used as decimal separator. In the price + string several prices may be concatenated, separated by a "/" + character, but there may only be one currency of each type. + + The price string is followed by an 8 character date string in the + format YYYYMMDD, describing for how long the price is valid. After + that is a contact URL, with which the user can contact the seller, + followed by a one byte 'received as' field. It describes how the + audio is delivered when bought according to the following list: + + $00 Other + $01 Standard CD album with other songs + $02 Compressed audio on CD + $03 File over the Internet + $04 Stream over the Internet + $05 As note sheets + $06 As note sheets in a book with other sheets + $07 Music on other media + $08 Non-musical merchandise + + Next follows a terminated string with the name of the seller followed + by a terminated string with a short description of the product. The + last thing is the ability to include a company logotype. The first of + them is the 'Picture MIME type' field containing information about + which picture format is used. In the event that the MIME media type + name is omitted, "image/" will be implied. Currently only "image/png" + and "image/jpeg" are allowed. This format string is followed by the + binary picture data. This two last fields may be omitted if no + picture is attached. There may be more than one 'commercial frame' in + a tag, but no two may be identical. + +
+ Text encoding $xx + Price string $00 + Valid until + Contact URL $00 + Received as $xx + Name of seller $00 (00) + Description $00 (00) + Picture MIME type $00 + Seller logo + + +4.25. Encryption method registration + + To identify with which method a frame has been encrypted the + encryption method must be registered in the tag with this frame. The + 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for this specific encryption method. Questions regarding the + encryption method should be sent to the indicated email address. The + 'Method symbol' contains a value that is associated with this method + throughout the whole tag, in the range $80-F0. All other values are + reserved. The 'Method symbol' may optionally be followed by + encryption specific data. There may be several "ENCR" frames in a tag + but only one containing the same symbol and only one containing the + same owner identifier. The method must be used somewhere in the tag. + See the description of the frame encryption flag in the ID3v2 + structure document [ID3v2-strct] for more information. + +
+ Owner identifier $00 + Method symbol $xx + Encryption data + + +4.26. Group identification registration + + This frame enables grouping of otherwise unrelated frames. This can + be used when some frames are to be signed. To identify which frames + belongs to a set of frames a group identifier must be registered in + the tag with this frame. The 'Owner identifier' is a null-terminated + string with a URL [URL] containing an email address, or a link to a + location where an email address can be found, that belongs to the + organisation responsible for this grouping. Questions regarding the + grouping should be sent to the indicated email address. The 'Group + symbol' contains a value that associates the frame with this group + throughout the whole tag, in the range $80-F0. All other values are + reserved. The 'Group symbol' may optionally be followed by some group + specific data, e.g. a digital signature. There may be several "GRID" + frames in a tag but only one containing the same symbol and only one + containing the same owner identifier. The group symbol must be used + somewhere in the tag. See the description of the frame grouping flag + in the ID3v2 structure document [ID3v2-strct] for more information. + +
+ Owner identifier $00 + Group symbol $xx + Group dependent data + + +4.27. Private frame + + This frame is used to contain information from a software producer + that its program uses and does not fit into the other frames. The + frame consists of an 'Owner identifier' string and the binary data. + The 'Owner identifier' is a null-terminated string with a URL [URL] + containing an email address, or a link to a location where an email + address can be found, that belongs to the organisation responsible + for the frame. Questions regarding the frame should be sent to the + indicated email address. The tag may contain more than one "PRIV" + frame but only with different contents. + +
+ Owner identifier $00 + The private data + + +4.28. Signature frame + + This frame enables a group of frames, grouped with the 'Group + identification registration', to be signed. Although signatures can + reside inside the registration frame, it might be desired to store + the signature elsewhere, e.g. in watermarks. There may be more than + one 'signature frame' in a tag, but no two may be identical. + +
+ Group symbol $xx + Signature + + +4.29. Seek frame + + This frame indicates where other tags in a file/stream can be found. + The 'minimum offset to next tag' is calculated from the end of this + tag to the beginning of the next. There may only be one 'seek frame' + in a tag. + +
+ Minimum offset to next tag $xx xx xx xx + + +4.30. Audio seek point index + + Audio files with variable bit rates are intrinsically difficult to + deal with in the case of seeking within the file. The ASPI frame + makes seeking easier by providing a list a seek points within the + audio file. The seek points are a fractional offset within the audio + data, providing a starting point from which to find an appropriate + point to start decoding. The presence of an ASPI frame requires the + existence of a TLEN frame, indicating the duration of the file in + milliseconds. There may only be one 'audio seek point index' frame in + a tag. + +
+ Indexed data start (S) $xx xx xx xx + Indexed data length (L) $xx xx xx xx + Number of index points (N) $xx xx + Bits per index point (b) $xx + + Then for every index point the following data is included; + + Fraction at index (Fi) $xx (xx) + + 'Indexed data start' is a byte offset from the beginning of the file. + 'Indexed data length' is the byte length of the audio data being + indexed. 'Number of index points' is the number of index points, as + the name implies. The recommended number is 100. 'Bits per index + point' is 8 or 16, depending on the chosen precision. 8 bits works + well for short files (less than 5 minutes of audio), while 16 bits is + advantageous for long files. 'Fraction at index' is the numerator of + the fraction representing a relative position in the data. The + denominator is 2 to the power of b. + + Here are the algorithms to be used in the calculation. The known data + must be the offset of the start of the indexed data (S), the offset + of the end of the indexed data (E), the number of index points (N), + the offset at index i (Oi). We calculate the fraction at index i + (Fi). + + Oi is the offset of the frame whose start is soonest after the point + for which the time offset is (i/N * duration). + + The frame data should be calculated as follows: + + Fi = Oi/L * 2^b (rounded down to the nearest integer) + + Offset calculation should be calculated as follows from data in the + frame: + + Oi = (Fi/2^b)*L (rounded up to the nearest integer) + + +5. Copyright + + Copyright (C) Martin Nilsson 2000. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + "AS IS" basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +6. References + + [CDDB] Compact Disc Data Base + + + + [ID3v2.3.0] Martin Nilsson, "ID3v2 informal standard". + + + + [ID3v2-strct] Martin Nilsson, + "ID3 tag version 2.4.0 - Main Structure" + + + + [ISO-639-2] ISO/FDIS 639-2. + Codes for the representation of names of languages, Part 2: Alpha-3 + code. Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-4217] ISO 4217:1995. + Codes for the representation of currencies and funds. + Technical committee / subcommittee: TC 68 + + [ISO-8859-1] ISO/IEC DIS 8859-1. + 8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1. Technical committee / subcommittee: JTC 1 / SC 2 + + [ISRC] ISO 3901:1986 + International Standard Recording Code (ISRC). + Technical committee / subcommittee: TC 46 / SC 9 + + [JFIF] JPEG File Interchange Format, version 1.02 + + + + [KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate + Requirement Levels', RFC 2119, March 1997. + + + + [MIME] Freed, N. and N. Borenstein, "Multipurpose Internet Mail + Extensions (MIME) Part One: Format of Internet Message Bodies", + RFC 2045, November 1996. + + + + [MPEG] ISO/IEC 11172-3:1993. + Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + Generic coding of moving pictures and associated audio information, + Part 3: Audio. + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995) + + + [PNG] Portable Network Graphics, version 1.0 + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, "Uniform Resource + Locators (URL).", RFC 1738, December 1994. + + + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, "ZLIB + Compressed + Data Format Specification version 3.3", RFC 1950, May 1996. + + + + +7. Appendix + + +A. Appendix A - Genre List from ID3v1 + + The following genres is defined in ID3v1 + + 0.Blues + 1.Classic Rock + 2.Country + 3.Dance + 4.Disco + 5.Funk + 6.Grunge + 7.Hip-Hop + 8.Jazz + 9.Metal + 10.New Age + 11.Oldies + 12.Other + 13.Pop + 14.R&B + 15.Rap + 16.Reggae + 17.Rock + 18.Techno + 19.Industrial + 20.Alternative + 21.Ska + 22.Death Metal + 23.Pranks + 24.Soundtrack + 25.Euro-Techno + 26.Ambient + 27.Trip-Hop + 28.Vocal + 29.Jazz+Funk + 30.Fusion + 31.Trance + 32.Classical + 33.Instrumental + 34.Acid + 35.House + 36.Game + 37.Sound Clip + 38.Gospel + 39.Noise + 40.AlternRock + 41.Bass + 42.Soul + 43.Punk + 44.Space + 45.Meditative + 46.Instrumental Pop + 47.Instrumental Rock + 48.Ethnic + 49.Gothic + 50.Darkwave + 51.Techno-Industrial + 52.Electronic + 53.Pop-Folk + 54.Eurodance + 55.Dream + 56.Southern Rock + 57.Comedy + 58.Cult + 59.Gangsta + 60.Top 40 + 61.Christian Rap + 62.Pop/Funk + 63.Jungle + 64.Native American + 65.Cabaret + 66.New Wave + 67.Psychadelic + 68.Rave + 69.Showtunes + 70.Trailer + 71.Lo-Fi + 72.Tribal + 73.Acid Punk + 74.Acid Jazz + 75.Polka + 76.Retro + 77.Musical + 78.Rock & Roll + 79.Hard Rock + + +8. Author's Address + + Written by + + Martin Nilsson + Rydsvgen 246 C. 30 + SE-584 34 Linkping + Sweden + + Email: nilsson@id3.org diff --git a/external/taglib/source/mpeg/id3v2/id3v2.4.0-structure.txt b/external/taglib/source/mpeg/id3v2/id3v2.4.0-structure.txt new file mode 100644 index 0000000..5fa156a --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2.4.0-structure.txt @@ -0,0 +1,733 @@ + +Informal standard M. Nilsson +Document: id3v2.4.0-structure.txt 16 September 2001 + + + ID3 tag version 2.4.0 - Main Structure + +Status of this document + + This document is an informal standard and replaces the ID3v2.3.0 + standard [ID3v2]. A formal standard will use another revision number + even if the content is identical to document. The contents in this + document may change for clarifications but never for added or altered + functionallity. + + Distribution of this document is unlimited. + + +Abstract + + This document describes the main structure of ID3v2.4.0, which is a + revised version of the ID3v2 informal standard [ID3v2] version + 2.3.0. The ID3v2 offers a flexible way of storing audio meta + information within the audio file itself. The information may be + technical information, such as equalisation curves, as well as + title, performer, copyright etc. + + ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order + to allow for implementations to be revised as easily as possible. + + +1. Table of contents + + Status of this document + Abstract + 1. Table of contents + 2. Conventions in this document + 2. Standard overview + 3. ID3v2 overview + 3.1. ID3v2 header + 3.2. ID3v2 extended header + 3.3. Padding + 3.4. ID3v2 footer + 4. ID3v2 frames overview + 4.1. Frame header flags + 4.1.1. Frame status flags + 4.1.2. Frame format flags + 5. Tag location + 6. Unsynchronisation + 6.1. The unsynchronisation scheme + 6.2. Synchsafe integers + 7. Copyright + 8. References + 9. Author's Address + + +2. Conventions in this document + + Text within "" is a text string exactly as it appears in a tag. + Numbers preceded with $ are hexadecimal and numbers preceded with % + are binary. $xx is used to indicate a byte with unknown content. %x + is used to indicate a bit with unknown content. The most significant + bit (MSB) of a byte is called 'bit 7' and the least significant bit + (LSB) is called 'bit 0'. + + A tag is the whole tag described in this document. A frame is a block + of information in the tag. The tag consists of a header, frames and + optional padding. A field is a piece of information; one value, a + string etc. A numeric string is a string that consists of the + characters "0123456789" only. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119 [KEYWORDS]. + + +3. ID3v2 overview + + ID3v2 is a general tagging format for audio, which makes it possible + to store meta data about the audio inside the audio file itself. The + ID3 tag described in this document is mainly targeted at files + encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III + and MPEG-2.5, but may work with other types of encoded audio or as a + stand alone format for audio meta data. + + ID3v2 is designed to be as flexible and expandable as possible to + meet new meta information needs that might arise. To achieve that + ID3v2 is constructed as a container for several information blocks, + called frames, whose format need not be known to the software that + encounters them. At the start of every frame is an unique and + predefined identifier, a size descriptor that allows software to skip + unknown frames and a flags field. The flags describes encoding + details and if the frame should remain in the tag, should it be + unknown to the software, if the file is altered. + + The bitorder in ID3v2 is most significant bit first (MSB). The + byteorder in multibyte numbers is most significant byte first (e.g. + $12345678 would be encoded $12 34 56 78), also known as big endian + and network byte order. + + Overall tag structure: + + +-----------------------------+ + | Header (10 bytes) | + +-----------------------------+ + | Extended Header | + | (variable length, OPTIONAL) | + +-----------------------------+ + | Frames (variable length) | + +-----------------------------+ + | Padding | + | (variable length, OPTIONAL) | + +-----------------------------+ + | Footer (10 bytes, OPTIONAL) | + +-----------------------------+ + + In general, padding and footer are mutually exclusive. See details in + sections 3.3, 3.4 and 5. + + +3.1. ID3v2 header + + The first part of the ID3v2 tag is the 10 byte tag header, laid out + as follows: + + ID3v2/file identifier "ID3" + ID3v2 version $04 00 + ID3v2 flags %abcd0000 + ID3v2 size 4 * %0xxxxxxx + + The first three bytes of the tag are always "ID3", to indicate that + this is an ID3v2 tag, directly followed by the two version bytes. The + first byte of ID3v2 version is its major version, while the second + byte is its revision number. In this case this is ID3v2.4.0. All + revisions are backwards compatible while major versions are not. If + software with ID3v2.4.0 and below support should encounter version + five or higher it should simply ignore the whole tag. Version or + revision will never be $FF. + + The version is followed by the ID3v2 flags field, of which currently + four flags are used. + + + a - Unsynchronisation + + Bit 7 in the 'ID3v2 flags' indicates whether or not + unsynchronisation is applied on all frames (see section 6.1 for + details); a set bit indicates usage. + + + b - Extended header + + The second bit (bit 6) indicates whether or not the header is + followed by an extended header. The extended header is described in + section 3.2. A set bit indicates the presence of an extended + header. + + + c - Experimental indicator + + The third bit (bit 5) is used as an 'experimental indicator'. This + flag SHALL always be set when the tag is in an experimental stage. + + + d - Footer present + + Bit 4 indicates that a footer (section 3.4) is present at the very + end of the tag. A set bit indicates the presence of a footer. + + + All the other flags MUST be cleared. If one of these undefined flags + are set, the tag might not be readable for a parser that does not + know the flags function. + + The ID3v2 tag size is stored as a 32 bit synchsafe integer (section + 6.2), making a total of 28 effective bits (representing up to 256MB). + + The ID3v2 tag size is the sum of the byte length of the extended + header, the padding and the frames after unsynchronisation. If a + footer is present this equals to ('total size' - 20) bytes, otherwise + ('total size' - 10) bytes. + + An ID3v2 tag can be detected with the following pattern: + $49 44 33 yy yy xx zz zz zz zz + Where yy is less than $FF, xx is the 'flags' byte and zz is less than + $80. + + +3.2. Extended header + + The extended header contains information that can provide further + insight in the structure of the tag, but is not vital to the correct + parsing of the tag information; hence the extended header is + optional. + + Extended header size 4 * %0xxxxxxx + Number of flag bytes $01 + Extended Flags $xx + + Where the 'Extended header size' is the size of the whole extended + header, stored as a 32 bit synchsafe integer. An extended header can + thus never have a size of fewer than six bytes. + + The extended flags field, with its size described by 'number of flag + bytes', is defined as: + + %0bcd0000 + + Each flag that is set in the extended header has data attached, which + comes in the order in which the flags are encountered (i.e. the data + for flag 'b' comes before the data for flag 'c'). Unset flags cannot + have any attached data. All unknown flags MUST be unset and their + corresponding data removed when a tag is modified. + + Every set flag's data starts with a length byte, which contains a + value between 0 and 127 ($00 - $7f), followed by data that has the + field length indicated by the length byte. If a flag has no attached + data, the value $00 is used as length byte. + + + b - Tag is an update + + If this flag is set, the present tag is an update of a tag found + earlier in the present file or stream. If frames defined as unique + are found in the present tag, they are to override any + corresponding ones found in the earlier tag. This flag has no + corresponding data. + + Flag data length $00 + + c - CRC data present + + If this flag is set, a CRC-32 [ISO-3309] data is included in the + extended header. The CRC is calculated on all the data between the + header and footer as indicated by the header's tag length field, + minus the extended header. Note that this includes the padding (if + there is any), but excludes the footer. The CRC-32 is stored as an + 35 bit synchsafe integer, leaving the upper four bits always + zeroed. + + Flag data length $05 + Total frame CRC 5 * %0xxxxxxx + + d - Tag restrictions + + For some applications it might be desired to restrict a tag in more + ways than imposed by the ID3v2 specification. Note that the + presence of these restrictions does not affect how the tag is + decoded, merely how it was restricted before encoding. If this flag + is set the tag is restricted as follows: + + Flag data length $01 + Restrictions %ppqrrstt + + p - Tag size restrictions + + 00 No more than 128 frames and 1 MB total tag size. + 01 No more than 64 frames and 128 KB total tag size. + 10 No more than 32 frames and 40 KB total tag size. + 11 No more than 32 frames and 4 KB total tag size. + + q - Text encoding restrictions + + 0 No restrictions + 1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or + UTF-8 [UTF-8]. + + r - Text fields size restrictions + + 00 No restrictions + 01 No string is longer than 1024 characters. + 10 No string is longer than 128 characters. + 11 No string is longer than 30 characters. + + Note that nothing is said about how many bytes is used to + represent those characters, since it is encoding dependent. If a + text frame consists of more than one string, the sum of the + strungs is restricted as stated. + + s - Image encoding restrictions + + 0 No restrictions + 1 Images are encoded only with PNG [PNG] or JPEG [JFIF]. + + t - Image size restrictions + + 00 No restrictions + 01 All images are 256x256 pixels or smaller. + 10 All images are 64x64 pixels or smaller. + 11 All images are exactly 64x64 pixels, unless required + otherwise. + + +3.3. Padding + + It is OPTIONAL to include padding after the final frame (at the end + of the ID3 tag), making the size of all the frames together smaller + than the size given in the tag header. A possible purpose of this + padding is to allow for adding a few additional frames or enlarge + existing frames within the tag without having to rewrite the entire + file. The value of the padding bytes must be $00. A tag MUST NOT have + any padding between the frames or between the tag header and the + frames. Furthermore it MUST NOT have any padding when a tag footer is + added to the tag. + + +3.4. ID3v2 footer + + To speed up the process of locating an ID3v2 tag when searching from + the end of a file, a footer can be added to the tag. It is REQUIRED + to add a footer to an appended tag, i.e. a tag located after all + audio data. The footer is a copy of the header, but with a different + identifier. + + ID3v2 identifier "3DI" + ID3v2 version $04 00 + ID3v2 flags %abcd0000 + ID3v2 size 4 * %0xxxxxxx + + +4. ID3v2 frame overview + + All ID3v2 frames consists of one frame header followed by one or more + fields containing the actual information. The header is always 10 + bytes and laid out as follows: + + Frame ID $xx xx xx xx (four characters) + Size 4 * %0xxxxxxx + Flags $xx xx + + The frame ID is made out of the characters capital A-Z and 0-9. + Identifiers beginning with "X", "Y" and "Z" are for experimental + frames and free for everyone to use, without the need to set the + experimental bit in the tag header. Bear in mind that someone else + might have used the same identifier as you. All other identifiers are + either used or reserved for future use. + + The frame ID is followed by a size descriptor containing the size of + the data in the final frame, after encryption, compression and + unsynchronisation. The size is excluding the frame header ('total + frame size' - 10 bytes) and stored as a 32 bit synchsafe integer. + + In the frame header the size descriptor is followed by two flag + bytes. These flags are described in section 4.1. + + There is no fixed order of the frames' appearance in the tag, + although it is desired that the frames are arranged in order of + significance concerning the recognition of the file. An example of + such order: UFID, TIT2, MCDI, TRCK ... + + A tag MUST contain at least one frame. A frame must be at least 1 + byte big, excluding the header. + + If nothing else is said, strings, including numeric strings and URLs + [URL], are represented as ISO-8859-1 [ISO-8859-1] characters in the + range $20 - $FF. Such strings are represented in frame descriptions + as , or if newlines are allowed. If + nothing else is said newline character is forbidden. In ISO-8859-1 a + newline is represented, when allowed, with $0A only. + + Frames that allow different types of text encoding contains a text + encoding description byte. Possible encodings: + + $00 ISO-8859-1 [ISO-8859-1]. Terminated with $00. + $01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All + strings in the same frame SHALL have the same byteorder. + Terminated with $00 00. + $02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM. + Terminated with $00 00. + $03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00. + + Strings dependent on encoding are represented in frame descriptions + as , or if newlines are allowed. Any empty strings of + type $01 which are NULL-terminated may have the Unicode BOM followed + by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00). + + The timestamp fields are based on a subset of ISO 8601. When being as + precise as possible the format of a time string is + yyyy-MM-ddTHH:mm:ss (year, "-", month, "-", day, "T", hour (out of + 24), ":", minutes, ":", seconds), but the precision may be reduced by + removing as many time indicators as wanted. Hence valid timestamps + are + yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and + yyyy-MM-ddTHH:mm:ss. All time stamps are UTC. For durations, use + the slash character as described in 8601, and for multiple non- + contiguous dates, use multiple strings, if allowed by the frame + definition. + + The three byte language field, present in several frames, is used to + describe the language of the frame's content, according to ISO-639-2 + [ISO-639-2]. The language should be represented in lower case. If the + language is not known the string "XXX" should be used. + + All URLs [URL] MAY be relative, e.g. "picture.png", "../doc.txt". + + If a frame is longer than it should be, e.g. having more fields than + specified in this document, that indicates that additions to the + frame have been made in a later version of the ID3v2 standard. This + is reflected by the revision number in the header of the tag. + + +4.1. Frame header flags + + In the frame header the size descriptor is followed by two flag + bytes. All unused flags MUST be cleared. The first byte is for + 'status messages' and the second byte is a format description. If an + unknown flag is set in the first byte the frame MUST NOT be changed + without that bit cleared. If an unknown flag is set in the second + byte the frame is likely to not be readable. Some flags in the second + byte indicates that extra information is added to the header. These + fields of extra information is ordered as the flags that indicates + them. The flags field is defined as follows (l and o left out because + ther resemblence to one and zero): + + %0abc0000 %0h00kmnp + + Some frame format flags indicate that additional information fields + are added to the frame. This information is added after the frame + header and before the frame data in the same order as the flags that + indicates them. I.e. the four bytes of decompressed size will precede + the encryption method byte. These additions affects the 'frame size' + field, but are not subject to encryption or compression. + + The default status flags setting for a frame is, unless stated + otherwise, 'preserved if tag is altered' and 'preserved if file is + altered', i.e. %00000000. + + +4.1.1. Frame status flags + + a - Tag alter preservation + + This flag tells the tag parser what to do with this frame if it is + unknown and the tag is altered in any way. This applies to all + kinds of alterations, including adding more padding and reordering + the frames. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + b - File alter preservation + + This flag tells the tag parser what to do with this frame if it is + unknown and the file, excluding the tag, is altered. This does not + apply when the audio is completely replaced with other audio data. + + 0 Frame should be preserved. + 1 Frame should be discarded. + + + c - Read only + + This flag, if set, tells the software that the contents of this + frame are intended to be read only. Changing the contents might + break something, e.g. a signature. If the contents are changed, + without knowledge of why the frame was flagged read only and + without taking the proper means to compensate, e.g. recalculating + the signature, the bit MUST be cleared. + + +4.1.2. Frame format flags + + h - Grouping identity + + This flag indicates whether or not this frame belongs in a group + with other frames. If set, a group identifier byte is added to the + frame. Every frame with the same group identifier belongs to the + same group. + + 0 Frame does not contain group information + 1 Frame contains group information + + + k - Compression + + This flag indicates whether or not the frame is compressed. + A 'Data Length Indicator' byte MUST be included in the frame. + + 0 Frame is not compressed. + 1 Frame is compressed using zlib [zlib] deflate method. + If set, this requires the 'Data Length Indicator' bit + to be set as well. + + + m - Encryption + + This flag indicates whether or not the frame is encrypted. If set, + one byte indicating with which method it was encrypted will be + added to the frame. See description of the ENCR frame for more + information about encryption method registration. Encryption + should be done after compression. Whether or not setting this flag + requires the presence of a 'Data Length Indicator' depends on the + specific algorithm used. + + 0 Frame is not encrypted. + 1 Frame is encrypted. + + n - Unsynchronisation + + This flag indicates whether or not unsynchronisation was applied + to this frame. See section 6 for details on unsynchronisation. + If this flag is set all data from the end of this header to the + end of this frame has been unsynchronised. Although desirable, the + presence of a 'Data Length Indicator' is not made mandatory by + unsynchronisation. + + 0 Frame has not been unsynchronised. + 1 Frame has been unsyrchronised. + + p - Data length indicator + + This flag indicates that a data length indicator has been added to + the frame. The data length indicator is the value one would write + as the 'Frame length' if all of the frame format flags were + zeroed, represented as a 32 bit synchsafe integer. + + 0 There is no Data Length Indicator. + 1 A data length Indicator has been added to the frame. + + +5. Tag location + + The default location of an ID3v2 tag is prepended to the audio so + that players can benefit from the information when the data is + streamed. It is however possible to append the tag, or make a + prepend/append combination. When deciding upon where an unembedded + tag should be located, the following order of preference SHOULD be + considered. + + 1. Prepend the tag. + + 2. Prepend a tag with all vital information and add a second tag at + the end of the file, before tags from other tagging systems. The + first tag is required to have a SEEK frame. + + 3. Add a tag at the end of the file, before tags from other tagging + systems. + + In case 2 and 3 the tag can simply be appended if no other known tags + are present. The suggested method to find ID3v2 tags are: + + 1. Look for a prepended tag using the pattern found in section 3.1. + + 2. If a SEEK frame was found, use its values to guide further + searching. + + 3. Look for a tag footer, scanning from the back of the file. + + For every new tag that is found, the old tag should be discarded + unless the update flag in the extended header (section 3.2) is set. + + +6. Unsynchronisation + + The only purpose of unsynchronisation is to make the ID3v2 tag as + compatible as possible with existing software and hardware. There is + no use in 'unsynchronising' tags if the file is only to be processed + only by ID3v2 aware software and hardware. Unsynchronisation is only + useful with tags in MPEG 1/2 layer I, II and III, MPEG 2.5 and AAC + files. + + +6.1. The unsynchronisation scheme + + Whenever a false synchronisation is found within the tag, one zeroed + byte is inserted after the first false synchronisation byte. The + format of synchronisations that should be altered by ID3 encoders is + as follows: + + %11111111 111xxxxx + + and should be replaced with: + + %11111111 00000000 111xxxxx + + This has the side effect that all $FF 00 combinations have to be + altered, so they will not be affected by the decoding process. + Therefore all the $FF 00 combinations have to be replaced with the + $FF 00 00 combination during the unsynchronisation. + + To indicate usage of the unsynchronisation, the unsynchronisation + flag in the frame header should be set. This bit MUST be set if the + frame was altered by the unsynchronisation and SHOULD NOT be set if + unaltered. If all frames in the tag are unsynchronised the + unsynchronisation flag in the tag header SHOULD be set. It MUST NOT + be set if the tag has a frame which is not unsynchronised. + + Assume the first byte of the audio to be $FF. The special case when + the last byte of the last frame is $FF and no padding nor footer is + used will then introduce a false synchronisation. This can be solved + by adding a footer, adding padding or unsynchronising the frame and + add $00 to the end of the frame data, thus adding more byte to the + frame size than a normal unsynchronisation would. Although not + preferred, it is allowed to apply the last method on all frames + ending with $FF. + + It is preferred that the tag is either completely unsynchronised or + not unsynchronised at all. A completely unsynchronised tag has no + false synchonisations in it, as defined above, and does not end with + $FF. A completely non-unsynchronised tag contains no unsynchronised + frames, and thus the unsynchronisation flag in the header is cleared. + + Do bear in mind, that if compression or encryption is used, the + unsynchronisation scheme MUST be applied afterwards. When decoding an + unsynchronised frame, the unsynchronisation scheme MUST be reversed + first, encryption and decompression afterwards. + + +6.2. Synchsafe integers + + In some parts of the tag it is inconvenient to use the + unsychronisation scheme because the size of unsynchronised data is + not known in advance, which is particularly problematic with size + descriptors. The solution in ID3v2 is to use synchsafe integers, in + which there can never be any false synchs. Synchsafe integers are + integers that keep its highest bit (bit 7) zeroed, making seven bits + out of eight available. Thus a 32 bit synchsafe integer can store 28 + bits of information. + + Example: + + 255 (%11111111) encoded as a 16 bit synchsafe integer is 383 + (%00000001 01111111). + + +7. Copyright + + Copyright (C) Martin Nilsson 2000. All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that a reference to this document is included on all + such copies and derivative works. However, this document itself may + not be modified in any way and reissued as the original document. + + The limited permissions granted above are perpetual and will not be + revoked. + + This document and the information contained herein is provided on an + 'AS IS' basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +8. References + + [ID3v2] Martin Nilsson, 'ID3v2 informal standard'. + + + + [ISO-639-2] ISO/FDIS 639-2. + 'Codes for the representation of names of languages, Part 2: Alpha-3 + code.' Technical committee / subcommittee: TC 37 / SC 2 + + [ISO-3309] ISO 3309 + 'Information Processing Systems--Data Communication High-Level Data + Link Control Procedure--Frame Structure', IS 3309, October 1984, 3rd + Edition. + + [ISO-8859-1] ISO/IEC DIS 8859-1. + '8-bit single-byte coded graphic character sets, Part 1: Latin + alphabet No. 1.' Technical committee / subcommittee: JTC 1 / SC 2 + + [JFIF] 'JPEG File Interchange Format, version 1.02' + + + + [KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate + Requirement Levels', RFC 2119, March 1997. + + + + [MPEG] ISO/IEC 11172-3:1993. + 'Coding of moving pictures and associated audio for digital storage + media at up to about 1,5 Mbit/s, Part 3: Audio.' + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC 13818-3:1995 + 'Generic coding of moving pictures and associated audio information, + Part 3: Audio.' + Technical committee / subcommittee: JTC 1 / SC 29 + and + ISO/IEC DIS 13818-3 + 'Generic coding of moving pictures and associated audio information, + Part 3: Audio (Revision of ISO/IEC 13818-3:1995)' + + [PNG] 'Portable Network Graphics, version 1.0' + + + + [UNICODE] The Unicode Consortium, + 'The Unicode Standard Version 3.0', ISBN 0-201-61633-5. + + + + [URL] T. Berners-Lee, L. Masinter & M. McCahill, 'Uniform Resource + Locators (URL)', RFC 1738, December 1994. + + + + [UTF-8] F. Yergeau, 'UTF-8, a transformation format of ISO 10646', + RFC 2279, January 1998. + + + + [UTF-16] F. Yergeau, 'UTF-16, an encoding of ISO 10646', RFC 2781, + February 2000. + + + + [ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, 'ZLIB + Compressed Data Format Specification version 3.3', RFC 1950, + May 1996. + + + + +9. Author's Address + + Written by + + Martin Nilsson + Rydsvgen 246 C. 30 + SE-584 34 Linkping + Sweden + + Email: nilsson@id3.org + diff --git a/external/taglib/source/mpeg/id3v2/id3v2.h b/external/taglib/source/mpeg/id3v2/id3v2.h new file mode 100644 index 0000000..bef8251 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2.h @@ -0,0 +1,24 @@ +#ifndef TAGLIB_ID3V2_H +#define TAGLIB_ID3V2_H + +namespace TagLib { + //! An ID3v2 implementation + + /*! + * This is a relatively complete and flexible framework for working with ID3v2 + * tags. + * + * \see ID3v2::Tag + */ + namespace ID3v2 { + /*! + * Used to specify which version of the ID3 standard to use when saving tags. + */ + enum Version { + v3 = 3, //size; +} + +void ExtendedHeader::setData(const ByteVector &data) +{ + parse(data); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ExtendedHeader::parse(const ByteVector &data) +{ + d->size = SynchData::toUInt(data.mid(0, 4)); // (structure 3.2 "Extended header size") +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2extendedheader.h b/external/taglib/source/mpeg/id3v2/id3v2extendedheader.h new file mode 100644 index 0000000..6466233 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2extendedheader.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2EXTENDEDHEADER_H +#define TAGLIB_ID3V2EXTENDEDHEADER_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "taglib.h" + +namespace TagLib { + + namespace ID3v2 { + + //! ID3v2 extended header implementation + + /*! + * This class implements ID3v2 extended headers. It attempts to follow, + * both semantically and programmatically, the structure specified in + * the ID3v2 standard. The API is based on the properties of ID3v2 extended + * headers specified there. If any of the terms used in this documentation + * are unclear please check the specification in the linked section. + * (Structure, 3.2) + */ + + class TAGLIB_EXPORT ExtendedHeader + { + public: + /*! + * Constructs an empty ID3v2 extended header. + */ + ExtendedHeader(); + + /*! + * Destroys the extended header. + */ + virtual ~ExtendedHeader(); + + /*! + * Returns the size of the extended header. This is variable for the + * extended header. + */ + unsigned int size() const; + + /*! + * Sets the data that will be used as the extended header. Since the + * length is not known before the extended header has been parsed, this + * should just be a pointer to the first byte of the extended header. It + * will determine the length internally and make that available through + * size(). + */ + void setData(const ByteVector &data); + + protected: + /*! + * Called by setData() to parse the extended header data. It makes this + * information available through the public API. + */ + void parse(const ByteVector &data); + + private: + ExtendedHeader(const ExtendedHeader &); + ExtendedHeader &operator=(const ExtendedHeader &); + + class ExtendedHeaderPrivate; + ExtendedHeaderPrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2footer.cpp b/external/taglib/source/mpeg/id3v2/id3v2footer.cpp new file mode 100644 index 0000000..3622724 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2footer.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "id3v2footer.h" +#include "id3v2header.h" + +using namespace TagLib; +using namespace ID3v2; + +class Footer::FooterPrivate +{ +}; + +Footer::Footer() : + d(0) +{ +} + +Footer::~Footer() +{ +} + +unsigned int Footer::size() +{ + return 10; +} + +ByteVector Footer::render(const Header *header) const +{ + ByteVector headerData = header->render(); + headerData[0] = '3'; + headerData[1] = 'D'; + headerData[2] = 'I'; + return headerData; +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2footer.h b/external/taglib/source/mpeg/id3v2/id3v2footer.h new file mode 100644 index 0000000..5eb3800 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2footer.h @@ -0,0 +1,82 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FOOTER_H +#define TAGLIB_ID3V2FOOTER_H + +#include "taglib_export.h" +#include "tbytevector.h" + +namespace TagLib { + + namespace ID3v2 { + + class Header; + + //! ID3v2 footer implementation + + /*! + * Per the ID3v2 specification, the tag's footer is just a copy of the + * information in the header. As such there is no API for reading the + * data from the header, it can just as easily be done from the header. + * + * In fact, at this point, TagLib does not even parse the footer since + * it is not useful internally. However, if the flag to include a footer + * has been set in the ID3v2::Tag, TagLib will render a footer. + */ + + class TAGLIB_EXPORT Footer + { + public: + /*! + * Constructs an empty ID3v2 footer. + */ + Footer(); + /*! + * Destroys the footer. + */ + virtual ~Footer(); + + /*! + * Returns the size of the footer. Presently this is always 10 bytes. + */ + static unsigned int size(); + + /*! + * Renders the footer based on the data in \a header. + */ + ByteVector render(const Header *header) const; + + private: + Footer(const Footer &); + Footer &operator=(const Footer &); + + class FooterPrivate; + FooterPrivate *d; + }; + + } +} +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2frame.cpp b/external/taglib/source/mpeg/id3v2/id3v2frame.cpp new file mode 100644 index 0000000..ae735b5 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2frame.cpp @@ -0,0 +1,832 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include + +#include "id3v2tag.h" +#include "id3v2frame.h" +#include "id3v2synchdata.h" + +#include "tpropertymap.h" +#include "frames/textidentificationframe.h" +#include "frames/urllinkframe.h" +#include "frames/unsynchronizedlyricsframe.h" +#include "frames/commentsframe.h" +#include "frames/uniquefileidentifierframe.h" +#include "frames/unknownframe.h" +#include "frames/podcastframe.h" + +using namespace TagLib; +using namespace ID3v2; + +class Frame::FramePrivate +{ +public: + FramePrivate() : + header(0) + {} + + ~FramePrivate() + { + delete header; + } + + Frame::Header *header; +}; + +namespace +{ + bool isValidFrameID(const ByteVector &frameID) + { + if(frameID.size() != 4) + return false; + + for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { + if( (*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9') ) { + return false; + } + } + return true; + } +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// static methods +//////////////////////////////////////////////////////////////////////////////// + +unsigned int Frame::headerSize() +{ + return Header::size(); +} + +unsigned int Frame::headerSize(unsigned int version) +{ + return Header::size(version); +} + +ByteVector Frame::textDelimiter(String::Type t) +{ + if(t == String::UTF16 || t == String::UTF16BE || t == String::UTF16LE) + return ByteVector(2, '\0'); + return ByteVector(1, '\0'); +} + +const String Frame::instrumentPrefix("PERFORMER:"); +const String Frame::commentPrefix("COMMENT:"); +const String Frame::lyricsPrefix("LYRICS:"); +const String Frame::urlPrefix("URL:"); + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Frame *Frame::createTextualFrame(const String &key, const StringList &values) //static +{ + // check if the key is contained in the key<=>frameID mapping + ByteVector frameID = keyToFrameID(key); + if(!frameID.isEmpty()) { + // Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number), GRP1 (Grouping) are in fact text frames. + if(frameID[0] == 'T' || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN" || frameID == "GRP1"){ // text frame + TextIdentificationFrame *frame = new TextIdentificationFrame(frameID, String::UTF8); + frame->setText(values); + return frame; + } if((frameID[0] == 'W') && (values.size() == 1)){ // URL frame (not WXXX); support only one value + UrlLinkFrame* frame = new UrlLinkFrame(frameID); + frame->setUrl(values.front()); + return frame; + } if(frameID == "PCST") { + return new PodcastFrame(); + } + } + if(key == "MUSICBRAINZ_TRACKID" && values.size() == 1) { + UniqueFileIdentifierFrame *frame = new UniqueFileIdentifierFrame("http://musicbrainz.org", values.front().data(String::UTF8)); + return frame; + } + // now we check if it's one of the "special" cases: + // -LYRICS: depending on the number of values, use USLT or TXXX (with description=LYRICS) + if((key == "LYRICS" || key.startsWith(lyricsPrefix)) && values.size() == 1){ + UnsynchronizedLyricsFrame *frame = new UnsynchronizedLyricsFrame(String::UTF8); + frame->setDescription(key == "LYRICS" ? key : key.substr(lyricsPrefix.size())); + frame->setText(values.front()); + return frame; + } + // -URL: depending on the number of values, use WXXX or TXXX (with description=URL) + if((key == "URL" || key.startsWith(urlPrefix)) && values.size() == 1){ + UserUrlLinkFrame *frame = new UserUrlLinkFrame(String::UTF8); + frame->setDescription(key == "URL" ? key : key.substr(urlPrefix.size())); + frame->setUrl(values.front()); + return frame; + } + // -COMMENT: depending on the number of values, use COMM or TXXX (with description=COMMENT) + if((key == "COMMENT" || key.startsWith(commentPrefix)) && values.size() == 1){ + CommentsFrame *frame = new CommentsFrame(String::UTF8); + if (key != "COMMENT"){ + frame->setDescription(key.substr(commentPrefix.size())); + } + frame->setText(values.front()); + return frame; + } + // if non of the above cases apply, we use a TXXX frame with the key as description + return new UserTextIdentificationFrame(keyToTXXX(key), values, String::UTF8); +} + +Frame::~Frame() +{ + delete d; +} + +ByteVector Frame::frameID() const +{ + if(d->header) + return d->header->frameID(); + return ByteVector(); +} + +unsigned int Frame::size() const +{ + if(d->header) + return d->header->frameSize(); + return 0; +} + +void Frame::setData(const ByteVector &data) +{ + parse(data); +} + +void Frame::setText(const String &) +{ + +} + +ByteVector Frame::render() const +{ + ByteVector fieldData = renderFields(); + d->header->setFrameSize(fieldData.size()); + ByteVector headerData = d->header->render(); + + return headerData + fieldData; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Frame::Frame(const ByteVector &data) : + d(new FramePrivate()) +{ + d->header = new Header(data); +} + +Frame::Frame(Header *h) : + d(new FramePrivate()) +{ + d->header = h; +} + +Frame::Header *Frame::header() const +{ + return d->header; +} + +void Frame::setHeader(Header *h, bool deleteCurrent) +{ + if(deleteCurrent) + delete d->header; + + d->header = h; +} + +void Frame::parse(const ByteVector &data) +{ + if(d->header) + d->header->setData(data); + else + d->header = new Header(data); + + parseFields(fieldData(data)); +} + +ByteVector Frame::fieldData(const ByteVector &frameData) const +{ + unsigned int headerSize = Header::size(d->header->version()); + + unsigned int frameDataOffset = headerSize; + unsigned int frameDataLength = size(); + + if(d->header->compression() || d->header->dataLengthIndicator()) { + frameDataLength = SynchData::toUInt(frameData.mid(headerSize, 4)); + frameDataOffset += 4; + } + + if(zlib::isAvailable() && d->header->compression() && !d->header->encryption()) { + if(frameData.size() <= frameDataOffset) { + debug("Compressed frame doesn't have enough data to decode"); + return ByteVector(); + } + + const ByteVector outData = zlib::decompress(frameData.mid(frameDataOffset)); + if(!outData.isEmpty() && frameDataLength != outData.size()) { + debug("frameDataLength does not match the data length returned by zlib"); + } + + return outData; + } + + return frameData.mid(frameDataOffset, frameDataLength); +} + +String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position) +{ + int start = 0; + + if(!position) + position = &start; + + ByteVector delimiter = textDelimiter(encoding); + + int end = data.find(delimiter, *position, delimiter.size()); + + if(end < *position) + return String(); + + String str; + if(encoding == String::Latin1) + str = Tag::latin1StringHandler()->parse(data.mid(*position, end - *position)); + else + str = String(data.mid(*position, end - *position), encoding); + + *position = end + delimiter.size(); + + return str; +} + +String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) // static +{ + return checkEncoding(fields, encoding, 4); +} + +String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding, unsigned int version) // static +{ + if((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4) + return String::UTF16; + + if(encoding != String::Latin1) + return encoding; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { + if(!(*it).isLatin1()) { + if(version == 4) { + debug("Frame::checkEncoding() -- Rendering using UTF8."); + return String::UTF8; + } + debug("Frame::checkEncoding() -- Rendering using UTF16."); + return String::UTF16; + } + } + + return String::Latin1; +} + +String::Type Frame::checkTextEncoding(const StringList &fields, String::Type encoding) const +{ + return checkEncoding(fields, encoding, header()->version()); +} + +namespace +{ + const std::pair frameTranslation[] = { + // Text information frames + std::make_pair("TALB", "ALBUM"), + std::make_pair("TBPM", "BPM"), + std::make_pair("TCOM", "COMPOSER"), + std::make_pair("TCON", "GENRE"), + std::make_pair("TCOP", "COPYRIGHT"), + std::make_pair("TDEN", "ENCODINGTIME"), + std::make_pair("TDLY", "PLAYLISTDELAY"), + std::make_pair("TDOR", "ORIGINALDATE"), + std::make_pair("TDRC", "DATE"), + // std::make_pair("TRDA", "DATE"), // id3 v2.3, replaced by TDRC in v2.4 + // std::make_pair("TDAT", "DATE"), // id3 v2.3, replaced by TDRC in v2.4 + // std::make_pair("TYER", "DATE"), // id3 v2.3, replaced by TDRC in v2.4 + // std::make_pair("TIME", "DATE"), // id3 v2.3, replaced by TDRC in v2.4 + std::make_pair("TDRL", "RELEASEDATE"), + std::make_pair("TDTG", "TAGGINGDATE"), + std::make_pair("TENC", "ENCODEDBY"), + std::make_pair("TEXT", "LYRICIST"), + std::make_pair("TFLT", "FILETYPE"), + //std::make_pair("TIPL", "INVOLVEDPEOPLE"), handled separately + std::make_pair("TIT1", "WORK"), // 'Work' in iTunes + std::make_pair("TIT2", "TITLE"), + std::make_pair("TIT3", "SUBTITLE"), + std::make_pair("TKEY", "INITIALKEY"), + std::make_pair("TLAN", "LANGUAGE"), + std::make_pair("TLEN", "LENGTH"), + //std::make_pair("TMCL", "MUSICIANCREDITS"), handled separately + std::make_pair("TMED", "MEDIA"), + std::make_pair("TMOO", "MOOD"), + std::make_pair("TOAL", "ORIGINALALBUM"), + std::make_pair("TOFN", "ORIGINALFILENAME"), + std::make_pair("TOLY", "ORIGINALLYRICIST"), + std::make_pair("TOPE", "ORIGINALARTIST"), + std::make_pair("TOWN", "OWNER"), + std::make_pair("TPE1", "ARTIST"), + std::make_pair("TPE2", "ALBUMARTIST"), // id3's spec says 'PERFORMER', but most programs use 'ALBUMARTIST' + std::make_pair("TPE3", "CONDUCTOR"), + std::make_pair("TPE4", "REMIXER"), // could also be ARRANGER + std::make_pair("TPOS", "DISCNUMBER"), + std::make_pair("TPRO", "PRODUCEDNOTICE"), + std::make_pair("TPUB", "LABEL"), + std::make_pair("TRCK", "TRACKNUMBER"), + std::make_pair("TRSN", "RADIOSTATION"), + std::make_pair("TRSO", "RADIOSTATIONOWNER"), + std::make_pair("TSOA", "ALBUMSORT"), + std::make_pair("TSOC", "COMPOSERSORT"), + std::make_pair("TSOP", "ARTISTSORT"), + std::make_pair("TSOT", "TITLESORT"), + std::make_pair("TSO2", "ALBUMARTISTSORT"), // non-standard, used by iTunes + std::make_pair("TSRC", "ISRC"), + std::make_pair("TSSE", "ENCODING"), + // URL frames + std::make_pair("WCOP", "COPYRIGHTURL"), + std::make_pair("WOAF", "FILEWEBPAGE"), + std::make_pair("WOAR", "ARTISTWEBPAGE"), + std::make_pair("WOAS", "AUDIOSOURCEWEBPAGE"), + std::make_pair("WORS", "RADIOSTATIONWEBPAGE"), + std::make_pair("WPAY", "PAYMENTWEBPAGE"), + std::make_pair("WPUB", "PUBLISHERWEBPAGE"), + //std::make_pair("WXXX", "URL"), handled specially + // Other frames + std::make_pair("COMM", "COMMENT"), + //std::make_pair("USLT", "LYRICS"), handled specially + // Apple iTunes proprietary frames + std::make_pair("PCST", "PODCAST"), + std::make_pair("TCAT", "PODCASTCATEGORY"), + std::make_pair("TDES", "PODCASTDESC"), + std::make_pair("TGID", "PODCASTID"), + std::make_pair("WFED", "PODCASTURL"), + std::make_pair("MVNM", "MOVEMENTNAME"), + std::make_pair("MVIN", "MOVEMENTNUMBER"), + std::make_pair("GRP1", "GROUPING"), + std::make_pair("TCMP", "COMPILATION"), + }; + const size_t frameTranslationSize = sizeof(frameTranslation) / sizeof(frameTranslation[0]); + + const std::pair txxxFrameTranslation[] = { + std::make_pair("MUSICBRAINZ ALBUM ID", "MUSICBRAINZ_ALBUMID"), + std::make_pair("MUSICBRAINZ ARTIST ID", "MUSICBRAINZ_ARTISTID"), + std::make_pair("MUSICBRAINZ ALBUM ARTIST ID", "MUSICBRAINZ_ALBUMARTISTID"), + std::make_pair("MUSICBRAINZ ALBUM RELEASE COUNTRY", "RELEASECOUNTRY"), + std::make_pair("MUSICBRAINZ ALBUM STATUS", "RELEASESTATUS"), + std::make_pair("MUSICBRAINZ ALBUM TYPE", "RELEASETYPE"), + std::make_pair("MUSICBRAINZ RELEASE GROUP ID", "MUSICBRAINZ_RELEASEGROUPID"), + std::make_pair("MUSICBRAINZ RELEASE TRACK ID", "MUSICBRAINZ_RELEASETRACKID"), + std::make_pair("MUSICBRAINZ WORK ID", "MUSICBRAINZ_WORKID"), + std::make_pair("ACOUSTID ID", "ACOUSTID_ID"), + std::make_pair("ACOUSTID FINGERPRINT", "ACOUSTID_FINGERPRINT"), + std::make_pair("MUSICIP PUID", "MUSICIP_PUID"), + }; + const size_t txxxFrameTranslationSize = sizeof(txxxFrameTranslation) / sizeof(txxxFrameTranslation[0]); + + // list of deprecated frames and their successors + const std::pair deprecatedFrames[] = { + std::make_pair("TRDA", "TDRC"), // 2.3 -> 2.4 (http://en.wikipedia.org/wiki/ID3) + std::make_pair("TDAT", "TDRC"), // 2.3 -> 2.4 + std::make_pair("TYER", "TDRC"), // 2.3 -> 2.4 + std::make_pair("TIME", "TDRC"), // 2.3 -> 2.4 + }; + const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]); +} // namespace + +String Frame::frameIDToKey(const ByteVector &id) +{ + ByteVector id24 = id; + for(size_t i = 0; i < deprecatedFramesSize; ++i) { + if(id24 == deprecatedFrames[i].first) { + id24 = deprecatedFrames[i].second; + break; + } + } + for(size_t i = 0; i < frameTranslationSize; ++i) { + if(id24 == frameTranslation[i].first) + return frameTranslation[i].second; + } + return String(); +} + +ByteVector Frame::keyToFrameID(const String &s) +{ + const String key = s.upper(); + for(size_t i = 0; i < frameTranslationSize; ++i) { + if(key == frameTranslation[i].second) + return frameTranslation[i].first; + } + return ByteVector(); +} + +String Frame::txxxToKey(const String &description) +{ + const String d = description.upper(); + for(size_t i = 0; i < txxxFrameTranslationSize; ++i) { + if(d == txxxFrameTranslation[i].first) + return txxxFrameTranslation[i].second; + } + return d; +} + +String Frame::keyToTXXX(const String &s) +{ + const String key = s.upper(); + for(size_t i = 0; i < txxxFrameTranslationSize; ++i) { + if(key == txxxFrameTranslation[i].second) + return txxxFrameTranslation[i].first; + } + return s; +} + +PropertyMap Frame::asProperties() const +{ + if(dynamic_cast< const UnknownFrame *>(this)) { + PropertyMap m; + m.unsupportedData().append("UNKNOWN/" + frameID()); + return m; + } + const ByteVector &id = frameID(); + // workaround until this function is virtual + if(id == "TXXX") + return dynamic_cast< const UserTextIdentificationFrame* >(this)->asProperties(); + // Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number), GRP1 (Grouping) are in fact text frames. + if(id[0] == 'T' || id == "WFED" || id == "MVNM" || id == "MVIN" || id == "GRP1") + return dynamic_cast< const TextIdentificationFrame* >(this)->asProperties(); + if(id == "WXXX") + return dynamic_cast< const UserUrlLinkFrame* >(this)->asProperties(); + if(id[0] == 'W') + return dynamic_cast< const UrlLinkFrame* >(this)->asProperties(); + if(id == "COMM") + return dynamic_cast< const CommentsFrame* >(this)->asProperties(); + if(id == "USLT") + return dynamic_cast< const UnsynchronizedLyricsFrame* >(this)->asProperties(); + if(id == "UFID") + return dynamic_cast< const UniqueFileIdentifierFrame* >(this)->asProperties(); + if(id == "PCST") + return dynamic_cast< const PodcastFrame* >(this)->asProperties(); + PropertyMap m; + m.unsupportedData().append(id); + return m; +} + +void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, + PropertyMap &tiplProperties, PropertyMap &tmclProperties) +{ + singleFrameProperties.clear(); + tiplProperties.clear(); + tmclProperties.clear(); + for(PropertyMap::ConstIterator it = original.begin(); it != original.end(); ++it) { + if(TextIdentificationFrame::involvedPeopleMap().contains(it->first)) + tiplProperties.insert(it->first, it->second); + else if(it->first.startsWith(TextIdentificationFrame::instrumentPrefix)) + tmclProperties.insert(it->first, it->second); + else + singleFrameProperties.insert(it->first, it->second); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// Frame::Header class +//////////////////////////////////////////////////////////////////////////////// + +class Frame::Header::HeaderPrivate +{ +public: + HeaderPrivate() : + frameSize(0), + version(4), + tagAlterPreservation(false), + fileAlterPreservation(false), + readOnly(false), + groupingIdentity(false), + compression(false), + encryption(false), + unsynchronisation(false), + dataLengthIndicator(false) + {} + + ByteVector frameID; + unsigned int frameSize; + unsigned int version; + + // flags + + bool tagAlterPreservation; + bool fileAlterPreservation; + bool readOnly; + bool groupingIdentity; + bool compression; + bool encryption; + bool unsynchronisation; + bool dataLengthIndicator; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members (Frame::Header) +//////////////////////////////////////////////////////////////////////////////// + +unsigned int Frame::Header::size() +{ + return size(4); +} + +unsigned int Frame::Header::size(unsigned int version) +{ + switch(version) { + case 0: + case 1: + case 2: + return 6; + case 3: + case 4: + default: + return 10; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// public members (Frame::Header) +//////////////////////////////////////////////////////////////////////////////// + +Frame::Header::Header(const ByteVector &data, bool synchSafeInts) : + d(new HeaderPrivate()) +{ + setData(data, synchSafeInts); +} + +Frame::Header::Header(const ByteVector &data, unsigned int version) : + d(new HeaderPrivate()) +{ + setData(data, version); +} + +Frame::Header::~Header() +{ + delete d; +} + +void Frame::Header::setData(const ByteVector &data, bool synchSafeInts) +{ + setData(data, static_cast(synchSafeInts ? 4 : 3)); +} + +void Frame::Header::setData(const ByteVector &data, unsigned int version) +{ + d->version = version; + + switch(version) { + case 0: + case 1: + case 2: + { + // ID3v2.2 + + if(data.size() < 3) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first three bytes + + d->frameID = data.mid(0, 3); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 6) { + d->frameSize = 0; + return; + } + + d->frameSize = data.toUInt(3, 3, true); + + break; + } + case 3: + { + // ID3v2.3 + + if(data.size() < 4) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first four bytes + + d->frameID = data.mid(0, 4); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 10) { + d->frameSize = 0; + return; + } + + // Set the size -- the frame size is the four bytes starting at byte four in + // the frame header (structure 4) + + d->frameSize = data.toUInt(4U); + + { // read the first byte of flags + std::bitset<8> flags(data[8]); + d->tagAlterPreservation = flags[7]; // (structure 3.3.1.a) + d->fileAlterPreservation = flags[6]; // (structure 3.3.1.b) + d->readOnly = flags[5]; // (structure 3.3.1.c) + } + + { // read the second byte of flags + std::bitset<8> flags(data[9]); + d->compression = flags[7]; // (structure 3.3.1.i) + d->encryption = flags[6]; // (structure 3.3.1.j) + d->groupingIdentity = flags[5]; // (structure 3.3.1.k) + } + break; + } + case 4: + default: + { + // ID3v2.4 + + if(data.size() < 4) { + debug("You must at least specify a frame ID."); + return; + } + + // Set the frame ID -- the first four bytes + + d->frameID = data.mid(0, 4); + + // If the full header information was not passed in, do not continue to the + // steps to parse the frame size and flags. + + if(data.size() < 10) { + d->frameSize = 0; + return; + } + + // Set the size -- the frame size is the four bytes starting at byte four in + // the frame header (structure 4) + + d->frameSize = SynchData::toUInt(data.mid(4, 4)); +#ifndef NO_ITUNES_HACKS + // iTunes writes v2.4 tags with v2.3-like frame sizes + if(d->frameSize > 127) { + if(!isValidFrameID(data.mid(d->frameSize + 10, 4))) { + unsigned int uintSize = data.toUInt(4U); + if(isValidFrameID(data.mid(uintSize + 10, 4))) { + d->frameSize = uintSize; + } + } + } +#endif + + { // read the first byte of flags + std::bitset<8> flags(data[8]); + d->tagAlterPreservation = flags[6]; // (structure 4.1.1.a) + d->fileAlterPreservation = flags[5]; // (structure 4.1.1.b) + d->readOnly = flags[4]; // (structure 4.1.1.c) + } + + { // read the second byte of flags + std::bitset<8> flags(data[9]); + d->groupingIdentity = flags[6]; // (structure 4.1.2.h) + d->compression = flags[3]; // (structure 4.1.2.k) + d->encryption = flags[2]; // (structure 4.1.2.m) + d->unsynchronisation = flags[1]; // (structure 4.1.2.n) + d->dataLengthIndicator = flags[0]; // (structure 4.1.2.p) + } + break; + } + } +} + +ByteVector Frame::Header::frameID() const +{ + return d->frameID; +} + +void Frame::Header::setFrameID(const ByteVector &id) +{ + d->frameID = id.mid(0, 4); +} + +unsigned int Frame::Header::frameSize() const +{ + return d->frameSize; +} + +void Frame::Header::setFrameSize(unsigned int size) +{ + d->frameSize = size; +} + +unsigned int Frame::Header::version() const +{ + return d->version; +} + +void Frame::Header::setVersion(unsigned int version) +{ + d->version = version; +} + +bool Frame::Header::tagAlterPreservation() const +{ + return d->tagAlterPreservation; +} + +void Frame::Header::setTagAlterPreservation(bool preserve) +{ + d->tagAlterPreservation = preserve; +} + +bool Frame::Header::fileAlterPreservation() const +{ + return d->fileAlterPreservation; +} + +bool Frame::Header::readOnly() const +{ + return d->readOnly; +} + +bool Frame::Header::groupingIdentity() const +{ + return d->groupingIdentity; +} + +bool Frame::Header::compression() const +{ + return d->compression; +} + +bool Frame::Header::encryption() const +{ + return d->encryption; +} + +bool Frame::Header::unsycronisation() const +{ + return unsynchronisation(); +} + +bool Frame::Header::unsynchronisation() const +{ + return d->unsynchronisation; +} + +bool Frame::Header::dataLengthIndicator() const +{ + return d->dataLengthIndicator; +} + +ByteVector Frame::Header::render() const +{ + ByteVector flags(2, char(0)); // just blank for the moment + + ByteVector v = d->frameID + + (d->version == 3 + ? ByteVector::fromUInt(d->frameSize) + : SynchData::fromUInt(d->frameSize)) + + flags; + + return v; +} + +bool Frame::Header::frameAlterPreservation() const +{ + return fileAlterPreservation(); +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2frame.h b/external/taglib/source/mpeg/id3v2/id3v2frame.h new file mode 100644 index 0000000..2e744fc --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2frame.h @@ -0,0 +1,523 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAME_H +#define TAGLIB_ID3V2FRAME_H + +#include "tstring.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class StringList; + class PropertyMap; + + namespace ID3v2 { + + class Tag; + class FrameFactory; + + //! ID3v2 frame implementation + + /*! + * This class is the main ID3v2 frame implementation. In ID3v2, a tag is + * split between a collection of frames (which are in turn split into fields + * (Structure, 4) + * (Frames). This class provides an API for + * gathering information about and modifying ID3v2 frames. Functionality + * specific to a given frame type is handed in one of the many subclasses. + */ + + class TAGLIB_EXPORT Frame + { + friend class Tag; + friend class FrameFactory; + friend class TableOfContentsFrame; + friend class ChapterFrame; + + public: + + /*! + * Creates a textual frame which corresponds to a single key in the PropertyMap + * interface. These are all (User)TextIdentificationFrames except TIPL and TMCL, + * all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame. + */ + static Frame *createTextualFrame(const String &key, const StringList &values); + + /*! + * Destroys this Frame instance. + */ + virtual ~Frame(); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Returns the size of the frame. + */ + unsigned int size() const; + + /*! + * Returns the size of the frame header + * + * \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use + * the call below which accepts an ID3v2 version number. In the next + * non-binary compatible release this will be made into a non-static + * member that checks the internal ID3v2 version. + */ + static unsigned int headerSize(); // BIC: make non-static + + /*! + * Returns the size of the frame header for the given ID3v2 version. + * + * \deprecated Please see the explanation above. + */ + // BIC: remove + static unsigned int headerSize(unsigned int version); + + /*! + * Sets the data that will be used as the frame. Since the length is not + * known before the frame has been parsed, this should just be a pointer to + * the first byte of the frame. It will determine the length internally + * and make that available through size(). + */ + void setData(const ByteVector &data); + + /*! + * Set the text of frame in the sanest way possible. This should only be + * reimplemented in frames where there is some logical mapping to text. + * + * \note If the frame type supports multiple text encodings, this will not + * change the text encoding of the frame; the string will be converted to + * that frame's encoding. Please use the specific APIs of the frame types + * to set the encoding if that is desired. + */ + virtual void setText(const String &text); + + /*! + * This returns the textual representation of the data in the frame. + * Subclasses must reimplement this method to provide a string + * representation of the frame's data. + */ + virtual String toString() const = 0; + + /*! + * Render the frame back to its binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * Returns the text delimiter that is used between fields for the string + * type \a t. + */ + static ByteVector textDelimiter(String::Type t); + + /*! + * The string with which an instrument name is prefixed to build a key in a PropertyMap; + * used to translate PropertyMaps to TMCL frames. In the current implementation, this + * is "PERFORMER:". + */ + static const String instrumentPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX + * frame for a non-standard key. In the current implementation, this is "COMMENT:". + */ + static const String commentPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX + * frame for a non-standard key. In the current implementation, this is "LYRICS:". + */ + static const String lyricsPrefix; + /*! + * The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX + * frame for a non-standard key. In the current implementation, this is "URL:". + */ + static const String urlPrefix; + + protected: + class Header; + + /*! + * Constructs an ID3v2 frame using \a data to read the header information. + * All other processing of \a data should be handled in a subclass. + * + * \note This need not contain anything more than a frame ID, but + * \e must contain at least that. + */ + explicit Frame(const ByteVector &data); + + /*! + * This creates an Frame using the header \a h. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + Frame(Header *h); + + /*! + * Returns a pointer to the frame header. + */ + Header *header() const; + + /*! + * Sets the header to \a h. If \a deleteCurrent is true, this will free + * the memory of the current header. + * + * The ownership of this header will be assigned to the frame and the + * header will be deleted when the frame is destroyed. + */ + void setHeader(Header *h, bool deleteCurrent = true); + + /*! + * Called by setData() to parse the frame data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + /*! + * Called by parse() to parse the field data. It makes this information + * available through the public API. This must be overridden by the + * subclasses. + */ + virtual void parseFields(const ByteVector &data) = 0; + + /*! + * Render the field data back to a binary format in a ByteVector. This + * must be overridden by subclasses. + */ + virtual ByteVector renderFields() const = 0; + + /*! + * Returns a ByteVector containing the field data given the frame data. + * This correctly adjusts for the header size plus any additional frame + * data that's specified in the frame header flags. + */ + ByteVector fieldData(const ByteVector &frameData) const; + + /*! + * Reads a String of type \a encoding from the ByteVector \a data. If \a + * position is passed in it is used both as the starting point and is + * updated to return the position just after the string that has been read. + * This is useful for reading strings sequentially. + */ + String readStringField(const ByteVector &data, String::Type encoding, + int *position = 0); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. + */ + // BIC: remove and make non-static + static String::Type checkEncoding(const StringList &fields, + String::Type encoding); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. This method + * also checks the ID3v2 version and makes sure the encoding can be used + * in the specified version. + */ + // BIC: remove and make non-static + static String::Type checkEncoding(const StringList &fields, + String::Type encoding, unsigned int version); + + /*! + * Checks a the list of string values to see if they can be used with the + * specified encoding and returns the recommended encoding. This method + * also checks the ID3v2 version and makes sure the encoding can be used + * in the version specified by the frame's header. + */ + String::Type checkTextEncoding(const StringList &fields, + String::Type encoding) const; + + + /*! + * Parses the contents of this frame as PropertyMap. If that fails, the returned + * PropertyMap will be empty, and its unsupportedData() will contain this frame's + * ID. + * BIC: Will be a virtual function in future releases. + */ + PropertyMap asProperties() const; + + /*! + * Returns an appropriate ID3 frame ID for the given free-form tag key. This method + * will return an empty ByteVector if no specialized translation is found. + */ + static ByteVector keyToFrameID(const String &); + + /*! + * Returns a free-form tag name for the given ID3 frame ID. Note that this does not work + * for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned. + */ + static String frameIDToKey(const ByteVector &); + + /*! + * Returns an appropriate TXXX frame description for the given free-form tag key. + */ + static String keyToTXXX(const String &); + + /*! + * Returns a free-form tag name for the given ID3 frame description. + */ + static String txxxToKey(const String &); + + /*! + * This helper function splits the PropertyMap \a original into three ProperytMaps + * \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that: + * - \a singleFrameProperties contains only of keys which can be represented with + * exactly one ID3 frame per key. In the current implementation + * this is everything except for the fixed "involved people" keys and keys of the + * form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are + * mapped to a TMCL frame. + * - \a tiplProperties will consist of those keys that are present in + * TextIdentificationFrame::involvedPeopleMap() + * - \a tmclProperties contains the "musician credits" keys which should be mapped + * to a TMCL frame + */ + static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, + PropertyMap &tiplProperties, PropertyMap &tmclProperties); + + private: + Frame(const Frame &); + Frame &operator=(const Frame &); + + class FramePrivate; + friend class FramePrivate; + FramePrivate *d; + }; + + //! ID3v2 frame header implementation + + /*! + * The ID3v2 Frame Header (Structure, 4) + * + * Every ID3v2::Frame has an associated header that gives some general + * properties of the frame and also makes it possible to identify the frame + * type. + * + * As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the + * frame headers and then creates the appropriate Frame subclass based on + * the type and attaches the header. + */ + + class TAGLIB_EXPORT Frame::Header + { + public: + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \deprecated Please use the constructor below that accepts a version + * number. + */ + TAGLIB_DEPRECATED Header(const ByteVector &data, bool synchSafeInts); + + /*! + * Construct a Frame Header based on \a data. \a data must at least + * contain a 4 byte frame ID, and optionally can contain flag data and the + * frame size. i.e. Just the frame id -- "TALB" -- is a valid value. + * + * \a version should be the ID3v2 version of the tag. + */ + explicit Header(const ByteVector &data, unsigned int version = 4); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Sets the data for the Header. + * + * \deprecated Please use the version below that accepts an ID3v2 version + * number. + */ + TAGLIB_DEPRECATED void setData(const ByteVector &data, bool synchSafeInts); + + /*! + * Sets the data for the Header. \a version should indicate the ID3v2 + * version number of the tag that this frame is contained in. + */ + void setData(const ByteVector &data, unsigned int version = 4); + + /*! + * Returns the Frame ID (Structure, 4) + * (Frames, 4) + */ + ByteVector frameID() const; + + /*! + * Sets the frame's ID to \a id. Only the first four bytes of \a id will + * be used. + * + * \warning This method should in general be avoided. It exists simply to + * provide a mechanism for transforming frames from a deprecated frame type + * to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4. + */ + void setFrameID(const ByteVector &id); + + /*! + * Returns the size of the frame data portion, as set when setData() was + * called or set explicitly via setFrameSize(). + */ + unsigned int frameSize() const; + + /*! + * Sets the size of the frame data portion. + */ + void setFrameSize(unsigned int size); + + /*! + * Returns the ID3v2 version of the header, as passed in from the + * construction of the header or set via setVersion(). + */ + unsigned int version() const; + + /*! + * Sets the ID3v2 version of the header, changing has impact on the + * correct parsing/rendering of frame data. + */ + void setVersion(unsigned int version); + + /*! + * Returns the size of the frame header in bytes. + * + * \deprecated Please use the version of this method that accepts a + * version. This is only accurate for ID3v2.3 and ID3v2.4. This will be + * removed in the next binary incompatible release (2.0) and will be + * replaced with a non-static method that checks the frame version. + */ + // BIC: make non-static + static unsigned int size(); + + /*! + * Returns the size of the frame header in bytes for the ID3v2 version + * that's given. + * + * \deprecated Please see the explanation in the version above. + */ + // BIC: remove + static unsigned int size(unsigned int version); + + /*! + * Returns true if the flag for tag alter preservation is set. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see setTagAlterPreservation() + */ + bool tagAlterPreservation() const; + + /*! + * Sets the flag for preservation of this frame if the tag is set. If + * this is set to true the frame will not be written when the tag is + * saved. + * + * The semantics are a little backwards from what would seem natural + * (setting the preservation flag to throw away the frame), but this + * follows the ID3v2 standard. + * + * \see tagAlterPreservation() + */ + void setTagAlterPreservation(bool discard); + + /*! + * Returns true if the flag for file alter preservation is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool fileAlterPreservation() const; + + /*! + * Returns true if the frame is meant to be read only. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool readOnly() const; + + /*! + * Returns true if the flag for the grouping identity is set. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool groupingIdentity() const; + + /*! + * Returns true if compression is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool compression() const; + + /*! + * Returns true if encryption is enabled for this frame. + * + * \note This flag is currently ignored internally in TagLib. + */ + bool encryption() const; + +#ifndef DO_NOT_DOCUMENT + bool unsycronisation() const; +#endif + + /*! + * Returns true if unsynchronisation is enabled for this frame. + */ + bool unsynchronisation() const; + + /*! + * Returns true if the flag for a data length indicator is set. + */ + bool dataLengthIndicator() const; + + /*! + * Render the Header back to binary format in a ByteVector. + */ + ByteVector render() const; + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED bool frameAlterPreservation() const; + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2framefactory.cpp b/external/taglib/source/mpeg/id3v2/id3v2framefactory.cpp new file mode 100644 index 0000000..f59af52 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2framefactory.cpp @@ -0,0 +1,551 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "id3v2framefactory.h" +#include "id3v2synchdata.h" +#include "id3v1genres.h" + +#include "frames/attachedpictureframe.h" +#include "frames/commentsframe.h" +#include "frames/relativevolumeframe.h" +#include "frames/textidentificationframe.h" +#include "frames/uniquefileidentifierframe.h" +#include "frames/unknownframe.h" +#include "frames/generalencapsulatedobjectframe.h" +#include "frames/urllinkframe.h" +#include "frames/unsynchronizedlyricsframe.h" +#include "frames/popularimeterframe.h" +#include "frames/privateframe.h" +#include "frames/ownershipframe.h" +#include "frames/synchronizedlyricsframe.h" +#include "frames/eventtimingcodesframe.h" +#include "frames/chapterframe.h" +#include "frames/tableofcontentsframe.h" +#include "frames/podcastframe.h" + +using namespace TagLib; +using namespace ID3v2; + +namespace +{ + void updateGenre(TextIdentificationFrame *frame) + { + StringList fields = frame->fieldList(); + StringList newfields; + + for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) { + String s = *it; + int offset = 0; + int end = 0; + + while(s.length() > offset && s[offset] == '(' && + (end = s.find(")", offset + 1)) > offset) { + // "(12)Genre" + const String genreCode = s.substr(offset + 1, end - 1); + s = s.substr(end + 1); + bool ok; + int number = genreCode.toInt(&ok); + if((ok && number >= 0 && number <= 255 && + !(ID3v1::genre(number) == s)) || + genreCode == "RX" || genreCode == "CR") + newfields.append(genreCode); + } + if(!s.isEmpty()) + // "Genre" or "12" + newfields.append(s); + } + + if(newfields.isEmpty()) + fields.append(String()); + + frame->setText(newfields); + } +} // namespace + +class FrameFactory::FrameFactoryPrivate +{ +public: + FrameFactoryPrivate() : + defaultEncoding(String::Latin1), + useDefaultEncoding(false) {} + + String::Type defaultEncoding; + bool useDefaultEncoding; + + template void setTextEncoding(T *frame) + { + if(useDefaultEncoding) + frame->setTextEncoding(defaultEncoding); + } +}; + +FrameFactory FrameFactory::factory; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FrameFactory *FrameFactory::instance() +{ + return &factory; +} + +Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const +{ + return createFrame(data, static_cast(synchSafeInts ? 4 : 3)); +} + +Frame *FrameFactory::createFrame(const ByteVector &data, unsigned int version) const +{ + Header tagHeader; + tagHeader.setMajorVersion(version); + return createFrame(data, &tagHeader); +} + +Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const +{ + return createFrame(origData, const_cast(tagHeader)); +} + +Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const +{ + ByteVector data = origData; + unsigned int version = tagHeader->majorVersion(); + Frame::Header *header = new Frame::Header(data, version); + ByteVector frameID = header->frameID(); + + // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1 + // characters. Also make sure that there is data in the frame. + + if(frameID.size() != (version < 3 ? 3 : 4) || + header->frameSize() <= static_cast(header->dataLengthIndicator() ? 4 : 0) || + header->frameSize() > data.size()) + { + delete header; + return 0; + } + +#ifndef NO_ITUNES_HACKS + if(version == 3 && frameID.size() == 4 && frameID[3] == '\0') { + // iTunes v2.3 tags store v2.2 frames - convert now + frameID = frameID.mid(0, 3); + header->setFrameID(frameID); + header->setVersion(2); + updateFrame(header); + header->setVersion(3); + } +#endif + + for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) { + if( (*it < 'A' || *it > 'Z') && (*it < '0' || *it > '9') ) { + delete header; + return 0; + } + } + + if(version > 3 && (tagHeader->unsynchronisation() || header->unsynchronisation())) { + // Data lengths are not part of the encoded data, but since they are synch-safe + // integers they will be never actually encoded. + ByteVector frameData = data.mid(Frame::Header::size(version), header->frameSize()); + frameData = SynchData::decode(frameData); + data = data.mid(0, Frame::Header::size(version)) + frameData; + } + + // TagLib doesn't mess with encrypted frames, so just treat them + // as unknown frames. + + if(!zlib::isAvailable() && header->compression()) { + debug("Compressed frames are currently not supported."); + return new UnknownFrame(data, header); + } + + if(header->encryption()) { + debug("Encrypted frames are currently not supported."); + return new UnknownFrame(data, header); + } + + if(!updateFrame(header)) { + header->setTagAlterPreservation(true); + return new UnknownFrame(data, header); + } + + // updateFrame() might have updated the frame ID. + + frameID = header->frameID(); + + // This is where things get necissarily nasty. Here we determine which + // Frame subclass (or if none is found simply an Frame) based + // on the frame ID. Since there are a lot of possibilities, that means + // a lot of if blocks. + + // Text Identification (frames 4.2) + + // Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number), GRP1 (Grouping) are in fact text frames. + if(frameID.startsWith("T") || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN" || frameID == "GRP1") { + + TextIdentificationFrame *f = frameID != "TXXX" + ? new TextIdentificationFrame(data, header) + : new UserTextIdentificationFrame(data, header); + + d->setTextEncoding(f); + + if(frameID == "TCON") + updateGenre(f); + + return f; + } + + // Comments (frames 4.10) + + if(frameID == "COMM") { + CommentsFrame *f = new CommentsFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // Attached Picture (frames 4.14) + + if(frameID == "APIC") { + AttachedPictureFrame *f = new AttachedPictureFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // ID3v2.2 Attached Picture + + if(frameID == "PIC") { + AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header); + d->setTextEncoding(f); + return f; + } + + // Relative Volume Adjustment (frames 4.11) + + if(frameID == "RVA2") + return new RelativeVolumeFrame(data, header); + + // Unique File Identifier (frames 4.1) + + if(frameID == "UFID") + return new UniqueFileIdentifierFrame(data, header); + + // General Encapsulated Object (frames 4.15) + + if(frameID == "GEOB") { + GeneralEncapsulatedObjectFrame *f = new GeneralEncapsulatedObjectFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // URL link (frames 4.3) + + if(frameID.startsWith("W")) { + if(frameID != "WXXX") { + return new UrlLinkFrame(data, header); + } + UserUrlLinkFrame *f = new UserUrlLinkFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // Unsynchronized lyric/text transcription (frames 4.8) + + if(frameID == "USLT") { + UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header); + if(d->useDefaultEncoding) + f->setTextEncoding(d->defaultEncoding); + return f; + } + + // Synchronized lyrics/text (frames 4.9) + + if(frameID == "SYLT") { + SynchronizedLyricsFrame *f = new SynchronizedLyricsFrame(data, header); + if(d->useDefaultEncoding) + f->setTextEncoding(d->defaultEncoding); + return f; + } + + // Event timing codes (frames 4.5) + + if(frameID == "ETCO") + return new EventTimingCodesFrame(data, header); + + // Popularimeter (frames 4.17) + + if(frameID == "POPM") + return new PopularimeterFrame(data, header); + + // Private (frames 4.27) + + if(frameID == "PRIV") + return new PrivateFrame(data, header); + + // Ownership (frames 4.22) + + if(frameID == "OWNE") { + OwnershipFrame *f = new OwnershipFrame(data, header); + d->setTextEncoding(f); + return f; + } + + // Chapter (ID3v2 chapters 1.0) + + if(frameID == "CHAP") + return new ChapterFrame(tagHeader, data, header); + + // Table of contents (ID3v2 chapters 1.0) + + if(frameID == "CTOC") + return new TableOfContentsFrame(tagHeader, data, header); + + // Apple proprietary PCST (Podcast) + + if(frameID == "PCST") + return new PodcastFrame(data, header); + + return new UnknownFrame(data, header); +} + +void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const +{ + if(tag->header()->majorVersion() < 4 && + tag->frameList("TDRC").size() == 1 && + tag->frameList("TDAT").size() == 1) + { + TextIdentificationFrame *tdrc = + dynamic_cast(tag->frameList("TDRC").front()); + UnknownFrame *tdat = dynamic_cast(tag->frameList("TDAT").front()); + + if(tdrc && + tdrc->fieldList().size() == 1 && + tdrc->fieldList().front().size() == 4 && + tdat && + tdat->data().size() >= 5) + { + String date(tdat->data().mid(1), String::Type(tdat->data()[0])); + if(date.length() == 4) { + tdrc->setText(tdrc->toString() + '-' + date.substr(2, 2) + '-' + date.substr(0, 2)); + if(tag->frameList("TIME").size() == 1) { + UnknownFrame *timeframe = dynamic_cast(tag->frameList("TIME").front()); + if(timeframe && timeframe->data().size() >= 5) { + String time(timeframe->data().mid(1), String::Type(timeframe->data()[0])); + if(time.length() == 4) { + tdrc->setText(tdrc->toString() + 'T' + time.substr(0, 2) + ':' + time.substr(2, 2)); + } + } + } + } + } + } +} + +String::Type FrameFactory::defaultTextEncoding() const +{ + return d->defaultEncoding; +} + +void FrameFactory::setDefaultTextEncoding(String::Type encoding) +{ + d->useDefaultEncoding = true; + d->defaultEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +FrameFactory::FrameFactory() : + d(new FrameFactoryPrivate()) +{ +} + +FrameFactory::~FrameFactory() +{ + delete d; +} + +namespace +{ + // Frame conversion table ID3v2.2 -> 2.4 + const std::pair frameConversion2[] = { + std::make_pair("BUF", "RBUF"), + std::make_pair("CNT", "PCNT"), + std::make_pair("COM", "COMM"), + std::make_pair("CRA", "AENC"), + std::make_pair("ETC", "ETCO"), + std::make_pair("GEO", "GEOB"), + std::make_pair("IPL", "TIPL"), + std::make_pair("MCI", "MCDI"), + std::make_pair("MLL", "MLLT"), + std::make_pair("POP", "POPM"), + std::make_pair("REV", "RVRB"), + std::make_pair("SLT", "SYLT"), + std::make_pair("STC", "SYTC"), + std::make_pair("TAL", "TALB"), + std::make_pair("TBP", "TBPM"), + std::make_pair("TCM", "TCOM"), + std::make_pair("TCO", "TCON"), + std::make_pair("TCP", "TCMP"), + std::make_pair("TCR", "TCOP"), + std::make_pair("TDY", "TDLY"), + std::make_pair("TEN", "TENC"), + std::make_pair("TFT", "TFLT"), + std::make_pair("TKE", "TKEY"), + std::make_pair("TLA", "TLAN"), + std::make_pair("TLE", "TLEN"), + std::make_pair("TMT", "TMED"), + std::make_pair("TOA", "TOAL"), + std::make_pair("TOF", "TOFN"), + std::make_pair("TOL", "TOLY"), + std::make_pair("TOR", "TDOR"), + std::make_pair("TOT", "TOAL"), + std::make_pair("TP1", "TPE1"), + std::make_pair("TP2", "TPE2"), + std::make_pair("TP3", "TPE3"), + std::make_pair("TP4", "TPE4"), + std::make_pair("TPA", "TPOS"), + std::make_pair("TPB", "TPUB"), + std::make_pair("TRC", "TSRC"), + std::make_pair("TRD", "TDRC"), + std::make_pair("TRK", "TRCK"), + std::make_pair("TS2", "TSO2"), + std::make_pair("TSA", "TSOA"), + std::make_pair("TSC", "TSOC"), + std::make_pair("TSP", "TSOP"), + std::make_pair("TSS", "TSSE"), + std::make_pair("TST", "TSOT"), + std::make_pair("TT1", "TIT1"), + std::make_pair("TT2", "TIT2"), + std::make_pair("TT3", "TIT3"), + std::make_pair("TXT", "TOLY"), + std::make_pair("TXX", "TXXX"), + std::make_pair("TYE", "TDRC"), + std::make_pair("UFI", "UFID"), + std::make_pair("ULT", "USLT"), + std::make_pair("WAF", "WOAF"), + std::make_pair("WAR", "WOAR"), + std::make_pair("WAS", "WOAS"), + std::make_pair("WCM", "WCOM"), + std::make_pair("WCP", "WCOP"), + std::make_pair("WPB", "WPUB"), + std::make_pair("WXX", "WXXX"), + + // Apple iTunes nonstandard frames + std::make_pair("PCS", "PCST"), + std::make_pair("TCT", "TCAT"), + std::make_pair("TDR", "TDRL"), + std::make_pair("TDS", "TDES"), + std::make_pair("TID", "TGID"), + std::make_pair("WFD", "WFED"), + std::make_pair("MVN", "MVNM"), + std::make_pair("MVI", "MVIN"), + std::make_pair("GP1", "GRP1"), + }; + const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]); + + // Frame conversion table ID3v2.3 -> 2.4 + const std::pair frameConversion3[] = { + std::make_pair("TORY", "TDOR"), + std::make_pair("TYER", "TDRC"), + std::make_pair("IPLS", "TIPL"), + }; + const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConversion3[0]); +} // namespace + +bool FrameFactory::updateFrame(Frame::Header *header) const +{ + const ByteVector frameID = header->frameID(); + + switch(header->version()) { + + case 2: // ID3v2.2 + { + if(frameID == "CRM" || + frameID == "EQU" || + frameID == "LNK" || + frameID == "RVA" || + frameID == "TIM" || + frameID == "TSI" || + frameID == "TDA") + { + debug("ID3v2.4 no longer supports the frame type " + String(frameID) + + ". It will be discarded from the tag."); + return false; + } + + // ID3v2.2 only used 3 bytes for the frame ID, so we need to convert all of + // the frames to their 4 byte ID3v2.4 equivalent. + + for(size_t i = 0; i < frameConversion2Size; ++i) { + if(frameID == frameConversion2[i].first) { + header->setFrameID(frameConversion2[i].second); + break; + } + } + + break; + } + + case 3: // ID3v2.3 + { + if(frameID == "EQUA" || + frameID == "RVAD" || + frameID == "TIME" || + frameID == "TRDA" || + frameID == "TSIZ" || + frameID == "TDAT") + { + debug("ID3v2.4 no longer supports the frame type " + String(frameID) + + ". It will be discarded from the tag."); + return false; + } + + for(size_t i = 0; i < frameConversion3Size; ++i) { + if(frameID == frameConversion3[i].first) { + header->setFrameID(frameConversion3[i].second); + break; + } + } + + break; + } + + default: + + // This should catch a typo that existed in TagLib up to and including + // version 1.1 where TRDC was used for the year rather than TDRC. + + if(frameID == "TRDC") + header->setFrameID("TDRC"); + + break; + } + + return true; +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2framefactory.h b/external/taglib/source/mpeg/id3v2/id3v2framefactory.h new file mode 100644 index 0000000..9605c78 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2framefactory.h @@ -0,0 +1,169 @@ + /*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2FRAMEFACTORY_H +#define TAGLIB_ID3V2FRAMEFACTORY_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "id3v2frame.h" +#include "id3v2header.h" + +namespace TagLib { + + namespace ID3v2 { + + class TextIdentificationFrame; + + //! A factory for creating ID3v2 frames during parsing + + /*! + * This factory abstracts away the frame creation process and instantiates + * the appropriate ID3v2::Frame subclasses based on the contents of the + * data. + * + * Reimplementing this factory is the key to adding support for frame types + * not directly supported by TagLib to your application. To do so you would + * subclass this factory and reimplement createFrame(). Then by setting your + * factory to be the default factory in ID3v2::Tag constructor you can + * implement behavior that will allow for new ID3v2::Frame subclasses (also + * provided by you) to be used. + * + * This implements both abstract factory and singleton patterns + * of which more information is available on the web and in software design + * textbooks (Notably Design Patters). + * + * \note You do not need to use this factory to create new frames to add to + * an ID3v2::Tag. You can instantiate frame subclasses directly (with new) + * and add them to a tag using ID3v2::Tag::addFrame() + * + * \see ID3v2::Tag::addFrame() + */ + + class TAGLIB_EXPORT FrameFactory + { + public: + static FrameFactory *instance(); + /*! + * Create a frame based on \a data. \a synchSafeInts should only be set + * false if we are parsing an old tag (v2.3 or older) that does not support + * synchsafe ints. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + TAGLIB_DEPRECATED Frame *createFrame(const ByteVector &data, bool synchSafeInts) const; + + /*! + * Create a frame based on \a data. \a version should indicate the ID3v2 + * version of the tag. As ID3v2.4 is the most current version of the + * standard 4 is the default. + * + * \deprecated Please use the method below that accepts a ID3v2::Header + * instance in new code. + */ + TAGLIB_DEPRECATED Frame *createFrame(const ByteVector &data, unsigned int version = 4) const; + + /*! + * \deprecated + */ + // BIC: remove + Frame *createFrame(const ByteVector &data, Header *tagHeader) const; + /*! + * Create a frame based on \a data. \a tagHeader should be a valid + * ID3v2::Header instance. + */ + // BIC: make virtual + Frame *createFrame(const ByteVector &data, const Header *tagHeader) const; + + /*! + * After a tag has been read, this tries to rebuild some of them + * information, most notably the recording date, from frames that + * have been deprecated and can't be upgraded directly. + */ + // BIC: Make virtual + void rebuildAggregateFrames(ID3v2::Tag *tag) const; + + /*! + * Returns the default text encoding for text frames. If setTextEncoding() + * has not been explicitly called this will only be used for new text + * frames. However, if this value has been set explicitly all frames will be + * converted to this type (unless it's explicitly set differently for the + * individual frame) when being rendered. + * + * \see setDefaultTextEncoding() + */ + String::Type defaultTextEncoding() const; + + /*! + * Set the default text encoding for all text frames that are created to + * \a encoding. If no value is set the frames with either default to the + * encoding type that was parsed and new frames default to Latin1. + * + * Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE. + * + * \see defaultTextEncoding() + */ + void setDefaultTextEncoding(String::Type encoding); + + protected: + /*! + * Constructs a frame factory. Because this is a singleton this method is + * protected, but may be used for subclasses. + */ + FrameFactory(); + + /*! + * Destroys the frame factory. + */ + virtual ~FrameFactory(); + + /*! + * This method checks for compliance to the current ID3v2 standard (2.4) + * and does nothing in the common case. However if a frame is found that + * is not compatible with the current standard, this method either updates + * the frame or indicates that it should be discarded. + * + * This method with return true (with or without changes to the frame) if + * this frame should be kept or false if it should be discarded. + * + * See the id3v2.4.0-changes.txt document for further information. + */ + virtual bool updateFrame(Frame::Header *header) const; + + private: + FrameFactory(const FrameFactory &); + FrameFactory &operator=(const FrameFactory &); + + static FrameFactory factory; + + class FrameFactoryPrivate; + FrameFactoryPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2header.cpp b/external/taglib/source/mpeg/id3v2/id3v2header.cpp new file mode 100644 index 0000000..3496cff --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2header.cpp @@ -0,0 +1,238 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include + +#include "id3v2header.h" +#include "id3v2footer.h" +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +class Header::HeaderPrivate +{ +public: + HeaderPrivate() : + majorVersion(4), + revisionNumber(0), + unsynchronisation(false), + extendedHeader(false), + experimentalIndicator(false), + footerPresent(false), + tagSize(0) {} + + unsigned int majorVersion; + unsigned int revisionNumber; + + bool unsynchronisation; + bool extendedHeader; + bool experimentalIndicator; + bool footerPresent; + + unsigned int tagSize; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +unsigned int Header::size() +{ + return 10; +} + +ByteVector Header::fileIdentifier() +{ + return ByteVector::fromCString("ID3"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Header::Header() : + d(new HeaderPrivate()) +{ +} + +Header::Header(const ByteVector &data) : + d(new HeaderPrivate()) +{ + parse(data); +} + +Header::~Header() +{ + delete d; +} + +unsigned int Header::majorVersion() const +{ + return d->majorVersion; +} + +void Header::setMajorVersion(unsigned int version) +{ + d->majorVersion = version; +} + +unsigned int Header::revisionNumber() const +{ + return d->revisionNumber; +} + +bool Header::unsynchronisation() const +{ + return d->unsynchronisation; +} + +bool Header::extendedHeader() const +{ + return d->extendedHeader; +} + +bool Header::experimentalIndicator() const +{ + return d->experimentalIndicator; +} + +bool Header::footerPresent() const +{ + return d->footerPresent; +} + +unsigned int Header::tagSize() const +{ + return d->tagSize; +} + +unsigned int Header::completeTagSize() const +{ + if(d->footerPresent) + return d->tagSize + size() + Footer::size(); + return d->tagSize + size(); +} + +void Header::setTagSize(unsigned int s) +{ + d->tagSize = s; +} + +void Header::setData(const ByteVector &data) +{ + parse(data); +} + +ByteVector Header::render() const +{ + ByteVector v; + + // add the file identifier -- "ID3" + v.append(fileIdentifier()); + + // add the version number -- we always render a 2.4.0 tag regardless of what + // the tag originally was. + + v.append(char(majorVersion())); + v.append(char(0)); + + // Currently we don't actually support writing extended headers, footers or + // unsynchronized tags, make sure that the flags are set accordingly. + + d->extendedHeader = false; + d->footerPresent = false; + d->unsynchronisation = false; + + // render and add the flags + std::bitset<8> flags; + + flags[7] = d->unsynchronisation; + flags[6] = d->extendedHeader; + flags[5] = d->experimentalIndicator; + flags[4] = d->footerPresent; + + v.append(char(flags.to_ulong())); + + // add the size + v.append(SynchData::fromUInt(d->tagSize)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void Header::parse(const ByteVector &data) +{ + if(data.size() < size()) + return; + + // do some sanity checking -- even in ID3v2.3.0 and less the tag size is a + // synch-safe integer, so all bytes must be less than 128. If this is not + // true then this is an invalid tag. + + // note that we're doing things a little out of order here -- the size is + // later in the bytestream than the version + + ByteVector sizeData = data.mid(6, 4); + + if(sizeData.size() != 4) { + d->tagSize = 0; + debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!"); + return; + } + + for(ByteVector::ConstIterator it = sizeData.begin(); it != sizeData.end(); it++) { + if(static_cast(*it) >= 128) { + d->tagSize = 0; + debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128."); + return; + } + } + + // The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier") + + // Read the version number from the fourth and fifth bytes. + d->majorVersion = data[3]; // (structure 3.1 "major version") + d->revisionNumber = data[4]; // (structure 3.1 "revision number") + + // Read the flags, the first four bits of the sixth byte. + std::bitset<8> flags(data[5]); + + d->unsynchronisation = flags[7]; // (structure 3.1.a) + d->extendedHeader = flags[6]; // (structure 3.1.b) + d->experimentalIndicator = flags[5]; // (structure 3.1.c) + d->footerPresent = flags[4]; // (structure 3.1.d) + + // Get the size from the remaining four bytes (read above) + + d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size") +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2header.h b/external/taglib/source/mpeg/id3v2/id3v2header.h new file mode 100644 index 0000000..a1f2985 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2header.h @@ -0,0 +1,176 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2HEADER_H +#define TAGLIB_ID3V2HEADER_H + +#include "tbytevector.h" +#include "taglib_export.h" +#include "id3v2.h" + +namespace TagLib { + + namespace ID3v2 { + + //! An implementation of ID3v2 headers + + /*! + * This class implements ID3v2 headers. It attempts to follow, both + * semantically and programmatically, the structure specified in + * the ID3v2 standard. The API is based on the properties of ID3v2 headers + * specified there. If any of the terms used in this documentation are + * unclear please check the specification in the linked section. + * (Structure, 3.1) + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Constructs an empty ID3v2 header. + */ + Header(); + + /*! + * Constructs an ID3v2 header based on \a data. parse() is called + * immediately. + */ + Header(const ByteVector &data); + + /*! + * Destroys the header. + */ + virtual ~Header(); + + /*! + * Returns the major version number. (Note: This is the 4, not the 2 in + * ID3v2.4.0. The 2 is implied.) + */ + unsigned int majorVersion() const; + + /*! + * Set the the major version number to \a version. (Note: This is + * the 4, not the 2 in ID3v2.4.0. The 2 is implied.) + * \see majorVersion() + * + * \note This is used by the internal parser; this will not change the + * version which is written and in general should not be called by API + * users. + */ + void setMajorVersion(unsigned int version); + + /*! + * Returns the revision number. (Note: This is the 0, not the 4 in + * ID3v2.4.0. The 2 is implied.) + */ + unsigned int revisionNumber() const; + + /*! + * Returns true if unsynchronisation has been applied to all frames. + */ + bool unsynchronisation() const; + + /*! + * Returns true if an extended header is present in the tag. + */ + bool extendedHeader() const; + + /*! + * Returns true if the experimental indicator flag is set. + */ + bool experimentalIndicator() const; + + /*! + * Returns true if a footer is present in the tag. + */ + bool footerPresent() const; + /*! + * Returns the tag size in bytes. This is the size of the frame content. + * The size of the \e entire tag will be this plus the header size (10 + * bytes) and, if present, the footer size (potentially another 10 bytes). + * + * \note This is the value as read from the header to which TagLib attempts + * to provide an API to; it was not a design decision on the part of TagLib + * to not include the mentioned portions of the tag in the \e size. + * + * \see completeTagSize() + */ + unsigned int tagSize() const; + + /*! + * Returns the tag size, including the header and, if present, the footer + * size. + * + * \see tagSize() + */ + unsigned int completeTagSize() const; + + /*! + * Set the tag size to \a s. + * \see tagSize() + */ + void setTagSize(unsigned int s); + + /*! + * Returns the size of the header. Presently this is always 10 bytes. + */ + static unsigned int size(); + + /*! + * Returns the string used to identify and ID3v2 tag inside of a file. + * Presently this is always "ID3". + */ + static ByteVector fileIdentifier(); + + /*! + * Sets the data that will be used as the header. 10 bytes, starting from + * the beginning of \a data are used. + */ + void setData(const ByteVector &data); + + /*! + * Renders the Header back to binary format. + */ + ByteVector render() const; + + protected: + /*! + * Called by setData() to parse the header data. It makes this information + * available through the public API. + */ + void parse(const ByteVector &data); + + private: + Header(const Header &); + Header &operator=(const Header &); + + class HeaderPrivate; + HeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2synchdata.cpp b/external/taglib/source/mpeg/id3v2/id3v2synchdata.cpp new file mode 100644 index 0000000..ba848de --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2synchdata.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "id3v2synchdata.h" + +using namespace TagLib; +using namespace ID3v2; + +unsigned int SynchData::toUInt(const ByteVector &data) +{ + unsigned int sum = 0; + bool notSynchSafe = false; + int last = data.size() > 4 ? 3 : data.size() - 1; + + for(int i = 0; i <= last; i++) { + if(data[i] & 0x80) { + notSynchSafe = true; + break; + } + + sum |= (data[i] & 0x7f) << ((last - i) * 7); + } + + if(notSynchSafe) { + // Invalid data; assume this was created by some buggy software that just + // put normal integers here rather than syncsafe ones, and try it that + // way. + if(data.size() >= 4) { + sum = data.toUInt(0, true); + } + else { + ByteVector tmp(data); + tmp.resize(4); + sum = tmp.toUInt(0, true); + } + } + + return sum; +} + +ByteVector SynchData::fromUInt(unsigned int value) +{ + ByteVector v(4, 0); + + for(int i = 0; i < 4; i++) + v[i] = static_cast(value >> ((3 - i) * 7) & 0x7f); + + return v; +} + +ByteVector SynchData::decode(const ByteVector &data) +{ + if (data.size() == 0) { + return ByteVector(); + } + + // We have this optimized method instead of using ByteVector::replace(), + // since it makes a great difference when decoding huge unsynchronized frames. + + ByteVector result(data.size()); + + ByteVector::ConstIterator src = data.begin(); + ByteVector::Iterator dst = result.begin(); + + while(src < data.end() - 1) { + *dst++ = *src++; + + if(*(src - 1) == '\xff' && *src == '\x00') + src++; + } + + if(src < data.end()) + *dst++ = *src++; + + result.resize(static_cast(dst - result.begin())); + + return result; +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2synchdata.h b/external/taglib/source/mpeg/id3v2/id3v2synchdata.h new file mode 100644 index 0000000..13e0716 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2synchdata.h @@ -0,0 +1,70 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2SYNCHDATA_H +#define TAGLIB_ID3V2SYNCHDATA_H + +#include "tbytevector.h" +#include "taglib.h" + +namespace TagLib { + + namespace ID3v2 { + + //! A few functions for ID3v2 synch safe integer conversion + + /*! + * In the ID3v2.4 standard most integer values are encoded as "synch safe" + * integers which are encoded in such a way that they will not give false + * MPEG syncs and confuse MPEG decoders. This namespace provides some + * methods for converting to and from these values to ByteVectors for + * things rendering and parsing ID3v2 data. + */ + + namespace SynchData + { + /*! + * This returns the unsigned integer value of \a data where \a data is a + * ByteVector that contains a \e synchsafe integer (Structure, + * 6.2). The default \a length of + * 4 is used if another value is not specified. + */ + TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data); + + /*! + * Returns a 4 byte (32 bit) synchsafe integer based on \a value. + */ + TAGLIB_EXPORT ByteVector fromUInt(unsigned int value); + + /*! + * Convert the data from unsynchronized data to its original format. + */ + TAGLIB_EXPORT ByteVector decode(const ByteVector &input); + } + + } +} + +#endif diff --git a/external/taglib/source/mpeg/id3v2/id3v2tag.cpp b/external/taglib/source/mpeg/id3v2/id3v2tag.cpp new file mode 100644 index 0000000..156c6d5 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2tag.cpp @@ -0,0 +1,847 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "id3v2tag.h" +#include "id3v2header.h" +#include "id3v2extendedheader.h" +#include "id3v2footer.h" +#include "id3v2synchdata.h" +#include "id3v1genres.h" + +#include "frames/textidentificationframe.h" +#include "frames/commentsframe.h" +#include "frames/urllinkframe.h" +#include "frames/uniquefileidentifierframe.h" +#include "frames/unsynchronizedlyricsframe.h" +#include "frames/unknownframe.h" + +using namespace TagLib; +using namespace ID3v2; + +namespace +{ + const ID3v2::Latin1StringHandler defaultStringHandler; + const ID3v2::Latin1StringHandler *stringHandler = &defaultStringHandler; + + const long MinPaddingSize = 1024; + const long MaxPaddingSize = 1024 * 1024; + + bool contains(const char **a, const ByteVector &v) + { + for(int i = 0; a[i]; i++) + { + if(v == a[i]) + return true; + } + return false; + } +} // namespace + +class ID3v2::Tag::TagPrivate +{ +public: + TagPrivate() : + factory(0), + file(0), + tagOffset(0), + extendedHeader(0), + footer(0) + { + frameList.setAutoDelete(true); + } + + ~TagPrivate() + { + delete extendedHeader; + delete footer; + } + + const FrameFactory *factory; + + File *file; + long tagOffset; + + Header header; + ExtendedHeader *extendedHeader; + Footer *footer; + + FrameListMap frameListMap; + FrameList frameList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// StringHandler implementation +//////////////////////////////////////////////////////////////////////////////// + +Latin1StringHandler::Latin1StringHandler() +{ +} + +Latin1StringHandler::~Latin1StringHandler() +{ +} + +String Latin1StringHandler::parse(const ByteVector &data) const +{ + return String(data, String::Latin1); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ID3v2::Tag::Tag() : + d(new TagPrivate()) +{ + d->factory = FrameFactory::instance(); +} + +ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) : + d(new TagPrivate()) +{ + d->factory = factory; + d->file = file; + d->tagOffset = tagOffset; + + read(); +} + +ID3v2::Tag::~Tag() +{ + delete d; +} + +String ID3v2::Tag::title() const +{ + if(!d->frameListMap["TIT2"].isEmpty()) + return d->frameListMap["TIT2"].front()->toString(); + return String(); +} + +String ID3v2::Tag::artist() const +{ + if(!d->frameListMap["TPE1"].isEmpty()) + return d->frameListMap["TPE1"].front()->toString(); + return String(); +} + +String ID3v2::Tag::album() const +{ + if(!d->frameListMap["TALB"].isEmpty()) + return d->frameListMap["TALB"].front()->toString(); + return String(); +} + +String ID3v2::Tag::comment() const +{ + const FrameList &comments = d->frameListMap["COMM"]; + + if(comments.isEmpty()) + return String(); + + for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it) + { + CommentsFrame *frame = dynamic_cast(*it); + + if(frame && frame->description().isEmpty()) + return (*it)->toString(); + } + + return comments.front()->toString(); +} + +String ID3v2::Tag::genre() const +{ + // TODO: In the next major version (TagLib 2.0) a list of multiple genres + // should be separated by " / " instead of " ". For the moment to keep + // the behavior the same as released versions it is being left with " ". + + const FrameList &tconFrames = d->frameListMap["TCON"]; + TextIdentificationFrame *f; + if(tconFrames.isEmpty() || + !(f = dynamic_cast(tconFrames.front()))) + { + return String(); + } + + // ID3v2.4 lists genres as the fields in its frames field list. If the field + // is simply a number it can be assumed that it is an ID3v1 genre number. + // Here was assume that if an ID3v1 string is present that it should be + // appended to the genre string. Multiple fields will be appended as the + // string is built. + + StringList fields = f->fieldList(); + + StringList genres; + + for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) { + + if((*it).isEmpty()) + continue; + + bool ok; + int number = (*it).toInt(&ok); + if(ok && number >= 0 && number <= 255) { + *it = ID3v1::genre(number); + } + + if(std::find(genres.begin(), genres.end(), *it) == genres.end()) + genres.append(*it); + } + + return genres.toString(); +} + +unsigned int ID3v2::Tag::year() const +{ + if(!d->frameListMap["TDRC"].isEmpty()) + return d->frameListMap["TDRC"].front()->toString().substr(0, 4).toInt(); + return 0; +} + +unsigned int ID3v2::Tag::track() const +{ + if(!d->frameListMap["TRCK"].isEmpty()) + return d->frameListMap["TRCK"].front()->toString().toInt(); + return 0; +} + +void ID3v2::Tag::setTitle(const String &s) +{ + setTextFrame("TIT2", s); +} + +void ID3v2::Tag::setArtist(const String &s) +{ + setTextFrame("TPE1", s); +} + +void ID3v2::Tag::setAlbum(const String &s) +{ + setTextFrame("TALB", s); +} + +void ID3v2::Tag::setComment(const String &s) +{ + if(s.isEmpty()) { + removeFrames("COMM"); + return; + } + + const FrameList &comments = d->frameListMap["COMM"]; + + if(!comments.isEmpty()) { + for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it) { + CommentsFrame *frame = dynamic_cast(*it); + if(frame && frame->description().isEmpty()) { + (*it)->setText(s); + return; + } + } + + comments.front()->setText(s); + return; + } + + CommentsFrame *f = new CommentsFrame(d->factory->defaultTextEncoding()); + addFrame(f); + f->setText(s); +} + +void ID3v2::Tag::setGenre(const String &s) +{ + if(s.isEmpty()) { + removeFrames("TCON"); + return; + } + + // iTunes can't handle correctly encoded ID3v2.4 numerical genres. Just use + // strings until iTunes sucks less. + +#ifdef NO_ITUNES_HACKS + + int index = ID3v1::genreIndex(s); + + if(index != 255) + setTextFrame("TCON", String::number(index)); + else + setTextFrame("TCON", s); + +#else + + setTextFrame("TCON", s); + +#endif +} + +void ID3v2::Tag::setYear(unsigned int i) +{ + if(i == 0) { + removeFrames("TDRC"); + return; + } + setTextFrame("TDRC", String::number(i)); +} + +void ID3v2::Tag::setTrack(unsigned int i) +{ + if(i == 0) { + removeFrames("TRCK"); + return; + } + setTextFrame("TRCK", String::number(i)); +} + +bool ID3v2::Tag::isEmpty() const +{ + return d->frameList.isEmpty(); +} + +Header *ID3v2::Tag::header() const +{ + return &(d->header); +} + +ExtendedHeader *ID3v2::Tag::extendedHeader() const +{ + return d->extendedHeader; +} + +Footer *ID3v2::Tag::footer() const +{ + return d->footer; +} + +const FrameListMap &ID3v2::Tag::frameListMap() const +{ + return d->frameListMap; +} + +const FrameList &ID3v2::Tag::frameList() const +{ + return d->frameList; +} + +const FrameList &ID3v2::Tag::frameList(const ByteVector &frameID) const +{ + return d->frameListMap[frameID]; +} + +void ID3v2::Tag::addFrame(Frame *frame) +{ + d->frameList.append(frame); + d->frameListMap[frame->frameID()].append(frame); +} + +void ID3v2::Tag::removeFrame(Frame *frame, bool del) +{ + // remove the frame from the frame list + FrameList::Iterator it = d->frameList.find(frame); + d->frameList.erase(it); + + // ...and from the frame list map + it = d->frameListMap[frame->frameID()].find(frame); + d->frameListMap[frame->frameID()].erase(it); + + // ...and delete as desired + if(del) + delete frame; +} + +void ID3v2::Tag::removeFrames(const ByteVector &id) +{ + FrameList l = d->frameListMap[id]; + for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) + removeFrame(*it, true); +} + +PropertyMap ID3v2::Tag::properties() const +{ + PropertyMap properties; + for(FrameList::ConstIterator it = frameList().begin(); it != frameList().end(); ++it) { + PropertyMap props = (*it)->asProperties(); + properties.merge(props); + } + return properties; +} + +void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) +{ + for(StringList::ConstIterator it = properties.begin(); it != properties.end(); ++it){ + if(it->startsWith("UNKNOWN/")) { + String frameID = it->substr(String("UNKNOWN/").size()); + if(frameID.size() != 4) + continue; // invalid specification + ByteVector id = frameID.data(String::Latin1); + // delete all unknown frames of given type + FrameList l = frameList(id); + for(FrameList::ConstIterator fit = l.begin(); fit != l.end(); fit++) + if (dynamic_cast(*fit) != 0) + removeFrame(*fit); + } + else if(it->size() == 4){ + ByteVector id = it->data(String::Latin1); + removeFrames(id); + } + else { + ByteVector id = it->substr(0,4).data(String::Latin1); + if(it->size() <= 5) + continue; // invalid specification + String description = it->substr(5); + Frame *frame = 0; + if(id == "TXXX") + frame = UserTextIdentificationFrame::find(this, description); + else if(id == "WXXX") + frame = UserUrlLinkFrame::find(this, description); + else if(id == "COMM") + frame = CommentsFrame::findByDescription(this, description); + else if(id == "USLT") + frame = UnsynchronizedLyricsFrame::findByDescription(this, description); + else if(id == "UFID") + frame = UniqueFileIdentifierFrame::findByOwner(this, description); + if(frame) + removeFrame(frame); + } + } +} + +PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps) +{ + FrameList framesToDelete; + // we split up the PropertyMap into the "normal" keys and the "complicated" ones, + // which are those according to TIPL or TMCL frames. + PropertyMap properties; + PropertyMap tiplProperties; + PropertyMap tmclProperties; + Frame::splitProperties(origProps, properties, tiplProperties, tmclProperties); + for(FrameListMap::ConstIterator it = frameListMap().begin(); it != frameListMap().end(); ++it){ + for(FrameList::ConstIterator lit = it->second.begin(); lit != it->second.end(); ++lit){ + PropertyMap frameProperties = (*lit)->asProperties(); + if(it->first == "TIPL") { + if (tiplProperties != frameProperties) + framesToDelete.append(*lit); + else + tiplProperties.erase(frameProperties); + } else if(it->first == "TMCL") { + if (tmclProperties != frameProperties) + framesToDelete.append(*lit); + else + tmclProperties.erase(frameProperties); + } else if(!properties.contains(frameProperties)) + framesToDelete.append(*lit); + else + properties.erase(frameProperties); + } + } + for(FrameList::ConstIterator it = framesToDelete.begin(); it != framesToDelete.end(); ++it) + removeFrame(*it); + + // now create remaining frames: + // start with the involved people list (TIPL) + if(!tiplProperties.isEmpty()) + addFrame(TextIdentificationFrame::createTIPLFrame(tiplProperties)); + // proceed with the musician credit list (TMCL) + if(!tmclProperties.isEmpty()) + addFrame(TextIdentificationFrame::createTMCLFrame(tmclProperties)); + // now create the "one key per frame" frames + for(PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) + addFrame(Frame::createTextualFrame(it->first, it->second)); + return PropertyMap(); // ID3 implements the complete PropertyMap interface, so an empty map is returned +} + +ByteVector ID3v2::Tag::render() const +{ + return render(ID3v2::v4); +} + +void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const +{ +#ifdef NO_ITUNES_HACKS + static const char *unsupportedFrames[] = { + "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", + "TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", 0 + }; +#else + // iTunes writes and reads TSOA, TSOT, TSOP to ID3v2.3. + static const char *unsupportedFrames[] = { + "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", + "TMOO", "TPRO", "TSST", 0 + }; +#endif + ID3v2::TextIdentificationFrame *frameTDOR = 0; + ID3v2::TextIdentificationFrame *frameTDRC = 0; + ID3v2::TextIdentificationFrame *frameTIPL = 0; + ID3v2::TextIdentificationFrame *frameTMCL = 0; + ID3v2::TextIdentificationFrame *frameTCON = 0; + + for(FrameList::ConstIterator it = d->frameList.begin(); it != d->frameList.end(); it++) { + ID3v2::Frame *frame = *it; + ByteVector frameID = frame->header()->frameID(); + + if(contains(unsupportedFrames, frameID)) + { + debug("A frame that is not supported in ID3v2.3 \'" + String(frameID) + + "\' has been discarded"); + continue; + } + + if(frameID == "TDOR") + frameTDOR = dynamic_cast(frame); + else if(frameID == "TDRC") + frameTDRC = dynamic_cast(frame); + else if(frameID == "TIPL") + frameTIPL = dynamic_cast(frame); + else if(frameID == "TMCL") + frameTMCL = dynamic_cast(frame); + else if(frame && frameID == "TCON") + frameTCON = dynamic_cast(frame); + else + frames->append(frame); + } + + if(frameTDOR) { + String content = frameTDOR->toString(); + + if(content.size() >= 4) { + ID3v2::TextIdentificationFrame *frameTORY = + new ID3v2::TextIdentificationFrame("TORY", String::Latin1); + frameTORY->setText(content.substr(0, 4)); + frames->append(frameTORY); + newFrames->append(frameTORY); + } + } + + if(frameTDRC) { + String content = frameTDRC->toString(); + if(content.size() >= 4) { + ID3v2::TextIdentificationFrame *frameTYER = + new ID3v2::TextIdentificationFrame("TYER", String::Latin1); + frameTYER->setText(content.substr(0, 4)); + frames->append(frameTYER); + newFrames->append(frameTYER); + if(content.size() >= 10 && content[4] == '-' && content[7] == '-') { + ID3v2::TextIdentificationFrame *frameTDAT = + new ID3v2::TextIdentificationFrame("TDAT", String::Latin1); + frameTDAT->setText(content.substr(8, 2) + content.substr(5, 2)); + frames->append(frameTDAT); + newFrames->append(frameTDAT); + if(content.size() >= 16 && content[10] == 'T' && content[13] == ':') { + ID3v2::TextIdentificationFrame *frameTIME = + new ID3v2::TextIdentificationFrame("TIME", String::Latin1); + frameTIME->setText(content.substr(11, 2) + content.substr(14, 2)); + frames->append(frameTIME); + newFrames->append(frameTIME); + } + } + } + } + + if(frameTIPL || frameTMCL) { + ID3v2::TextIdentificationFrame *frameIPLS = + new ID3v2::TextIdentificationFrame("IPLS", String::Latin1); + + StringList people; + + if(frameTMCL) { + StringList v24People = frameTMCL->fieldList(); + for(unsigned int i = 0; i + 1 < v24People.size(); i += 2) { + people.append(v24People[i]); + people.append(v24People[i+1]); + } + } + if(frameTIPL) { + StringList v24People = frameTIPL->fieldList(); + for(unsigned int i = 0; i + 1 < v24People.size(); i += 2) { + people.append(v24People[i]); + people.append(v24People[i+1]); + } + } + + frameIPLS->setText(people); + frames->append(frameIPLS); + newFrames->append(frameIPLS); + } + + if(frameTCON) { + StringList genres = frameTCON->fieldList(); + String combined; + String genreText; + const bool hasMultipleGenres = genres.size() > 1; + + // If there are multiple genres, add them as multiple references to ID3v1 + // genres if such a reference exists. The first genre for which no ID3v1 + // genre number exists can be finally added as a refinement. + for(StringList::ConstIterator it = genres.begin(); it != genres.end(); ++it) { + bool ok = false; + int number = it->toInt(&ok); + if((ok && number >= 0 && number <= 255) || *it == "RX" || *it == "CR") + combined += '(' + *it + ')'; + else if(hasMultipleGenres && (number = ID3v1::genreIndex(*it)) != 255) + combined += '(' + String::number(number) + ')'; + else if(genreText.isEmpty()) + genreText = *it; + } + if(!genreText.isEmpty()) + combined += genreText; + + frameTCON = new ID3v2::TextIdentificationFrame("TCON", String::Latin1); + frameTCON->setText(combined); + frames->append(frameTCON); + newFrames->append(frameTCON); + } +} + +ByteVector ID3v2::Tag::render(int version) const +{ + return render(version == 3 ? v3 : v4); +} + +ByteVector ID3v2::Tag::render(Version version) const +{ + // We need to render the "tag data" first so that we have to correct size to + // render in the tag's header. The "tag data" -- everything that is included + // in ID3v2::Header::tagSize() -- includes the extended header, frames and + // padding, but does not include the tag's header or footer. + + // TODO: Render the extended header. + + // Downgrade the frames that ID3v2.3 doesn't support. + + FrameList newFrames; + newFrames.setAutoDelete(true); + + FrameList frameList; + if(version == v4) { + frameList = d->frameList; + } + else { + downgradeFrames(&frameList, &newFrames); + } + + // Reserve a 10-byte blank space for an ID3v2 tag header. + + ByteVector tagData(Header::size(), '\0'); + + // Loop through the frames rendering them and adding them to the tagData. + + for(FrameList::ConstIterator it = frameList.begin(); it != frameList.end(); it++) { + (*it)->header()->setVersion(version == v3 ? 3 : 4); + if((*it)->header()->frameID().size() != 4) { + debug("An ID3v2 frame of unsupported or unknown type \'" + + String((*it)->header()->frameID()) + "\' has been discarded"); + continue; + } + if(!(*it)->header()->tagAlterPreservation()) { + const ByteVector frameData = (*it)->render(); + if(frameData.size() == Frame::headerSize((*it)->header()->version())) { + debug("An empty ID3v2 frame \'" + + String((*it)->header()->frameID()) + "\' has been discarded"); + continue; + } + tagData.append(frameData); + } + } + + // Compute the amount of padding, and append that to tagData. + + long originalSize = d->header.tagSize(); + long paddingSize = originalSize - (tagData.size() - Header::size()); + + if(paddingSize <= 0) { + paddingSize = MinPaddingSize; + } + else { + // Padding won't increase beyond 1% of the file size or 1MB. + + long threshold = d->file ? d->file->length() / 100 : 0; + threshold = std::max(threshold, MinPaddingSize); + threshold = std::min(threshold, MaxPaddingSize); + + if(paddingSize > threshold) + paddingSize = MinPaddingSize; + } + + tagData.resize(static_cast(tagData.size() + paddingSize), '\0'); + + // Set the version and data size. + d->header.setMajorVersion(version); + d->header.setTagSize(tagData.size() - Header::size()); + + // TODO: This should eventually include d->footer->render(). + const ByteVector headerData = d->header.render(); + std::copy(headerData.begin(), headerData.end(), tagData.begin()); + + return tagData; +} + +Latin1StringHandler const *ID3v2::Tag::latin1StringHandler() +{ + return stringHandler; +} + +void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler) +{ + if(handler) + stringHandler = handler; + else + stringHandler = &defaultStringHandler; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ID3v2::Tag::read() +{ + if(!d->file) + return; + + if(!d->file->isOpen()) + return; + + d->file->seek(d->tagOffset); + d->header.setData(d->file->readBlock(Header::size())); + + // If the tag size is 0, then this is an invalid tag (tags must contain at + // least one frame) + + if(d->header.tagSize() != 0) + parse(d->file->readBlock(d->header.tagSize())); + + // Look for duplicate ID3v2 tags and treat them as an extra blank of this one. + // It leads to overwriting them with zero when saving the tag. + + // This is a workaround for some faulty files that have duplicate ID3v2 tags. + // Unfortunately, TagLib itself may write such duplicate tags until v1.10. + + unsigned int extraSize = 0; + + while(true) { + + d->file->seek(d->tagOffset + d->header.completeTagSize() + extraSize); + + const ByteVector data = d->file->readBlock(Header::size()); + if(data.size() < Header::size() || !data.startsWith(Header::fileIdentifier())) + break; + + extraSize += Header(data).completeTagSize(); + } + + if(extraSize != 0) { + debug("ID3v2::Tag::read() - Duplicate ID3v2 tags found."); + d->header.setTagSize(d->header.tagSize() + extraSize); + } +} + +void ID3v2::Tag::parse(const ByteVector &origData) +{ + ByteVector data = origData; + + if(d->header.unsynchronisation() && d->header.majorVersion() <= 3) + data = SynchData::decode(data); + + unsigned int frameDataPosition = 0; + unsigned int frameDataLength = data.size(); + + // check for extended header + + if(d->header.extendedHeader()) { + if(!d->extendedHeader) + d->extendedHeader = new ExtendedHeader(); + d->extendedHeader->setData(data); + if(d->extendedHeader->size() <= data.size()) { + frameDataPosition += d->extendedHeader->size(); + frameDataLength -= d->extendedHeader->size(); + } + } + + // check for footer -- we don't actually need to parse it, as it *must* + // contain the same data as the header, but we do need to account for its + // size. + + if(d->header.footerPresent() && Footer::size() <= frameDataLength) + frameDataLength -= Footer::size(); + + // parse frames + + // Make sure that there is at least enough room in the remaining frame data for + // a frame header. + + while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) { + + // If the next data is position is 0, assume that we've hit the padding + // portion of the frame data. + + if(data.at(frameDataPosition) == 0) { + if(d->header.footerPresent()) { + debug("Padding *and* a footer found. This is not allowed by the spec."); + } + + break; + } + + Frame *frame = d->factory->createFrame(data.mid(frameDataPosition), + &d->header); + + if(!frame) + return; + + // Checks to make sure that frame parsed correctly. + + if(frame->size() <= 0) { + delete frame; + return; + } + + frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion()); + addFrame(frame); + } + + d->factory->rebuildAggregateFrames(this); +} + +void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) +{ + if(value.isEmpty()) { + removeFrames(id); + return; + } + + if(!d->frameListMap[id].isEmpty()) + d->frameListMap[id].front()->setText(value); + else { + const String::Type encoding = d->factory->defaultTextEncoding(); + TextIdentificationFrame *f = new TextIdentificationFrame(id, encoding); + addFrame(f); + f->setText(value); + } +} diff --git a/external/taglib/source/mpeg/id3v2/id3v2tag.h b/external/taglib/source/mpeg/id3v2/id3v2tag.h new file mode 100644 index 0000000..74d1df1 --- /dev/null +++ b/external/taglib/source/mpeg/id3v2/id3v2tag.h @@ -0,0 +1,411 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_ID3V2TAG_H +#define TAGLIB_ID3V2TAG_H + +#include "tag.h" +#include "tbytevector.h" +#include "tstring.h" +#include "tlist.h" +#include "tmap.h" +#include "taglib_export.h" + +#include "id3v2.h" +#include "id3v2framefactory.h" + +namespace TagLib { + + class File; + + namespace ID3v2 { + + class Header; + class ExtendedHeader; + class Footer; + + typedef List FrameList; + typedef Map FrameListMap; + + //! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags. + + /*! + * ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only + * supports genuine ISO-8859-1 by default. However, in practice, non + * ISO-8859-1 encodings are often used instead of ISO-8859-1, such as + * Windows-1252 for western languages, Shift_JIS for Japanese and so on. + * + * Here is an option to read such tags by subclassing this class, + * reimplementing parse() and setting your reimplementation as the default + * with ID3v2::Tag::setStringHandler(). + * + * \note Writing non-ISO-8859-1 tags is not implemented intentionally. + * Use UTF-16 or UTF-8 instead. + * + * \see ID3v2::Tag::setStringHandler() + */ + class TAGLIB_EXPORT Latin1StringHandler + { + public: + Latin1StringHandler(); + virtual ~Latin1StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an ISO-8859-1 (Latin1) character array. + */ + virtual String parse(const ByteVector &data) const; + }; + + //! The main class in the ID3v2 implementation + + /*! + * This is the main class in the ID3v2 implementation. It serves two + * functions. This first, as is obvious from the public API, is to provide a + * container for the other ID3v2 related classes. In addition, through the + * read() and parse() protected methods, it provides the most basic level of + * parsing. In these methods the ID3v2 tag is extracted from the file and + * split into data components. + * + * ID3v2 tags have several parts, TagLib attempts to provide an interface + * for them all. header(), footer() and extendedHeader() correspond to those + * data structures in the ID3v2 standard and the APIs for the classes that + * they return attempt to reflect this. + * + * Also ID3v2 tags are built up from a list of frames, which are in turn + * have a header and a list of fields. TagLib provides two ways of accessing + * the list of frames that are in a given ID3v2 tag. The first is simply + * via the frameList() method. This is just a list of pointers to the frames. + * The second is a map from the frame type -- i.e. "COMM" for comments -- and + * a list of frames of that type. (In some cases ID3v2 allows for multiple + * frames of the same type, hence this being a map to a list rather than just + * a map to an individual frame.) + * + * More information on the structure of frames can be found in the ID3v2::Frame + * class. + * + * read() and parse() pass binary data to the other ID3v2 class structures, + * they do not handle parsing of flags or fields, for instance. Those are + * handled by similar functions within those classes. + * + * \note All pointers to data structures within the tag will become invalid + * when the tag is destroyed. + * + * \warning Dealing with the nasty details of ID3v2 is not for the faint of + * heart and should not be done without much meditation on the spec. It's + * rather long, but if you're planning on messing with this class and others + * that deal with the details of ID3v2 (rather than the nice, safe, abstract + * TagLib::Tag and friends), it's worth your time to familiarize yourself + * with said spec (which is distributed with the TagLib sources). TagLib + * tries to do most of the work, but with a little luck, you can still + * convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a + * working knowledge of ID3v2 structure. You're been warned. + */ + + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty ID3v2 tag. + * + * \note You must create at least one frame for this tag to be valid. + */ + Tag(); + + /*! + * Constructs an ID3v2 tag read from \a file starting at \a tagOffset. + * \a factory specifies which FrameFactory will be used for the + * construction of new frames. + * + * \note You should be able to ignore the \a factory parameter in almost + * all situations. You would want to specify your own FrameFactory + * subclass in the case that you are extending TagLib to support additional + * frame types, which would be incorporated into your factory. + * + * \see FrameFactory + */ + Tag(File *file, long tagOffset, + const FrameFactory *factory = FrameFactory::instance()); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns a pointer to the tag's header. + */ + Header *header() const; + + /*! + * Returns a pointer to the tag's extended header or null if there is no + * extended header. + */ + ExtendedHeader *extendedHeader() const; + + /*! + * Returns a pointer to the tag's footer or null if there is no footer. + * + * \deprecated I don't see any reason to keep this around since there's + * nothing useful to be retrieved from the footer, but well, again, I'm + * prone to change my mind, so this gets to stay around until near a + * release. + */ + TAGLIB_DEPRECATED Footer *footer() const; + + /*! + * Returns a reference to the frame list map. This is an FrameListMap of + * all of the frames in the tag. + * + * This is the most convenient structure for accessing the tag's frames. + * Many frame types allow multiple instances of the same frame type so this + * is a map of lists. In most cases however there will only be a single + * frame of a certain type. + * + * Let's say for instance that you wanted to access the frame for total + * beats per minute -- the TBPM frame. + * + * \code + * TagLib::MPEG::File f("foo.mp3"); + * + * // Check to make sure that it has an ID3v2 tag + * + * if(f.ID3v2Tag()) { + * + * // Get the list of frames for a specific frame type + * + * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"]; + * + * if(!l.isEmpty()) + * std::cout << l.front()->toString() << std::endl; + * } + * + * \endcode + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + * + * \see frameList() + */ + const FrameListMap &frameListMap() const; + + /*! + * Returns a reference to the frame list. This is an FrameList of all of + * the frames in the tag in the order that they were parsed. + * + * This can be useful if for example you want iterate over the tag's frames + * in the order that they occur in the tag. + * + * \warning You should not modify this data structure directly, instead + * use addFrame() and removeFrame(). + */ + const FrameList &frameList() const; + + /*! + * Returns the frame list for frames with the id \a frameID or an empty + * list if there are no frames of that type. This is just a convenience + * and is equivalent to: + * + * \code + * frameListMap()[frameID]; + * \endcode + * + * \see frameListMap() + */ + const FrameList &frameList(const ByteVector &frameID) const; + + /*! + * Add a frame to the tag. At this point the tag takes ownership of + * the frame and will handle freeing its memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void addFrame(Frame *frame); + + /*! + * Remove a frame from the tag. If \a del is true the frame's memory + * will be freed; if it is false, it must be deleted by the user. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrame(Frame *frame, bool del = true); + + /*! + * Remove all frames of type \a id from the tag and free their memory. + * + * \note Using this method will invalidate any pointers on the list + * returned by frameList() + */ + void removeFrames(const ByteVector &id); + + /*! + * Implements the unified property interface -- export function. + * This function does some work to translate the hard-specified ID3v2 + * frame types into a free-form string-to-stringlist PropertyMap: + * - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned + * key is used + * - if the frame ID is "TXXX" (user text frame), the description() is + * used as key + * - if the frame ID is "WXXX" (user url frame), + * - if the description is empty or "URL", the key "URL" is used + * - otherwise, the key "URL:" is used; + * - if the frame ID is "COMM" (comments frame), + * - if the description is empty or "COMMENT", the key "COMMENT" + * is used + * - otherwise, the key "COMMENT:" is used; + * - if the frame ID is "USLT" (unsynchronized lyrics), + * - if the description is empty or "LYRICS", the key "LYRICS" is used + * - otherwise, the key "LYRICS:" is used; + * - if the frame ID is "TIPL" (involved peoples list), and if all the + * roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(), + * then "=" will be contained in the returned object for each + * - if the frame ID is "TMCL" (musician credit list), then + * "PERFORMER:=" will be contained in the returned + * PropertyMap for each defined musician + * In any other case, the unsupportedData() of the returned object will contain + * the frame's ID and, in case of a frame ID which is allowed to appear more than + * once, the description, separated by a "/". + * + */ + PropertyMap properties() const; + + /*! + * Removes unsupported frames given by \a properties. The elements of + * \a properties must be taken from properties().unsupportedData(); they + * are of one of the following forms: + * - a four-character frame ID, if the ID3 specification allows only one + * frame with that ID (thus, the frame is uniquely determined) + * - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX", + * "COMM", or "USLT", + * - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib. + * In that case, *all* unknown frames with the given ID will be removed. + */ + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * See the comments in properties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Render the tag back to binary data, suitable to be written to disk. + */ + ByteVector render() const; + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED ByteVector render(int version) const; + + /*! + * Render the tag back to binary data, suitable to be written to disk. + * + * The \a version parameter specifies whether ID3v2.4 (default) or ID3v2.3 + * should be used. + */ + ByteVector render(Version version) const; + + /*! + * Gets the current string handler that decides how the "Latin-1" data + * will be converted to and from binary data. + * + * \see Latin1StringHandler + */ + static Latin1StringHandler const *latin1StringHandler(); + + /*! + * Sets the string handler that decides how the "Latin-1" data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default ISO-8859-1 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see Latin1StringHandler + */ + static void setLatin1StringHandler(const Latin1StringHandler *handler); + + protected: + /*! + * Reads data from the file specified in the constructor. It does basic + * parsing of the data in the largest chunks. It partitions the tag into + * the Header, the body of the tag (which contains the ExtendedHeader and + * frames) and Footer. + */ + void read(); + + /*! + * This is called by read to parse the body of the tag. It determines if an + * extended header exists and adds frames to the FrameListMap. + */ + void parse(const ByteVector &data); + + /*! + * Sets the value of the text frame with the Frame ID \a id to \a value. + * If the frame does not exist, it is created. + */ + void setTextFrame(const ByteVector &id, const String &value); + + /*! + * Downgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3. + */ + void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const; + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/mpeg/mpegfile.cpp b/external/taglib/source/mpeg/mpegfile.cpp new file mode 100644 index 0000000..5f14e49 --- /dev/null +++ b/external/taglib/source/mpeg/mpegfile.cpp @@ -0,0 +1,585 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mpegfile.h" +#include "mpegheader.h" +#include "mpegutils.h" +#include "tpropertymap.h" + +using namespace TagLib; + +namespace +{ + enum { ID3v2Index = 0, APEIndex = 1, ID3v1Index = 2 }; +} + +class MPEG::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Location(-1), + ID3v2OriginalSize(0), + APELocation(-1), + APEOriginalSize(0), + ID3v1Location(-1), + properties(0) {} + + ~FilePrivate() + { + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + + long ID3v2Location; + long ID3v2OriginalSize; + + long APELocation; + long APEOriginalSize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +namespace +{ + // Dummy file class to make a stream work with MPEG::Header. + + class AdapterFile : public TagLib::File + { + public: + AdapterFile(IOStream *stream) : File(stream) {} + + Tag *tag() const { return 0; } + AudioProperties *audioProperties() const { return 0; } + bool save() { return false; } + }; +} // namespace + +bool MPEG::File::isSupported(IOStream *stream) +{ + if(!stream || !stream->isOpen()) + return false; + + // An MPEG file has MPEG frame headers. An ID3v2 tag may precede. + + // MPEG frame headers are really confusing with irrelevant binary data. + // So we check if a frame header is really valid. + + long headerOffset; + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true, &headerOffset); + + if(buffer.isEmpty()) + return false; + + const long originalPosition = stream->tell(); + AdapterFile file(stream); + + for(unsigned int i = 0; i < buffer.size() - 1; ++i) { + if(isFrameSync(buffer, i)) { + const Header header(&file, headerOffset + i, true); + if(header.isValid()) { + stream->seek(originalPosition); + return true; + } + } + } + + stream->seek(originalPosition); + return false; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +MPEG::File::~File() +{ + delete d; +} + +TagLib::Tag *MPEG::File::tag() const +{ + return &d->tag; +} + +PropertyMap MPEG::File::properties() const +{ + return d->tag.properties(); +} + +void MPEG::File::removeUnsupportedProperties(const StringList &properties) +{ + d->tag.removeUnsupportedProperties(properties); +} + +PropertyMap MPEG::File::setProperties(const PropertyMap &properties) +{ + // update ID3v1 tag if it exists, but ignore the return value + + if(ID3v1Tag()) + ID3v1Tag()->setProperties(properties); + + return ID3v2Tag(true)->setProperties(properties); +} + +MPEG::Properties *MPEG::File::audioProperties() const +{ + return d->properties; +} + +bool MPEG::File::save() +{ + return save(AllTags); +} + +bool MPEG::File::save(int tags) +{ + return save(tags, StripOthers); +} + +bool MPEG::File::save(int tags, bool stripOthers) +{ + return save(tags, stripOthers ? StripOthers : StripNone, ID3v2::v4); +} + +bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version) +{ + return save(tags, + stripOthers ? StripOthers : StripNone, + id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4); +} + +bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags) +{ + return save(tags, + stripOthers ? StripOthers : StripNone, + id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4, + duplicateTags ? Duplicate : DoNotDuplicate); +} + +bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, DuplicateTags duplicate) +{ + if(readOnly()) { + debug("MPEG::File::save() -- File is read only."); + return false; + } + + // Create the tags if we've been asked to. + + if(duplicate == Duplicate) { + + // Copy the values from the tag that does exist into the new tag, + // except if the existing tag is to be stripped. + + if((tags & ID3v2) && ID3v1Tag() && !(strip == StripOthers && !(tags & ID3v1))) + Tag::duplicate(ID3v1Tag(), ID3v2Tag(true), false); + + if((tags & ID3v1) && d->tag[ID3v2Index] && !(strip == StripOthers && !(tags & ID3v2))) + Tag::duplicate(ID3v2Tag(), ID3v1Tag(true), false); + } + + // Remove all the tags not going to be saved. + + if(strip == StripOthers) + File::strip(~tags, false); + + if(ID3v2 & tags) { + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + + // ID3v2 tag is not empty. Update the old one or create a new one. + + if(d->ID3v2Location < 0) + d->ID3v2Location = 0; + + const ByteVector data = ID3v2Tag()->render(version); + insert(data, d->ID3v2Location, d->ID3v2OriginalSize); + + if(d->APELocation >= 0) + d->APELocation += (static_cast(data.size()) - d->ID3v2OriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->ID3v2OriginalSize); + + d->ID3v2OriginalSize = data.size(); + } + else { + + // ID3v2 tag is empty. Remove the old one. + + File::strip(ID3v2, false); + } + } + + if(ID3v1 & tags) { + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + File::strip(ID3v1, false); + } + } + + if(APE & tags) { + + if(APETag() && !APETag()->isEmpty()) { + + // APE tag is not empty. Update the old one or create a new one. + + if(d->APELocation < 0) { + if(d->ID3v1Location >= 0) + d->APELocation = d->ID3v1Location; + else + d->APELocation = length(); + } + + const ByteVector data = APETag()->render(); + insert(data, d->APELocation, d->APEOriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->APEOriginalSize); + + d->APEOriginalSize = data.size(); + } + else { + + // APE tag is empty. Remove the old one. + + File::strip(APE, false); + } + } + + return true; +} + +ID3v2::Tag *MPEG::File::ID3v2Tag(bool create) +{ + return d->tag.access(ID3v2Index, create); +} + +ID3v1::Tag *MPEG::File::ID3v1Tag(bool create) +{ + return d->tag.access(ID3v1Index, create); +} + +APE::Tag *MPEG::File::APETag(bool create) +{ + return d->tag.access(APEIndex, create); +} + +bool MPEG::File::strip(int tags) +{ + return strip(tags, true); +} + +bool MPEG::File::strip(int tags, bool freeMemory) +{ + if(readOnly()) { + debug("MPEG::File::strip() - Cannot strip tags from a read only file."); + return false; + } + + if((tags & ID3v2) && d->ID3v2Location >= 0) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + + if(d->APELocation >= 0) + d->APELocation -= d->ID3v2OriginalSize; + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->ID3v2OriginalSize; + + d->ID3v2Location = -1; + d->ID3v2OriginalSize = 0; + + if(freeMemory) + d->tag.set(ID3v2Index, 0); + } + + if((tags & ID3v1) && d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + + d->ID3v1Location = -1; + + if(freeMemory) + d->tag.set(ID3v1Index, 0); + } + + if((tags & APE) && d->APELocation >= 0) { + removeBlock(d->APELocation, d->APEOriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->APEOriginalSize; + + d->APELocation = -1; + d->APEOriginalSize = 0; + + if(freeMemory) + d->tag.set(APEIndex, 0); + } + + return true; +} + +void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +long MPEG::File::nextFrameOffset(long position) +{ + ByteVector frameSyncBytes(2, '\0'); + + while(true) { + seek(position); + const ByteVector buffer = readBlock(bufferSize()); + if(buffer.isEmpty()) + return -1; + + for(unsigned int i = 0; i < buffer.size(); ++i) { + frameSyncBytes[0] = frameSyncBytes[1]; + frameSyncBytes[1] = buffer[i]; + if(isFrameSync(frameSyncBytes)) { + const Header header(this, position + i - 1, true); + if(header.isValid()) + return position + i - 1; + } + } + + position += bufferSize(); + } +} + +long MPEG::File::previousFrameOffset(long position) +{ + ByteVector frameSyncBytes(2, '\0'); + + while(position > 0) { + const long bufferLength = std::min(position, bufferSize()); + position -= bufferLength; + + seek(position); + const ByteVector buffer = readBlock(bufferLength); + + for(int i = buffer.size() - 1; i >= 0; --i) { + frameSyncBytes[1] = frameSyncBytes[0]; + frameSyncBytes[0] = buffer[i]; + if(isFrameSync(frameSyncBytes)) { + const Header header(this, position + i, true); + if(header.isValid()) + return position + i + header.frameLength(); + } + } + } + + return -1; +} + +long MPEG::File::firstFrameOffset() +{ + long position = 0; + + if(hasID3v2Tag()) + position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize(); + + return nextFrameOffset(position); +} + +long MPEG::File::lastFrameOffset() +{ + long position; + + if(hasAPETag()) + position = d->APELocation - 1; + else if(hasID3v1Tag()) + position = d->ID3v1Location - 1; + else + position = length(); + + return previousFrameOffset(position); +} + +bool MPEG::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +bool MPEG::File::hasID3v2Tag() const +{ + return (d->ID3v2Location >= 0); +} + +bool MPEG::File::hasAPETag() const +{ + return (d->APELocation >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::File::read(bool readProperties) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + } + + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + // Look for an APE tag + + d->APELocation = Utils::findAPE(this, d->ID3v1Location); + + if(d->APELocation >= 0) { + d->tag.set(APEIndex, new APE::Tag(this, d->APELocation)); + d->APEOriginalSize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APE::Footer::size() - d->APEOriginalSize; + } + + if(readProperties) + d->properties = new Properties(this); + + // Make sure that we have our default tag types available. + + ID3v2Tag(true); + ID3v1Tag(true); +} + +long MPEG::File::findID3v2() +{ + if(!isValid()) + return -1; + + // An ID3v2 tag or MPEG frame is most likely be at the beginning of the file. + + const ByteVector headerID = ID3v2::Header::fileIdentifier(); + + seek(0); + if(readBlock(headerID.size()) == headerID) + return 0; + + const Header firstHeader(this, 0, true); + if(firstHeader.isValid()) + return -1; + + // Look for an ID3v2 tag until reaching the first valid MPEG frame. + + ByteVector frameSyncBytes(2, '\0'); + ByteVector tagHeaderBytes(3, '\0'); + long position = 0; + + while(true) { + seek(position); + const ByteVector buffer = readBlock(bufferSize()); + if(buffer.isEmpty()) + return -1; + + for(unsigned int i = 0; i < buffer.size(); ++i) { + frameSyncBytes[0] = frameSyncBytes[1]; + frameSyncBytes[1] = buffer[i]; + if(isFrameSync(frameSyncBytes)) { + const Header header(this, position + i - 1, true); + if(header.isValid()) + return -1; + } + + tagHeaderBytes[0] = tagHeaderBytes[1]; + tagHeaderBytes[1] = tagHeaderBytes[2]; + tagHeaderBytes[2] = buffer[i]; + if(tagHeaderBytes == headerID) + return position + i - 2; + } + + position += bufferSize(); + } +} diff --git a/external/taglib/source/mpeg/mpegfile.h b/external/taglib/source/mpeg/mpegfile.h new file mode 100644 index 0000000..3fcb727 --- /dev/null +++ b/external/taglib/source/mpeg/mpegfile.h @@ -0,0 +1,387 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGFILE_H +#define TAGLIB_MPEGFILE_H + +#include "taglib_export.h" +#include "tfile.h" +#include "tag.h" + +#include "mpegproperties.h" + +#include "id3v2.h" + +namespace TagLib { + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of TagLib::File with MPEG (MP3) specific methods + + namespace MPEG { + + //! An MPEG file class with some useful methods specific to MPEG + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to MPEG files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches APE tags. + APE = 0x0004, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs an MPEG file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPEG file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + // BIC: merge with the above constructor + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an MPEG file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to a tag that is the union of the ID3v2 and ID3v1 + * tags. The ID3v2 tag is given priority in reading the information -- if + * requested information exists in both the ID3v2 tag and the ID3v1 tag, + * the information from the ID3v2 tag will be returned. + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use the tag-type specific calls. + * + * \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag, + * but a union of the two this pointer may not be cast to the specific + * tag types. + * + * \see ID3v1Tag() + * \see ID3v2Tag() + * \see APETag() + */ + virtual Tag *tag() const; + + /*! + * Implements the reading part of the unified property interface. + * If the file contains more than one tag, only the + * first one (in the order ID3v2, APE, ID3v1) will be converted to the + * PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the writing part of the unified tag dictionary interface. + * In order to avoid problems with deprecated tag formats, this method + * always creates an ID3v2 tag if necessary. + * If an ID3v1 tag exists, it will be updated as well, within the + * limitations of that format. + * The returned PropertyMap refers to the ID3v2 tag only. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the MPEG::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this + * will duplicate its content into the other tag. This returns true + * if saving was successful. + * + * If neither exists or if both tags are empty, this will strip the tags + * from the file. + * + * This is the same as calling save(AllTags); + * + * If you would like more granular control over the content of the tags, + * with the concession of generality, use parameterized save call below. + * + * \see save(int tags) + */ + virtual bool save(); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. The save() method above + * uses AllTags. This returns true if saving was successful. + * + * This strips all tags not included in the mask, but does not modify them + * in memory, so later calls to save() which make use of these tags will + * remain valid. This also strips empty tags. + */ + bool save(int tags); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version); + + /*! + * \deprecated + */ + // BIC: combine with the above method + TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags); + + /*! + * Save the file. This will attempt to save all of the tag types that are + * specified by OR-ing together TagTypes values. + * + * \a strip can be set to strip all tags except those in \a tags. Those + * tags will not be modified in memory, and thus remain valid. + * + * \a version specifies the ID3v2 version to be used for writing tags. By + * default, the latest standard, ID3v2.4 is used. + * + * If \a duplicate is set to DuplicateTags and at least one tag -- ID3v1 + * or ID3v2 -- exists this will duplicate its content into the other tag. + */ + bool save(int tags, StripTags strip, + ID3v2::Version version = ID3v2::v4, + DuplicateTags duplicate = Duplicate); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * This is equivalent to strip(tags, true) + * + * \note This will also invalidate pointers to the ID3 and APE tags + * as their memory will be freed. + * + * \note This will update the file immediately. + */ + bool strip(int tags = AllTags); + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * If \a freeMemory is true the ID3 and APE tags will be deleted and + * pointers to them will be invalidated. + * + * \note This will update the file immediately. + */ + // BIC: merge with the method above + bool strip(int tags, bool freeMemory); + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Returns the position in the file of the first MPEG frame. + */ + long firstFrameOffset(); + + /*! + * Returns the position in the file of the next MPEG frame, + * using the current position as start + */ + long nextFrameOffset(long position); + + /*! + * Returns the position in the file of the previous MPEG frame, + * using the current position as start + */ + long previousFrameOffset(long position); + + /*! + * Returns the position in the file of the last MPEG frame. + */ + long lastFrameOffset(); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Returns whether or not the given \a stream can be opened as an MPEG + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/mpegheader.cpp b/external/taglib/source/mpeg/mpegheader.cpp new file mode 100644 index 0000000..5a5015d --- /dev/null +++ b/external/taglib/source/mpeg/mpegheader.cpp @@ -0,0 +1,322 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "mpegheader.h" +#include "mpegutils.h" + +using namespace TagLib; + +class MPEG::Header::HeaderPrivate : public RefCounter +{ +public: + HeaderPrivate() : + isValid(false), + version(Version1), + layer(0), + protectionEnabled(false), + bitrate(0), + sampleRate(0), + isPadded(false), + channelMode(Stereo), + isCopyrighted(false), + isOriginal(false), + frameLength(0), + samplesPerFrame(0) {} + + bool isValid; + Version version; + int layer; + bool protectionEnabled; + int bitrate; + int sampleRate; + bool isPadded; + ChannelMode channelMode; + bool isCopyrighted; + bool isOriginal; + int frameLength; + int samplesPerFrame; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::Header::Header(const ByteVector &data) : + d(new HeaderPrivate()) +{ + debug("MPEG::Header::Header() - This constructor is no longer used."); +} + +MPEG::Header::Header(File *file, long offset, bool checkLength) : + d(new HeaderPrivate()) +{ + parse(file, offset, checkLength); +} + +MPEG::Header::Header(const Header &h) : + d(h.d) +{ + d->ref(); +} + +MPEG::Header::~Header() +{ + if(d->deref()) + delete d; +} + +bool MPEG::Header::isValid() const +{ + return d->isValid; +} + +MPEG::Header::Version MPEG::Header::version() const +{ + return d->version; +} + +int MPEG::Header::layer() const +{ + return d->layer; +} + +bool MPEG::Header::protectionEnabled() const +{ + return d->protectionEnabled; +} + +int MPEG::Header::bitrate() const +{ + return d->bitrate; +} + +int MPEG::Header::sampleRate() const +{ + return d->sampleRate; +} + +bool MPEG::Header::isPadded() const +{ + return d->isPadded; +} + +MPEG::Header::ChannelMode MPEG::Header::channelMode() const +{ + return d->channelMode; +} + +bool MPEG::Header::isCopyrighted() const +{ + return d->isCopyrighted; +} + +bool MPEG::Header::isOriginal() const +{ + return d->isOriginal; +} + +int MPEG::Header::frameLength() const +{ + return d->frameLength; +} + +int MPEG::Header::samplesPerFrame() const +{ + return d->samplesPerFrame; +} + +MPEG::Header &MPEG::Header::operator=(const Header &h) +{ + if(&h == this) + return *this; + + if(d->deref()) + delete d; + + d = h.d; + d->ref(); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::Header::parse(File *file, long offset, bool checkLength) +{ + file->seek(offset); + const ByteVector data = file->readBlock(4); + + if(data.size() < 4) { + debug("MPEG::Header::parse() -- data is too short for an MPEG frame header."); + return; + } + + // Check for the MPEG synch bytes. + + if(!isFrameSync(data)) { + debug("MPEG::Header::parse() -- MPEG header did not match MPEG synch."); + return; + } + + // Set the MPEG version + + const int versionBits = (static_cast(data[1]) >> 3) & 0x03; + + if(versionBits == 0) + d->version = Version2_5; + else if(versionBits == 2) + d->version = Version2; + else if(versionBits == 3) + d->version = Version1; + else + return; + + // Set the MPEG layer + + const int layerBits = (static_cast(data[1]) >> 1) & 0x03; + + if(layerBits == 1) + d->layer = 3; + else if(layerBits == 2) + d->layer = 2; + else if(layerBits == 3) + d->layer = 1; + else + return; + + d->protectionEnabled = (static_cast(data[1] & 0x01) == 0); + + // Set the bitrate + + static const int bitrates[2][3][16] = { + { // Version 1 + { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // layer 1 + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, // layer 2 + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } // layer 3 + }, + { // Version 2 or 2.5 + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, // layer 1 + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, // layer 2 + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } // layer 3 + } + }; + + const int versionIndex = (d->version == Version1) ? 0 : 1; + const int layerIndex = (d->layer > 0) ? d->layer - 1 : 0; + + // The bitrate index is encoded as the first 4 bits of the 3rd byte, + // i.e. 1111xxxx + + const int bitrateIndex = (static_cast(data[2]) >> 4) & 0x0F; + + d->bitrate = bitrates[versionIndex][layerIndex][bitrateIndex]; + + if(d->bitrate == 0) + return; + + // Set the sample rate + + static const int sampleRates[3][4] = { + { 44100, 48000, 32000, 0 }, // Version 1 + { 22050, 24000, 16000, 0 }, // Version 2 + { 11025, 12000, 8000, 0 } // Version 2.5 + }; + + // The sample rate index is encoded as two bits in the 3nd byte, i.e. xxxx11xx + + const int samplerateIndex = (static_cast(data[2]) >> 2) & 0x03; + + d->sampleRate = sampleRates[d->version][samplerateIndex]; + + if(d->sampleRate == 0) { + return; + } + + // The channel mode is encoded as a 2 bit value at the end of the 3nd byte, + // i.e. xxxxxx11 + + d->channelMode = static_cast((static_cast(data[3]) >> 6) & 0x03); + + // TODO: Add mode extension for completeness + + d->isOriginal = ((static_cast(data[3]) & 0x04) != 0); + d->isCopyrighted = ((static_cast(data[3]) & 0x08) != 0); + d->isPadded = ((static_cast(data[2]) & 0x02) != 0); + + // Samples per frame + + static const int samplesPerFrame[3][2] = { + // MPEG1, 2/2.5 + { 384, 384 }, // Layer I + { 1152, 1152 }, // Layer II + { 1152, 576 } // Layer III + }; + + d->samplesPerFrame = samplesPerFrame[layerIndex][versionIndex]; + + // Calculate the frame length + + static const int paddingSize[3] = { 4, 1, 1 }; + + d->frameLength = d->samplesPerFrame * d->bitrate * 125 / d->sampleRate; + + if(d->isPadded) + d->frameLength += paddingSize[layerIndex]; + + if(checkLength) { + + // Check if the frame length has been calculated correctly, or the next frame + // header is right next to the end of this frame. + + // The MPEG versions, layers and sample rates of the two frames should be + // consistent. Otherwise, we assume that either or both of the frames are + // broken. + + file->seek(offset + d->frameLength); + const ByteVector nextData = file->readBlock(4); + + if(nextData.size() < 4) + return; + + const unsigned int HeaderMask = 0xfffe0c00; + + const unsigned int header = data.toUInt(0, true) & HeaderMask; + const unsigned int nextHeader = nextData.toUInt(0, true) & HeaderMask; + + if(header != nextHeader) + return; + } + + // Now that we're done parsing, set this to be a valid frame. + + d->isValid = true; +} diff --git a/external/taglib/source/mpeg/mpegheader.h b/external/taglib/source/mpeg/mpegheader.h new file mode 100644 index 0000000..ca51184 --- /dev/null +++ b/external/taglib/source/mpeg/mpegheader.h @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGHEADER_H +#define TAGLIB_MPEGHEADER_H + +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + class File; + + namespace MPEG { + + //! An implementation of MP3 frame headers + + /*! + * This is an implementation of MPEG Layer III headers. The API follows more + * or less the binary format of these headers. I've used + * this + * document as a reference. + */ + + class TAGLIB_EXPORT Header + { + public: + /*! + * Parses an MPEG header based on \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Header(const ByteVector &data); + + /*! + * Parses an MPEG header based on \a file and \a offset. + * + * \note If \a checkLength is true, this requires the next MPEG frame to + * check if the frame length is parsed and calculated correctly. So it's + * suitable for seeking for the first valid frame. + */ + Header(File *file, long offset, bool checkLength = true); + + /*! + * Does a shallow copy of \a h. + */ + Header(const Header &h); + + /*! + * Destroys this Header instance. + */ + virtual ~Header(); + + /*! + * Returns true if the frame is at least an appropriate size and has + * legal values. + */ + bool isValid() const; + + /*! + * The MPEG Version. + */ + enum Version { + //! MPEG Version 1 + Version1 = 0, + //! MPEG Version 2 + Version2 = 1, + //! MPEG Version 2.5 + Version2_5 = 2 + }; + + /*! + * Returns the MPEG Version of the header. + */ + Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the bitrate encoded in the header. + */ + int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + int sampleRate() const; + + /*! + * Returns true if the frame is padded. + */ + bool isPadded() const; + + /*! + * There are a few combinations or one or two channel audio that are + * possible: + */ + enum ChannelMode { + //! Stereo + Stereo = 0, + //! Stereo + JointStereo = 1, + //! Dual Mono + DualChannel = 2, + //! Mono + SingleChannel = 3 + }; + + /*! + * Returns the channel mode for this frame. + */ + ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + /*! + * Returns the frame length in bytes. + */ + int frameLength() const; + + /*! + * Returns the number of frames per sample. + */ + int samplesPerFrame() const; + + /*! + * Makes a shallow copy of the header. + */ + Header &operator=(const Header &h); + + private: + void parse(File *file, long offset, bool checkLength); + + class HeaderPrivate; + HeaderPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/mpegproperties.cpp b/external/taglib/source/mpeg/mpegproperties.cpp new file mode 100644 index 0000000..5eec84f --- /dev/null +++ b/external/taglib/source/mpeg/mpegproperties.cpp @@ -0,0 +1,221 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "mpegproperties.h" +#include "mpegfile.h" +#include "xingheader.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +class MPEG::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + xingHeader(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + layer(0), + version(Header::Version1), + channelMode(Header::Stereo), + protectionEnabled(false), + isCopyrighted(false), + isOriginal(false) {} + + ~PropertiesPrivate() + { + delete xingHeader; + } + + XingHeader *xingHeader; + int length; + int bitrate; + int sampleRate; + int channels; + int layer; + Header::Version version; + Header::ChannelMode channelMode; + bool protectionEnabled; + bool isCopyrighted; + bool isOriginal; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +MPEG::Properties::~Properties() +{ + delete d; +} + +int MPEG::Properties::length() const +{ + return lengthInSeconds(); +} + +int MPEG::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int MPEG::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int MPEG::Properties::bitrate() const +{ + return d->bitrate; +} + +int MPEG::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int MPEG::Properties::channels() const +{ + return d->channels; +} + +const MPEG::XingHeader *MPEG::Properties::xingHeader() const +{ + return d->xingHeader; +} + +MPEG::Header::Version MPEG::Properties::version() const +{ + return d->version; +} + +int MPEG::Properties::layer() const +{ + return d->layer; +} + +bool MPEG::Properties::protectionEnabled() const +{ + return d->protectionEnabled; +} + +MPEG::Header::ChannelMode MPEG::Properties::channelMode() const +{ + return d->channelMode; +} + +bool MPEG::Properties::isCopyrighted() const +{ + return d->isCopyrighted; +} + +bool MPEG::Properties::isOriginal() const +{ + return d->isOriginal; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::Properties::read(File *file) +{ + // Only the first valid frame is required if we have a VBR header. + + const long firstFrameOffset = file->firstFrameOffset(); + if(firstFrameOffset < 0) { + debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream."); + return; + } + + const Header firstHeader(file, firstFrameOffset, false); + + // Check for a VBR header that will help us in gathering information about a + // VBR stream. + + file->seek(firstFrameOffset); + d->xingHeader = new XingHeader(file->readBlock(firstHeader.frameLength())); + if(!d->xingHeader->isValid()) { + delete d->xingHeader; + d->xingHeader = 0; + } + + if(d->xingHeader && firstHeader.samplesPerFrame() > 0 && firstHeader.sampleRate() > 0) { + + // Read the length and the bitrate from the VBR header. + + const double timePerFrame = firstHeader.samplesPerFrame() * 1000.0 / firstHeader.sampleRate(); + const double length = timePerFrame * d->xingHeader->totalFrames(); + + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(d->xingHeader->totalSize() * 8.0 / length + 0.5); + } + else if(firstHeader.bitrate() > 0) { + + // Since there was no valid VBR header found, we hope that we're in a constant + // bitrate file. + + // TODO: Make this more robust with audio property detection for VBR without a + // Xing header. + + d->bitrate = firstHeader.bitrate(); + + // Look for the last MPEG audio frame to calculate the stream length. + + const long lastFrameOffset = file->lastFrameOffset(); + if(lastFrameOffset < 0) { + debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream."); + } + else + { + const Header lastHeader(file, lastFrameOffset, false); + const long streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength(); + if (streamLength > 0) + d->length = static_cast(streamLength * 8.0 / d->bitrate + 0.5); + } + } + + d->sampleRate = firstHeader.sampleRate(); + d->channels = firstHeader.channelMode() == Header::SingleChannel ? 1 : 2; + d->version = firstHeader.version(); + d->layer = firstHeader.layer(); + d->protectionEnabled = firstHeader.protectionEnabled(); + d->channelMode = firstHeader.channelMode(); + d->isCopyrighted = firstHeader.isCopyrighted(); + d->isOriginal = firstHeader.isOriginal(); +} diff --git a/external/taglib/source/mpeg/mpegproperties.h b/external/taglib/source/mpeg/mpegproperties.h new file mode 100644 index 0000000..a1a1af4 --- /dev/null +++ b/external/taglib/source/mpeg/mpegproperties.h @@ -0,0 +1,152 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGPROPERTIES_H +#define TAGLIB_MPEGPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +#include "mpegheader.h" + +namespace TagLib { + + namespace MPEG { + + class File; + class XingHeader; + + //! An implementation of audio property reading for MP3 + + /*! + * This reads the data from an MPEG Layer III stream found in the + * AudioProperties API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of MPEG::Properties with the data read from the + * MPEG::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this MPEG Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns a pointer to the Xing/VBRI header if one exists or null if no + * Xing/VBRI header was found. + */ + const XingHeader *xingHeader() const; + + /*! + * Returns the MPEG Version of the file. + */ + Header::Version version() const; + + /*! + * Returns the layer version. This will be between the values 1-3. + */ + int layer() const; + + /*! + * Returns true if the MPEG protection bit is enabled. + */ + bool protectionEnabled() const; + + /*! + * Returns the channel mode for this frame. + */ + Header::ChannelMode channelMode() const; + + /*! + * Returns true if the copyrighted bit is set. + */ + bool isCopyrighted() const; + + /*! + * Returns true if the "original" bit is set. + */ + bool isOriginal() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/mpeg/mpegutils.h b/external/taglib/source/mpeg/mpegutils.h new file mode 100644 index 0000000..31b45a4 --- /dev/null +++ b/external/taglib/source/mpeg/mpegutils.h @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MPEGUTILS_H +#define TAGLIB_MPEGUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace MPEG + { + namespace + { + + /*! + * MPEG frames can be recognized by the bit pattern 11111111 111, so the + * first byte is easy to check for, however checking to see if the second byte + * starts with \e 111 is a bit more tricky, hence these functions. + * + * \note This does not check the length of the vector, since this is an + * internal utility function. + */ + inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0) + { + // 0xFF in the second byte is possible in theory, but it's very unlikely. + + const unsigned char b1 = bytes[offset + 0]; + const unsigned char b2 = bytes[offset + 1]; + return (b1 == 0xFF && b2 != 0xFF && (b2 & 0xE0) == 0xE0); + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/source/mpeg/xingheader.cpp b/external/taglib/source/mpeg/xingheader.cpp new file mode 100644 index 0000000..6c2b25d --- /dev/null +++ b/external/taglib/source/mpeg/xingheader.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + copyright : (C) 2003 by Ismael Orenstein + email : orenstein@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "xingheader.h" +#include "mpegfile.h" + +using namespace TagLib; + +class MPEG::XingHeader::XingHeaderPrivate +{ +public: + XingHeaderPrivate() : + frames(0), + size(0), + type(MPEG::XingHeader::Invalid) {} + + unsigned int frames; + unsigned int size; + + MPEG::XingHeader::HeaderType type; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +MPEG::XingHeader::XingHeader(const ByteVector &data) : + d(new XingHeaderPrivate()) +{ + parse(data); +} + +MPEG::XingHeader::~XingHeader() +{ + delete d; +} + +bool MPEG::XingHeader::isValid() const +{ + return (d->type != Invalid && d->frames > 0 && d->size > 0); +} + +unsigned int MPEG::XingHeader::totalFrames() const +{ + return d->frames; +} + +unsigned int MPEG::XingHeader::totalSize() const +{ + return d->size; +} + +MPEG::XingHeader::HeaderType MPEG::XingHeader::type() const +{ + return d->type; +} + +int MPEG::XingHeader::xingHeaderOffset(TagLib::MPEG::Header::Version /*v*/, + TagLib::MPEG::Header::ChannelMode /*c*/) +{ + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void MPEG::XingHeader::parse(const ByteVector &data) +{ + // Look for a Xing header. + + long offset = data.find("Xing"); + if(offset < 0) + offset = data.find("Info"); + + if(offset >= 0) { + + // Xing header found. + + if(data.size() < static_cast(offset + 16)) { + debug("MPEG::XingHeader::parse() -- Xing header found but too short."); + return; + } + + if((data[offset + 7] & 0x03) != 0x03) { + debug("MPEG::XingHeader::parse() -- Xing header doesn't contain the required information."); + return; + } + + d->frames = data.toUInt(offset + 8, true); + d->size = data.toUInt(offset + 12, true); + d->type = Xing; + } + else { + + // Xing header not found. Then look for a VBRI header. + + offset = data.find("VBRI"); + + if(offset >= 0) { + + // VBRI header found. + + if(data.size() < static_cast(offset + 32)) { + debug("MPEG::XingHeader::parse() -- VBRI header found but too short."); + return; + } + + d->frames = data.toUInt(offset + 14, true); + d->size = data.toUInt(offset + 10, true); + d->type = VBRI; + } + } +} diff --git a/external/taglib/source/mpeg/xingheader.h b/external/taglib/source/mpeg/xingheader.h new file mode 100644 index 0000000..ce75619 --- /dev/null +++ b/external/taglib/source/mpeg/xingheader.h @@ -0,0 +1,129 @@ +/*************************************************************************** + copyright : (C) 2003 by Ismael Orenstein + email : orenstein@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XINGHEADER_H +#define TAGLIB_XINGHEADER_H + +#include "mpegheader.h" +#include "taglib_export.h" + +namespace TagLib { + + class ByteVector; + + namespace MPEG { + + class File; + + //! An implementation of the Xing/VBRI headers + + /*! + * This is a minimalistic implementation of the Xing/VBRI VBR headers. + * Xing/VBRI headers are often added to VBR (variable bit rate) MP3 streams + * to make it easy to compute the length and quality of a VBR stream. Our + * implementation is only concerned with the total size of the stream (so + * that we can calculate the total playing time and the average bitrate). + * It uses + * this text and the XMMS sources as references. + */ + + class TAGLIB_EXPORT XingHeader + { + public: + /*! + * The type of the VBR header. + */ + enum HeaderType + { + /*! + * Invalid header or no VBR header found. + */ + Invalid = 0, + + /*! + * Xing header. + */ + Xing = 1, + + /*! + * VBRI header. + */ + VBRI = 2, + }; + + /*! + * Parses an Xing/VBRI header based on \a data which contains the entire + * first MPEG frame. + */ + XingHeader(const ByteVector &data); + + /*! + * Destroy this XingHeader instance. + */ + virtual ~XingHeader(); + + /*! + * Returns true if the data was parsed properly and if there is a valid + * Xing/VBRI header present. + */ + bool isValid() const; + + /*! + * Returns the total number of frames. + */ + unsigned int totalFrames() const; + + /*! + * Returns the total size of stream in bytes. + */ + unsigned int totalSize() const; + + /*! + * Returns the type of the VBR header. + */ + HeaderType type() const; + + /*! + * Returns the offset for the start of this Xing header, given the + * version and channels of the frame + * + * \deprecated Always returns 0. + */ + TAGLIB_DEPRECATED static int xingHeaderOffset(TagLib::MPEG::Header::Version v, + TagLib::MPEG::Header::ChannelMode c); + + private: + XingHeader(const XingHeader &); + XingHeader &operator=(const XingHeader &); + + void parse(const ByteVector &data); + + class XingHeaderPrivate; + XingHeaderPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/ogg/flac/oggflacfile.cpp b/external/taglib/source/ogg/flac/oggflacfile.cpp new file mode 100644 index 0000000..07ea9dc --- /dev/null +++ b/external/taglib/source/ogg/flac/oggflacfile.cpp @@ -0,0 +1,321 @@ +/*************************************************************************** + copyright : (C) 2004-2005 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include "oggflacfile.h" + +using namespace TagLib; +using TagLib::FLAC::Properties; + +class Ogg::FLAC::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0), + streamStart(0), + streamLength(0), + scanned(false), + hasXiphComment(false), + commentPacket(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + + Properties *properties; + ByteVector streamInfoData; + ByteVector xiphCommentData; + long streamStart; + long streamLength; + bool scanned; + + bool hasXiphComment; + int commentPacket; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool Ogg::FLAC::File::isSupported(IOStream *stream) +{ + // An Ogg FLAC file has IDs "OggS" and "fLaC" somewhere. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); + return (buffer.find("OggS") >= 0 && buffer.find("fLaC") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::FLAC::File::File(FileName file, bool readProperties, + Properties::ReadStyle propertiesStyle) : + Ogg::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties, propertiesStyle); +} + +Ogg::FLAC::File::File(IOStream *stream, bool readProperties, + Properties::ReadStyle propertiesStyle) : + Ogg::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties, propertiesStyle); +} + +Ogg::FLAC::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Ogg::FLAC::File::tag() const +{ + return d->comment; +} + +PropertyMap Ogg::FLAC::File::properties() const +{ + return d->comment->properties(); +} + +PropertyMap Ogg::FLAC::File::setProperties(const PropertyMap &properties) +{ + return d->comment->setProperties(properties); +} + +Properties *Ogg::FLAC::File::audioProperties() const +{ + return d->properties; +} + + +bool Ogg::FLAC::File::save() +{ + d->xiphCommentData = d->comment->render(false); + + // Create FLAC metadata-block: + + // Put the size in the first 32 bit (I assume no more than 24 bit are used) + + ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size()); + + // Set the type of the metadata-block to be a Xiph / Vorbis comment + + v[0] = 4; + + // Append the comment-data after the 32 bit header + + v.append(d->xiphCommentData); + + // Save the packet at the old spot + // FIXME: Use padding if size is increasing + + setPacket(d->commentPacket, v); + + return Ogg::File::save(); +} + +bool Ogg::FLAC::File::hasXiphComment() const +{ + return d->hasXiphComment; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + // Sanity: Check if we really have an Ogg/FLAC file + +/* + ByteVector oggHeader = packet(0); + + if (oggHeader.mid(28,4) != "fLaC") { + debug("Ogg::FLAC::File::read() -- Not an Ogg/FLAC file"); + setValid(false); + return; + }*/ + + // Look for FLAC metadata, including vorbis comments + + scan(); + + if (!d->scanned) { + setValid(false); + return; + } + + + if(d->hasXiphComment) + d->comment = new Ogg::XiphComment(xiphCommentData()); + else + d->comment = new Ogg::XiphComment(); + + + if(readProperties) + d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle); +} + +ByteVector Ogg::FLAC::File::streamInfoData() +{ + scan(); + return d->streamInfoData; +} + +ByteVector Ogg::FLAC::File::xiphCommentData() +{ + scan(); + return d->xiphCommentData; +} + +long Ogg::FLAC::File::streamLength() +{ + scan(); + return d->streamLength; +} + +void Ogg::FLAC::File::scan() +{ + // Scan the metadata pages + + if(d->scanned) + return; + + if(!isValid()) + return; + + int ipacket = 0; + long overhead = 0; + + ByteVector metadataHeader = packet(ipacket); + if(metadataHeader.isEmpty()) + return; + + if(!metadataHeader.startsWith("fLaC")) { + // FLAC 1.1.2+ + // See https://xiph.org/flac/ogg_mapping.html for the header specification. + if(metadataHeader.size() < 13) + return; + + if(metadataHeader[0] != 0x7f) + return; + + if(metadataHeader.mid(1, 4) != "FLAC") + return; + + if(metadataHeader[5] != 1 && metadataHeader[6] != 0) + return; // not version 1.0 + + if(metadataHeader.mid(9, 4) != "fLaC") + return; + + metadataHeader = metadataHeader.mid(13); + } + else { + // FLAC 1.1.0 & 1.1.1 + metadataHeader = packet(++ipacket); + } + + ByteVector header = metadataHeader.mid(0, 4); + if(header.size() != 4) { + debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC metadata header"); + return; + } + + // Header format (from spec): + // <1> Last-metadata-block flag + // <7> BLOCK_TYPE + // 0 : STREAMINFO + // 1 : PADDING + // .. + // 4 : VORBIS_COMMENT + // .. + // <24> Length of metadata to follow + + char blockType = header[0] & 0x7f; + bool lastBlock = (header[0] & 0x80) != 0; + unsigned int length = header.toUInt(1, 3, true); + overhead += length; + + // Sanity: First block should be the stream_info metadata + + if(blockType != 0) { + debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC stream"); + return; + } + + d->streamInfoData = metadataHeader.mid(4, length); + + // Search through the remaining metadata + + while(!lastBlock) { + metadataHeader = packet(++ipacket); + header = metadataHeader.mid(0, 4); + if(header.size() != 4) { + debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC metadata header"); + return; + } + + blockType = header[0] & 0x7f; + lastBlock = (header[0] & 0x80) != 0; + length = header.toUInt(1, 3, true); + overhead += length; + + if(blockType == 1) { + // debug("Ogg::FLAC::File::scan() -- Padding found"); + } + else if(blockType == 4) { + // debug("Ogg::FLAC::File::scan() -- Vorbis-comments found"); + d->xiphCommentData = metadataHeader.mid(4, length); + d->hasXiphComment = true; + d->commentPacket = ipacket; + } + else if(blockType > 5) { + debug("Ogg::FLAC::File::scan() -- Unknown metadata block"); + } + } + + // End of metadata, now comes the datastream + d->streamStart = overhead; + d->streamLength = File::length() - d->streamStart; + + d->scanned = true; +} diff --git a/external/taglib/source/ogg/flac/oggflacfile.h b/external/taglib/source/ogg/flac/oggflacfile.h new file mode 100644 index 0000000..b2686e4 --- /dev/null +++ b/external/taglib/source/ogg/flac/oggflacfile.h @@ -0,0 +1,170 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGFLACFILE_H +#define TAGLIB_OGGFLACFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "flacproperties.h" + +namespace TagLib { + + class Tag; + + namespace Ogg { + + //! An implementation of Ogg FLAC metadata + + /*! + * This is implementation of FLAC metadata for Ogg FLAC files. For "pure" + * FLAC files look under the FLAC hierarchy. + * + * Unlike "pure" FLAC-files, Ogg FLAC only supports Xiph-comments, + * while the audio-properties are the same. + */ + namespace FLAC { + + using TagLib::FLAC::Properties; + + //! An implementation of TagLib::File with Ogg/FLAC specific methods + + /*! + * This implements and provides an interface for Ogg/FLAC files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to Ogg FLAC files. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs an Ogg/FLAC file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will always be a XiphComment. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has a XiphComment. Use hasXiphComment() to check if + * the file on disk actually has a XiphComment. + * + * \note The Tag is still owned by the FLAC::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasXiphComment() + */ + virtual XiphComment *tag() const; + + /*! + * Returns the FLAC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + + /*! + * Save the file. This will primarily save and update the XiphComment. + * Returns true if the save is successful. + */ + virtual bool save(); + + /*! + * Returns the length of the audio-stream, used by FLAC::Properties for + * calculating the bitrate. + */ + long streamLength(); + + /*! + * Returns whether or not the file on disk actually has a XiphComment. + * + * \see tag() + */ + bool hasXiphComment() const; + + /*! + * Check if the given \a stream can be opened as an Ogg FLAC file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + ByteVector streamInfoData(); + ByteVector xiphCommentData(); + + class FilePrivate; + FilePrivate *d; + }; + } // namespace FLAC + } // namespace Ogg +} // namespace TagLib + +#endif diff --git a/external/taglib/source/ogg/oggfile.cpp b/external/taglib/source/ogg/oggfile.cpp new file mode 100644 index 0000000..1f2cce9 --- /dev/null +++ b/external/taglib/source/ogg/oggfile.cpp @@ -0,0 +1,312 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "oggfile.h" +#include "oggpage.h" +#include "oggpageheader.h" + +using namespace TagLib; + +namespace +{ + // Returns the first packet index of the right next page to the given one. + unsigned int nextPacketIndex(const Ogg::Page *page) + { + if(page->header()->lastPacketCompleted()) + return page->firstPacketIndex() + page->packetCount(); + return page->firstPacketIndex() + page->packetCount() - 1; + } +} // namespace + +class Ogg::File::FilePrivate +{ +public: + FilePrivate() : + firstPageHeader(0), + lastPageHeader(0) + { + pages.setAutoDelete(true); + } + + ~FilePrivate() + { + delete firstPageHeader; + delete lastPageHeader; + } + + unsigned int streamSerialNumber; + List pages; + PageHeader *firstPageHeader; + PageHeader *lastPageHeader; + Map dirtyPackets; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::File::~File() +{ + delete d; +} + +ByteVector Ogg::File::packet(unsigned int i) +{ + // Check to see if we're called setPacket() for this packet since the last + // save: + + if(d->dirtyPackets.contains(i)) + return d->dirtyPackets[i]; + + // If we haven't indexed the page where the packet we're interested in starts, + // begin reading pages until we have. + + if(!readPages(i)) { + debug("Ogg::File::packet() -- Could not find the requested packet."); + return ByteVector(); + } + + // Look for the first page in which the requested packet starts. + + List::ConstIterator it = d->pages.begin(); + while((*it)->containsPacket(i) == Page::DoesNotContainPacket) + ++it; + + // If the packet is completely contained in the first page that it's in. + + // If the packet is *not* completely contained in the first page that it's a + // part of then that packet trails off the end of the page. Continue appending + // the pages' packet data until we hit a page that either does not end with the + // packet that we're fetching or where the last packet is complete. + + ByteVector packet = (*it)->packets()[i - (*it)->firstPacketIndex()]; + + while(nextPacketIndex(*it) <= i) { + ++it; + packet.append((*it)->packets().front()); + } + + return packet; +} + +void Ogg::File::setPacket(unsigned int i, const ByteVector &p) +{ + if(!readPages(i)) { + debug("Ogg::File::setPacket() -- Could not set the requested packet."); + return; + } + + d->dirtyPackets[i] = p; +} + +const Ogg::PageHeader *Ogg::File::firstPageHeader() +{ + if(!d->firstPageHeader) { + const long firstPageHeaderOffset = find("OggS"); + if(firstPageHeaderOffset < 0) + return 0; + + d->firstPageHeader = new PageHeader(this, firstPageHeaderOffset); + } + + return d->firstPageHeader->isValid() ? d->firstPageHeader : 0; +} + +const Ogg::PageHeader *Ogg::File::lastPageHeader() +{ + if(!d->lastPageHeader) { + const long lastPageHeaderOffset = rfind("OggS"); + if(lastPageHeaderOffset < 0) + return 0; + + d->lastPageHeader = new PageHeader(this, lastPageHeaderOffset); + } + + return d->lastPageHeader->isValid() ? d->lastPageHeader : 0; +} + +bool Ogg::File::save() +{ + if(readOnly()) { + debug("Ogg::File::save() - Cannot save to a read only file."); + return false; + } + + Map::ConstIterator it; + for(it = d->dirtyPackets.begin(); it != d->dirtyPackets.end(); ++it) + writePacket(it->first, it->second); + + d->dirtyPackets.clear(); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::File::File(FileName file) : + TagLib::File(file), + d(new FilePrivate()) +{ +} + +Ogg::File::File(IOStream *stream) : + TagLib::File(stream), + d(new FilePrivate()) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +bool Ogg::File::readPages(unsigned int i) +{ + while(true) { + unsigned int packetIndex; + long offset; + + if(d->pages.isEmpty()) { + packetIndex = 0; + offset = find("OggS"); + if(offset < 0) + return false; + } + else { + const Page *page = d->pages.back(); + packetIndex = nextPacketIndex(page); + offset = page->fileOffset() + page->size(); + } + + // Enough pages have been fetched. + + if(packetIndex > i) + return true; + + // Read the next page and add it to the page list. + + Page *nextPage = new Page(this, offset); + if(!nextPage->header()->isValid()) { + delete nextPage; + return false; + } + + nextPage->setFirstPacketIndex(packetIndex); + d->pages.append(nextPage); + + if(nextPage->header()->lastPageOfStream()) + return false; + } +} + +void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) +{ + if(!readPages(i)) { + debug("Ogg::File::writePacket() -- Could not find the requested packet."); + return; + } + + // Look for the pages where the requested packet should belong to. + + List::ConstIterator it = d->pages.begin(); + while((*it)->containsPacket(i) == Page::DoesNotContainPacket) + ++it; + + const Page *firstPage = *it; + + while(nextPacketIndex(*it) <= i) + ++it; + + const Page *lastPage = *it; + + // Replace the requested packet and create new pages to replace the located pages. + + ByteVectorList packets = firstPage->packets(); + packets[i - firstPage->firstPacketIndex()] = packet; + + if(firstPage != lastPage && lastPage->packetCount() > 1) { + ByteVectorList lastPagePackets = lastPage->packets(); + lastPagePackets.erase(lastPagePackets.begin()); + packets.append(lastPagePackets); + } + + // TODO: This pagination method isn't accurate for what's being done here. + // This should account for real possibilities like non-aligned packets and such. + + List pages = Page::paginate(packets, + Page::SinglePagePerGroup, + firstPage->header()->streamSerialNumber(), + firstPage->pageSequenceNumber(), + firstPage->header()->firstPacketContinued(), + lastPage->header()->lastPacketCompleted()); + pages.setAutoDelete(true); + + // Write the pages. + + ByteVector data; + for(it = pages.begin(); it != pages.end(); ++it) + data.append((*it)->render()); + + const unsigned long originalOffset = firstPage->fileOffset(); + const unsigned long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset; + + insert(data, originalOffset, originalLength); + + // Renumber the following pages if the pages have been split or merged. + + const int numberOfNewPages + = pages.back()->pageSequenceNumber() - lastPage->pageSequenceNumber(); + + if(numberOfNewPages != 0) { + long pageOffset = originalOffset + data.size(); + + while(true) { + Page page(this, pageOffset); + if(!page.header()->isValid()) + break; + + page.setPageSequenceNumber(page.pageSequenceNumber() + numberOfNewPages); + const ByteVector data = page.render(); + + seek(pageOffset + 18); + writeBlock(data.mid(18, 8)); + + if(page.header()->lastPageOfStream()) + break; + + pageOffset += page.size(); + } + } + + // Discard all the pages to keep them up-to-date by fetching them again. + + d->pages.clear(); +} diff --git a/external/taglib/source/ogg/oggfile.h b/external/taglib/source/ogg/oggfile.h new file mode 100644 index 0000000..7d889c2 --- /dev/null +++ b/external/taglib/source/ogg/oggfile.h @@ -0,0 +1,127 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "taglib_export.h" +#include "tfile.h" +#include "tbytevectorlist.h" + +#ifndef TAGLIB_OGGFILE_H +#define TAGLIB_OGGFILE_H + +namespace TagLib { + + //! A namespace for the classes used by Ogg-based metadata files + + namespace Ogg { + + class PageHeader; + + //! An implementation of TagLib::File with some helpers for Ogg based formats + + /*! + * This is an implementation of Ogg file page and packet rendering and is of + * use to Ogg based formats. While the API is small this handles the + * non-trivial details of breaking up an Ogg stream into packets and makes + * these available (via subclassing) to the codec meta data implementations. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + virtual ~File(); + + /*! + * Returns the packet contents for the i-th packet (starting from zero) + * in the Ogg bitstream. + * + * \warning This requires reading at least the packet header for every page + * up to the requested page. + */ + ByteVector packet(unsigned int i); + + /*! + * Sets the packet with index \a i to the value \a p. + */ + void setPacket(unsigned int i, const ByteVector &p); + + /*! + * Returns a pointer to the PageHeader for the first page in the stream or + * null if the page could not be found. + */ + const PageHeader *firstPageHeader(); + + /*! + * Returns a pointer to the PageHeader for the last page in the stream or + * null if the page could not be found. + */ + const PageHeader *lastPageHeader(); + + virtual bool save(); + + protected: + /*! + * Constructs an Ogg file from \a file. + * + * \note This constructor is protected since Ogg::File shouldn't be + * instantiated directly but rather should be used through the codec + * specific subclasses. + */ + File(FileName file); + + /*! + * Constructs an Ogg file from \a stream. + * + * \note This constructor is protected since Ogg::File shouldn't be + * instantiated directly but rather should be used through the codec + * specific subclasses. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + /*! + * Reads the pages from the beginning of the file until enough to compose + * the requested packet. + */ + bool readPages(unsigned int i); + + /*! + * Writes the requested packet to the file. + */ + void writePacket(unsigned int i, const ByteVector &packet); + + class FilePrivate; + FilePrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/ogg/oggpage.cpp b/external/taglib/source/ogg/oggpage.cpp new file mode 100644 index 0000000..8cd15a5 --- /dev/null +++ b/external/taglib/source/ogg/oggpage.cpp @@ -0,0 +1,314 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include + +#include "oggpage.h" +#include "oggpageheader.h" +#include "oggfile.h" + +using namespace TagLib; + +class Ogg::Page::PagePrivate +{ +public: + PagePrivate(File *f = 0, long pageOffset = -1) : + file(f), + fileOffset(pageOffset), + header(f, pageOffset), + firstPacketIndex(-1) {} + + File *file; + long fileOffset; + PageHeader header; + int firstPacketIndex; + ByteVectorList packets; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::Page::Page(Ogg::File *file, long pageOffset) : + d(new PagePrivate(file, pageOffset)) +{ +} + +Ogg::Page::~Page() +{ + delete d; +} + +long Ogg::Page::fileOffset() const +{ + return d->fileOffset; +} + +const Ogg::PageHeader *Ogg::Page::header() const +{ + return &d->header; +} + +int Ogg::Page::pageSequenceNumber() const +{ + return d->header.pageSequenceNumber(); +} + +void Ogg::Page::setPageSequenceNumber(int sequenceNumber) +{ + d->header.setPageSequenceNumber(sequenceNumber); +} + +int Ogg::Page::firstPacketIndex() const +{ + return d->firstPacketIndex; +} + +void Ogg::Page::setFirstPacketIndex(int index) +{ + d->firstPacketIndex = index; +} + +Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const +{ + const int lastPacketIndex = d->firstPacketIndex + packetCount() - 1; + if(index < d->firstPacketIndex || index > lastPacketIndex) + return DoesNotContainPacket; + + ContainsPacketFlags flags = DoesNotContainPacket; + + if(index == d->firstPacketIndex) + flags = ContainsPacketFlags(flags | BeginsWithPacket); + + if(index == lastPacketIndex) + flags = ContainsPacketFlags(flags | EndsWithPacket); + + // If there's only one page and it's complete: + + if(packetCount() == 1 && + !d->header.firstPacketContinued() && + d->header.lastPacketCompleted()) + { + flags = ContainsPacketFlags(flags | CompletePacket); + } + + // Or if there is more than one page and the page is + // (a) the first page and it's complete or + // (b) the last page and it's complete or + // (c) a page in the middle. + else if(packetCount() > 1 && + ((flags & BeginsWithPacket && !d->header.firstPacketContinued()) || + (flags & EndsWithPacket && d->header.lastPacketCompleted()) || + (!(flags & BeginsWithPacket) && !(flags & EndsWithPacket)))) + { + flags = ContainsPacketFlags(flags | CompletePacket); + } + + return flags; +} + +unsigned int Ogg::Page::packetCount() const +{ + return d->header.packetSizes().size(); +} + +ByteVectorList Ogg::Page::packets() const +{ + if(!d->packets.isEmpty()) + return d->packets; + + ByteVectorList l; + + if(d->file && d->header.isValid()) { + + d->file->seek(d->fileOffset + d->header.size()); + + List packetSizes = d->header.packetSizes(); + + List::ConstIterator it = packetSizes.begin(); + for(; it != packetSizes.end(); ++it) + l.append(d->file->readBlock(*it)); + } + else + debug("Ogg::Page::packets() -- attempting to read packets from an invalid page."); + + return l; +} + +int Ogg::Page::size() const +{ + return d->header.size() + d->header.dataSize(); +} + +ByteVector Ogg::Page::render() const +{ + ByteVector data; + + data.append(d->header.render()); + + if(d->packets.isEmpty()) { + if(d->file) { + d->file->seek(d->fileOffset + d->header.size()); + data.append(d->file->readBlock(d->header.dataSize())); + } + else + debug("Ogg::Page::render() -- this page is empty!"); + } + else { + ByteVectorList::ConstIterator it = d->packets.begin(); + for(; it != d->packets.end(); ++it) + data.append(*it); + } + + // Compute and set the checksum for the Ogg page. The checksum is taken over + // the entire page with the 4 bytes reserved for the checksum zeroed and then + // inserted in bytes 22-25 of the page header. + + const ByteVector checksum = ByteVector::fromUInt(data.checksum(), false); + std::copy(checksum.begin(), checksum.end(), data.begin() + 22); + + return data; +} + +List Ogg::Page::paginate(const ByteVectorList &packets, + PaginationStrategy strategy, + unsigned int streamSerialNumber, + int firstPage, + bool firstPacketContinued, + bool lastPacketCompleted, + bool containsLastPacket) +{ + // SplitSize must be a multiple of 255 in order to get the lacing values right + // create pages of about 8KB each + + static const unsigned int SplitSize = 32 * 255; + + // Force repagination if the segment table will exceed the size limit. + + if(strategy != Repaginate) { + + size_t tableSize = 0; + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) + tableSize += it->size() / 255 + 1; + + if(tableSize > 255) + strategy = Repaginate; + } + + List l; + + // Handle creation of multiple pages with appropriate pagination. + + if(strategy == Repaginate) { + + int pageIndex = firstPage; + + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) { + + const bool lastPacketInList = (it == --packets.end()); + + // mark very first packet? + + bool continued = (firstPacketContinued && it == packets.begin()); + unsigned int pos = 0; + + while(pos < it->size()) { + + const bool lastSplit = (pos + SplitSize >= it->size()); + + ByteVectorList packetList; + packetList.append(it->mid(pos, SplitSize)); + + l.append(new Page(packetList, + streamSerialNumber, + pageIndex, + continued, + lastSplit && (lastPacketInList ? lastPacketCompleted : true), + lastSplit && (containsLastPacket && lastPacketInList))); + pageIndex++; + continued = true; + + pos += SplitSize; + } + } + } + else { + l.append(new Page(packets, + streamSerialNumber, + firstPage, + firstPacketContinued, + lastPacketCompleted, + containsLastPacket)); + } + + return l; +} + +Ogg::Page* Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/) +{ + debug("Ogg::Page::getCopyWithNewPageSequenceNumber() -- This function is obsolete. Returning null."); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::Page::Page(const ByteVectorList &packets, + unsigned int streamSerialNumber, + int pageNumber, + bool firstPacketContinued, + bool lastPacketCompleted, + bool containsLastPacket) : + d(new PagePrivate()) +{ + d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued); + d->header.setLastPageOfStream(containsLastPacket); + d->header.setFirstPacketContinued(firstPacketContinued); + d->header.setLastPacketCompleted(lastPacketCompleted); + d->header.setStreamSerialNumber(streamSerialNumber); + d->header.setPageSequenceNumber(pageNumber); + + // Build a page from the list of packets. + + ByteVector data; + List packetSizes; + + for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) { + packetSizes.append((*it).size()); + data.append(*it); + } + d->packets = packets; + d->header.setPacketSizes(packetSizes); + + // https://xiph.org/ogg/doc/framing.html, absolute granule position: + // A special value of '-1' (in two's complement) indicates that no packets + // finish on this page. + if(!lastPacketCompleted && packets.size() <= 1) + d->header.setAbsoluteGranularPosition(-1); +} diff --git a/external/taglib/source/ogg/oggpage.h b/external/taglib/source/ogg/oggpage.h new file mode 100644 index 0000000..af3fe2c --- /dev/null +++ b/external/taglib/source/ogg/oggpage.h @@ -0,0 +1,228 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGE_H +#define TAGLIB_OGGPAGE_H + +#include "taglib_export.h" +#include "tbytevectorlist.h" + +namespace TagLib { + + namespace Ogg { + + class File; + class PageHeader; + + //! An implementation of Ogg pages + + /*! + * This is an implementation of the pages that make up an Ogg stream. + * This handles parsing pages and breaking them down into packets and handles + * the details of packets spanning multiple pages and pages that contain + * multiple packets. + * + * In most Xiph.org formats the comments are found in the first few packets, + * this however is a reasonably complete implementation of Ogg pages that + * could potentially be useful for non-meta data purposes. + */ + + class TAGLIB_EXPORT Page + { + public: + /*! + * Read an Ogg page from the \a file at the position \a pageOffset. + */ + Page(File *file, long pageOffset); + + virtual ~Page(); + + /*! + * Returns the page's position within the file (in bytes). + */ + long fileOffset() const; + + /*! + * Returns a pointer to the header for this page. This pointer will become + * invalid when the page is deleted. + */ + const PageHeader *header() const; + + /*! + * Returns the index of the page within the Ogg stream. This helps make it + * possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ + int pageSequenceNumber() const; + + /*! + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ + void setPageSequenceNumber(int sequenceNumber); + + /*! + * Returns a copy of the page with \a sequenceNumber set as sequence number. + * + * \see header() + * \see PageHeader::setPageSequenceNumber() + * + * \deprecated Always returns null. + */ + TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the index of the first packet wholly or partially contained in + * this page. + * + * \see setFirstPacketIndex() + */ + int firstPacketIndex() const; + + /*! + * Sets the index of the first packet in the page. + * + * \see firstPacketIndex() + */ + void setFirstPacketIndex(int index); + + /*! + * When checking to see if a page contains a given packet this set of flags + * represents the possible values for that packets status in the page. + * + * \see containsPacket() + */ + enum ContainsPacketFlags { + //! No part of the packet is contained in the page + DoesNotContainPacket = 0x0000, + //! The packet is wholly contained in the page + CompletePacket = 0x0001, + //! The page starts with the given packet + BeginsWithPacket = 0x0002, + //! The page ends with the given packet + EndsWithPacket = 0x0004 + }; + + /*! + * Checks to see if the specified \a packet is contained in the current + * page. + * + * \see ContainsPacketFlags + */ + ContainsPacketFlags containsPacket(int index) const; + + /*! + * Returns the number of packets (whole or partial) in this page. + */ + unsigned int packetCount() const; + + /*! + * Returns a list of the packets in this page. + * + * \note Either or both the first and last packets may be only partial. + * \see PageHeader::firstPacketContinued() + */ + ByteVectorList packets() const; + + /*! + * Returns the size of the page in bytes. + */ + int size() const; + + ByteVector render() const; + + /*! + * Defines a strategy for pagination, or grouping pages into Ogg packets, + * for use with pagination methods. + * + * \note Yes, I'm aware that this is not a canonical "Strategy Pattern", + * the term was simply convenient. + */ + enum PaginationStrategy { + /*! + * Attempt to put the specified set of packets into a single Ogg packet. + * If the sum of the packet data is greater than will fit into a single + * Ogg page -- 65280 bytes -- this will fall back to repagination using + * the recommended page sizes. + */ + SinglePagePerGroup, + /*! + * Split the packet or group of packets into pages that conform to the + * sizes recommended in the Ogg standard. + */ + Repaginate + }; + + /*! + * Pack \a packets into Ogg pages using the \a strategy for pagination. + * The page number indicator inside of the rendered packets will start + * with \a firstPage and be incremented for each page rendered. + * \a containsLastPacket should be set to true if \a packets contains the + * last page in the stream and will set the appropriate flag in the last + * rendered Ogg page's header. \a streamSerialNumber should be set to + * the serial number for this stream. + * + * \note The "absolute granule position" is currently always zeroed using + * this method as this suffices for the comment headers. + * + * \warning The pages returned by this method must be deleted by the user. + * You can use List::setAutoDelete(true) to set these pages to be + * automatically deleted when this list passes out of scope. + * + * \see PaginationStrategy + * \see List::setAutoDelete() + */ + static List paginate(const ByteVectorList &packets, + PaginationStrategy strategy, + unsigned int streamSerialNumber, + int firstPage, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + protected: + /*! + * Creates an Ogg packet based on the data in \a packets. The page number + * for each page will be set to \a pageNumber. + */ + Page(const ByteVectorList &packets, + unsigned int streamSerialNumber, + int pageNumber, + bool firstPacketContinued = false, + bool lastPacketCompleted = true, + bool containsLastPacket = false); + + private: + Page(const Page &); + Page &operator=(const Page &); + + class PagePrivate; + PagePrivate *d; + }; + } +} +#endif diff --git a/external/taglib/source/ogg/oggpageheader.cpp b/external/taglib/source/ogg/oggpageheader.cpp new file mode 100644 index 0000000..b867567 --- /dev/null +++ b/external/taglib/source/ogg/oggpageheader.cpp @@ -0,0 +1,312 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include + +#include "oggpageheader.h" +#include "oggfile.h" + +using namespace TagLib; + +class Ogg::PageHeader::PageHeaderPrivate +{ +public: + PageHeaderPrivate() : + isValid(false), + firstPacketContinued(false), + lastPacketCompleted(false), + firstPageOfStream(false), + lastPageOfStream(false), + absoluteGranularPosition(0), + streamSerialNumber(0), + pageSequenceNumber(-1), + size(0), + dataSize(0) {} + + bool isValid; + List packetSizes; + bool firstPacketContinued; + bool lastPacketCompleted; + bool firstPageOfStream; + bool lastPageOfStream; + long long absoluteGranularPosition; + unsigned int streamSerialNumber; + int pageSequenceNumber; + int size; + int dataSize; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) : + d(new PageHeaderPrivate()) +{ + if(file && pageOffset >= 0) + read(file, pageOffset); +} + +Ogg::PageHeader::~PageHeader() +{ + delete d; +} + +bool Ogg::PageHeader::isValid() const +{ + return d->isValid; +} + +List Ogg::PageHeader::packetSizes() const +{ + return d->packetSizes; +} + +void Ogg::PageHeader::setPacketSizes(const List &sizes) +{ + d->packetSizes = sizes; +} + +bool Ogg::PageHeader::firstPacketContinued() const +{ + return d->firstPacketContinued; +} + +void Ogg::PageHeader::setFirstPacketContinued(bool continued) +{ + d->firstPacketContinued = continued; +} + +bool Ogg::PageHeader::lastPacketCompleted() const +{ + return d->lastPacketCompleted; +} + +void Ogg::PageHeader::setLastPacketCompleted(bool completed) +{ + d->lastPacketCompleted = completed; +} + +bool Ogg::PageHeader::firstPageOfStream() const +{ + return d->firstPageOfStream; +} + +void Ogg::PageHeader::setFirstPageOfStream(bool first) +{ + d->firstPageOfStream = first; +} + +bool Ogg::PageHeader::lastPageOfStream() const +{ + return d->lastPageOfStream; +} + +void Ogg::PageHeader::setLastPageOfStream(bool last) +{ + d->lastPageOfStream = last; +} + +long long Ogg::PageHeader::absoluteGranularPosition() const +{ + return d->absoluteGranularPosition; +} + +void Ogg::PageHeader::setAbsoluteGranularPosition(long long agp) +{ + d->absoluteGranularPosition = agp; +} + +int Ogg::PageHeader::pageSequenceNumber() const +{ + return d->pageSequenceNumber; +} + +void Ogg::PageHeader::setPageSequenceNumber(int sequenceNumber) +{ + d->pageSequenceNumber = sequenceNumber; +} + +unsigned int Ogg::PageHeader::streamSerialNumber() const +{ + return d->streamSerialNumber; +} + +void Ogg::PageHeader::setStreamSerialNumber(unsigned int n) +{ + d->streamSerialNumber = n; +} + +int Ogg::PageHeader::size() const +{ + return d->size; +} + +int Ogg::PageHeader::dataSize() const +{ + return d->dataSize; +} + +ByteVector Ogg::PageHeader::render() const +{ + ByteVector data; + + // capture pattern + + data.append("OggS"); + + // stream structure version + + data.append(char(0)); + + // header type flag + + std::bitset<8> flags; + flags[0] = d->firstPacketContinued; + flags[1] = d->pageSequenceNumber == 0; + flags[2] = d->lastPageOfStream; + + data.append(char(flags.to_ulong())); + + // absolute granular position + + data.append(ByteVector::fromLongLong(d->absoluteGranularPosition, false)); + + // stream serial number + + data.append(ByteVector::fromUInt(d->streamSerialNumber, false)); + + // page sequence number + + data.append(ByteVector::fromUInt(d->pageSequenceNumber, false)); + + // checksum -- this is left empty and should be filled in by the Ogg::Page + // class + + data.append(ByteVector(4, 0)); + + // page segment count and page segment table + + ByteVector pageSegments = lacingValues(); + + data.append(static_cast(pageSegments.size())); + data.append(pageSegments); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) +{ + file->seek(pageOffset); + + // An Ogg page header is at least 27 bytes, so we'll go ahead and read that + // much and then get the rest when we're ready for it. + + const ByteVector data = file->readBlock(27); + + // Sanity check -- make sure that we were in fact able to read as much data as + // we asked for and that the page begins with "OggS". + + if(data.size() != 27 || !data.startsWith("OggS")) { + debug("Ogg::PageHeader::read() -- error reading page header"); + return; + } + + const std::bitset<8> flags(data[5]); + + d->firstPacketContinued = flags.test(0); + d->firstPageOfStream = flags.test(1); + d->lastPageOfStream = flags.test(2); + + d->absoluteGranularPosition = data.toLongLong(6, false); + d->streamSerialNumber = data.toUInt(14, false); + d->pageSequenceNumber = data.toUInt(18, false); + + // Byte number 27 is the number of page segments, which is the only variable + // length portion of the page header. After reading the number of page + // segments we'll then read in the corresponding data for this count. + + int pageSegmentCount = static_cast(data[26]); + + const ByteVector pageSegments = file->readBlock(pageSegmentCount); + + // Another sanity check. + + if(pageSegmentCount < 1 || int(pageSegments.size()) != pageSegmentCount) + return; + + // The base size of an Ogg page 27 bytes plus the number of lacing values. + + d->size = 27 + pageSegmentCount; + + int packetSize = 0; + + for(int i = 0; i < pageSegmentCount; i++) { + d->dataSize += static_cast(pageSegments[i]); + packetSize += static_cast(pageSegments[i]); + + if(static_cast(pageSegments[i]) < 255) { + d->packetSizes.append(packetSize); + packetSize = 0; + } + } + + if(packetSize > 0) { + d->packetSizes.append(packetSize); + d->lastPacketCompleted = false; + } + else + d->lastPacketCompleted = true; + + d->isValid = true; +} + +ByteVector Ogg::PageHeader::lacingValues() const +{ + ByteVector data; + + for(List::ConstIterator it = d->packetSizes.begin(); it != d->packetSizes.end(); ++it) { + + // The size of a packet in an Ogg page is indicated by a series of "lacing + // values" where the sum of the values is the packet size in bytes. Each of + // these values is a byte. A value of less than 255 (0xff) indicates the end + // of the packet. + + data.resize(data.size() + (*it / 255), '\xff'); + + if(it != --d->packetSizes.end() || d->lastPacketCompleted) + data.append(static_cast(*it % 255)); + } + + return data; +} diff --git a/external/taglib/source/ogg/oggpageheader.h b/external/taglib/source/ogg/oggpageheader.h new file mode 100644 index 0000000..571155f --- /dev/null +++ b/external/taglib/source/ogg/oggpageheader.h @@ -0,0 +1,232 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OGGPAGEHEADER_H +#define TAGLIB_OGGPAGEHEADER_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + namespace Ogg { + + class File; + + //! An implementation of the page headers associated with each Ogg::Page + + /*! + * This class implements Ogg page headers which contain the information + * about Ogg pages needed to break them into packets which can be passed on + * to the codecs. + */ + + class TAGLIB_EXPORT PageHeader + { + public: + /*! + * Reads a PageHeader from \a file starting at \a pageOffset. The defaults + * create a page with no (and as such, invalid) data that must be set + * later. + */ + PageHeader(File *file = 0, long pageOffset = -1); + + /*! + * Deletes this instance of the PageHeader. + */ + virtual ~PageHeader(); + + /*! + * Returns true if the header parsed properly and is valid. + */ + bool isValid() const; + + /*! + * Ogg pages contain a list of packets (which are used by the contained + * codecs). The sizes of these pages is encoded in the page header. This + * returns a list of the packet sizes in bytes. + * + * \see setPacketSizes() + */ + List packetSizes() const; + + /*! + * Sets the sizes of the packets in this page to \a sizes. Internally this + * updates the lacing values in the header. + * + * \see packetSizes() + */ + void setPacketSizes(const List &sizes); + + /*! + * Some packets can be continued across multiple pages. If the + * first packet in the current page is a continuation this will return + * true. If this is page starts with a new packet this will return false. + * + * \see lastPacketCompleted() + * \see setFirstPacketContinued() + */ + bool firstPacketContinued() const; + + /*! + * Sets the internal flag indicating if the first packet in this page is + * continued to \a continued. + * + * \see firstPacketContinued() + */ + void setFirstPacketContinued(bool continued); + + /*! + * Returns true if the last packet of this page is completely contained in + * this page. + * + * \see firstPacketContinued() + * \see setLastPacketCompleted() + */ + bool lastPacketCompleted() const; + + /*! + * Sets the internal flag indicating if the last packet in this page is + * complete to \a completed. + * + * \see lastPacketCompleted() + */ + void setLastPacketCompleted(bool completed); + + /*! + * This returns true if this is the first page of the Ogg (logical) stream. + * + * \see setFirstPageOfStream() + */ + bool firstPageOfStream() const; + + /*! + * Marks this page as the first page of the Ogg stream. + * + * \see firstPageOfStream() + */ + void setFirstPageOfStream(bool first); + + /*! + * This returns true if this is the last page of the Ogg (logical) stream. + * + * \see setLastPageOfStream() + */ + bool lastPageOfStream() const; + + /*! + * Marks this page as the last page of the Ogg stream. + * + * \see lastPageOfStream() + */ + void setLastPageOfStream(bool last); + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. In the case of Vorbis this contains the PCM + * value and is used to calculate the length of the stream. + * + * \see setAbsoluteGranularPosition() + */ + long long absoluteGranularPosition() const; + + /*! + * A special value of containing the position of the packet to be + * interpreted by the codec. It is only supported here so that it may be + * copied from one page to another. + * + * \see absoluteGranularPosition() + */ + void setAbsoluteGranularPosition(long long agp); + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This returns the serial number of + * the stream associated with this packet. + * + * \see setStreamSerialNumber() + */ + unsigned int streamSerialNumber() const; + + /*! + * Every Ogg logical stream is given a random serial number which is common + * to every page in that logical stream. This sets this pages serial + * number. This method should be used when adding new pages to a logical + * stream. + * + * \see streamSerialNumber() + */ + void setStreamSerialNumber(unsigned int n); + + /*! + * Returns the index of the page within the Ogg stream. This helps make it + * possible to determine if pages have been lost. + * + * \see setPageSequenceNumber() + */ + int pageSequenceNumber() const; + + /*! + * Sets the page's position in the stream to \a sequenceNumber. + * + * \see pageSequenceNumber() + */ + void setPageSequenceNumber(int sequenceNumber); + + /*! + * Returns the complete header size. + */ + int size() const; + + /*! + * Returns the size of the data portion of the page -- i.e. the size of the + * page less the header size. + */ + int dataSize() const; + + /*! + * Render the page header to binary data. + * + * \note The checksum -- bytes 22 - 25 -- will be left empty and must be + * filled in when rendering the entire page. + */ + ByteVector render() const; + + private: + PageHeader(const PageHeader &); + PageHeader &operator=(const PageHeader &); + + void read(Ogg::File *file, long pageOffset); + ByteVector lacingValues() const; + + class PageHeaderPrivate; + PageHeaderPrivate *d; + }; + + } +} + +#endif diff --git a/external/taglib/source/ogg/opus/opusfile.cpp b/external/taglib/source/ogg/opus/opusfile.cpp new file mode 100644 index 0000000..d4f191a --- /dev/null +++ b/external/taglib/source/ogg/opus/opusfile.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "opusfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Opus::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool Ogg::Opus::File::isSupported(IOStream *stream) +{ + // An Opus file has IDs "OggS" and "OpusHead" somewhere. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); + return (buffer.find("OggS") >= 0 && buffer.find("OpusHead") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + Ogg::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + Ogg::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Opus::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Opus::File::tag() const +{ + return d->comment; +} + +PropertyMap Opus::File::properties() const +{ + return d->comment->properties(); +} + +PropertyMap Opus::File::setProperties(const PropertyMap &properties) +{ + return d->comment->setProperties(properties); +} + +Opus::Properties *Opus::File::audioProperties() const +{ + return d->properties; +} + +bool Opus::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment(); + + setPacket(1, ByteVector("OpusTags", 8) + d->comment->render(false)); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Opus::File::read(bool readProperties) +{ + ByteVector opusHeaderData = packet(0); + + if(!opusHeaderData.startsWith("OpusHead")) { + setValid(false); + debug("Opus::File::read() -- invalid Opus identification header"); + return; + } + + ByteVector commentHeaderData = packet(1); + + if(!commentHeaderData.startsWith("OpusTags")) { + setValid(false); + debug("Opus::File::read() -- invalid Opus tags header"); + return; + } + + d->comment = new Ogg::XiphComment(commentHeaderData.mid(8)); + + if(readProperties) + d->properties = new Properties(this); +} diff --git a/external/taglib/source/ogg/opus/opusfile.h b/external/taglib/source/ogg/opus/opusfile.h new file mode 100644 index 0000000..0e094ea --- /dev/null +++ b/external/taglib/source/ogg/opus/opusfile.h @@ -0,0 +1,138 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OPUSFILE_H +#define TAGLIB_OPUSFILE_H + +#include "oggfile.h" +#include "xiphcomment.h" + +#include "opusproperties.h" + +namespace TagLib { + + namespace Ogg { + + //! A namespace containing classes for Opus metadata + + namespace Opus { + + //! An implementation of Ogg::File with Opus specific methods + + /*! + * This is the central class in the Ogg Opus metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Opus specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs an Opus file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an Opus file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Opus::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as an Opus + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/ogg/opus/opusproperties.cpp b/external/taglib/source/ogg/opus/opusproperties.cpp new file mode 100644 index 0000000..b60cc01 --- /dev/null +++ b/external/taglib/source/ogg/opus/opusproperties.cpp @@ -0,0 +1,183 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include "opusproperties.h" +#include "opusfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Opus::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + inputSampleRate(0), + channels(0), + opusVersion(0) {} + + int length; + int bitrate; + int inputSampleRate; + int channels; + int opusVersion; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Opus::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +Opus::Properties::~Properties() +{ + delete d; +} + +int Opus::Properties::length() const +{ + return lengthInSeconds(); +} + +int Ogg::Opus::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int Ogg::Opus::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int Opus::Properties::bitrate() const +{ + return d->bitrate; +} + +int Opus::Properties::sampleRate() const +{ + // Opus can decode any stream at a sample rate of 8, 12, 16, 24, or 48 kHz, + // so there is no single sample rate. Let's assume it's the highest + // possible. + return 48000; +} + +int Opus::Properties::channels() const +{ + return d->channels; +} + +int Opus::Properties::inputSampleRate() const +{ + return d->inputSampleRate; +} + +int Opus::Properties::opusVersion() const +{ + return d->opusVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Opus::Properties::read(File *file) +{ + // Get the identification header from the Ogg implementation. + + // http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1 + + const ByteVector data = file->packet(0); + + // *Magic Signature* + unsigned int pos = 8; + + // *Version* (8 bits, unsigned) + d->opusVersion = static_cast(data.at(pos)); + pos += 1; + + // *Output Channel Count* 'C' (8 bits, unsigned) + d->channels = static_cast(data.at(pos)); + pos += 1; + + // *Pre-skip* (16 bits, unsigned, little endian) + const unsigned short preSkip = data.toUShort(pos, false); + pos += 2; + + // *Input Sample Rate* (32 bits, unsigned, little endian) + d->inputSampleRate = data.toUInt(pos, false); + pos += 4; + + // *Output Gain* (16 bits, signed, little endian) + pos += 2; + + // *Channel Mapping Family* (8 bits, unsigned) + pos += 1; + + const Ogg::PageHeader *first = file->firstPageHeader(); + const Ogg::PageHeader *last = file->lastPageHeader(); + + if(first && last) { + const long long start = first->absoluteGranularPosition(); + const long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0) { + const long long frameCount = (end - start - preSkip); + + if(frameCount > 0) { + const double length = frameCount * 1000.0 / 48000.0; + long fileLengthWithoutOverhead = file->length(); + // Ignore the two mandatory header packets, see "3. Packet Organization" + // in https://tools.ietf.org/html/rfc7845.html + for (unsigned int i = 0; i < 2; ++i) { + fileLengthWithoutOverhead -= file->packet(i).size(); + } + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(fileLengthWithoutOverhead * 8.0 / length + 0.5); + } + } + else { + debug("Opus::Properties::read() -- The PCM values for the start or " + "end of this file was incorrect."); + } + } + else + debug("Opus::Properties::read() -- Could not find valid first and last Ogg pages."); +} diff --git a/external/taglib/source/ogg/opus/opusproperties.h b/external/taglib/source/ogg/opus/opusproperties.h new file mode 100644 index 0000000..2e44dea --- /dev/null +++ b/external/taglib/source/ogg/opus/opusproperties.h @@ -0,0 +1,134 @@ +/*************************************************************************** + copyright : (C) 2012 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_OPUSPROPERTIES_H +#define TAGLIB_OPUSPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace Ogg { + + namespace Opus { + + class File; + + //! An implementation of audio property reading for Ogg Opus + + /*! + * This reads the data from an Ogg Opus stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Opus::Properties with the data read from the + * Opus::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this Opus::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + * + * \note Always returns 48000, because Opus can decode any stream at a + * sample rate of 8, 12, 16, 24, or 48 kHz, + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * The Opus codec supports decoding at multiple sample rates, there is no + * single sample rate of the encoded stream. This returns the sample rate + * of the original audio stream. + */ + int inputSampleRate() const; + + /*! + * Returns the Opus version, in the range 0...255. + */ + int opusVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/ogg/speex/speexfile.cpp b/external/taglib/source/ogg/speex/speexfile.cpp new file mode 100644 index 0000000..394cb17 --- /dev/null +++ b/external/taglib/source/ogg/speex/speexfile.cpp @@ -0,0 +1,144 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "speexfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Speex::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool Ogg::Speex::File::isSupported(IOStream *stream) +{ + // A Speex file has IDs "OggS" and "Speex " somewhere. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); + return (buffer.find("OggS") >= 0 && buffer.find("Speex ") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + Ogg::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + Ogg::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Speex::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Speex::File::tag() const +{ + return d->comment; +} + +PropertyMap Speex::File::properties() const +{ + return d->comment->properties(); +} + +PropertyMap Speex::File::setProperties(const PropertyMap &properties) +{ + return d->comment->setProperties(properties); +} + +Speex::Properties *Speex::File::audioProperties() const +{ + return d->properties; +} + +bool Speex::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment(); + + setPacket(1, d->comment->render()); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::File::read(bool readProperties) +{ + ByteVector speexHeaderData = packet(0); + + if(!speexHeaderData.startsWith("Speex ")) { + debug("Speex::File::read() -- invalid Speex identification header"); + setValid(false); + return; + } + + ByteVector commentHeaderData = packet(1); + + d->comment = new Ogg::XiphComment(commentHeaderData); + + if(readProperties) + d->properties = new Properties(this); +} diff --git a/external/taglib/source/ogg/speex/speexfile.h b/external/taglib/source/ogg/speex/speexfile.h new file mode 100644 index 0000000..1be7113 --- /dev/null +++ b/external/taglib/source/ogg/speex/speexfile.h @@ -0,0 +1,138 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include "oggfile.h" +#include "xiphcomment.h" + +#include "speexproperties.h" + +namespace TagLib { + + namespace Ogg { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs a Speex file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a Speex file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns whether or not the given \a stream can be opened as a Speex + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/ogg/speex/speexproperties.cpp b/external/taglib/source/ogg/speex/speexproperties.cpp new file mode 100644 index 0000000..b7a11cc --- /dev/null +++ b/external/taglib/source/ogg/speex/speexproperties.cpp @@ -0,0 +1,207 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include "speexproperties.h" +#include "speexfile.h" + +using namespace TagLib; +using namespace TagLib::Ogg; + +class Speex::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + bitrateNominal(0), + sampleRate(0), + channels(0), + speexVersion(0), + vbr(false), + mode(0) {} + + int length; + int bitrate; + int bitrateNominal; + int sampleRate; + int channels; + int speexVersion; + bool vbr; + int mode; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +Speex::Properties::~Properties() +{ + delete d; +} + +int Speex::Properties::length() const +{ + return lengthInSeconds(); +} + +int Speex::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int Speex::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int Speex::Properties::bitrate() const +{ + return d->bitrate; +} + +int Speex::Properties::bitrateNominal() const +{ + return d->bitrateNominal; +} + +int Speex::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Speex::Properties::channels() const +{ + return d->channels; +} + +int Speex::Properties::speexVersion() const +{ + return d->speexVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::Properties::read(File *file) +{ + // Get the identification header from the Ogg implementation. + + const ByteVector data = file->packet(0); + if(data.size() < 64) { + debug("Speex::Properties::read() -- data is too short."); + return; + } + + unsigned int pos = 28; + + // speex_version_id; /**< Version for Speex (for checking compatibility) */ + d->speexVersion = data.toUInt(pos, false); + pos += 4; + + // header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + pos += 4; + + // rate; /**< Sampling rate used */ + d->sampleRate = data.toUInt(pos, false); + pos += 4; + + // mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + d->mode = data.toUInt(pos, false); + pos += 4; + + // mode_bitstream_version; /**< Version ID of the bit-stream */ + pos += 4; + + // nb_channels; /**< Number of channels encoded */ + d->channels = data.toUInt(pos, false); + pos += 4; + + // bitrate; /**< Bit-rate used */ + d->bitrateNominal = data.toUInt(pos, false); + pos += 4; + + // frame_size; /**< Size of frames */ + // unsigned int frameSize = data.mid(pos, 4).toUInt(false); + pos += 4; + + // vbr; /**< 1 for a VBR encoding, 0 otherwise */ + d->vbr = data.toUInt(pos, false) == 1; + pos += 4; + + // frames_per_packet; /**< Number of frames stored per Ogg packet */ + // unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false); + + const Ogg::PageHeader *first = file->firstPageHeader(); + const Ogg::PageHeader *last = file->lastPageHeader(); + + if(first && last) { + const long long start = first->absoluteGranularPosition(); + const long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) { + const long long frameCount = end - start; + + if(frameCount > 0) { + const double length = frameCount * 1000.0 / d->sampleRate; + long fileLengthWithoutOverhead = file->length(); + // Ignore the two header packets, see "Ogg file format" in + // https://www.speex.org/docs/manual/speex-manual/node8.html + for (unsigned int i = 0; i < 2; ++i) { + fileLengthWithoutOverhead -= file->packet(i).size(); + } + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(fileLengthWithoutOverhead * 8.0 / length + 0.5); + } + } + else { + debug("Speex::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); + } + } + else + debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages."); + + // Alternative to the actual average bitrate. + + if(d->bitrate == 0 && d->bitrateNominal > 0) + d->bitrate = static_cast(d->bitrateNominal / 1000.0 + 0.5); +} diff --git a/external/taglib/source/ogg/speex/speexproperties.h b/external/taglib/source/ogg/speex/speexproperties.h new file mode 100644 index 0000000..3f5a20f --- /dev/null +++ b/external/taglib/source/ogg/speex/speexproperties.h @@ -0,0 +1,129 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace Ogg { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Speex::Properties with the data read from the + * Speex::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this Speex::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the nominal bit rate as read from the Speex header in kb/s. + */ + int bitrateNominal() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the Speex version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/ogg/vorbis/vorbisfile.cpp b/external/taglib/source/ogg/vorbis/vorbisfile.cpp new file mode 100644 index 0000000..b4f221a --- /dev/null +++ b/external/taglib/source/ogg/vorbis/vorbisfile.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "vorbisfile.h" + +using namespace TagLib; + +class Vorbis::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +namespace TagLib { + /*! + * Vorbis headers can be found with one type ID byte and the string "vorbis" in + * an Ogg stream. 0x03 indicates the comment header. + */ + static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', 0 }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool Vorbis::File::isSupported(IOStream *stream) +{ + // An Ogg Vorbis file has IDs "OggS" and "\x01vorbis" somewhere. + + const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false); + return (buffer.find("OggS") >= 0 && buffer.find("\x01vorbis") >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Vorbis::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + Ogg::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Vorbis::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + Ogg::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +Vorbis::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Vorbis::File::tag() const +{ + return d->comment; +} + +PropertyMap Vorbis::File::properties() const +{ + return d->comment->properties(); +} + +PropertyMap Vorbis::File::setProperties(const PropertyMap &properties) +{ + return d->comment->setProperties(properties); +} + +Vorbis::Properties *Vorbis::File::audioProperties() const +{ + return d->properties; +} + +bool Vorbis::File::save() +{ + ByteVector v(vorbisCommentHeaderID); + + if(!d->comment) + d->comment = new Ogg::XiphComment(); + v.append(d->comment->render()); + + setPacket(1, v); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Vorbis::File::read(bool readProperties) +{ + ByteVector commentHeaderData = packet(1); + + if(commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) { + debug("Vorbis::File::read() - Could not find the Vorbis comment header."); + setValid(false); + return; + } + + d->comment = new Ogg::XiphComment(commentHeaderData.mid(7)); + + if(readProperties) + d->properties = new Properties(this); +} diff --git a/external/taglib/source/ogg/vorbis/vorbisfile.h b/external/taglib/source/ogg/vorbis/vorbisfile.h new file mode 100644 index 0000000..04c0c04 --- /dev/null +++ b/external/taglib/source/ogg/vorbis/vorbisfile.h @@ -0,0 +1,157 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISFILE_H +#define TAGLIB_VORBISFILE_H + +#include "taglib_export.h" +#include "oggfile.h" +#include "xiphcomment.h" + +#include "vorbisproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + //! A namespace containing classes for Vorbis metadata + + namespace Vorbis { + + + //! An implementation of Ogg::File with Vorbis specific methods + + /*! + * This is the central class in the Ogg Vorbis metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Vorbis specifically. + */ + + class TAGLIB_EXPORT File : public Ogg::File + { + public: + /*! + * Constructs a Vorbis file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a Vorbis file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + + /*! + * Implements the unified property interface -- export function. + * This forwards directly to XiphComment::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified tag dictionary interface -- import function. + * Like properties(), this is a forwarder to the file's XiphComment. + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the Vorbis::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Check if the given \a stream can be opened as an Ogg Vorbis file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::Vorbis::File File; } } +#endif + +} + +#endif diff --git a/external/taglib/source/ogg/vorbis/vorbisproperties.cpp b/external/taglib/source/ogg/vorbis/vorbisproperties.cpp new file mode 100644 index 0000000..4000c25 --- /dev/null +++ b/external/taglib/source/ogg/vorbis/vorbisproperties.cpp @@ -0,0 +1,211 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include "vorbisproperties.h" +#include "vorbisfile.h" + +using namespace TagLib; + +class Vorbis::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + vorbisVersion(0), + bitrateMaximum(0), + bitrateNominal(0), + bitrateMinimum(0) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int vorbisVersion; + int bitrateMaximum; + int bitrateNominal; + int bitrateMinimum; +}; + +namespace TagLib { + /*! + * Vorbis headers can be found with one type ID byte and the string "vorbis" in + * an Ogg stream. 0x01 indicates the setup header. + */ + static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 }; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Vorbis::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +Vorbis::Properties::~Properties() +{ + delete d; +} + +int Vorbis::Properties::length() const +{ + return lengthInSeconds(); +} + +int Vorbis::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int Vorbis::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int Vorbis::Properties::bitrate() const +{ + return d->bitrate; +} + +int Vorbis::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Vorbis::Properties::channels() const +{ + return d->channels; +} + +int Vorbis::Properties::vorbisVersion() const +{ + return d->vorbisVersion; +} + +int Vorbis::Properties::bitrateMaximum() const +{ + return d->bitrateMaximum; +} + +int Vorbis::Properties::bitrateNominal() const +{ + return d->bitrateNominal; +} + +int Vorbis::Properties::bitrateMinimum() const +{ + return d->bitrateMinimum; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Vorbis::Properties::read(File *file) +{ + // Get the identification header from the Ogg implementation. + + const ByteVector data = file->packet(0); + if(data.size() < 28) { + debug("Vorbis::Properties::read() -- data is too short."); + return; + } + + unsigned int pos = 0; + + if(data.mid(pos, 7) != vorbisSetupHeaderID) { + debug("Vorbis::Properties::read() -- invalid Vorbis identification header"); + return; + } + + pos += 7; + + d->vorbisVersion = data.toUInt(pos, false); + pos += 4; + + d->channels = static_cast(data[pos]); + pos += 1; + + d->sampleRate = data.toUInt(pos, false); + pos += 4; + + d->bitrateMaximum = data.toUInt(pos, false); + pos += 4; + + d->bitrateNominal = data.toUInt(pos, false); + pos += 4; + + d->bitrateMinimum = data.toUInt(pos, false); + pos += 4; + + // Find the length of the file. See http://wiki.xiph.org/VorbisStreamLength/ + // for my notes on the topic. + + const Ogg::PageHeader *first = file->firstPageHeader(); + const Ogg::PageHeader *last = file->lastPageHeader(); + + if(first && last) { + const long long start = first->absoluteGranularPosition(); + const long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) { + const long long frameCount = end - start; + + if(frameCount > 0) { + const double length = frameCount * 1000.0 / d->sampleRate; + long fileLengthWithoutOverhead = file->length(); + // Ignore the three initial header packets, see "1.3.1. Decode Setup" in + // https://xiph.org/vorbis/doc/Vorbis_I_spec.html + for (unsigned int i = 0; i < 3; ++i) { + fileLengthWithoutOverhead -= file->packet(i).size(); + } + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(fileLengthWithoutOverhead * 8.0 / length + 0.5); + } + } + else { + debug("Vorbis::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); + } + } + else + debug("Vorbis::Properties::read() -- Could not find valid first and last Ogg pages."); + + // Alternative to the actual average bitrate. + + if(d->bitrate == 0 && d->bitrateNominal > 0) + d->bitrate = static_cast(d->bitrateNominal / 1000.0 + 0.5); +} diff --git a/external/taglib/source/ogg/vorbis/vorbisproperties.h b/external/taglib/source/ogg/vorbis/vorbisproperties.h new file mode 100644 index 0000000..472e039 --- /dev/null +++ b/external/taglib/source/ogg/vorbis/vorbisproperties.h @@ -0,0 +1,160 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISPROPERTIES_H +#define TAGLIB_VORBISPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + +/* + * This is just to make this appear to be in the Ogg namespace in the + * documentation. The typedef below will make this work with the current code. + * In the next BIC version of TagLib this will be really moved into the Ogg + * namespace. + */ + +#ifdef DOXYGEN + namespace Ogg { +#endif + + namespace Vorbis { + + class File; + + //! An implementation of audio property reading for Ogg Vorbis + + /*! + * This reads the data from an Ogg Vorbis stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int vorbisVersion() const; + + /*! + * Returns the maximum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMaximum() const; + + /*! + * Returns the nominal bitrate as read from the Vorbis identification + * header. + */ + int bitrateNominal() const; + + /*! + * Returns the minimum bitrate as read from the Vorbis identification + * header. + */ + int bitrateMinimum() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +/* + * To keep compatibility with the current version put Vorbis in the Ogg namespace + * only in the docs and provide a typedef to make it work. In the next BIC + * version this will be removed and it will only exist in the Ogg namespace. + */ + +#ifdef DOXYGEN + } +#else + namespace Ogg { namespace Vorbis { typedef TagLib::AudioProperties AudioProperties; } } +#endif + +} + +#endif diff --git a/external/taglib/source/ogg/xiphcomment.cpp b/external/taglib/source/ogg/xiphcomment.cpp new file mode 100644 index 0000000..b53098f --- /dev/null +++ b/external/taglib/source/ogg/xiphcomment.cpp @@ -0,0 +1,515 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include +#include + +using namespace TagLib; + +namespace +{ + typedef Ogg::FieldListMap::Iterator FieldIterator; + typedef Ogg::FieldListMap::ConstIterator FieldConstIterator; + + typedef List PictureList; + typedef PictureList::Iterator PictureIterator; + typedef PictureList::Iterator PictureConstIterator; +} + +class Ogg::XiphComment::XiphCommentPrivate +{ +public: + XiphCommentPrivate() + { + pictureList.setAutoDelete(true); + } + + FieldListMap fieldListMap; + String vendorID; + String commentField; + PictureList pictureList; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Ogg::XiphComment::XiphComment() : + d(new XiphCommentPrivate()) +{ +} + +Ogg::XiphComment::XiphComment(const ByteVector &data) : + d(new XiphCommentPrivate()) +{ + parse(data); +} + +Ogg::XiphComment::~XiphComment() +{ + delete d; +} + +String Ogg::XiphComment::title() const +{ + StringList value = d->fieldListMap.value("TITLE"); + return value.isEmpty() ? String() : value.toString(); +} + +String Ogg::XiphComment::artist() const +{ + StringList value = d->fieldListMap.value("ARTIST"); + return value.isEmpty() ? String() : value.toString(); +} + +String Ogg::XiphComment::album() const +{ + StringList value = d->fieldListMap.value("ALBUM"); + return value.isEmpty() ? String() : value.toString(); +} + +String Ogg::XiphComment::comment() const +{ + StringList value = d->fieldListMap.value("DESCRIPTION"); + if(!value.isEmpty()) { + d->commentField = "DESCRIPTION"; + return value.toString(); + } + + value = d->fieldListMap.value("COMMENT"); + if(!value.isEmpty()) { + d->commentField = "COMMENT"; + return value.toString(); + } + + return String(); +} + +String Ogg::XiphComment::genre() const +{ + StringList value = d->fieldListMap.value("GENRE"); + return value.isEmpty() ? String() : value.toString(); +} + +unsigned int Ogg::XiphComment::year() const +{ + StringList value = d->fieldListMap.value("DATE"); + if(!value.isEmpty()) + return value.front().toInt(); + value = d->fieldListMap.value("YEAR"); + if(!value.isEmpty()) + return value.front().toInt(); + return 0; +} + +unsigned int Ogg::XiphComment::track() const +{ + StringList value = d->fieldListMap.value("TRACKNUMBER"); + if(!value.isEmpty()) + return value.front().toInt(); + value = d->fieldListMap.value("TRACKNUM"); + if(!value.isEmpty()) + return value.front().toInt(); + return 0; +} + +void Ogg::XiphComment::setTitle(const String &s) +{ + addField("TITLE", s); +} + +void Ogg::XiphComment::setArtist(const String &s) +{ + addField("ARTIST", s); +} + +void Ogg::XiphComment::setAlbum(const String &s) +{ + addField("ALBUM", s); +} + +void Ogg::XiphComment::setComment(const String &s) +{ + if(d->commentField.isEmpty()) { + if(!d->fieldListMap.value("DESCRIPTION").isEmpty()) + d->commentField = "DESCRIPTION"; + else + d->commentField = "COMMENT"; + } + + addField(d->commentField, s); +} + +void Ogg::XiphComment::setGenre(const String &s) +{ + addField("GENRE", s); +} + +void Ogg::XiphComment::setYear(unsigned int i) +{ + removeFields("YEAR"); + if(i == 0) + removeFields("DATE"); + else + addField("DATE", String::number(i)); +} + +void Ogg::XiphComment::setTrack(unsigned int i) +{ + removeFields("TRACKNUM"); + if(i == 0) + removeFields("TRACKNUMBER"); + else + addField("TRACKNUMBER", String::number(i)); +} + +bool Ogg::XiphComment::isEmpty() const +{ + for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) { + if(!(*it).second.isEmpty()) + return false; + } + + return true; +} + +unsigned int Ogg::XiphComment::fieldCount() const +{ + unsigned int count = 0; + + for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) + count += (*it).second.size(); + + count += d->pictureList.size(); + + return count; +} + +const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const +{ + return d->fieldListMap; +} + +PropertyMap Ogg::XiphComment::properties() const +{ + return d->fieldListMap; +} + +PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties) +{ + // check which keys are to be deleted + StringList toRemove; + for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) + if (!properties.contains(it->first)) + toRemove.append(it->first); + + for(StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it) + removeFields(*it); + + // now go through keys in \a properties and check that the values match those in the xiph comment + PropertyMap invalid; + PropertyMap::ConstIterator it = properties.begin(); + for(; it != properties.end(); ++it) + { + if(!checkKey(it->first)) + invalid.insert(it->first, it->second); + else if(!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) { + const StringList &sl = it->second; + if(sl.isEmpty()) + // zero size string list -> remove the tag with all values + removeFields(it->first); + else { + // replace all strings in the list for the tag + StringList::ConstIterator valueIterator = sl.begin(); + addField(it->first, *valueIterator, true); + ++valueIterator; + for(; valueIterator != sl.end(); ++valueIterator) + addField(it->first, *valueIterator, false); + } + } + } + return invalid; +} + +bool Ogg::XiphComment::checkKey(const String &key) +{ + if(key.size() < 1) + return false; + + // A key may consist of ASCII 0x20 through 0x7D, 0x3D ('=') excluded. + + for(String::ConstIterator it = key.begin(); it != key.end(); it++) { + if(*it < 0x20 || *it > 0x7D || *it == 0x3D) + return false; + } + + return true; +} + +String Ogg::XiphComment::vendorID() const +{ + return d->vendorID; +} + +void Ogg::XiphComment::addField(const String &key, const String &value, bool replace) +{ + if(!checkKey(key)) { + debug("Ogg::XiphComment::addField() - Invalid key. Field not added."); + return; + } + + const String upperKey = key.upper(); + + if(replace) + removeFields(upperKey); + + if(!key.isEmpty() && !value.isEmpty()) + d->fieldListMap[upperKey].append(value); +} + +void Ogg::XiphComment::removeField(const String &key, const String &value) +{ + if(!value.isNull()) + removeFields(key, value); + else + removeFields(key); +} + +void Ogg::XiphComment::removeFields(const String &key) +{ + d->fieldListMap.erase(key.upper()); +} + +void Ogg::XiphComment::removeFields(const String &key, const String &value) +{ + StringList &fields = d->fieldListMap[key.upper()]; + for(StringList::Iterator it = fields.begin(); it != fields.end(); ) { + if(*it == value) + it = fields.erase(it); + else + ++it; + } +} + +void Ogg::XiphComment::removeAllFields() +{ + d->fieldListMap.clear(); +} + +bool Ogg::XiphComment::contains(const String &key) const +{ + return !d->fieldListMap.value(key.upper()).isEmpty(); +} + +void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del) +{ + PictureIterator it = d->pictureList.find(picture); + if(it != d->pictureList.end()) + d->pictureList.erase(it); + + if(del) + delete picture; +} + +void Ogg::XiphComment::removeAllPictures() +{ + d->pictureList.clear(); +} + +void Ogg::XiphComment::addPicture(FLAC::Picture * picture) +{ + d->pictureList.append(picture); +} + +List Ogg::XiphComment::pictureList() +{ + return d->pictureList; +} + +ByteVector Ogg::XiphComment::render() const +{ + return render(true); +} + +ByteVector Ogg::XiphComment::render(bool addFramingBit) const +{ + ByteVector data; + + // Add the vendor ID length and the vendor ID. It's important to use the + // length of the data(String::UTF8) rather than the length of the the string + // since this is UTF8 text and there may be more characters in the data than + // in the UTF16 string. + + ByteVector vendorData = d->vendorID.data(String::UTF8); + + data.append(ByteVector::fromUInt(vendorData.size(), false)); + data.append(vendorData); + + // Add the number of fields. + + data.append(ByteVector::fromUInt(fieldCount(), false)); + + // Iterate over the the field lists. Our iterator returns a + // std::pair where the first String is the field name and + // the StringList is the values associated with that field. + + FieldListMap::ConstIterator it = d->fieldListMap.begin(); + for(; it != d->fieldListMap.end(); ++it) { + + // And now iterate over the values of the current list. + + String fieldName = (*it).first; + StringList values = (*it).second; + + StringList::ConstIterator valuesIt = values.begin(); + for(; valuesIt != values.end(); ++valuesIt) { + ByteVector fieldData = fieldName.data(String::UTF8); + fieldData.append('='); + fieldData.append((*valuesIt).data(String::UTF8)); + + data.append(ByteVector::fromUInt(fieldData.size(), false)); + data.append(fieldData); + } + } + + for(PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) { + ByteVector picture = (*it)->render().toBase64(); + data.append(ByteVector::fromUInt(picture.size() + 23, false)); + data.append("METADATA_BLOCK_PICTURE="); + data.append(picture); + } + + // Append the "framing bit". + + if(addFramingBit) + data.append(char(1)); + + return data; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void Ogg::XiphComment::parse(const ByteVector &data) +{ + // The first thing in the comment data is the vendor ID length, followed by a + // UTF8 string with the vendor ID. + + unsigned int pos = 0; + + const unsigned int vendorLength = data.toUInt(0, false); + pos += 4; + + d->vendorID = String(data.mid(pos, vendorLength), String::UTF8); + pos += vendorLength; + + // Next the number of fields in the comment vector. + + const unsigned int commentFields = data.toUInt(pos, false); + pos += 4; + + if(commentFields > (data.size() - 8) / 4) { + return; + } + + for(unsigned int i = 0; i < commentFields; i++) { + + // Each comment field is in the format "KEY=value" in a UTF8 string and has + // 4 bytes before the text starts that gives the length. + + const unsigned int commentLength = data.toUInt(pos, false); + pos += 4; + + const ByteVector entry = data.mid(pos, commentLength); + pos += commentLength; + + // Don't go past data end + + if(pos > data.size()) + break; + + // Check for field separator + + const int sep = entry.find('='); + if(sep < 1) { + debug("Ogg::XiphComment::parse() - Discarding a field. Separator not found."); + continue; + } + + // Parse the key + + const String key = String(entry.mid(0, sep), String::UTF8).upper(); + if(!checkKey(key)) { + debug("Ogg::XiphComment::parse() - Discarding a field. Invalid key."); + continue; + } + + if(key == "METADATA_BLOCK_PICTURE" || key == "COVERART") { + + // Handle Pictures separately + + const ByteVector picturedata = ByteVector::fromBase64(entry.mid(sep + 1)); + if(picturedata.isEmpty()) { + debug("Ogg::XiphComment::parse() - Discarding a field. Invalid base64 data"); + continue; + } + + if(key[0] == L'M') { + + // Decode FLAC Picture + + FLAC::Picture * picture = new FLAC::Picture(); + if(picture->parse(picturedata)) { + d->pictureList.append(picture); + } + else { + delete picture; + debug("Ogg::XiphComment::parse() - Failed to decode FLAC Picture block"); + } + } + else { + + // Assume it's some type of image file + + FLAC::Picture * picture = new FLAC::Picture(); + picture->setData(picturedata); + picture->setMimeType("image/"); + picture->setType(FLAC::Picture::Other); + d->pictureList.append(picture); + } + } + else { + + // Parse the text + + addField(key, String(entry.mid(sep + 1), String::UTF8), false); + } + } +} diff --git a/external/taglib/source/ogg/xiphcomment.h b/external/taglib/source/ogg/xiphcomment.h new file mode 100644 index 0000000..7925fa0 --- /dev/null +++ b/external/taglib/source/ogg/xiphcomment.h @@ -0,0 +1,280 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_VORBISCOMMENT_H +#define TAGLIB_VORBISCOMMENT_H + +#include "tag.h" +#include "tlist.h" +#include "tmap.h" +#include "tstring.h" +#include "tstringlist.h" +#include "tbytevector.h" +#include "flacpicture.h" +#include "taglib_export.h" + +#ifdef _MSC_VER +// Explained at end of tpropertymap.cpp +extern template class TAGLIB_EXPORT TagLib::Map; +#endif + +namespace TagLib { + + namespace Ogg { + + /*! + * A mapping between a list of field names, or keys, and a list of values + * associated with that field. + * + * \see XiphComment::fieldListMap() + */ + typedef Map FieldListMap; + + //! Ogg Vorbis comment implementation + + /*! + * This class is an implementation of the Ogg Vorbis comment specification, + * to be found in section 5 of the Ogg Vorbis specification. Because this + * format is also used in other (currently unsupported) Xiph.org formats, it + * has been made part of a generic implementation rather than being limited + * to strictly Vorbis. + * + * Vorbis comments are a simple vector of keys and values, called fields. + * Multiple values for a given key are supported. + * + * \see fieldListMap() + */ + + class TAGLIB_EXPORT XiphComment : public TagLib::Tag + { + public: + /*! + * Constructs an empty Vorbis comment. + */ + XiphComment(); + + /*! + * Constructs a Vorbis comment from \a data. + */ + XiphComment(const ByteVector &data); + + /*! + * Destroys this instance of the XiphComment. + */ + virtual ~XiphComment(); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns the number of fields present in the comment. + */ + unsigned int fieldCount() const; + + /*! + * Returns a reference to the map of field lists. Because Xiph comments + * support multiple fields with the same key, a pure Map would not work. + * As such this is a Map of string lists, keyed on the comment field name. + * + * The standard set of Xiph/Vorbis fields (which may or may not be + * contained in any specific comment) is: + * + *
    + *
  • TITLE
  • + *
  • VERSION
  • + *
  • ALBUM
  • + *
  • ARTIST
  • + *
  • PERFORMER
  • + *
  • COPYRIGHT
  • + *
  • ORGANIZATION
  • + *
  • DESCRIPTION
  • + *
  • GENRE
  • + *
  • DATE
  • + *
  • LOCATION
  • + *
  • CONTACT
  • + *
  • ISRC
  • + *
+ * + * For a more detailed description of these fields, please see the Ogg + * Vorbis specification, section 5.2.2.1. + * + * \note The Ogg Vorbis comment specification does allow these key values + * to be either upper or lower case. However, it is conventional for them + * to be upper case. As such, TagLib, when parsing a Xiph/Vorbis comment, + * converts all fields to uppercase. When you are using this data + * structure, you will need to specify the field name in upper case. + * + * \warning You should not modify this data structure directly, instead + * use addField() and removeField(). + */ + const FieldListMap &fieldListMap() const; + + /*! + * Implements the unified property interface -- export function. + * The result is a one-to-one match of the Xiph comment, since it is + * completely compatible with the property interface (in fact, a Xiph + * comment is nothing more than a map from tag names to list of values, + * as is the dict interface). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * The tags from the given map will be stored one-to-one in the file, + * except for invalid keys (less than one character, non-ASCII, or + * containing '=' or '~') in which case the according values will + * be contained in the returned PropertyMap. + */ + PropertyMap setProperties(const PropertyMap&); + + /*! + * Check if the given String is a valid Xiph comment key. + */ + static bool checkKey(const String&); + + /*! + * Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the + * most common case always returns "Xiph.Org libVorbis I 20020717". + */ + String vendorID() const; + + /*! + * Add the field specified by \a key with the data \a value. If \a replace + * is true, then all of the other fields with the same key will be removed + * first. + * + * If the field value is empty, the field will be removed. + */ + void addField(const String &key, const String &value, bool replace = true); + + /*! + * Remove the field specified by \a key with the data \a value. If + * \a value is null, all of the fields with the given key will be removed. + * + * \deprecated Using this method may lead to a linkage error. + */ + // BIC: remove and merge with below + TAGLIB_DEPRECATED void removeField(const String &key, const String &value = String()); + + /*! + * Remove all the fields specified by \a key. + * + * \see removeAllFields() + */ + void removeFields(const String &key); + + /*! + * Remove all the fields specified by \a key with the data \a value. + * + * \see removeAllFields() + */ + void removeFields(const String &key, const String &value); + + /*! + * Remove all the fields in the comment. + * + * \see removeFields() + */ + void removeAllFields(); + + /*! + * Returns true if the field is contained within the comment. + * + * \note This is safer than checking for membership in the FieldListMap. + */ + bool contains(const String &key) const; + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + */ + ByteVector render() const; // BIC: remove and merge with below + + /*! + * Renders the comment to a ByteVector suitable for inserting into a file. + * + * If \a addFramingBit is true the standard Vorbis comment framing bit will + * be appended. However some formats (notably FLAC) do not work with this + * in place. + */ + ByteVector render(bool addFramingBit) const; + + + /*! + * Returns a list of pictures attached to the xiph comment. + */ + List pictureList(); + + /*! + * Removes an picture. If \a del is true the picture's memory + * will be freed; if it is false, it must be deleted by the user. + */ + void removePicture(FLAC::Picture *picture, bool del = true); + + /*! + * Remove all pictures. + */ + void removeAllPictures(); + + /*! + * Add a new picture to the comment block. The comment block takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(FLAC::Picture *picture); + + protected: + /*! + * Reads the tag from the file specified in the constructor and fills the + * FieldListMap. + */ + void parse(const ByteVector &data); + + private: + XiphComment(const XiphComment &); + XiphComment &operator=(const XiphComment &); + + class XiphCommentPrivate; + XiphCommentPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/riff/aiff/aifffile.cpp b/external/taglib/source/riff/aiff/aifffile.cpp new file mode 100644 index 0000000..6ef4c9b --- /dev/null +++ b/external/taglib/source/riff/aiff/aifffile.cpp @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "aifffile.h" + +using namespace TagLib; + +class RIFF::AIFF::File::FilePrivate +{ +public: + FilePrivate() : + properties(0), + tag(0), + hasID3v2(false) {} + + ~FilePrivate() + { + delete properties; + delete tag; + } + + Properties *properties; + ID3v2::Tag *tag; + + bool hasID3v2; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool RIFF::AIFF::File::isSupported(IOStream *stream) +{ + // An AIFF file has to start with "FORM????AIFF" or "FORM????AIFC". + + const ByteVector id = Utils::readHeader(stream, 12, false); + return (id.startsWith("FORM") && (id.containsAt("AIFF", 8) || id.containsAt("AIFC", 8))); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::AIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + RIFF::File(file, BigEndian), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +RIFF::AIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + RIFF::File(stream, BigEndian), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +RIFF::AIFF::File::~File() +{ + delete d; +} + +ID3v2::Tag *RIFF::AIFF::File::tag() const +{ + return d->tag; +} + +PropertyMap RIFF::AIFF::File::properties() const +{ + return d->tag->properties(); +} + +void RIFF::AIFF::File::removeUnsupportedProperties(const StringList &unsupported) +{ + d->tag->removeUnsupportedProperties(unsupported); +} + +PropertyMap RIFF::AIFF::File::setProperties(const PropertyMap &properties) +{ + return d->tag->setProperties(properties); +} + +RIFF::AIFF::Properties *RIFF::AIFF::File::audioProperties() const +{ + return d->properties; +} + +bool RIFF::AIFF::File::save() +{ + return save(ID3v2::v4); +} + +bool RIFF::AIFF::File::save(ID3v2::Version version) +{ + if(readOnly()) { + debug("RIFF::AIFF::File::save() -- File is read only."); + return false; + } + + if(!isValid()) { + debug("RIFF::AIFF::File::save() -- Trying to save invalid file."); + return false; + } + + if(d->hasID3v2) { + removeChunk("ID3 "); + removeChunk("id3 "); + d->hasID3v2 = false; + } + + if(tag() && !tag()->isEmpty()) { + setChunkData("ID3 ", d->tag->render(version)); + d->hasID3v2 = true; + } + + return true; +} + +bool RIFF::AIFF::File::hasID3v2Tag() const +{ + return d->hasID3v2; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::AIFF::File::read(bool readProperties) +{ + for(unsigned int i = 0; i < chunkCount(); ++i) { + const ByteVector name = chunkName(i); + if(name == "ID3 " || name == "id3 ") { + if(!d->tag) { + d->tag = new ID3v2::Tag(this, chunkOffset(i)); + d->hasID3v2 = true; + } + else { + debug("RIFF::AIFF::File::read() - Duplicate ID3v2 tag found."); + } + } + } + + if(!d->tag) + d->tag = new ID3v2::Tag(); + + if(readProperties) + d->properties = new Properties(this, Properties::Average); +} diff --git a/external/taglib/source/riff/aiff/aifffile.h b/external/taglib/source/riff/aiff/aifffile.h new file mode 100644 index 0000000..ceac576 --- /dev/null +++ b/external/taglib/source/riff/aiff/aifffile.h @@ -0,0 +1,157 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFFILE_H +#define TAGLIB_AIFFFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "aiffproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of AIFF metadata + + /*! + * This is implementation of AIFF metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace AIFF { + + //! An implementation of TagLib::File with AIFF specific methods + + /*! + * This implements and provides an interface for AIFF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to AIFF files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + /*! + * Constructs an AIFF file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an AIFF file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ + virtual ID3v2::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the AIFF::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Save using a specific ID3v2 version (e.g. v3) + */ + bool save(ID3v2::Version version); + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Check if the given \a stream can be opened as an AIFF file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + friend class Properties; + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/riff/aiff/aiffproperties.cpp b/external/taglib/source/riff/aiff/aiffproperties.cpp new file mode 100644 index 0000000..e1d954f --- /dev/null +++ b/external/taglib/source/riff/aiff/aiffproperties.cpp @@ -0,0 +1,192 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include "aifffile.h" +#include "aiffproperties.h" + +using namespace TagLib; + +class RIFF::AIFF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0), + sampleFrames(0) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; + + ByteVector compressionType; + String compressionName; + + unsigned int sampleFrames; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::AIFF::Properties::Properties(const ByteVector &, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("RIFF::AIFF::Properties::Properties() - This constructor is no longer used."); +} + +RIFF::AIFF::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +RIFF::AIFF::Properties::~Properties() +{ + delete d; +} + +int RIFF::AIFF::Properties::length() const +{ + return lengthInSeconds(); +} + +int RIFF::AIFF::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int RIFF::AIFF::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int RIFF::AIFF::Properties::bitrate() const +{ + return d->bitrate; +} + +int RIFF::AIFF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int RIFF::AIFF::Properties::channels() const +{ + return d->channels; +} + +int RIFF::AIFF::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int RIFF::AIFF::Properties::sampleWidth() const +{ + return bitsPerSample(); +} + +unsigned int RIFF::AIFF::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +bool RIFF::AIFF::Properties::isAiffC() const +{ + return (!d->compressionType.isEmpty()); +} + +ByteVector RIFF::AIFF::Properties::compressionType() const +{ + return d->compressionType; +} + +String RIFF::AIFF::Properties::compressionName() const +{ + return d->compressionName; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::AIFF::Properties::read(File *file) +{ + ByteVector data; + unsigned int streamLength = 0; + for(unsigned int i = 0; i < file->chunkCount(); i++) { + const ByteVector name = file->chunkName(i); + if(name == "COMM") { + if(data.isEmpty()) + data = file->chunkData(i); + else + debug("RIFF::AIFF::Properties::read() - Duplicate 'COMM' chunk found."); + } + else if(name == "SSND") { + if(streamLength == 0) + streamLength = file->chunkDataSize(i) + file->chunkPadding(i); + else + debug("RIFF::AIFF::Properties::read() - Duplicate 'SSND' chunk found."); + } + } + + if(data.size() < 18) { + debug("RIFF::AIFF::Properties::read() - 'COMM' chunk not found or too short."); + return; + } + + if(streamLength == 0) { + debug("RIFF::AIFF::Properties::read() - 'SSND' chunk not found."); + return; + } + + d->channels = data.toShort(0U); + d->sampleFrames = data.toUInt(2U); + d->bitsPerSample = data.toShort(6U); + + const long double sampleRate = data.toFloat80BE(8); + if(sampleRate >= 1.0) + d->sampleRate = static_cast(sampleRate + 0.5); + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } + + if(data.size() >= 23) { + d->compressionType = data.mid(18, 4); + d->compressionName + = String(data.mid(23, static_cast(data[22])), String::Latin1); + } +} diff --git a/external/taglib/source/riff/aiff/aiffproperties.h b/external/taglib/source/riff/aiff/aiffproperties.h new file mode 100644 index 0000000..dbb4c21 --- /dev/null +++ b/external/taglib/source/riff/aiff/aiffproperties.h @@ -0,0 +1,166 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_AIFFPROPERTIES_H +#define TAGLIB_AIFFPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace RIFF { + + namespace AIFF { + + class File; + + //! An implementation of audio property reading for AIFF + + /*! + * This reads the data from an AIFF stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of AIFF::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); + + /*! + * Create an instance of AIFF::Properties with the data read from the + * AIFF::File \a file. + */ + Properties(File *file, ReadStyle style); + + /*! + * Destroys this AIFF::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the number of bits per audio sample. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Returns the number of sample frames + */ + unsigned int sampleFrames() const; + + /*! + * Returns true if the file is in AIFF-C format, false if AIFF format. + */ + bool isAiffC() const; + + /*! + * Returns the compression type of the AIFF-C file. For example, "NONE" for + * not compressed, "ACE2" for ACE 2-to-1. + * + * If the file is in AIFF format, always returns an empty vector. + * + * \see isAiffC() + */ + ByteVector compressionType() const; + + /*! + * Returns the concrete compression name of the AIFF-C file. + * + * If the file is in AIFF format, always returns an empty string. + * + * \see isAiffC() + */ + String compressionName() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/riff/rifffile.cpp b/external/taglib/source/riff/rifffile.cpp new file mode 100644 index 0000000..005551f --- /dev/null +++ b/external/taglib/source/riff/rifffile.cpp @@ -0,0 +1,370 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "rifffile.h" +#include "riffutils.h" + +using namespace TagLib; + +struct Chunk +{ + ByteVector name; + unsigned int offset; + unsigned int size; + unsigned int padding; +}; + +class RIFF::File::FilePrivate +{ +public: + FilePrivate(Endianness endianness) : + endianness(endianness), + size(0), + sizeOffset(0) {} + + const Endianness endianness; + + unsigned int size; + long sizeOffset; + + std::vector chunks; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::File::~File() +{ + delete d; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::File::File(FileName file, Endianness endianness) : + TagLib::File(file), + d(new FilePrivate(endianness)) +{ + if(isOpen()) + read(); +} + +RIFF::File::File(IOStream *stream, Endianness endianness) : + TagLib::File(stream), + d(new FilePrivate(endianness)) +{ + if(isOpen()) + read(); +} + +unsigned int RIFF::File::riffSize() const +{ + return d->size; +} + +unsigned int RIFF::File::chunkCount() const +{ + return static_cast(d->chunks.size()); +} + +unsigned int RIFF::File::chunkDataSize(unsigned int i) const +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::chunkDataSize() - Index out of range. Returning 0."); + return 0; + } + + return d->chunks[i].size; +} + +unsigned int RIFF::File::chunkOffset(unsigned int i) const +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::chunkOffset() - Index out of range. Returning 0."); + return 0; + } + + return d->chunks[i].offset; +} + +unsigned int RIFF::File::chunkPadding(unsigned int i) const +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::chunkPadding() - Index out of range. Returning 0."); + return 0; + } + + return d->chunks[i].padding; +} + +ByteVector RIFF::File::chunkName(unsigned int i) const +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::chunkName() - Index out of range. Returning an empty vector."); + return ByteVector(); + } + + return d->chunks[i].name; +} + +ByteVector RIFF::File::chunkData(unsigned int i) +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::chunkData() - Index out of range. Returning an empty vector."); + return ByteVector(); + } + + seek(d->chunks[i].offset); + return readBlock(d->chunks[i].size); +} + +void RIFF::File::setChunkData(unsigned int i, const ByteVector &data) +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::setChunkData() - Index out of range."); + return; + } + + // Now update the specific chunk + + std::vector::iterator it = d->chunks.begin(); + std::advance(it, i); + + const long long originalSize = static_cast(it->size) + it->padding; + + writeChunk(it->name, data, it->offset - 8, it->size + it->padding + 8); + + it->size = data.size(); + it->padding = data.size() % 2; + + const long long diff = static_cast(it->size) + it->padding - originalSize; + + // Now update the internal offsets + + for(++it; it != d->chunks.end(); ++it) + it->offset += static_cast(diff); + + // Update the global size. + + updateGlobalSize(); +} + +void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data) +{ + setChunkData(name, data, false); +} + +void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate) +{ + if(d->chunks.empty()) { + debug("RIFF::File::setChunkData - No valid chunks found."); + return; + } + + if(alwaysCreate && name != "LIST") { + debug("RIFF::File::setChunkData - alwaysCreate should be used for only \"LIST\" chunks."); + return; + } + + if(!alwaysCreate) { + for(unsigned int i = 0; i < d->chunks.size(); i++) { + if(d->chunks[i].name == name) { + setChunkData(i, data); + return; + } + } + } + + // Couldn't find an existing chunk, so let's create a new one. + + // Adjust the padding of the last chunk to place the new chunk at even position. + + Chunk &last = d->chunks.back(); + + long offset = last.offset + last.size + last.padding; + if(offset & 1) { + if(last.padding == 1) { + last.padding = 0; // This should not happen unless the file is corrupted. + offset--; + removeBlock(offset, 1); + } + else { + insert(ByteVector("\0", 1), offset, 0); + last.padding = 1; + offset++; + } + } + + // Now add the chunk to the file. + + writeChunk(name, data, offset, 0); + + // And update our internal structure + + Chunk chunk; + chunk.name = name; + chunk.size = data.size(); + chunk.offset = offset + 8; + chunk.padding = data.size() % 2; + + d->chunks.push_back(chunk); + + // Update the global size. + + updateGlobalSize(); +} + +void RIFF::File::removeChunk(unsigned int i) +{ + if(i >= d->chunks.size()) { + debug("RIFF::File::removeChunk() - Index out of range."); + return; + } + + std::vector::iterator it = d->chunks.begin(); + std::advance(it, i); + + const unsigned int removeSize = it->size + it->padding + 8; + removeBlock(it->offset - 8, removeSize); + it = d->chunks.erase(it); + + for(; it != d->chunks.end(); ++it) + it->offset -= removeSize; + + // Update the global size. + + updateGlobalSize(); +} + +void RIFF::File::removeChunk(const ByteVector &name) +{ + for(int i = static_cast(d->chunks.size()) - 1; i >= 0; --i) { + if(d->chunks[i].name == name) + removeChunk(i); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::File::read() +{ + const bool bigEndian = (d->endianness == BigEndian); + + long offset = tell(); + + offset += 4; + d->sizeOffset = offset; + + seek(offset); + d->size = readBlock(4).toUInt(bigEndian); + + offset += 8; + + // + 8: chunk header at least, fix for additional junk bytes + while(offset + 8 <= length()) { + + seek(offset); + const ByteVector chunkName = readBlock(4); + const unsigned int chunkSize = readBlock(4).toUInt(bigEndian); + + if(!isValidChunkName(chunkName)) { + debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID"); + break; + } + + if(static_cast(offset) + 8 + chunkSize > length()) { + debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)"); + break; + } + + Chunk chunk; + chunk.name = chunkName; + chunk.size = chunkSize; + chunk.offset = offset + 8; + chunk.padding = 0; + + offset = chunk.offset + chunk.size; + + // Check padding + + if(offset & 1) { + seek(offset); + const ByteVector iByte = readBlock(1); + if(iByte.size() == 1) { + bool skipPadding = iByte[0] == '\0'; + if(!skipPadding) { + // Padding byte is not zero, check if it is good to ignore it + const ByteVector fourCcAfterPadding = readBlock(4); + if(isValidChunkName(fourCcAfterPadding)) { + // Use the padding, it is followed by a valid chunk name. + skipPadding = true; + } + } + if(skipPadding) { + chunk.padding = 1; + offset++; + } + } + } + + d->chunks.push_back(chunk); + } +} + +void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, + unsigned long offset, unsigned long replace) +{ + ByteVector combined; + + combined.append(name); + combined.append(ByteVector::fromUInt(data.size(), d->endianness == BigEndian)); + combined.append(data); + + if(data.size() & 1) + combined.resize(combined.size() + 1, '\0'); + + insert(combined, offset, replace); +} + +void RIFF::File::updateGlobalSize() +{ + const Chunk first = d->chunks.front(); + const Chunk last = d->chunks.back(); + d->size = last.offset + last.size + last.padding - first.offset + 12; + + const ByteVector data = ByteVector::fromUInt(d->size, d->endianness == BigEndian); + insert(data, d->sizeOffset, 4); +} diff --git a/external/taglib/source/riff/rifffile.h b/external/taglib/source/riff/rifffile.h new file mode 100644 index 0000000..5c606b4 --- /dev/null +++ b/external/taglib/source/riff/rifffile.h @@ -0,0 +1,161 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RIFFFILE_H +#define TAGLIB_RIFFFILE_H + +#include "taglib_export.h" +#include "tfile.h" + +namespace TagLib { + + //! An implementation of TagLib::File with RIFF specific methods + + namespace RIFF { + + //! An RIFF file class with some useful methods specific to RIFF + + /*! + * This implements the generic TagLib::File API and additionally provides + * access to properties that are distinct to RIFF files, notably access + * to the different ID3 tags. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + protected: + + enum Endianness { BigEndian, LittleEndian }; + + File(FileName file, Endianness endianness); + File(IOStream *stream, Endianness endianness); + + /*! + * \return The size of the main RIFF chunk. + */ + unsigned int riffSize() const; + + /*! + * \return The number of chunks in the file. + */ + unsigned int chunkCount() const; + + /*! + * \return The offset within the file for the selected chunk number. + */ + unsigned int chunkOffset(unsigned int i) const; + + /*! + * \return The size of the chunk data. + */ + unsigned int chunkDataSize(unsigned int i) const; + + /*! + * \return The size of the padding after the chunk (can be either 0 or 1). + */ + unsigned int chunkPadding(unsigned int i) const; + + /*! + * \return The name of the specified chunk, for instance, "COMM" or "ID3 " + */ + ByteVector chunkName(unsigned int i) const; + + /*! + * Reads the chunk data from the file and returns it. + * + * \note This \e will move the read pointer for the file. + */ + ByteVector chunkData(unsigned int i); + + /*! + * Sets the data for the specified chunk to \a data. + * + * \warning This will update the file immediately. + */ + void setChunkData(unsigned int i, const ByteVector &data); + + /*! + * Sets the data for the chunk \a name to \a data. If a chunk with the + * given name already exists it will be overwritten, otherwise it will be + * created after the existing chunks. + * + * \warning This will update the file immediately. + */ + void setChunkData(const ByteVector &name, const ByteVector &data); + + /*! + * Sets the data for the chunk \a name to \a data. If a chunk with the + * given name already exists it will be overwritten, otherwise it will be + * created after the existing chunks. + * + * \note If \a alwaysCreate is true, a new chunk is created regardless of + * whether or not the chunk \a name exists. It should only be used for + * "LIST" chunks. + * + * \warning This will update the file immediately. + */ + void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate); + + /*! + * Removes the specified chunk. + * + * \warning This will update the file immediately. + */ + void removeChunk(unsigned int i); + + /*! + * Removes the chunk \a name. + * + * \warning This will update the file immediately. + * \warning This removes all the chunks with the given name. + */ + void removeChunk(const ByteVector &name); + + private: + File(const File &); + File &operator=(const File &); + + void read(); + void writeChunk(const ByteVector &name, const ByteVector &data, + unsigned long offset, unsigned long replace = 0); + + /*! + * Update the global RIFF size based on the current internal structure. + */ + void updateGlobalSize(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/riff/riffutils.h b/external/taglib/source/riff/riffutils.h new file mode 100644 index 0000000..ecb985a --- /dev/null +++ b/external/taglib/source/riff/riffutils.h @@ -0,0 +1,60 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_RIFFUTILS_H +#define TAGLIB_RIFFUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib +{ + namespace RIFF + { + namespace + { + + inline bool isValidChunkName(const ByteVector &name) + { + if(name.size() != 4) + return false; + + for(ByteVector::ConstIterator it = name.begin(); it != name.end(); ++it) { + const int c = static_cast(*it); + if(c < 32 || 127 < c) + return false; + } + + return true; + } + + } + } +} + +#endif + +#endif diff --git a/external/taglib/source/riff/wav/infotag.cpp b/external/taglib/source/riff/wav/infotag.cpp new file mode 100644 index 0000000..716701d --- /dev/null +++ b/external/taglib/source/riff/wav/infotag.cpp @@ -0,0 +1,252 @@ +/*************************************************************************** + copyright : (C) 2012 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include "infotag.h" +#include "riffutils.h" + +using namespace TagLib; +using namespace RIFF::Info; + +namespace +{ + const RIFF::Info::StringHandler defaultStringHandler; + const RIFF::Info::StringHandler *stringHandler = &defaultStringHandler; +} + +class RIFF::Info::Tag::TagPrivate +{ +public: + FieldListMap fieldListMap; +}; + +//////////////////////////////////////////////////////////////////////////////// +// StringHandler implementation +//////////////////////////////////////////////////////////////////////////////// + +StringHandler::StringHandler() +{ +} + +StringHandler::~StringHandler() +{ +} + +String RIFF::Info::StringHandler::parse(const ByteVector &data) const +{ + return String(data, String::UTF8); +} + +ByteVector RIFF::Info::StringHandler::render(const String &s) const +{ + return s.data(String::UTF8); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::Info::Tag::Tag(const ByteVector &data) : + d(new TagPrivate()) +{ + parse(data); +} + +RIFF::Info::Tag::Tag() : + d(new TagPrivate()) +{ +} + +RIFF::Info::Tag::~Tag() +{ + delete d; +} + +String RIFF::Info::Tag::title() const +{ + return fieldText("INAM"); +} + +String RIFF::Info::Tag::artist() const +{ + return fieldText("IART"); +} + +String RIFF::Info::Tag::album() const +{ + return fieldText("IPRD"); +} + +String RIFF::Info::Tag::comment() const +{ + return fieldText("ICMT"); +} + +String RIFF::Info::Tag::genre() const +{ + return fieldText("IGNR"); +} + +unsigned int RIFF::Info::Tag::year() const +{ + return fieldText("ICRD").substr(0, 4).toInt(); +} + +unsigned int RIFF::Info::Tag::track() const +{ + return fieldText("IPRT").toInt(); +} + +void RIFF::Info::Tag::setTitle(const String &s) +{ + setFieldText("INAM", s); +} + +void RIFF::Info::Tag::setArtist(const String &s) +{ + setFieldText("IART", s); +} + +void RIFF::Info::Tag::setAlbum(const String &s) +{ + setFieldText("IPRD", s); +} + +void RIFF::Info::Tag::setComment(const String &s) +{ + setFieldText("ICMT", s); +} + +void RIFF::Info::Tag::setGenre(const String &s) +{ + setFieldText("IGNR", s); +} + +void RIFF::Info::Tag::setYear(unsigned int i) +{ + if(i != 0) + setFieldText("ICRD", String::number(i)); + else + d->fieldListMap.erase("ICRD"); +} + +void RIFF::Info::Tag::setTrack(unsigned int i) +{ + if(i != 0) + setFieldText("IPRT", String::number(i)); + else + d->fieldListMap.erase("IPRT"); +} + +bool RIFF::Info::Tag::isEmpty() const +{ + return d->fieldListMap.isEmpty(); +} + +FieldListMap RIFF::Info::Tag::fieldListMap() const +{ + return d->fieldListMap; +} + +String RIFF::Info::Tag::fieldText(const ByteVector &id) const +{ + if(d->fieldListMap.contains(id)) + return String(d->fieldListMap[id]); + return String(); +} + +void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) +{ + // id must be four-byte long pure ascii string. + if(!isValidChunkName(id)) + return; + + if(!s.isEmpty()) + d->fieldListMap[id] = s; + else + removeField(id); +} + +void RIFF::Info::Tag::removeField(const ByteVector &id) +{ + if(d->fieldListMap.contains(id)) + d->fieldListMap.erase(id); +} + +ByteVector RIFF::Info::Tag::render() const +{ + ByteVector data("INFO"); + + FieldListMap::ConstIterator it = d->fieldListMap.begin(); + for(; it != d->fieldListMap.end(); ++it) { + ByteVector text = stringHandler->render(it->second); + if(text.isEmpty()) + continue; + + data.append(it->first); + data.append(ByteVector::fromUInt(text.size() + 1, false)); + data.append(text); + + do { + data.append('\0'); + } while(data.size() & 1); + } + + if(data.size() == 4) + return ByteVector(); + return data; +} + +void RIFF::Info::Tag::setStringHandler(const StringHandler *handler) +{ + if(handler) + stringHandler = handler; + else + stringHandler = &defaultStringHandler; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::Info::Tag::parse(const ByteVector &data) +{ + unsigned int p = 4; + while(p < data.size()) { + const unsigned int size = data.toUInt(p + 4, false); + if(size > data.size() - p - 8) + break; + + const ByteVector id = data.mid(p, 4); + if(isValidChunkName(id)) { + const String text = stringHandler->parse(data.mid(p + 8, size)); + d->fieldListMap[id] = text; + } + + p += ((size + 1) & ~1) + 8; + } +} diff --git a/external/taglib/source/riff/wav/infotag.h b/external/taglib/source/riff/wav/infotag.h new file mode 100644 index 0000000..d1f0297 --- /dev/null +++ b/external/taglib/source/riff/wav/infotag.h @@ -0,0 +1,192 @@ +/*************************************************************************** + copyright : (C) 2012 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_INFOTAG_H +#define TAGLIB_INFOTAG_H + +#include "tag.h" +#include "tmap.h" +#include "tstring.h" +#include "tstringlist.h" +#include "tbytevector.h" +#include "taglib_export.h" + +namespace TagLib { + + class File; + + //! A RIFF INFO tag implementation. + namespace RIFF { + namespace Info { + + typedef Map FieldListMap; + + //! A abstraction for the string to data encoding in Info tags. + + /*! + * RIFF INFO tag has no clear definitions about character encodings. + * In practice, local encoding of each system is largely used and UTF-8 is + * popular too. + * + * Here is an option to read and write tags in your preferred encoding + * by subclassing this class, reimplementing parse() and render() and setting + * your reimplementation as the default with Info::Tag::setStringHandler(). + * + * \see ID3v1::Tag::setStringHandler() + */ + + class TAGLIB_EXPORT StringHandler + { + public: + StringHandler(); + ~StringHandler(); + + /*! + * Decode a string from \a data. The default implementation assumes that + * \a data is an UTF-8 character array. + */ + virtual String parse(const ByteVector &data) const; + + /*! + * Encode a ByteVector with the data from \a s. The default implementation + * assumes that \a s is an UTF-8 string. + */ + virtual ByteVector render(const String &s) const; + }; + + //! The main class in the ID3v2 implementation + + /*! + * This is the main class in the INFO tag implementation. RIFF INFO tag is a + * metadata format found in WAV audio and AVI video files. Though it is a part + * of Microsoft/IBM's RIFF specification, the author could not find the official + * documents about it. So, this implementation is referring to unofficial documents + * online and some applications' behaviors especially Windows Explorer. + */ + class TAGLIB_EXPORT Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty INFO tag. + */ + Tag(); + + /*! + * Constructs an INFO tag read from \a data which is contents of "LIST" chunk. + */ + Tag(const ByteVector &data); + + virtual ~Tag(); + + // Reimplementations + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + + virtual bool isEmpty() const; + + /*! + * Returns a copy of the internal fields of the tag. The returned map directly + * reflects the contents of the "INFO" chunk. + * + * \note Modifying this map does not affect the tag's internal data. + * Use setFieldText() and removeField() instead. + * + * \see setFieldText() + * \see removeField() + */ + FieldListMap fieldListMap() const; + + /* + * Gets the value of the field with the ID \a id. + */ + String fieldText(const ByteVector &id) const; + + /* + * Sets the value of the field with the ID \a id to \a s. + * If the field does not exist, it is created. + * If \s is empty, the field is removed. + * + * \note fieldId must be four-byte long pure ASCII string. This function + * performs nothing if fieldId is invalid. + */ + void setFieldText(const ByteVector &id, const String &s); + + /* + * Removes the field with the ID \a id. + */ + void removeField(const ByteVector &id); + + /*! + * Render the tag back to binary data, suitable to be written to disk. + * + * \note Returns empty ByteVector is the tag contains no fields. + */ + ByteVector render() const; + + /*! + * Sets the string handler that decides how the text data will be + * converted to and from binary data. + * If the parameter \a handler is null, the previous handler is + * released and default UTF-8 handler is restored. + * + * \note The caller is responsible for deleting the previous handler + * as needed after it is released. + * + * \see StringHandler + */ + static void setStringHandler(const StringHandler *handler); + + protected: + /*! + * Pareses the body of the tag in \a data. + */ + void parse(const ByteVector &data); + + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + }} +} + +#endif diff --git a/external/taglib/source/riff/wav/wavfile.cpp b/external/taglib/source/riff/wav/wavfile.cpp new file mode 100644 index 0000000..3dce70b --- /dev/null +++ b/external/taglib/source/riff/wav/wavfile.cpp @@ -0,0 +1,264 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "wavfile.h" +#include "id3v2tag.h" +#include "infotag.h" +#include "tagunion.h" + +using namespace TagLib; + +namespace +{ + enum { ID3v2Index = 0, InfoIndex = 1 }; +} + +class RIFF::WAV::File::FilePrivate +{ +public: + FilePrivate() : + properties(0), + hasID3v2(false), + hasInfo(false) {} + + ~FilePrivate() + { + delete properties; + } + + Properties *properties; + TagUnion tag; + + bool hasID3v2; + bool hasInfo; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool RIFF::WAV::File::isSupported(IOStream *stream) +{ + // A WAV file has to start with "RIFF????WAVE". + + const ByteVector id = Utils::readHeader(stream, 12, false); + return (id.startsWith("RIFF") && id.containsAt("WAVE", 8)); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::WAV::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + RIFF::File(file, LittleEndian), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +RIFF::WAV::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + RIFF::File(stream, LittleEndian), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +RIFF::WAV::File::~File() +{ + delete d; +} + +ID3v2::Tag *RIFF::WAV::File::tag() const +{ + return ID3v2Tag(); +} + +ID3v2::Tag *RIFF::WAV::File::ID3v2Tag() const +{ + return d->tag.access(ID3v2Index, false); +} + +RIFF::Info::Tag *RIFF::WAV::File::InfoTag() const +{ + return d->tag.access(InfoIndex, false); +} + +void RIFF::WAV::File::strip(TagTypes tags) +{ + removeTagChunks(tags); + + if(tags & ID3v2) + d->tag.set(ID3v2Index, new ID3v2::Tag()); + + if(tags & Info) + d->tag.set(InfoIndex, new RIFF::Info::Tag()); +} + +PropertyMap RIFF::WAV::File::properties() const +{ + return d->tag.properties(); +} + +void RIFF::WAV::File::removeUnsupportedProperties(const StringList &unsupported) +{ + d->tag.removeUnsupportedProperties(unsupported); +} + +PropertyMap RIFF::WAV::File::setProperties(const PropertyMap &properties) +{ + InfoTag()->setProperties(properties); + return ID3v2Tag()->setProperties(properties); +} + +RIFF::WAV::Properties *RIFF::WAV::File::audioProperties() const +{ + return d->properties; +} + +bool RIFF::WAV::File::save() +{ + return RIFF::WAV::File::save(AllTags); +} + +bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version) +{ + return save(tags, + stripOthers ? StripOthers : StripNone, + id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4); +} + +bool RIFF::WAV::File::save(TagTypes tags, StripTags strip, ID3v2::Version version) +{ + if(readOnly()) { + debug("RIFF::WAV::File::save() -- File is read only."); + return false; + } + + if(!isValid()) { + debug("RIFF::WAV::File::save() -- Trying to save invalid file."); + return false; + } + + if(strip == StripOthers) + File::strip(static_cast(AllTags & ~tags)); + + if(tags & ID3v2) { + removeTagChunks(ID3v2); + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + setChunkData("ID3 ", ID3v2Tag()->render(version)); + d->hasID3v2 = true; + } + } + + if(tags & Info) { + removeTagChunks(Info); + + if(InfoTag() && !InfoTag()->isEmpty()) { + setChunkData("LIST", InfoTag()->render(), true); + d->hasInfo = true; + } + } + + return true; +} + +bool RIFF::WAV::File::hasID3v2Tag() const +{ + return d->hasID3v2; +} + +bool RIFF::WAV::File::hasInfoTag() const +{ + return d->hasInfo; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::WAV::File::read(bool readProperties) +{ + for(unsigned int i = 0; i < chunkCount(); ++i) { + const ByteVector name = chunkName(i); + if(name == "ID3 " || name == "id3 ") { + if(!d->tag[ID3v2Index]) { + d->tag.set(ID3v2Index, new ID3v2::Tag(this, chunkOffset(i))); + d->hasID3v2 = true; + } + else { + debug("RIFF::WAV::File::read() - Duplicate ID3v2 tag found."); + } + } + else if(name == "LIST") { + const ByteVector data = chunkData(i); + if(data.startsWith("INFO")) { + if(!d->tag[InfoIndex]) { + d->tag.set(InfoIndex, new RIFF::Info::Tag(data)); + d->hasInfo = true; + } + else { + debug("RIFF::WAV::File::read() - Duplicate INFO tag found."); + } + } + } + } + + if(!d->tag[ID3v2Index]) + d->tag.set(ID3v2Index, new ID3v2::Tag()); + + if(!d->tag[InfoIndex]) + d->tag.set(InfoIndex, new RIFF::Info::Tag()); + + if(readProperties) + d->properties = new Properties(this, Properties::Average); +} + +void RIFF::WAV::File::removeTagChunks(TagTypes tags) +{ + if((tags & ID3v2) && d->hasID3v2) { + removeChunk("ID3 "); + removeChunk("id3 "); + + d->hasID3v2 = false; + } + + if((tags & Info) && d->hasInfo) { + for(int i = static_cast(chunkCount()) - 1; i >= 0; --i) { + if(chunkName(i) == "LIST" && chunkData(i).startsWith("INFO")) + removeChunk(i); + } + + d->hasInfo = false; + } +} diff --git a/external/taglib/source/riff/wav/wavfile.h b/external/taglib/source/riff/wav/wavfile.h new file mode 100644 index 0000000..bc9ce31 --- /dev/null +++ b/external/taglib/source/riff/wav/wavfile.h @@ -0,0 +1,215 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILE_H +#define TAGLIB_WAVFILE_H + +#include "rifffile.h" +#include "id3v2tag.h" +#include "infotag.h" +#include "wavproperties.h" + +namespace TagLib { + + namespace RIFF { + + //! An implementation of WAV metadata + + /*! + * This is implementation of WAV metadata. + * + * This supports an ID3v2 tag as well as reading stream from the ID3 RIFF + * chunk as well as properties from the file. + */ + + namespace WAV { + + //! An implementation of TagLib::File with WAV specific methods + + /*! + * This implements and provides an interface for WAV files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WAV files. + */ + + class TAGLIB_EXPORT File : public TagLib::RIFF::File + { + public: + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v2 tags. + ID3v2 = 0x0001, + //! Matches INFO tags. + Info = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a WAV file from \a file. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a WAV file from \a stream. If \a readProperties is true the + * file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the ID3v2 Tag for this file. + * + * \note This method does not return all the tags for this file for + * backward compatibility. Will be fixed in TagLib 2.0. + */ + ID3v2::Tag *tag() const; + + /*! + * Returns the ID3v2 Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the + * file on disk actually has an ID3v2 tag. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag() const; + + /*! + * Returns the RIFF INFO Tag for this file. + * + * \note This always returns a valid pointer regardless of whether or not + * the file on disk has a RIFF INFO tag. Use hasInfoTag() to check if the + * file on disk actually has a RIFF INFO tag. + * + * \see hasInfoTag() + */ + Info::Tag *InfoTag() const; + + /*! + * This will strip the tags that match the OR-ed together TagTypes from the + * file. By default it strips all tags. It returns true if the tags are + * successfully stripped. + * + * \note This will update the file immediately. + */ + void strip(TagTypes tags = AllTags); + + /*! + * Implements the unified property interface -- export function. + * This method forwards to ID3v2::Tag::properties(). + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * This method forwards to ID3v2::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the WAV::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * \deprecated + */ + TAGLIB_DEPRECATED bool save(TagTypes tags, bool stripOthers, int id3v2Version = 4); + + /*! + * Save the file. If \a strip is specified, it is possible to choose if + * tags not specified in \a tags should be stripped from the file or + * retained. With \a version, it is possible to specify whether ID3v2.4 + * or ID3v2.3 should be used. + */ + bool save(TagTypes tags, StripTags strip = StripOthers, + ID3v2::Version version = ID3v2::v4); + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the file on disk actually has a RIFF INFO tag. + * + * \see InfoTag() + */ + bool hasInfoTag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a WAV + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + void removeTagChunks(TagTypes tags); + + friend class Properties; + + class FilePrivate; + FilePrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/riff/wav/wavproperties.cpp b/external/taglib/source/riff/wav/wavproperties.cpp new file mode 100644 index 0000000..812da7d --- /dev/null +++ b/external/taglib/source/riff/wav/wavproperties.cpp @@ -0,0 +1,221 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include "wavfile.h" +#include "wavproperties.h" + +using namespace TagLib; + +namespace +{ + // Quoted from RFC 2361. + enum WaveFormat + { + FORMAT_UNKNOWN = 0x0000, + FORMAT_PCM = 0x0001, + FORMAT_IEEE_FLOAT = 0x0003 + }; +} + +class RIFF::WAV::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + format(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0), + sampleFrames(0) {} + + int format; + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; + unsigned int sampleFrames; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +RIFF::WAV::Properties::Properties(const ByteVector &, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used."); +} + +RIFF::WAV::Properties::Properties(const ByteVector &, unsigned int, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used."); +} + +TagLib::RIFF::WAV::Properties::Properties(File *file, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file); +} + +RIFF::WAV::Properties::~Properties() +{ + delete d; +} + +int RIFF::WAV::Properties::length() const +{ + return lengthInSeconds(); +} + +int RIFF::WAV::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int RIFF::WAV::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int RIFF::WAV::Properties::bitrate() const +{ + return d->bitrate; +} + +int RIFF::WAV::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int RIFF::WAV::Properties::channels() const +{ + return d->channels; +} + +int RIFF::WAV::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int RIFF::WAV::Properties::sampleWidth() const +{ + return bitsPerSample(); +} + +unsigned int RIFF::WAV::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +int RIFF::WAV::Properties::format() const +{ + return d->format; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void RIFF::WAV::Properties::read(File *file) +{ + ByteVector data; + unsigned int streamLength = 0; + unsigned int totalSamples = 0; + + for(unsigned int i = 0; i < file->chunkCount(); ++i) { + const ByteVector name = file->chunkName(i); + if(name == "fmt ") { + if(data.isEmpty()) + data = file->chunkData(i); + else + debug("RIFF::WAV::Properties::read() - Duplicate 'fmt ' chunk found."); + } + else if(name == "data") { + if(streamLength == 0) + streamLength = file->chunkDataSize(i) + file->chunkPadding(i); + else + debug("RIFF::WAV::Properties::read() - Duplicate 'data' chunk found."); + } + else if(name == "fact") { + if(totalSamples == 0) + totalSamples = file->chunkData(i).toUInt(0, false); + else + debug("RIFF::WAV::Properties::read() - Duplicate 'fact' chunk found."); + } + } + + if(data.size() < 16) { + debug("RIFF::WAV::Properties::read() - 'fmt ' chunk not found or too short."); + return; + } + + if(streamLength == 0) { + debug("RIFF::WAV::Properties::read() - 'data' chunk not found."); + return; + } + + d->format = data.toShort(0, false); + if((d->format & 0xffff) == 0xfffe) { + // if extensible then read the format from the subformat + if(data.size() != 40) { + debug("RIFF::WAV::Properties::read() - extensible size incorrect"); + return; + } + d->format = data.toShort(24, false); + } + if(d->format != FORMAT_PCM && d->format != FORMAT_IEEE_FLOAT && totalSamples == 0) { + debug("RIFF::WAV::Properties::read() - Non-PCM format, but 'fact' chunk not found."); + return; + } + + d->channels = data.toShort(2, false); + d->sampleRate = data.toUInt(4, false); + d->bitsPerSample = data.toShort(14, false); + + if(d->format != FORMAT_PCM && !(d->format == FORMAT_IEEE_FLOAT && totalSamples == 0)) + d->sampleFrames = totalSamples; + else if(d->channels > 0 && d->bitsPerSample > 0) + d->sampleFrames = streamLength / (d->channels * ((d->bitsPerSample + 7) / 8)); + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } + else { + const unsigned int byteRate = data.toUInt(8, false); + if(byteRate > 0) { + d->length = static_cast(streamLength * 1000.0 / byteRate + 0.5); + d->bitrate = static_cast(byteRate * 8.0 / 1000.0 + 0.5); + } + } +} diff --git a/external/taglib/source/riff/wav/wavproperties.h b/external/taglib/source/riff/wav/wavproperties.h new file mode 100644 index 0000000..1ca7310 --- /dev/null +++ b/external/taglib/source/riff/wav/wavproperties.h @@ -0,0 +1,163 @@ +/*************************************************************************** + copyright : (C) 2008 by Scott Wheeler + email : wheeler@kde.org +***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPROPERTIES_H +#define TAGLIB_WAVPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + + class ByteVector; + + namespace RIFF { + + namespace WAV { + + class File; + + //! An implementation of audio property reading for WAV + + /*! + * This reads the data from an WAV stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style); + + /*! + * Create an instance of WAV::Properties with the data read from the + * ByteVector \a data and the length calculated using \a streamLength. + * + * \deprecated + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, unsigned int streamLength, ReadStyle style); + + /*! + * Create an instance of WAV::Properties with the data read from the + * WAV::File \a file. + */ + Properties(File *file, ReadStyle style); + + /*! + * Destroys this WAV::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the number of bits per audio sample. + * + * \note This method is just an alias of bitsPerSample(). + * + * \deprecated + */ + TAGLIB_DEPRECATED int sampleWidth() const; + + /*! + * Returns the number of sample frames. + */ + unsigned int sampleFrames() const; + + /*! + * Returns the format ID of the file. + * 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and + * so forth. + * + * \note For further information, refer to the WAVE Form Registration + * Numbers in RFC 2361. + */ + int format() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + } +} + +#endif diff --git a/external/taglib/source/s3m/s3mfile.cpp b/external/taglib/source/s3m/s3mfile.cpp new file mode 100644 index 0000000..da78829 --- /dev/null +++ b/external/taglib/source/s3m/s3mfile.cpp @@ -0,0 +1,248 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "s3mfile.h" +#include "tstringlist.h" +#include "tdebug.h" +#include "modfileprivate.h" +#include "tpropertymap.h" + +#include + +using namespace TagLib; +using namespace S3M; + +class S3M::File::FilePrivate +{ +public: + FilePrivate(AudioProperties::ReadStyle propertiesStyle) + : properties(propertiesStyle) + { + } + + Mod::Tag tag; + S3M::Properties properties; +}; + +S3M::File::File(FileName file, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(file), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +S3M::File::File(IOStream *stream, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(stream), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +S3M::File::~File() +{ + delete d; +} + +Mod::Tag *S3M::File::tag() const +{ + return &d->tag; +} + +PropertyMap S3M::File::properties() const +{ + return d->tag.properties(); +} + +PropertyMap S3M::File::setProperties(const PropertyMap &properties) +{ + return d->tag.setProperties(properties); +} + +S3M::Properties *S3M::File::audioProperties() const +{ + return &d->properties; +} + +bool S3M::File::save() +{ + if(readOnly()) { + debug("S3M::File::save() - Cannot save to a read only file."); + return false; + } + // note: if title starts with "Extended Module: " + // the file would look like an .xm file + seek(0); + writeString(d->tag.title(), 27); + // string terminating NUL is not optional: + writeByte(0); + + seek(32); + + unsigned short length = 0; + unsigned short sampleCount = 0; + + if(!readU16L(length) || !readU16L(sampleCount)) + return false; + + seek(28, Current); + + int channels = 0; + for(int i = 0; i < 32; ++ i) { + unsigned char setting = 0; + if(!readByte(setting)) + return false; + // or if(setting >= 128)? + // or channels = i + 1;? + // need a better spec! + if(setting != 0xff) ++ channels; + } + + seek(channels, Current); + + StringList lines = d->tag.comment().split("\n"); + // write comment as sample names: + for(unsigned short i = 0; i < sampleCount; ++ i) { + seek(96L + length + (static_cast(i) << 1)); + + unsigned short instrumentOffset = 0; + if(!readU16L(instrumentOffset)) + return false; + seek((static_cast(instrumentOffset) << 4) + 48); + + if(i < lines.size()) + writeString(lines[i], 27); + else + writeString(String(), 27); + // string terminating NUL is not optional: + writeByte(0); + } + return true; +} + +void S3M::File::read(bool) +{ + if(!isOpen()) + return; + + READ_STRING(d->tag.setTitle, 28); + READ_BYTE_AS(mark); + READ_BYTE_AS(type); + + READ_ASSERT(mark == 0x1A && type == 0x10); + + seek(32); + + READ_U16L_AS(length); + READ_U16L_AS(sampleCount); + + d->properties.setSampleCount(sampleCount); + + READ_U16L(d->properties.setPatternCount); + READ_U16L(d->properties.setFlags); + READ_U16L(d->properties.setTrackerVersion); + READ_U16L(d->properties.setFileFormatVersion); + + READ_ASSERT(readBlock(4) == "SCRM"); + + READ_BYTE(d->properties.setGlobalVolume); + READ_BYTE(d->properties.setBpmSpeed); + READ_BYTE(d->properties.setTempo); + + READ_BYTE_AS(masterVolume); + d->properties.setMasterVolume(masterVolume & 0x7f); + d->properties.setStereo((masterVolume & 0x80) != 0); + + // I've seen players who call the next two bytes + // "ultra click" and "use panning values" (if == 0xFC). + // I don't see them in any spec, though. + // Hm, but there is "UltraClick-removal" and some other + // variables in ScreamTracker III's GUI. + + seek(12, Current); + + int channels = 0; + for(int i = 0; i < 32; ++ i) { + READ_BYTE_AS(setting); + // or if(setting >= 128)? + // or channels = i + 1;? + // need a better spec! + if(setting != 0xff) ++ channels; + } + d->properties.setChannels(channels); + + seek(96); + unsigned short realLength = 0; + for(unsigned short i = 0; i < length; ++ i) { + READ_BYTE_AS(order); + if(order == 255) break; + if(order != 254) ++ realLength; + } + d->properties.setLengthInPatterns(realLength); + + seek(channels, Current); + + // Note: The S3M spec mentions samples and instruments, but in + // the header there are only pointers to instruments. + // However, there I never found instruments (SCRI) but + // instead samples (SCRS). + StringList comment; + for(unsigned short i = 0; i < sampleCount; ++ i) { + seek(96L + length + (static_cast(i) << 1)); + + READ_U16L_AS(sampleHeaderOffset); + seek(static_cast(sampleHeaderOffset) << 4); + + READ_BYTE_AS(sampleType); + READ_STRING_AS(dosFileName, 13); + READ_U16L_AS(sampleDataOffset); + READ_U32L_AS(sampleLength); + READ_U32L_AS(repeatStart); + READ_U32L_AS(repeatStop); + READ_BYTE_AS(sampleVolume); + + seek(1, Current); + + READ_BYTE_AS(packing); + READ_BYTE_AS(sampleFlags); + READ_U32L_AS(baseFrequency); + + seek(12, Current); + + READ_STRING_AS(sampleName, 28); + // The next 4 bytes should be "SCRS", but I've found + // files that are otherwise ok with 4 nils instead. + // READ_ASSERT(readBlock(4) == "SCRS"); + + comment.append(sampleName); + } + + d->tag.setComment(comment.toString("\n")); + d->tag.setTrackerName("ScreamTracker III"); +} diff --git a/external/taglib/source/s3m/s3mfile.h b/external/taglib/source/s3m/s3mfile.h new file mode 100644 index 0000000..4011bd1 --- /dev/null +++ b/external/taglib/source/s3m/s3mfile.h @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_S3MFILE_H +#define TAGLIB_S3MFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "s3mproperties.h" + +namespace TagLib { + + namespace S3M { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs a ScreamTracker III from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs a ScreamTracker III file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the S3M::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + S3M::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving ScreamTracker III tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/s3m/s3mproperties.cpp b/external/taglib/source/s3m/s3mproperties.cpp new file mode 100644 index 0000000..e3e443c --- /dev/null +++ b/external/taglib/source/s3m/s3mproperties.cpp @@ -0,0 +1,219 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "s3mproperties.h" + +using namespace TagLib; +using namespace S3M; + +class S3M::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + lengthInPatterns(0), + channels(0), + stereo(false), + sampleCount(0), + patternCount(0), + flags(0), + trackerVersion(0), + fileFormatVersion(0), + globalVolume(0), + masterVolume(0), + tempo(0), + bpmSpeed(0) + { + } + + unsigned short lengthInPatterns; + int channels; + bool stereo; + unsigned short sampleCount; + unsigned short patternCount; + unsigned short flags; + unsigned short trackerVersion; + unsigned short fileFormatVersion; + unsigned char globalVolume; + unsigned char masterVolume; + unsigned char tempo; + unsigned char bpmSpeed; +}; + +S3M::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : + AudioProperties(propertiesStyle), + d(new PropertiesPrivate()) +{ +} + +S3M::Properties::~Properties() +{ + delete d; +} + +int S3M::Properties::length() const +{ + return 0; +} + +int S3M::Properties::lengthInSeconds() const +{ + return 0; +} + +int S3M::Properties::lengthInMilliseconds() const +{ + return 0; +} + +int S3M::Properties::bitrate() const +{ + return 0; +} + +int S3M::Properties::sampleRate() const +{ + return 0; +} + +int S3M::Properties::channels() const +{ + return d->channels; +} + +unsigned short S3M::Properties::lengthInPatterns() const +{ + return d->lengthInPatterns; +} + +bool S3M::Properties::stereo() const +{ + return d->stereo; +} + +unsigned short S3M::Properties::sampleCount() const +{ + return d->sampleCount; +} + +unsigned short S3M::Properties::patternCount() const +{ + return d->patternCount; +} + +unsigned short S3M::Properties::flags() const +{ + return d->flags; +} + +unsigned short S3M::Properties::trackerVersion() const +{ + return d->trackerVersion; +} + +unsigned short S3M::Properties::fileFormatVersion() const +{ + return d->fileFormatVersion; +} + +unsigned char S3M::Properties::globalVolume() const +{ + return d->globalVolume; +} + +unsigned char S3M::Properties::masterVolume() const +{ + return d->masterVolume; +} + +unsigned char S3M::Properties::tempo() const +{ + return d->tempo; +} + +unsigned char S3M::Properties::bpmSpeed() const +{ + return d->bpmSpeed; +} + +void S3M::Properties::setLengthInPatterns(unsigned short lengthInPatterns) +{ + d->lengthInPatterns = lengthInPatterns; +} + +void S3M::Properties::setChannels(int channels) +{ + d->channels = channels; +} + +void S3M::Properties::setStereo(bool stereo) +{ + d->stereo = stereo; +} + +void S3M::Properties::setSampleCount(unsigned short sampleCount) +{ + d->sampleCount = sampleCount; +} + +void S3M::Properties::setPatternCount(unsigned short patternCount) +{ + d->patternCount = patternCount; +} + +void S3M::Properties::setFlags(unsigned short flags) +{ + d->flags = flags; +} + +void S3M::Properties::setTrackerVersion(unsigned short trackerVersion) +{ + d->trackerVersion = trackerVersion; +} + +void S3M::Properties::setFileFormatVersion(unsigned short fileFormatVersion) +{ + d->fileFormatVersion = fileFormatVersion; +} + +void S3M::Properties::setGlobalVolume(unsigned char globalVolume) +{ + d->globalVolume = globalVolume; +} + +void S3M::Properties::setMasterVolume(unsigned char masterVolume) +{ + d->masterVolume = masterVolume; +} + +void S3M::Properties::setTempo(unsigned char tempo) +{ + d->tempo = tempo; +} + +void S3M::Properties::setBpmSpeed(unsigned char bpmSpeed) +{ + d->bpmSpeed = bpmSpeed; +} diff --git a/external/taglib/source/s3m/s3mproperties.h b/external/taglib/source/s3m/s3mproperties.h new file mode 100644 index 0000000..92b2a27 --- /dev/null +++ b/external/taglib/source/s3m/s3mproperties.h @@ -0,0 +1,94 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_S3MPROPERTIES_H +#define TAGLIB_S3MPROPERTIES_H + +#include "taglib.h" +#include "audioproperties.h" + +namespace TagLib { + namespace S3M { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + ST2Vibrato = 1, + ST2Tempo = 2, + AmigaSlides = 4, + Vol0MixOptimizations = 8, + AmigaLimits = 16, + EnableFilter = 32, + CustomData = 128 + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + bool stereo() const; + unsigned short sampleCount() const; + unsigned short patternCount() const; + unsigned short flags() const; + unsigned short trackerVersion() const; + unsigned short fileFormatVersion() const; + unsigned char globalVolume() const; + unsigned char masterVolume() const; + unsigned char tempo() const; + unsigned char bpmSpeed() const; + + void setChannels(int channels); + + void setLengthInPatterns (unsigned short lengthInPatterns); + void setStereo (bool stereo); + void setSampleCount (unsigned short sampleCount); + void setPatternCount (unsigned short patternCount); + void setFlags (unsigned short flags); + void setTrackerVersion (unsigned short trackerVersion); + void setFileFormatVersion(unsigned short fileFormatVersion); + void setGlobalVolume (unsigned char globalVolume); + void setMasterVolume (unsigned char masterVolume); + void setTempo (unsigned char tempo); + void setBpmSpeed (unsigned char bpmSpeed); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/tag.cpp b/external/taglib/source/tag.cpp new file mode 100644 index 0000000..3526226 --- /dev/null +++ b/external/taglib/source/tag.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tag.h" +#include "tstringlist.h" +#include "tpropertymap.h" + +using namespace TagLib; + +class Tag::TagPrivate +{ + +}; + +Tag::Tag() +{ + +} + +Tag::~Tag() +{ + +} + +bool Tag::isEmpty() const +{ + return (title().isEmpty() && + artist().isEmpty() && + album().isEmpty() && + comment().isEmpty() && + genre().isEmpty() && + year() == 0 && + track() == 0); +} + +PropertyMap Tag::properties() const +{ + PropertyMap map; + if(!(title().isEmpty())) + map["TITLE"].append(title()); + if(!(artist().isEmpty())) + map["ARTIST"].append(artist()); + if(!(album().isEmpty())) + map["ALBUM"].append(album()); + if(!(comment().isEmpty())) + map["COMMENT"].append(comment()); + if(!(genre().isEmpty())) + map["GENRE"].append(genre()); + if(!(year() == 0)) + map["DATE"].append(String::number(year())); + if(!(track() == 0)) + map["TRACKNUMBER"].append(String::number(track())); + return map; +} + +void Tag::removeUnsupportedProperties(const StringList&) +{ +} + +PropertyMap Tag::setProperties(const PropertyMap &origProps) +{ + PropertyMap properties(origProps); + properties.removeEmpty(); + StringList oneValueSet; + // can this be simplified by using some preprocessor defines / function pointers? + if(properties.contains("TITLE")) { + setTitle(properties["TITLE"].front()); + oneValueSet.append("TITLE"); + } else + setTitle(String()); + + if(properties.contains("ARTIST")) { + setArtist(properties["ARTIST"].front()); + oneValueSet.append("ARTIST"); + } else + setArtist(String()); + + if(properties.contains("ALBUM")) { + setAlbum(properties["ALBUM"].front()); + oneValueSet.append("ALBUM"); + } else + setAlbum(String()); + + if(properties.contains("COMMENT")) { + setComment(properties["COMMENT"].front()); + oneValueSet.append("COMMENT"); + } else + setComment(String()); + + if(properties.contains("GENRE")) { + setGenre(properties["GENRE"].front()); + oneValueSet.append("GENRE"); + } else + setGenre(String()); + + if(properties.contains("DATE")) { + bool ok; + int date = properties["DATE"].front().toInt(&ok); + if(ok) { + setYear(date); + oneValueSet.append("DATE"); + } else + setYear(0); + } + else + setYear(0); + + if(properties.contains("TRACKNUMBER")) { + bool ok; + int track = properties["TRACKNUMBER"].front().toInt(&ok); + if(ok) { + setTrack(track); + oneValueSet.append("TRACKNUMBER"); + } else + setTrack(0); + } + else + setTrack(0); + + // for each tag that has been set above, remove the first entry in the corresponding + // value list. The others will be returned as unsupported by this format. + for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { + if(properties[*it].size() == 1) + properties.erase(*it); + else + properties[*it].erase( properties[*it].begin() ); + } + return properties; +} + +void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static +{ + if(overwrite) { + target->setTitle(source->title()); + target->setArtist(source->artist()); + target->setAlbum(source->album()); + target->setComment(source->comment()); + target->setGenre(source->genre()); + target->setYear(source->year()); + target->setTrack(source->track()); + } + else { + if(target->title().isEmpty()) + target->setTitle(source->title()); + if(target->artist().isEmpty()) + target->setArtist(source->artist()); + if(target->album().isEmpty()) + target->setAlbum(source->album()); + if(target->comment().isEmpty()) + target->setComment(source->comment()); + if(target->genre().isEmpty()) + target->setGenre(source->genre()); + if(target->year() <= 0) + target->setYear(source->year()); + if(target->track() <= 0) + target->setTrack(source->track()); + } +} diff --git a/external/taglib/source/tag.h b/external/taglib/source/tag.h new file mode 100644 index 0000000..be9628c --- /dev/null +++ b/external/taglib/source/tag.h @@ -0,0 +1,201 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAG_H +#define TAGLIB_TAG_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib { + + //! A simple, generic interface to common audio meta data fields + + /*! + * This is an attempt to abstract away the difference in the meta data formats + * of various audio codecs and tagging schemes. As such it is generally a + * subset of what is available in the specific formats but should be suitable + * for most applications. This is meant to compliment the generic APIs found + * in TagLib::AudioProperties, TagLib::File and TagLib::FileRef. + */ + + class PropertyMap; + + class TAGLIB_EXPORT Tag + { + public: + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + /*! + * Exports the tags of the file as dictionary mapping (human readable) tag + * names (Strings) to StringLists of tag values. + * The default implementation in this class considers only the usual built-in + * tags (artist, album, ...) and only one value per key. + */ + PropertyMap properties() const; + + /*! + * Removes unsupported properties, or a subset of them, from the tag. + * The parameter \a properties must contain only entries from + * properties().unsupportedData(). + * BIC: Will become virtual in future releases. Currently the non-virtual + * standard implementation of TagLib::Tag does nothing, since there are + * no unsupported elements. + */ + void removeUnsupportedProperties(const StringList& properties); + + /*! + * Sets the tags of this File to those specified in \a properties. This default + * implementation sets only the tags for which setter methods exist in this class + * (artist, album, ...), and only one value per key; the rest will be contained + * in the returned PropertyMap. + */ + PropertyMap setProperties(const PropertyMap &properties); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const = 0; + + /*! + * Returns the artist name; if no artist name is present in the tag + * String::null will be returned. + */ + virtual String artist() const = 0; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const = 0; + + /*! + * Returns the track comment; if no comment is present in the tag + * String::null will be returned. + */ + virtual String comment() const = 0; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const = 0; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual unsigned int year() const = 0; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual unsigned int track() const = 0; + + /*! + * Sets the title to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setTitle(const String &s) = 0; + + /*! + * Sets the artist to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setArtist(const String &s) = 0; + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s) = 0; + + /*! + * Sets the comment to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setComment(const String &s) = 0; + + /*! + * Sets the genre to \a s. If \a s is String::null then this value will be + * cleared. For tag formats that use a fixed set of genres, the appropriate + * value will be selected based on a string comparison. A list of available + * genres for those formats should be available in that type's + * implementation. + */ + virtual void setGenre(const String &s) = 0; + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(unsigned int i) = 0; + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(unsigned int i) = 0; + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Copies the generic data from one tag to another. + * + * \note This will no affect any of the lower level details of the tag. For + * instance if any of the tag type specific data (maybe a URL for a band) is + * set, this will not modify or copy that. This just copies using the API + * in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ + static void duplicate(const Tag *source, Tag *target, bool overwrite = true); + + protected: + /*! + * Construct a Tag. This is protected since tags should only be instantiated + * through subclasses. + */ + Tag(); + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; +} + +#endif diff --git a/external/taglib/source/taglib_export.h b/external/taglib/source/taglib_export.h new file mode 100644 index 0000000..737ae64 --- /dev/null +++ b/external/taglib/source/taglib_export.h @@ -0,0 +1,43 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_EXPORT_H +#define TAGLIB_EXPORT_H + +#if defined(TAGLIB_STATIC) +#define TAGLIB_EXPORT +#elif (defined(_WIN32) || defined(_WIN64)) +#ifdef MAKE_TAGLIB_LIB +#define TAGLIB_EXPORT __declspec(dllexport) +#else +#define TAGLIB_EXPORT __declspec(dllimport) +#endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 1) +#define TAGLIB_EXPORT __attribute__ ((visibility("default"))) +#else +#define TAGLIB_EXPORT +#endif + +#endif diff --git a/external/taglib/source/tagunion.cpp b/external/taglib/source/tagunion.cpp new file mode 100644 index 0000000..85741b0 --- /dev/null +++ b/external/taglib/source/tagunion.cpp @@ -0,0 +1,248 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "id3v1tag.h" +#include "id3v2tag.h" +#include "apetag.h" +#include "xiphcomment.h" +#include "infotag.h" + +using namespace TagLib; + +#define stringUnion(method) \ + if(tag(0) && !tag(0)->method().isEmpty()) \ + return tag(0)->method(); \ + if(tag(1) && !tag(1)->method().isEmpty()) \ + return tag(1)->method(); \ + if(tag(2) && !tag(2)->method().isEmpty()) \ + return tag(2)->method(); \ + return String(); \ + +#define numberUnion(method) \ + if(tag(0) && tag(0)->method() > 0) \ + return tag(0)->method(); \ + if(tag(1) && tag(1)->method() > 0) \ + return tag(1)->method(); \ + if(tag(2) && tag(2)->method() > 0) \ + return tag(2)->method(); \ + return 0 + +#define setUnion(method, value) \ + if(tag(0)) \ + tag(0)->set##method(value); \ + if(tag(1)) \ + tag(1)->set##method(value); \ + if(tag(2)) \ + tag(2)->set##method(value); \ + +class TagUnion::TagUnionPrivate +{ +public: + TagUnionPrivate() : tags(3, static_cast(0)) + { + + } + + ~TagUnionPrivate() + { + delete tags[0]; + delete tags[1]; + delete tags[2]; + } + + std::vector tags; +}; + +TagUnion::TagUnion(Tag *first, Tag *second, Tag *third) : + d(new TagUnionPrivate()) +{ + d->tags[0] = first; + d->tags[1] = second; + d->tags[2] = third; +} + +TagUnion::~TagUnion() +{ + delete d; +} + +Tag *TagUnion::operator[](int index) const +{ + return tag(index); +} + +Tag *TagUnion::tag(int index) const +{ + return d->tags[index]; +} + +void TagUnion::set(int index, Tag *tag) +{ + delete d->tags[index]; + d->tags[index] = tag; +} + +PropertyMap TagUnion::properties() const +{ + // This is an ugly workaround but we can't add a virtual function. + // Should be virtual in taglib2. + + for(size_t i = 0; i < 3; ++i) { + + if(d->tags[i] && !d->tags[i]->isEmpty()) { + + if(dynamic_cast(d->tags[i])) + return dynamic_cast(d->tags[i])->properties(); + + if(dynamic_cast(d->tags[i])) + return dynamic_cast(d->tags[i])->properties(); + + if(dynamic_cast(d->tags[i])) + return dynamic_cast(d->tags[i])->properties(); + + if(dynamic_cast(d->tags[i])) + return dynamic_cast(d->tags[i])->properties(); + + if(dynamic_cast(d->tags[i])) + return dynamic_cast(d->tags[i])->properties(); + } + } + + return PropertyMap(); +} + +void TagUnion::removeUnsupportedProperties(const StringList &unsupported) +{ + // This is an ugly workaround but we can't add a virtual function. + // Should be virtual in taglib2. + + for(size_t i = 0; i < 3; ++i) { + + if(d->tags[i]) { + + if(dynamic_cast(d->tags[i])) + dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); + + else if(dynamic_cast(d->tags[i])) + dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); + + else if(dynamic_cast(d->tags[i])) + dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); + + else if(dynamic_cast(d->tags[i])) + dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); + + else if(dynamic_cast(d->tags[i])) + dynamic_cast(d->tags[i])->removeUnsupportedProperties(unsupported); + } + } +} + +String TagUnion::title() const +{ + stringUnion(title); +} + +String TagUnion::artist() const +{ + stringUnion(artist); +} + +String TagUnion::album() const +{ + stringUnion(album); +} + +String TagUnion::comment() const +{ + stringUnion(comment); +} + +String TagUnion::genre() const +{ + stringUnion(genre); +} + +unsigned int TagUnion::year() const +{ + numberUnion(year); +} + +unsigned int TagUnion::track() const +{ + numberUnion(track); +} + +void TagUnion::setTitle(const String &s) +{ + setUnion(Title, s); +} + +void TagUnion::setArtist(const String &s) +{ + setUnion(Artist, s); +} + +void TagUnion::setAlbum(const String &s) +{ + setUnion(Album, s); +} + +void TagUnion::setComment(const String &s) +{ + setUnion(Comment, s); +} + +void TagUnion::setGenre(const String &s) +{ + setUnion(Genre, s); +} + +void TagUnion::setYear(unsigned int i) +{ + setUnion(Year, i); +} + +void TagUnion::setTrack(unsigned int i) +{ + setUnion(Track, i); +} + +bool TagUnion::isEmpty() const +{ + if(d->tags[0] && !d->tags[0]->isEmpty()) + return false; + if(d->tags[1] && !d->tags[1]->isEmpty()) + return false; + if(d->tags[2] && !d->tags[2]->isEmpty()) + return false; + + return true; +} + diff --git a/external/taglib/source/tagunion.h b/external/taglib/source/tagunion.h new file mode 100644 index 0000000..1eb38a0 --- /dev/null +++ b/external/taglib/source/tagunion.h @@ -0,0 +1,98 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAGUNION_H +#define TAGLIB_TAGUNION_H + +#include "tag.h" + +#ifndef DO_NOT_DOCUMENT + +namespace TagLib { + + /*! + * \internal + */ + + class TagUnion : public Tag + { + public: + + enum AccessType { Read, Write }; + + /*! + * Creates a TagLib::Tag that is the union of \a first, \a second, and + * \a third. The TagUnion takes ownership of these tags and will handle + * their deletion. + */ + TagUnion(Tag *first = 0, Tag *second = 0, Tag *third = 0); + + virtual ~TagUnion(); + + Tag *operator[](int index) const; + Tag *tag(int index) const; + + void set(int index, Tag *tag); + + PropertyMap properties() const; + void removeUnsupportedProperties(const StringList &unsupported); + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual unsigned int year() const; + virtual unsigned int track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(unsigned int i); + virtual void setTrack(unsigned int i); + virtual bool isEmpty() const; + + template T *access(int index, bool create) + { + if(!create || tag(index)) + return static_cast(tag(index)); + + set(index, new T); + return static_cast(tag(index)); + } + + private: + TagUnion(const Tag &); + TagUnion &operator=(const Tag &); + + class TagUnionPrivate; + TagUnionPrivate *d; + }; +} + +#endif +#endif diff --git a/external/taglib/source/tagutils.cpp b/external/taglib/source/tagutils.cpp new file mode 100644 index 0000000..5fcd12a --- /dev/null +++ b/external/taglib/source/tagutils.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include + +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" + +#include "tagutils.h" + +using namespace TagLib; + +long Utils::findID3v1(File *file) +{ + if(!file->isValid()) + return -1; + + // Differentiate between a match of APEv2 magic and a match of ID3v1 magic. + + if (file->length() >= 131) { + file->seek(-131, File::End); + const long p = file->tell() + 3; + const TagLib::ByteVector data = file->readBlock(8); + + if(data.containsAt(ID3v1::Tag::fileIdentifier(), 3) && (data != APE::Tag::fileIdentifier())) + return p; + } else { + file->seek(-128, File::End); + const long p = file->tell(); + + if(file->readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + } + + return -1; +} + +long Utils::findID3v2(File *file) +{ + if(!file->isValid()) + return -1; + + file->seek(0); + + if(file->readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} + +long Utils::findAPE(File *file, long id3v1Location) +{ + if(!file->isValid()) + return -1; + + if(id3v1Location >= 0) + file->seek(id3v1Location - 32, File::Beginning); + else + file->seek(-32, File::End); + + const long p = file->tell(); + + if(file->readBlock(8) == APE::Tag::fileIdentifier()) + return p; + + return -1; +} + +ByteVector TagLib::Utils::readHeader(IOStream *stream, unsigned int length, + bool skipID3v2, long *headerOffset) +{ + if(!stream || !stream->isOpen()) + return ByteVector(); + + const long originalPosition = stream->tell(); + long bufferOffset = 0; + + if(skipID3v2) { + stream->seek(0); + const ByteVector data = stream->readBlock(ID3v2::Header::size()); + if(data.startsWith(ID3v2::Header::fileIdentifier())) + bufferOffset = ID3v2::Header(data).completeTagSize(); + } + + stream->seek(bufferOffset); + const ByteVector header = stream->readBlock(length); + stream->seek(originalPosition); + + if(headerOffset) + *headerOffset = bufferOffset; + + return header; +} diff --git a/external/taglib/source/tagutils.h b/external/taglib/source/tagutils.h new file mode 100644 index 0000000..4488a32 --- /dev/null +++ b/external/taglib/source/tagutils.h @@ -0,0 +1,55 @@ +/*************************************************************************** + copyright : (C) 2015 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TAGUTILS_H +#define TAGLIB_TAGUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +#include + +namespace TagLib { + + class File; + class IOStream; + + namespace Utils { + + long findID3v1(File *file); + + long findID3v2(File *file); + + long findAPE(File *file, long id3v1Location); + + ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2, + long *headerOffset = 0); + } +} + +#endif + +#endif diff --git a/external/taglib/source/toolkit/taglib.h b/external/taglib/source/toolkit/taglib.h new file mode 100644 index 0000000..8ea0b99 --- /dev/null +++ b/external/taglib/source/toolkit/taglib.h @@ -0,0 +1,179 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_H +#define TAGLIB_H + +#include "taglib_config.h" + +#define TAGLIB_MAJOR_VERSION 1 +#define TAGLIB_MINOR_VERSION 13 +#define TAGLIB_PATCH_VERSION 0 + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__) +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") +#else +#define TAGLIB_IGNORE_MISSING_DESTRUCTOR +#endif + +#if (defined(_MSC_VER) && _MSC_VER >= 1600) +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#else +#define TAGLIB_CONSTRUCT_BITSET(x) static_cast(x) +#endif + +#if __cplusplus >= 201402 +#define TAGLIB_DEPRECATED [[deprecated]] +#elif defined(__GNUC__) || defined(__clang__) +#define TAGLIB_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define TAGLIB_DEPRECATED __declspec(deprecated) +#else +#define TAGLIB_DEPRECATED +#endif + +#include + +//! A namespace for all TagLib related classes and functions + +/*! + * This namespace contains everything in TagLib. For projects working with + * TagLib extensively it may be convenient to add a + * \code + * using namespace TagLib; + * \endcode + */ + +namespace TagLib { + + class String; + + // These integer types are deprecated. Do not use them. + + typedef wchar_t wchar; // Assumed to be sufficient to store a UTF-16 char. + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned int uint; + typedef unsigned long ulong; + typedef unsigned long long ulonglong; + + /*! + * Unfortunately std::wstring isn't defined on some systems, (i.e. GCC < 3) + * so I'm providing something here that should be constant. + */ + typedef std::basic_string wstring; +} + +/*! + * \mainpage TagLib + * + * \section intro Introduction + * + * TagLib is a library for reading and editing audio meta data, commonly know as \e tags. + * + * Features: + * - A clean, high level, C++ API to handling audio meta data. + * - Format specific APIs for advanced API users. + * - ID3v1, ID3v2, APE, FLAC, Xiph, iTunes-style MP4 and WMA tag formats. + * - MP3, MPC, FLAC, MP4, ASF, AIFF, WAV, TrueAudio, WavPack, Ogg FLAC, Ogg Vorbis, Speex and Opus file formats. + * - Basic audio file properties such as length, sample rate, etc. + * - Long term binary and source compatibility. + * - Extensible design, notably the ability to add other formats or extend current formats as a library user. + * - Full support for unicode and internationalized tags. + * - Dual MPL and + * LGPL licenses. + * - No external toolkit dependencies. + * + * \section why Why TagLib? + * + * TagLib originally was written to provide an updated and improved ID3v2 implementation in C++ for use + * in a variety of Open Source projects. Since development began in 2002 and the 1.0 release in 2004 + * it has expanded to cover a wide variety of tag and file formats and is used in a wide variety of + * Open Source and proprietary applications. It now supports a variety of UNIXes, including Apple's OS + * X, as well as Microsoft Windows. + * + * \section commercial Usage in Commercial Applications + * + * TagLib's licenses \e do allow usage within propriety (\e closed) applications, however TagLib is \e not + * public domain. Please note the requirements of the LGPL or MPL, and adhere to at least one of them. + * In simple terms, you must at a minimum note your usage of TagLib, note the licensing terms of TagLib and + * if you make changes to TagLib publish them. Please review the licenses above before using TagLib in your + * software. Note that you may choose either the MPL or the LGPL, you do not have to fulfill the + * requirements of both. + * + * \section installing Installing TagLib + * + * Please see the TagLib website for the latest + * downloads. + * + * TagLib can be built using the CMake build system. TagLib installs a taglib-config and pkg-config file to + * make it easier to integrate into various build systems. Note that TagLib's include install directory \e must + * be included in the header include path. Simply adding will \e not work. + * + * \section start Getting Started + * + * TagLib provides both simple, abstract APIs which make it possible to ignore the differences between tagging + * formats and format specific APIs which allow programmers to work with the features of specific tagging + * schemes. There is a similar abstraction mechanism for AudioProperties. + * + * The best place to start is with the Class Hierarchy linked at the top of the page. The File and + * AudioProperties classes and their subclasses are the core of TagLib. The FileRef class is also a convenient + * way for using a value-based handle. + * + * \note When working with FileRef please consider that it has only the most basic (extension-based) file + * type resolution. Please see its documentation on how to plug in more advanced file type resolution. (Such + * resolution may be part of later TagLib releases by default.) + * + * Here's a very simple example with TagLib: + * + * \code + * + * TagLib::FileRef f("Latex Solar Beef.mp3"); + * TagLib::String artist = f.tag()->artist(); // artist == "Frank Zappa" + * + * f.tag()->setAlbum("Fillmore East"); + * f.save(); + * + * TagLib::FileRef g("Free City Rhymes.ogg"); + * TagLib::String album = g.tag()->album(); // album == "NYC Ghosts & Flowers" + * + * g.tag()->setTrack(1); + * g.save(); + * + * \endcode + * + * More examples can be found in the \e examples directory of the source distribution. + * + * \section Contact + * + * Questions about TagLib should be directed to the TagLib mailing list, not directly to the author. + * + * - TagLib Homepage + * - TagLib Mailing List (taglib-devel@kde.org) + * + * \author TagLib authors. + */ + +#endif diff --git a/external/taglib/source/toolkit/tbytevector.cpp b/external/taglib/source/toolkit/tbytevector.cpp new file mode 100644 index 0000000..b0d3aa9 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevector.cpp @@ -0,0 +1,1038 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tbytevector.h" + +// This is a bit ugly to keep writing over and over again. + +// A rather obscure feature of the C++ spec that I hadn't thought of that makes +// working with C libs much more efficient. There's more here: +// +// http://www.informit.com/isapi/product_id~{9C84DAB4-FE6E-49C5-BB0A-FB50331233EA}/content/index.asp + +namespace TagLib { + +template +int findChar( + const TIterator dataBegin, const TIterator dataEnd, + char c, unsigned int offset, int byteAlign) +{ + const size_t dataSize = dataEnd - dataBegin; + if(offset + 1 > dataSize) + return -1; + + // n % 0 is invalid + + if(byteAlign == 0) + return -1; + + for(TIterator it = dataBegin + offset; it < dataEnd; it += byteAlign) { + if(*it == c) + return static_cast(it - dataBegin); + } + + return -1; +} + +template +int findVector( + const TIterator dataBegin, const TIterator dataEnd, + const TIterator patternBegin, const TIterator patternEnd, + unsigned int offset, int byteAlign) +{ + const size_t dataSize = dataEnd - dataBegin; + const size_t patternSize = patternEnd - patternBegin; + if(patternSize == 0 || offset + patternSize > dataSize) + return -1; + + // Special case that pattern contains just single char. + + if(patternSize == 1) + return findChar(dataBegin, dataEnd, *patternBegin, offset, byteAlign); + + // n % 0 is invalid + + if(byteAlign == 0) + return -1; + + // We don't use sophisticated algorithms like Knuth-Morris-Pratt here. + + // In the current implementation of TagLib, data and patterns are too small + // for such algorithms to work effectively. + + for(TIterator it = dataBegin + offset; it < dataEnd - patternSize + 1; it += byteAlign) { + + TIterator itData = it; + TIterator itPattern = patternBegin; + + while(*itData == *itPattern) { + ++itData; + ++itPattern; + + if(itPattern == patternEnd) + return static_cast(it - dataBegin); + } + } + + return -1; +} + +template +T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignificantByteFirst) +{ + if(offset >= v.size()) { + debug("toNumber() -- No data to convert. Returning 0."); + return 0; + } + + length = std::min(length, v.size() - offset); + + T sum = 0; + for(size_t i = 0; i < length; i++) { + const size_t shift = (mostSignificantByteFirst ? length - 1 - i : i) * 8; + sum |= static_cast(static_cast(v[static_cast(offset + i)])) << shift; + } + + return sum; +} + +template +T toNumber(const ByteVector &v, size_t offset, bool mostSignificantByteFirst) +{ + const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian); + const bool swap = (mostSignificantByteFirst != isBigEndian); + + if(offset + sizeof(T) > v.size()) + return toNumber(v, offset, v.size() - offset, mostSignificantByteFirst); + + // Uses memcpy instead of reinterpret_cast to avoid an alignment exception. + T tmp; + ::memcpy(&tmp, v.data() + offset, sizeof(T)); + + if(swap) + return Utils::byteSwap(tmp); + return tmp; +} + +template +ByteVector fromNumber(T value, bool mostSignificantByteFirst) +{ + const bool isBigEndian = (Utils::systemByteOrder() == Utils::BigEndian); + const bool swap = (mostSignificantByteFirst != isBigEndian); + + if(swap) + value = Utils::byteSwap(value); + + return ByteVector(reinterpret_cast(&value), sizeof(T)); +} + +template +TFloat toFloat(const ByteVector &v, size_t offset) +{ + if(offset > v.size() - sizeof(TInt)) { + debug("toFloat() - offset is out of range. Returning 0."); + return 0.0; + } + + union { + TInt i; + TFloat f; + } tmp; + ::memcpy(&tmp, v.data() + offset, sizeof(TInt)); + + if(ENDIAN != Utils::systemByteOrder()) + tmp.i = Utils::byteSwap(tmp.i); + + return tmp.f; +} + +template +ByteVector fromFloat(TFloat value) +{ + union { + TInt i; + TFloat f; + } tmp; + tmp.f = value; + + if(ENDIAN != Utils::systemByteOrder()) + tmp.i = Utils::byteSwap(tmp.i); + + return ByteVector(reinterpret_cast(&tmp), sizeof(TInt)); +} + +template +long double toFloat80(const ByteVector &v, size_t offset) +{ + using std::swap; + + if(offset > v.size() - 10) { + debug("toFloat80() - offset is out of range. Returning 0."); + return 0.0; + } + + unsigned char bytes[10]; + ::memcpy(bytes, v.data() + offset, 10); + + if(ENDIAN == Utils::LittleEndian) { + swap(bytes[0], bytes[9]); + swap(bytes[1], bytes[8]); + swap(bytes[2], bytes[7]); + swap(bytes[3], bytes[6]); + swap(bytes[4], bytes[5]); + } + + // 1-bit sign + const bool negative = ((bytes[0] & 0x80) != 0); + + // 15-bit exponent + const int exponent = ((bytes[0] & 0x7F) << 8) | bytes[1]; + + // 64-bit fraction. Leading 1 is explicit. + const unsigned long long fraction + = (static_cast(bytes[2]) << 56) + | (static_cast(bytes[3]) << 48) + | (static_cast(bytes[4]) << 40) + | (static_cast(bytes[5]) << 32) + | (static_cast(bytes[6]) << 24) + | (static_cast(bytes[7]) << 16) + | (static_cast(bytes[8]) << 8) + | (static_cast(bytes[9])); + + long double val; + if(exponent == 0 && fraction == 0) + val = 0; + else { + if(exponent == 0x7FFF) { + debug("toFloat80() - can't handle the infinity or NaN. Returning 0."); + return 0.0; + } + val = ::ldexp(static_cast(fraction), exponent - 16383 - 63); + } + + if(negative) + return -val; + return val; +} + +class ByteVector::ByteVectorPrivate +{ +public: + ByteVectorPrivate(unsigned int l, char c) : + counter(new RefCounter()), + data(new std::vector(l, c)), + offset(0), + length(l) {} + + ByteVectorPrivate(const char *s, unsigned int l) : + counter(new RefCounter()), + data(new std::vector(s, s + l)), + offset(0), + length(l) {} + + ByteVectorPrivate(const ByteVectorPrivate &d, unsigned int o, unsigned int l) : + counter(d.counter), + data(d.data), + offset(d.offset + o), + length(l) + { + counter->ref(); + } + + ~ByteVectorPrivate() + { + if(counter->deref()) { + delete counter; + delete data; + } + } + + RefCounter *counter; + std::vector *data; + unsigned int offset; + unsigned int length; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +ByteVector ByteVector::null; + +ByteVector ByteVector::fromCString(const char *s, unsigned int length) +{ + if(length == 0xffffffff) + return ByteVector(s, static_cast(::strlen(s))); + return ByteVector(s, length); +} + +ByteVector ByteVector::fromUInt(unsigned int value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +ByteVector ByteVector::fromShort(short value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +ByteVector ByteVector::fromLongLong(long long value, bool mostSignificantByteFirst) +{ + return fromNumber(value, mostSignificantByteFirst); +} + +ByteVector ByteVector::fromFloat32LE(float value) +{ + return fromFloat(value); +} + +ByteVector ByteVector::fromFloat32BE(float value) +{ + return fromFloat(value); +} + +ByteVector ByteVector::fromFloat64LE(double value) +{ + return fromFloat(value); +} + +ByteVector ByteVector::fromFloat64BE(double value) +{ + return fromFloat(value); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ByteVector::ByteVector() : + d(new ByteVectorPrivate(0, '\0')) +{ +} + +ByteVector::ByteVector(unsigned int size, char value) : + d(new ByteVectorPrivate(size, value)) +{ +} + +ByteVector::ByteVector(const ByteVector &v) : + d(new ByteVectorPrivate(*v.d, 0, v.d->length)) +{ +} + +ByteVector::ByteVector(const ByteVector &v, unsigned int offset, unsigned int length) : + d(new ByteVectorPrivate(*v.d, offset, length)) +{ +} + +ByteVector::ByteVector(char c) : + d(new ByteVectorPrivate(1, c)) +{ +} + +ByteVector::ByteVector(const char *data, unsigned int length) : + d(new ByteVectorPrivate(data, length)) +{ +} + +ByteVector::ByteVector(const char *data) : + d(new ByteVectorPrivate(data, static_cast(::strlen(data)))) +{ +} + +ByteVector::~ByteVector() +{ + delete d; +} + +ByteVector &ByteVector::setData(const char *s, unsigned int length) +{ + ByteVector(s, length).swap(*this); + return *this; +} + +ByteVector &ByteVector::setData(const char *data) +{ + ByteVector(data).swap(*this); + return *this; +} + +char *ByteVector::data() +{ + detach(); + return (size() > 0) ? (&(*d->data)[d->offset]) : 0; +} + +const char *ByteVector::data() const +{ + return (size() > 0) ? (&(*d->data)[d->offset]) : 0; +} + +ByteVector ByteVector::mid(unsigned int index, unsigned int length) const +{ + index = std::min(index, size()); + length = std::min(length, size() - index); + + return ByteVector(*this, index, length); +} + +char ByteVector::at(unsigned int index) const +{ + return (index < size()) ? (*d->data)[d->offset + index] : 0; +} + +int ByteVector::find(const ByteVector &pattern, unsigned int offset, int byteAlign) const +{ + return findVector( + begin(), end(), pattern.begin(), pattern.end(), offset, byteAlign); +} + +int ByteVector::find(char c, unsigned int offset, int byteAlign) const +{ + return findChar(begin(), end(), c, offset, byteAlign); +} + +int ByteVector::rfind(const ByteVector &pattern, unsigned int offset, int byteAlign) const +{ + if(offset > 0) { + offset = size() - offset - pattern.size(); + if(offset >= size()) + offset = 0; + } + + const int pos = findVector( + rbegin(), rend(), pattern.rbegin(), pattern.rend(), offset, byteAlign); + + if(pos == -1) + return -1; + return size() - pos - pattern.size(); +} + +bool ByteVector::containsAt(const ByteVector &pattern, unsigned int offset, unsigned int patternOffset, unsigned int patternLength) const +{ + if(pattern.size() < patternLength) + patternLength = pattern.size(); + + // do some sanity checking -- all of these things are needed for the search to be valid + const unsigned int compareLength = patternLength - patternOffset; + if(offset + compareLength > size() || patternOffset >= pattern.size() || patternLength == 0) + return false; + + return (::memcmp(data() + offset, pattern.data() + patternOffset, compareLength) == 0); +} + +bool ByteVector::startsWith(const ByteVector &pattern) const +{ + return containsAt(pattern, 0); +} + +bool ByteVector::endsWith(const ByteVector &pattern) const +{ + return containsAt(pattern, size() - pattern.size()); +} + +ByteVector &ByteVector::replace(char oldByte, char newByte) +{ + detach(); + + for(ByteVector::Iterator it = begin(); it != end(); ++it) { + if(*it == oldByte) + *it = newByte; + } + + return *this; +} + +ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &with) +{ + if(pattern.size() == 1 && with.size() == 1) + return replace(pattern[0], with[0]); + + // Check if there is at least one occurrence of the pattern. + + int offset = find(pattern, 0); + if(offset == -1) + return *this; + + if(pattern.size() == with.size()) { + + // We think this case might be common enough to optimize it. + + detach(); + do + { + ::memcpy(data() + offset, with.data(), with.size()); + offset = find(pattern, offset + pattern.size()); + } while(offset != -1); + } + else { + + // Loop once to calculate the result size. + + unsigned int dstSize = size(); + do + { + dstSize += with.size() - pattern.size(); + offset = find(pattern, offset + pattern.size()); + } while(offset != -1); + + // Loop again to copy modified data to the new vector. + + ByteVector dst(dstSize); + int dstOffset = 0; + + offset = 0; + while(true) { + const int next = find(pattern, offset); + if(next == -1) { + ::memcpy(dst.data() + dstOffset, data() + offset, size() - offset); + break; + } + + ::memcpy(dst.data() + dstOffset, data() + offset, next - offset); + dstOffset += next - offset; + + ::memcpy(dst.data() + dstOffset, with.data(), with.size()); + dstOffset += with.size(); + + offset = next + pattern.size(); + } + + swap(dst); + } + + return *this; +} + +int ByteVector::endsWithPartialMatch(const ByteVector &pattern) const +{ + if(pattern.size() > size()) + return -1; + + const int startIndex = size() - pattern.size(); + + // try to match the last n-1 bytes from the vector (where n is the pattern + // size) -- continue trying to match n-2, n-3...1 bytes + + for(unsigned int i = 1; i < pattern.size(); i++) { + if(containsAt(pattern, startIndex + i, 0, pattern.size() - i)) + return startIndex + i; + } + + return -1; +} + +ByteVector &ByteVector::append(const ByteVector &v) +{ + if(v.isEmpty()) + return *this; + + detach(); + + const unsigned int originalSize = size(); + const unsigned int appendSize = v.size(); + + resize(originalSize + appendSize); + ::memcpy(data() + originalSize, v.data(), appendSize); + + return *this; +} + +ByteVector &ByteVector::append(char c) +{ + resize(size() + 1, c); + return *this; +} + +ByteVector &ByteVector::clear() +{ + ByteVector().swap(*this); + return *this; +} + +unsigned int ByteVector::size() const +{ + return d->length; +} + +ByteVector &ByteVector::resize(unsigned int size, char padding) +{ + if(size != d->length) { + detach(); + + // Remove the excessive length of the internal buffer first to pad correctly. + // This doesn't reallocate the buffer, since std::vector::resize() doesn't + // reallocate the buffer when shrinking. + + d->data->resize(d->offset + d->length); + d->data->resize(d->offset + size, padding); + + d->length = size; + } + + return *this; +} + +ByteVector::Iterator ByteVector::begin() +{ + detach(); + return d->data->begin() + d->offset; +} + +ByteVector::ConstIterator ByteVector::begin() const +{ + return d->data->begin() + d->offset; +} + +ByteVector::Iterator ByteVector::end() +{ + detach(); + return d->data->begin() + d->offset + d->length; +} + +ByteVector::ConstIterator ByteVector::end() const +{ + return d->data->begin() + d->offset + d->length; +} + +ByteVector::ReverseIterator ByteVector::rbegin() +{ + detach(); + return d->data->rbegin() + (d->data->size() - (d->offset + d->length)); +} + +ByteVector::ConstReverseIterator ByteVector::rbegin() const +{ + // Workaround for the Solaris Studio 12.4 compiler. + // We need a const reference to the data vector so we can ensure the const version of rbegin() is called. + const std::vector &v = *d->data; + return v.rbegin() + (v.size() - (d->offset + d->length)); +} + +ByteVector::ReverseIterator ByteVector::rend() +{ + detach(); + return d->data->rbegin() + (d->data->size() - d->offset); +} + +ByteVector::ConstReverseIterator ByteVector::rend() const +{ + // Workaround for the Solaris Studio 12.4 compiler. + // We need a const reference to the data vector so we can ensure the const version of rbegin() is called. + const std::vector &v = *d->data; + return v.rbegin() + (v.size() - d->offset); +} + +bool ByteVector::isNull() const +{ + return (d == null.d); +} + +bool ByteVector::isEmpty() const +{ + return (d->length == 0); +} + +unsigned int ByteVector::checksum() const +{ + static const unsigned int crcTable[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 + }; + + unsigned int sum = 0; + for(ByteVector::ConstIterator it = begin(); it != end(); ++it) + sum = (sum << 8) ^ crcTable[((sum >> 24) & 0xff) ^ static_cast(*it)]; + return sum; +} + +unsigned int ByteVector::toUInt(bool mostSignificantByteFirst) const +{ + return toNumber(*this, 0, mostSignificantByteFirst); +} + +unsigned int ByteVector::toUInt(unsigned int offset, bool mostSignificantByteFirst) const +{ + return toNumber(*this, offset, mostSignificantByteFirst); +} + +unsigned int ByteVector::toUInt(unsigned int offset, unsigned int length, bool mostSignificantByteFirst) const +{ + return toNumber(*this, offset, length, mostSignificantByteFirst); +} + +short ByteVector::toShort(bool mostSignificantByteFirst) const +{ + return toNumber(*this, 0, mostSignificantByteFirst); +} + +short ByteVector::toShort(unsigned int offset, bool mostSignificantByteFirst) const +{ + return toNumber(*this, offset, mostSignificantByteFirst); +} + +unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const +{ + return toNumber(*this, 0, mostSignificantByteFirst); +} + +unsigned short ByteVector::toUShort(unsigned int offset, bool mostSignificantByteFirst) const +{ + return toNumber(*this, offset, mostSignificantByteFirst); +} + +long long ByteVector::toLongLong(bool mostSignificantByteFirst) const +{ + return toNumber(*this, 0, mostSignificantByteFirst); +} + +long long ByteVector::toLongLong(unsigned int offset, bool mostSignificantByteFirst) const +{ + return toNumber(*this, offset, mostSignificantByteFirst); +} + +float ByteVector::toFloat32LE(size_t offset) const +{ + return toFloat(*this, offset); +} + +float ByteVector::toFloat32BE(size_t offset) const +{ + return toFloat(*this, offset); +} + +double ByteVector::toFloat64LE(size_t offset) const +{ + return toFloat(*this, offset); +} + +double ByteVector::toFloat64BE(size_t offset) const +{ + return toFloat(*this, offset); +} + +long double ByteVector::toFloat80LE(size_t offset) const +{ + return toFloat80(*this, offset); +} + +long double ByteVector::toFloat80BE(size_t offset) const +{ + return toFloat80(*this, offset); +} + +const char &ByteVector::operator[](int index) const +{ + return (*d->data)[d->offset + index]; +} + +char &ByteVector::operator[](int index) +{ + detach(); + return (*d->data)[d->offset + index]; +} + +bool ByteVector::operator==(const ByteVector &v) const +{ + if(size() != v.size()) + return false; + + return (::memcmp(data(), v.data(), size()) == 0); +} + +bool ByteVector::operator!=(const ByteVector &v) const +{ + return !(*this == v); +} + +bool ByteVector::operator==(const char *s) const +{ + if(size() != ::strlen(s)) + return false; + + return (::memcmp(data(), s, size()) == 0); +} + +bool ByteVector::operator!=(const char *s) const +{ + return !(*this == s); +} + +bool ByteVector::operator<(const ByteVector &v) const +{ + const int result = ::memcmp(data(), v.data(), std::min(size(), v.size())); + if(result != 0) + return result < 0; + return size() < v.size(); +} + +bool ByteVector::operator>(const ByteVector &v) const +{ + return (v < *this); +} + +ByteVector ByteVector::operator+(const ByteVector &v) const +{ + ByteVector sum(*this); + sum.append(v); + return sum; +} + +ByteVector &ByteVector::operator=(const ByteVector &v) +{ + ByteVector(v).swap(*this); + return *this; +} + +ByteVector &ByteVector::operator=(char c) +{ + ByteVector(c).swap(*this); + return *this; +} + +ByteVector &ByteVector::operator=(const char *data) +{ + ByteVector(data).swap(*this); + return *this; +} + +void ByteVector::swap(ByteVector &v) +{ + using std::swap; + + swap(d, v.d); +} + +ByteVector ByteVector::toHex() const +{ + static const char hexTable[17] = "0123456789abcdef"; + + ByteVector encoded(size() * 2); + char *p = encoded.data(); + + for(unsigned int i = 0; i < size(); i++) { + unsigned char c = data()[i]; + *p++ = hexTable[(c >> 4) & 0x0F]; + *p++ = hexTable[(c ) & 0x0F]; + } + + return encoded; +} + +ByteVector ByteVector::fromBase64(const ByteVector & input) +{ + static const unsigned char base64[256] = { + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x3e,0x80,0x80,0x80,0x3f, + 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, + 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x80,0x80,0x80,0x80,0x80, + 0x80,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80 + }; + + unsigned int len = input.size(); + + ByteVector output(len); + + const unsigned char * src = reinterpret_cast(input.data()); + unsigned char * dst = reinterpret_cast(output.data()); + + while(4 <= len) { + + // Check invalid character + if(base64[src[0]] == 0x80) + break; + + // Check invalid character + if(base64[src[1]] == 0x80) + break; + + // Decode first byte + *dst++ = ((base64[src[0]] << 2) & 0xfc) | ((base64[src[1]] >> 4) & 0x03); + + if(src[2] != '=') { + + // Check invalid character + if(base64[src[2]] == 0x80) + break; + + // Decode second byte + *dst++ = ((base64[src[1]] & 0x0f) << 4) | ((base64[src[2]] >> 2) & 0x0f); + + if(src[3] != '=') { + + // Check invalid character + if(base64[src[3]] == 0x80) + break; + + // Decode third byte + *dst++ = ((base64[src[2]] & 0x03) << 6) | (base64[src[3]] & 0x3f); + } + else { + // assume end of data + len -= 4; + break; + } + } + else { + // assume end of data + len -= 4; + break; + } + src += 4; + len -= 4; + } + + // Only return output if we processed all bytes + if(len == 0) { + output.resize(static_cast(dst - reinterpret_cast(output.data()))); + return output; + } + return ByteVector(); +} + +ByteVector ByteVector::toBase64() const +{ + static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if(!isEmpty()) { + unsigned int len = size(); + ByteVector output(4 * ((len - 1) / 3 + 1)); // note roundup + + const char * src = data(); + char * dst = output.data(); + while(3 <= len) { + *dst++ = alphabet[(src[0] >> 2) & 0x3f]; + *dst++ = alphabet[((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0f)]; + *dst++ = alphabet[((src[1] & 0x0f) << 2) | ((src[2] >> 6) & 0x03)]; + *dst++ = alphabet[src[2] & 0x3f]; + src += 3; + len -= 3; + } + if(len) { + *dst++ = alphabet[(src[0] >> 2) & 0x3f]; + if(len>1) { + *dst++ = alphabet[((src[0] & 0x03) << 4) | ((src[1] >> 4) & 0x0f)]; + *dst++ = alphabet[((src[1] & 0x0f) << 2)]; + } + else { + *dst++ = alphabet[(src[0] & 0x03) << 4]; + *dst++ = '='; + } + *dst++ = '='; + } + return output; + } + return ByteVector(); +} + + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void ByteVector::detach() +{ + if(d->counter->count() > 1) { + if(!isEmpty()) + ByteVector(&d->data->front() + d->offset, d->length).swap(*this); + else + ByteVector().swap(*this); + } +} +} // namespace TagLib + +//////////////////////////////////////////////////////////////////////////////// +// related functions +//////////////////////////////////////////////////////////////////////////////// + +std::ostream &operator<<(std::ostream &s, const TagLib::ByteVector &v) +{ + for(unsigned int i = 0; i < v.size(); i++) + s << v[i]; + return s; +} diff --git a/external/taglib/source/toolkit/tbytevector.h b/external/taglib/source/toolkit/tbytevector.h new file mode 100644 index 0000000..41373c7 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevector.h @@ -0,0 +1,635 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTOR_H +#define TAGLIB_BYTEVECTOR_H + +#include "taglib.h" +#include "taglib_export.h" + +#include +#include + +namespace TagLib { + + //! A byte vector + + /*! + * This class provides a byte vector with some methods that are useful for + * tagging purposes. Many of the search functions are tailored to what is + * useful for finding tag related patterns in a data array. + */ + + class TAGLIB_EXPORT ByteVector + { + public: +#ifndef DO_NOT_DOCUMENT + typedef std::vector::iterator Iterator; + typedef std::vector::const_iterator ConstIterator; + typedef std::vector::reverse_iterator ReverseIterator; + typedef std::vector::const_reverse_iterator ConstReverseIterator; +#endif + + /*! + * Constructs an empty byte vector. + */ + ByteVector(); + + /*! + * Construct a vector of size \a size with all values set to \a value by + * default. + */ + ByteVector(unsigned int size, char value = 0); + + /*! + * Constructs a byte vector that is a copy of \a v. + */ + ByteVector(const ByteVector &v); + + /*! + * Constructs a byte vector that is a copy of \a v. + */ + ByteVector(const ByteVector &v, unsigned int offset, unsigned int length); + + /*! + * Constructs a byte vector that contains \a c. + */ + ByteVector(char c); + + /*! + * Constructs a byte vector that copies \a data for up to \a length bytes. + */ + ByteVector(const char *data, unsigned int length); + + /*! + * Constructs a byte vector that copies \a data up to the first null + * byte. This is particularly useful for constructing byte arrays from + * string constants. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ + ByteVector(const char *data); + + /*! + * Destroys this ByteVector instance. + */ + virtual ~ByteVector(); + + /*! + * Sets the data for the byte array using the first \a length bytes of \a data + */ + ByteVector &setData(const char *data, unsigned int length); + + /*! + * Sets the data for the byte array copies \a data up to the first null + * byte. The behavior is undefined if \a data is not null terminated. + */ + ByteVector &setData(const char *data); + + /*! + * Returns a pointer to the internal data structure. + * + * \warning Care should be taken when modifying this data structure as it is + * easy to corrupt the ByteVector when doing so. Specifically, while the + * data may be changed, its length may not be. + */ + char *data(); + + /*! + * Returns a pointer to the internal data structure which may not be modified. + */ + const char *data() const; + + /*! + * Returns a byte vector made up of the bytes starting at \a index and + * for \a length bytes. If \a length is not specified it will return the bytes + * from \a index to the end of the vector. + */ + ByteVector mid(unsigned int index, unsigned int length = 0xffffffff) const; + + /*! + * This essentially performs the same as operator[](), but instead of causing + * a runtime error if the index is out of bounds, it will return a null byte. + */ + char at(unsigned int index) const; + + /*! + * Searches the ByteVector for \a pattern starting at \a offset and returns + * the offset. Returns -1 if the pattern was not found. If \a byteAlign is + * specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ + int find(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Searches the char for \a c starting at \a offset and returns + * the offset. Returns \a -1 if the pattern was not found. If \a byteAlign is + * specified the pattern will only be matched if it starts on a byte divisible + * by \a byteAlign (starting from \a offset). + */ + int find(char c, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Searches the ByteVector for \a pattern starting from either the end of the + * vector or \a offset and returns the offset. Returns -1 if the pattern was + * not found. If \a byteAlign is specified the pattern will only be matched + * if it starts on a byte divisible by \a byteAlign (starting from \a offset). + */ + int rfind(const ByteVector &pattern, unsigned int offset = 0, int byteAlign = 1) const; + + /*! + * Checks to see if the vector contains the \a pattern starting at position + * \a offset. Optionally, if you only want to search for part of the pattern + * you can specify an offset within the pattern to start from. Also, you can + * specify to only check for the first \a patternLength bytes of \a pattern with + * the \a patternLength argument. + */ + bool containsAt(const ByteVector &pattern, unsigned int offset, + unsigned int patternOffset = 0, unsigned int patternLength = 0xffffffff) const; + + /*! + * Returns true if the vector starts with \a pattern. + */ + bool startsWith(const ByteVector &pattern) const; + + /*! + * Returns true if the vector ends with \a pattern. + */ + bool endsWith(const ByteVector &pattern) const; + + /*! + * Replaces \a oldByte with \a newByte and returns a reference to the + * ByteVector after the operation. This \e does modify the vector. + */ + ByteVector &replace(char oldByte, char newByte); + + /*! + * Replaces \a pattern with \a with and returns a reference to the ByteVector + * after the operation. This \e does modify the vector. + */ + ByteVector &replace(const ByteVector &pattern, const ByteVector &with); + + /*! + * Checks for a partial match of \a pattern at the end of the vector. It + * returns the offset of the partial match within the vector, or -1 if the + * pattern is not found. This method is particularly useful when searching for + * patterns that start in one vector and end in another. When combined with + * startsWith() it can be used to find a pattern that overlaps two buffers. + * + * \note This will not match the complete pattern at the end of the string; use + * endsWith() for that. + */ + int endsWithPartialMatch(const ByteVector &pattern) const; + + /*! + * Appends \a v to the end of the ByteVector. + */ + ByteVector &append(const ByteVector &v); + + /*! + * Appends \a c to the end of the ByteVector. + */ + ByteVector &append(char c); + + /*! + * Clears the data. + */ + ByteVector &clear(); + + /*! + * Returns the size of the array. + */ + unsigned int size() const; + + /*! + * Resize the vector to \a size. If the vector is currently less than + * \a size, pad the remaining spaces with \a padding. Returns a reference + * to the resized vector. + */ + ByteVector &resize(unsigned int size, char padding = 0); + + /*! + * Returns an Iterator that points to the front of the vector. + */ + Iterator begin(); + + /*! + * Returns a ConstIterator that points to the front of the vector. + */ + ConstIterator begin() const; + + /*! + * Returns an Iterator that points to the back of the vector. + */ + Iterator end(); + + /*! + * Returns a ConstIterator that points to the back of the vector. + */ + ConstIterator end() const; + + /*! + * Returns a ReverseIterator that points to the front of the vector. + */ + ReverseIterator rbegin(); + + /*! + * Returns a ConstReverseIterator that points to the front of the vector. + */ + ConstReverseIterator rbegin() const; + + /*! + * Returns a ReverseIterator that points to the back of the vector. + */ + ReverseIterator rend(); + + /*! + * Returns a ConstReverseIterator that points to the back of the vector. + */ + ConstReverseIterator rend() const; + + /*! + * Returns true if the vector is null. + * + * \note A vector may be empty without being null. So do not use this + * method to check if the vector is empty. + * + * \see isEmpty() + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED bool isNull() const; + + /*! + * Returns true if the ByteVector is empty. + * + * \see size() + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns a CRC checksum of the byte vector's data. + * + * \note This uses an uncommon variant of CRC32 specializes in Ogg. + */ + // BIC: Remove or make generic. + unsigned int checksum() const; + + /*! + * Converts the first 4 bytes of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 4 bytes at \a offset of the vector to an unsigned integer. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the \a length bytes at \a offset of the vector to an unsigned + * integer. If \a length is larger than 4, the excess is ignored. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $00 $00 $01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see fromUInt() + */ + unsigned int toUInt(unsigned int offset, unsigned int length, + bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + short toShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 2 bytes at \a offset of the vector to a (signed) short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + short toShort(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 2 bytes at \a offset of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /*! + * Converts the first 8 bytes of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ + long long toLongLong(bool mostSignificantByteFirst = true) const; + + /*! + * Converts the 8 bytes at \a offset of the vector to a (signed) long long. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 00 00 00 00 00 00 01 == 0x0000000000000001 == 1, + * if false, $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see fromUInt() + */ + long long toLongLong(unsigned int offset, bool mostSignificantByteFirst = true) const; + + /* + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 + * 32-bit little-endian floating point number. + */ + float toFloat32LE(size_t offset) const; + + /* + * Converts the 4 bytes at \a offset of the vector to a float as an IEEE754 + * 32-bit big-endian floating point number. + */ + float toFloat32BE(size_t offset) const; + + /* + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 + * 64-bit little-endian floating point number. + */ + double toFloat64LE(size_t offset) const; + + /* + * Converts the 8 bytes at \a offset of the vector to a double as an IEEE754 + * 64-bit big-endian floating point number. + */ + double toFloat64BE(size_t offset) const; + + /* + * Converts the 10 bytes at \a offset of the vector to a long double as an + * IEEE754 80-bit little-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ + long double toFloat80LE(size_t offset) const; + + /* + * Converts the 10 bytes at \a offset of the vector to a long double as an + * IEEE754 80-bit big-endian floating point number. + * + * \note This may compromise the precision depends on the size of long double. + */ + long double toFloat80BE(size_t offset) const; + + /*! + * Creates a 4 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x00000001 == 1, if false, $01 00 00 00 == + * 0x01000000 == 1. + * + * \see toUInt() + */ + static ByteVector fromUInt(unsigned int value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 2 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 01 == 0x0001 == 1, if false, $01 00 == 0x0100 == 1. + * + * \see toShort() + */ + static ByteVector fromShort(short value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 8 byte ByteVector based on \a value. If + * \a mostSignificantByteFirst is true, then this will operate left to right + * in building the ByteVector. For example if \a mostSignificantByteFirst is + * true then $00 00 00 01 == 0x0000000000000001 == 1, if false, + * $01 00 00 00 00 00 00 00 == 0x0100000000000000 == 1. + * + * \see toLongLong() + */ + static ByteVector fromLongLong(long long value, bool mostSignificantByteFirst = true); + + /*! + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit + * little-endian floating point number. + * + * \see fromFloat32BE() + */ + static ByteVector fromFloat32LE(float value); + + /*! + * Creates a 4 byte ByteVector based on \a value as an IEEE754 32-bit + * big-endian floating point number. + * + * \see fromFloat32LE() + */ + static ByteVector fromFloat32BE(float value); + + /*! + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit + * little-endian floating point number. + * + * \see fromFloat64BE() + */ + static ByteVector fromFloat64LE(double value); + + /*! + * Creates a 8 byte ByteVector based on \a value as an IEEE754 64-bit + * big-endian floating point number. + * + * \see fromFloat64LE() + */ + static ByteVector fromFloat64BE(double value); + + /*! + * Returns a ByteVector based on the CString \a s. + */ + static ByteVector fromCString(const char *s, unsigned int length = 0xffffffff); + + /*! + * Returns a const reference to the byte at \a index. + */ + const char &operator[](int index) const; + + /*! + * Returns a reference to the byte at \a index. + */ + char &operator[](int index); + + /*! + * Returns true if this ByteVector and \a v are equal. + */ + bool operator==(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and \a v are not equal. + */ + bool operator!=(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * contain the same data. + */ + bool operator==(const char *s) const; + + /*! + * Returns true if this ByteVector and the null terminated C string \a s + * do not contain the same data. + */ + bool operator!=(const char *s) const; + + /*! + * Returns true if this ByteVector is less than \a v. The value of the + * vectors is determined by evaluating the character from left to right, and + * in the event one vector is a superset of the other, the size is used. + */ + bool operator<(const ByteVector &v) const; + + /*! + * Returns true if this ByteVector is greater than \a v. + */ + bool operator>(const ByteVector &v) const; + + /*! + * Returns a vector that is \a v appended to this vector. + */ + ByteVector operator+(const ByteVector &v) const; + + /*! + * Copies ByteVector \a v. + */ + ByteVector &operator=(const ByteVector &v); + + /*! + * Copies a byte \a c. + */ + ByteVector &operator=(char c); + + /*! + * Copies \a data up to the first null byte. + * + * \warning The behavior is undefined if \a data is not null terminated. + */ + ByteVector &operator=(const char *data); + + /*! + * Exchanges the content of the ByteVector by the content of \a v. + */ + void swap(ByteVector &v); + + /*! + * A static, empty ByteVector which is convenient and fast (since returning + * an empty or "null" value does not require instantiating a new ByteVector). + * + * \warning Do not modify this variable. It will mess up the internal state + * of TagLib. + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED static ByteVector null; + + /*! + * Returns a hex-encoded copy of the byte vector. + */ + ByteVector toHex() const; + + /*! + * Returns a base64 encoded copy of the byte vector + */ + ByteVector toBase64() const; + + /*! + * Decodes the base64 encoded byte vector. + */ + static ByteVector fromBase64(const ByteVector &); + + protected: + /* + * If this ByteVector is being shared via implicit sharing, do a deep copy + * of the data and separate from the shared members. This should be called + * by all non-const subclass members. + */ + void detach(); + + private: + class ByteVectorPrivate; + ByteVectorPrivate *d; + }; +} + +/*! + * \relates TagLib::ByteVector + * Streams the ByteVector \a v to the output stream \a s. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::ByteVector &v); + +#endif diff --git a/external/taglib/source/toolkit/tbytevectorlist.cpp b/external/taglib/source/toolkit/tbytevectorlist.cpp new file mode 100644 index 0000000..e71d4a7 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevectorlist.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tbytevectorlist.h" + +using namespace TagLib; + +class ByteVectorListPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, + int byteAlign) +{ + return split(v, pattern, byteAlign, 0); +} + +ByteVectorList ByteVectorList::split(const ByteVector &v, const ByteVector &pattern, + int byteAlign, int max) +{ + ByteVectorList l; + + unsigned int previousOffset = 0; + for(int offset = v.find(pattern, 0, byteAlign); + offset != -1 && (max == 0 || max > int(l.size()) + 1); + offset = v.find(pattern, offset + pattern.size(), byteAlign)) + { + if(offset - previousOffset >= 1) + l.append(v.mid(previousOffset, offset - previousOffset)); + else + l.append(ByteVector()); + + previousOffset = offset + pattern.size(); + } + + if(previousOffset < v.size()) + l.append(v.mid(previousOffset, v.size() - previousOffset)); + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ByteVectorList::ByteVectorList() +{ + +} + +ByteVectorList::ByteVectorList(const ByteVectorList &l) : List(l) +{ + +} + +ByteVectorList::~ByteVectorList() +{ + +} + +ByteVector ByteVectorList::toByteVector(const ByteVector &separator) const +{ + ByteVector v; + + ConstIterator it = begin(); + + while(it != end()) { + v.append(*it); + it++; + if(it != end()) + v.append(separator); + } + + return v; +} diff --git a/external/taglib/source/toolkit/tbytevectorlist.h b/external/taglib/source/toolkit/tbytevectorlist.h new file mode 100644 index 0000000..5852583 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevectorlist.h @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTORLIST_H +#define TAGLIB_BYTEVECTORLIST_H + +#include "taglib_export.h" +#include "tbytevector.h" +#include "tlist.h" + +namespace TagLib { + + //! A list of ByteVectors + + /*! + * A List specialization with some handy features useful for ByteVectors. + */ + + class TAGLIB_EXPORT ByteVectorList : public List + { + public: + + /*! + * Construct an empty ByteVectorList. + */ + ByteVectorList(); + + /*! + * Destroys this ByteVectorList instance. + */ + virtual ~ByteVectorList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + ByteVectorList(const ByteVectorList &l); + + /*! + * Convert the ByteVectorList to a ByteVector separated by \a separator. By + * default a space is used. + */ + ByteVector toByteVector(const ByteVector &separator = " ") const; + + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. + */ + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign = 1); + /*! + * Splits the ByteVector \a v into several strings at \a pattern. This will + * not include the pattern in the returned ByteVectors. \a max is the + * maximum number of entries that will be separated. If \a max for instance + * is 2 then a maximum of 1 match will be found and the vector will be split + * on that match. + */ + // BIC: merge with the function above + static ByteVectorList split(const ByteVector &v, const ByteVector &pattern, + int byteAlign, int max); + private: + class ByteVectorListPrivate; + ByteVectorListPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/source/toolkit/tbytevectorstream.cpp b/external/taglib/source/toolkit/tbytevectorstream.cpp new file mode 100644 index 0000000..333f528 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevectorstream.cpp @@ -0,0 +1,167 @@ +/*************************************************************************** + copyright : (C) 2011 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tbytevectorstream.h" +#include "tstring.h" +#include "tdebug.h" + +#include +#include + +#include + +using namespace TagLib; + +class ByteVectorStream::ByteVectorStreamPrivate +{ +public: + ByteVectorStreamPrivate(const ByteVector &data); + + ByteVector data; + long position; +}; + +ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) : + data(data), + position(0) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ByteVectorStream::ByteVectorStream(const ByteVector &data) : + d(new ByteVectorStreamPrivate(data)) +{ +} + +ByteVectorStream::~ByteVectorStream() +{ + delete d; +} + +FileName ByteVectorStream::name() const +{ + return FileName(""); // XXX do we need a name? +} + +ByteVector ByteVectorStream::readBlock(unsigned long length) +{ + if(length == 0) + return ByteVector(); + + ByteVector v = d->data.mid(d->position, length); + d->position += v.size(); + return v; +} + +void ByteVectorStream::writeBlock(const ByteVector &data) +{ + unsigned int size = data.size(); + if(long(d->position + size) > length()) { + truncate(d->position + size); + } + memcpy(d->data.data() + d->position, data.data(), size); + d->position += size; +} + +void ByteVectorStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) +{ + long sizeDiff = data.size() - replace; + if(sizeDiff < 0) { + removeBlock(start + data.size(), -sizeDiff); + } + else if(sizeDiff > 0) { + truncate(length() + sizeDiff); + unsigned long readPosition = start + replace; + unsigned long writePosition = start + data.size(); + memmove(d->data.data() + writePosition, d->data.data() + readPosition, length() - sizeDiff - readPosition); + } + seek(start); + writeBlock(data); +} + +void ByteVectorStream::removeBlock(unsigned long start, unsigned long length) +{ + unsigned long readPosition = start + length; + unsigned long writePosition = start; + if(readPosition < static_cast(ByteVectorStream::length())) { + unsigned long bytesToMove = ByteVectorStream::length() - readPosition; + memmove(d->data.data() + writePosition, d->data.data() + readPosition, bytesToMove); + writePosition += bytesToMove; + } + d->position = writePosition; + truncate(writePosition); +} + +bool ByteVectorStream::readOnly() const +{ + return false; +} + +bool ByteVectorStream::isOpen() const +{ + return true; +} + +void ByteVectorStream::seek(long offset, Position p) +{ + switch(p) { + case Beginning: + d->position = offset; + break; + case Current: + d->position += offset; + break; + case End: + d->position = length() + offset; // offset is expected to be negative + break; + } +} + +void ByteVectorStream::clear() +{ +} + +long ByteVectorStream::tell() const +{ + return d->position; +} + +long ByteVectorStream::length() +{ + return d->data.size(); +} + +void ByteVectorStream::truncate(long length) +{ + d->data.resize(length); +} + +ByteVector *ByteVectorStream::data() +{ + return &d->data; +} diff --git a/external/taglib/source/toolkit/tbytevectorstream.h b/external/taglib/source/toolkit/tbytevectorstream.h new file mode 100644 index 0000000..84327c4 --- /dev/null +++ b/external/taglib/source/toolkit/tbytevectorstream.h @@ -0,0 +1,145 @@ +/*************************************************************************** + copyright : (C) 2011 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_BYTEVECTORSTREAM_H +#define TAGLIB_BYTEVECTORSTREAM_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" +#include "tiostream.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + + //! In-memory Stream class using ByteVector for its storage. + + class TAGLIB_EXPORT ByteVectorStream : public IOStream + { + public: + /*! + * Construct a File object and opens the \a file. \a file should be a + * be a C-string in the local file system encoding. + */ + ByteVectorStream(const ByteVector &data); + + /*! + * Destroys this ByteVectorStream instance. + */ + virtual ~ByteVectorStream(); + + /*! + * Returns the file name in the local file system encoding. + */ + FileName name() const; + + /*! + * Reads a block of size \a length at the current get pointer. + */ + ByteVector readBlock(unsigned long length); + + /*! + * Attempts to write the block \a data at the current get pointer. If the + * file is currently only opened read only -- i.e. readOnly() returns true -- + * this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator + * for a ByteVector. And even this function is significantly slower than + * doing output with a char[]. + */ + void writeBlock(const ByteVector &data); + + /*! + * Insert \a data at position \a start in the file overwriting \a replace + * bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file + * after the insertion point. + */ + void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0); + + /*! + * Removes a block of the file starting a \a start and continuing for + * \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ + void removeBlock(unsigned long start = 0, unsigned long length = 0); + + /*! + * Returns true if the file is read only (or if the file can not be opened). + */ + bool readOnly() const; + + /*! + * Since the file can currently only be opened as an argument to the + * constructor (sort-of by design), this returns if that open succeeded. + */ + bool isOpen() const; + + /*! + * Move the I/O pointer to \a offset in the file from position \a p. This + * defaults to seeking from the beginning of the file. + * + * \see Position + */ + void seek(long offset, Position p = Beginning); + + /*! + * Reset the end-of-file and error flags on the file. + */ + void clear(); + + /*! + * Returns the current offset within the file. + */ + long tell() const; + + /*! + * Returns the length of the file. + */ + long length(); + + /*! + * Truncates the file to a \a length. + */ + void truncate(long length); + + ByteVector *data(); + + protected: + + private: + class ByteVectorStreamPrivate; + ByteVectorStreamPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/source/toolkit/tdebug.cpp b/external/taglib/source/toolkit/tdebug.cpp new file mode 100644 index 0000000..ca35f71 --- /dev/null +++ b/external/taglib/source/toolkit/tdebug.cpp @@ -0,0 +1,64 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE) + +#include "tdebug.h" +#include "tstring.h" +#include "tdebuglistener.h" +#include "tutils.h" + +#include +#include +#include + +namespace TagLib +{ + // The instance is defined in tdebuglistener.cpp. + extern DebugListener *debugListener; + + void debug(const String &s) + { + debugListener->printMessage("TagLib: " + s + "\n"); + } + + void debugData(const ByteVector &v) + { + for(unsigned int i = 0; i < v.size(); ++i) { + const std::string bits = std::bitset<8>(v[i]).to_string(); + const String msg = Utils::formatString( + "*** [%u] - char '%c' - int %d, 0x%02x, 0b%s\n", + i, v[i], v[i], v[i], bits.c_str()); + + debugListener->printMessage(msg); + } + } +} // namespace TagLib + +#endif diff --git a/external/taglib/source/toolkit/tdebug.h b/external/taglib/source/toolkit/tdebug.h new file mode 100644 index 0000000..80d00d3 --- /dev/null +++ b/external/taglib/source/toolkit/tdebug.h @@ -0,0 +1,70 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_DEBUG_H +#define TAGLIB_DEBUG_H + +namespace TagLib { + + class String; + class ByteVector; + +#ifndef DO_NOT_DOCUMENT +#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE) + + /*! + * A simple function that outputs the debug messages to the listener. + * The default listener redirects the messages to \a stderr when NDEBUG is + * not defined. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debug(const String &s); + + /*! + * For debugging binary data. + * + * \warning Do not use this outside of TagLib, it could lead to undefined + * symbols in your build if TagLib is built with NDEBUG defined and your + * application is not. + * + * \internal + */ + void debugData(const ByteVector &v); + +#else + + #define debug(x) ((void)0) + #define debugData(x) ((void)0) + +#endif +} + +#endif +#endif diff --git a/external/taglib/source/toolkit/tdebuglistener.cpp b/external/taglib/source/toolkit/tdebuglistener.cpp new file mode 100644 index 0000000..bf5c260 --- /dev/null +++ b/external/taglib/source/toolkit/tdebuglistener.cpp @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tdebuglistener.h" + +#include +#include + +#ifdef _WIN32 +# include +#endif + +using namespace TagLib; + +namespace +{ + class DefaultListener : public DebugListener + { + public: + virtual void printMessage(const String &msg) + { +#ifdef _WIN32 + + const wstring wstr = msg.toWString(); + const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); + if(len != 0) { + std::vector buf(len); + WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL); + + std::cerr << std::string(&buf[0]); + } + +#else + + std::cerr << msg; + +#endif + } + }; + + DefaultListener defaultListener; +} // namespace + +namespace TagLib +{ + DebugListener *debugListener = &defaultListener; + + DebugListener::DebugListener() + { + } + + DebugListener::~DebugListener() + { + } + + void setDebugListener(DebugListener *listener) + { + if(listener) + debugListener = listener; + else + debugListener = &defaultListener; + } +} // namespace TagLib diff --git a/external/taglib/source/toolkit/tdebuglistener.h b/external/taglib/source/toolkit/tdebuglistener.h new file mode 100644 index 0000000..3c8e118 --- /dev/null +++ b/external/taglib/source/toolkit/tdebuglistener.h @@ -0,0 +1,74 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_DEBUGLISTENER_H +#define TAGLIB_DEBUGLISTENER_H + +#include "taglib_export.h" +#include "tstring.h" + +namespace TagLib +{ + //! An abstraction for the listener to the debug messages. + + /*! + * This class enables you to handle the debug messages in your preferred + * way by subclassing this class, reimplementing printMessage() and setting + * your reimplementation as the default with setDebugListener(). + * + * \see setDebugListener() + */ + class TAGLIB_EXPORT DebugListener + { + public: + DebugListener(); + virtual ~DebugListener(); + + /*! + * When overridden in a derived class, redirects \a msg to your preferred + * channel such as stderr, Windows debugger or so forth. + */ + virtual void printMessage(const String &msg) = 0; + + private: + // Noncopyable + DebugListener(const DebugListener &); + DebugListener &operator=(const DebugListener &); + }; + + /*! + * Sets the listener that decides how the debug messages are redirected. + * If the parameter \a listener is null, the previous listener is released + * and default stderr listener is restored. + * + * \note The caller is responsible for deleting the previous listener + * as needed after it is released. + * + * \see DebugListener + */ + TAGLIB_EXPORT void setDebugListener(DebugListener *listener); +} + +#endif diff --git a/external/taglib/source/toolkit/tfile.cpp b/external/taglib/source/toolkit/tfile.cpp new file mode 100644 index 0000000..b7d0be4 --- /dev/null +++ b/external/taglib/source/toolkit/tfile.cpp @@ -0,0 +1,498 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tfile.h" +#include "tfilestream.h" +#include "tstring.h" +#include "tdebug.h" +#include "tpropertymap.h" + +#ifdef _WIN32 +# include +# include +#else +# include +# include +#endif + +#ifndef R_OK +# define R_OK 4 +#endif +#ifndef W_OK +# define W_OK 2 +#endif + +#include "asffile.h" +#include "mpegfile.h" +#include "vorbisfile.h" +#include "flacfile.h" +#include "oggflacfile.h" +#include "mpcfile.h" +#include "mp4file.h" +#include "wavpackfile.h" +#include "speexfile.h" +#include "opusfile.h" +#include "trueaudiofile.h" +#include "aifffile.h" +#include "wavfile.h" +#include "apefile.h" +#include "modfile.h" +#include "s3mfile.h" +#include "itfile.h" +#include "xmfile.h" +#include "mp4file.h" + +using namespace TagLib; + +class File::FilePrivate +{ +public: + FilePrivate(IOStream *stream, bool owner) : + stream(stream), + streamOwner(owner), + valid(true) {} + + ~FilePrivate() + { + if(streamOwner) + delete stream; + } + + IOStream *stream; + bool streamOwner; + bool valid; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +File::File(FileName fileName) : + d(new FilePrivate(new FileStream(fileName), true)) +{ +} + +File::File(IOStream *stream) : + d(new FilePrivate(stream, false)) +{ +} + +File::~File() +{ + delete d; +} + +FileName File::name() const +{ + return d->stream->name(); +} + +PropertyMap File::properties() const +{ + // ugly workaround until this method is virtual + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + if(dynamic_cast(this)) + return dynamic_cast(this)->properties(); + return tag()->properties(); +} + +void File::removeUnsupportedProperties(const StringList &properties) +{ + // here we only consider those formats that could possibly contain + // unsupported properties + if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else if(dynamic_cast(this)) + dynamic_cast(this)->removeUnsupportedProperties(properties); + else + tag()->removeUnsupportedProperties(properties); +} + +PropertyMap File::setProperties(const PropertyMap &properties) +{ + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + if(dynamic_cast(this)) + return dynamic_cast(this)->setProperties(properties); + return tag()->setProperties(properties); +} + +ByteVector File::readBlock(unsigned long length) +{ + return d->stream->readBlock(length); +} + +void File::writeBlock(const ByteVector &data) +{ + d->stream->writeBlock(data); +} + +long File::find(const ByteVector &pattern, long fromOffset, const ByteVector &before) +{ + if(!d->stream || pattern.size() > bufferSize()) + return -1; + + // The position in the file that the current buffer starts at. + + long bufferOffset = fromOffset; + ByteVector buffer; + + // These variables are used to keep track of a partial match that happens at + // the end of a buffer. + + int previousPartialMatch = -1; + int beforePreviousPartialMatch = -1; + + // Save the location of the current read pointer. We will restore the + // position using seek() before all returns. + + long originalPosition = tell(); + + // Start the search at the offset. + + seek(fromOffset); + + // This loop is the crux of the find method. There are three cases that we + // want to account for: + // + // (1) The previously searched buffer contained a partial match of the search + // pattern and we want to see if the next one starts with the remainder of + // that pattern. + // + // (2) The search pattern is wholly contained within the current buffer. + // + // (3) The current buffer ends with a partial match of the pattern. We will + // note this for use in the next iteration, where we will check for the rest + // of the pattern. + // + // All three of these are done in two steps. First we check for the pattern + // and do things appropriately if a match (or partial match) is found. We + // then check for "before". The order is important because it gives priority + // to "real" matches. + + for(buffer = readBlock(bufferSize()); buffer.size() > 0; buffer = readBlock(bufferSize())) { + + // (1) previous partial match + + if(previousPartialMatch >= 0 && int(bufferSize()) > previousPartialMatch) { + const int patternOffset = (bufferSize() - previousPartialMatch); + if(buffer.containsAt(pattern, 0, patternOffset)) { + seek(originalPosition); + return bufferOffset - bufferSize() + previousPartialMatch; + } + } + + if(!before.isEmpty() && beforePreviousPartialMatch >= 0 && int(bufferSize()) > beforePreviousPartialMatch) { + const int beforeOffset = (bufferSize() - beforePreviousPartialMatch); + if(buffer.containsAt(before, 0, beforeOffset)) { + seek(originalPosition); + return -1; + } + } + + // (2) pattern contained in current buffer + + long location = buffer.find(pattern); + if(location >= 0) { + seek(originalPosition); + return bufferOffset + location; + } + + if(!before.isEmpty() && buffer.find(before) >= 0) { + seek(originalPosition); + return -1; + } + + // (3) partial match + + previousPartialMatch = buffer.endsWithPartialMatch(pattern); + + if(!before.isEmpty()) + beforePreviousPartialMatch = buffer.endsWithPartialMatch(before); + + bufferOffset += bufferSize(); + } + + // Since we hit the end of the file, reset the status before continuing. + + clear(); + + seek(originalPosition); + + return -1; +} + + +long File::rfind(const ByteVector &pattern, long fromOffset, const ByteVector &before) +{ + if(!d->stream || pattern.size() > bufferSize()) + return -1; + + // The position in the file that the current buffer starts at. + + ByteVector buffer; + + // These variables are used to keep track of a partial match that happens at + // the end of a buffer. + + /* + int previousPartialMatch = -1; + int beforePreviousPartialMatch = -1; + */ + + // Save the location of the current read pointer. We will restore the + // position using seek() before all returns. + + long originalPosition = tell(); + + // Start the search at the offset. + + if(fromOffset == 0) + fromOffset = length(); + + long bufferLength = bufferSize(); + long bufferOffset = fromOffset + pattern.size(); + + // See the notes in find() for an explanation of this algorithm. + + while(true) { + + if(bufferOffset > bufferLength) { + bufferOffset -= bufferLength; + } + else { + bufferLength = bufferOffset; + bufferOffset = 0; + } + seek(bufferOffset); + + buffer = readBlock(bufferLength); + if(buffer.isEmpty()) + break; + + // TODO: (1) previous partial match + + // (2) pattern contained in current buffer + + const long location = buffer.rfind(pattern); + if(location >= 0) { + seek(originalPosition); + return bufferOffset + location; + } + + if(!before.isEmpty() && buffer.find(before) >= 0) { + seek(originalPosition); + return -1; + } + + // TODO: (3) partial match + } + + // Since we hit the end of the file, reset the status before continuing. + + clear(); + + seek(originalPosition); + + return -1; +} + +void File::insert(const ByteVector &data, unsigned long start, unsigned long replace) +{ + d->stream->insert(data, start, replace); +} + +void File::removeBlock(unsigned long start, unsigned long length) +{ + d->stream->removeBlock(start, length); +} + +bool File::readOnly() const +{ + return d->stream->readOnly(); +} + +bool File::isOpen() const +{ + return d->stream->isOpen(); +} + +bool File::isValid() const +{ + return isOpen() && d->valid; +} + +void File::seek(long offset, Position p) +{ + d->stream->seek(offset, IOStream::Position(p)); +} + +void File::truncate(long length) +{ + d->stream->truncate(length); +} + +void File::clear() +{ + d->stream->clear(); +} + +long File::tell() const +{ + return d->stream->tell(); +} + +long File::length() +{ + return d->stream->length(); +} + +bool File::isReadable(const char *file) +{ + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later + + return _access_s(file, R_OK) == 0; + +#else + + return access(file, R_OK) == 0; + +#endif + +} + +bool File::isWritable(const char *file) +{ + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) // VC++2005 or later + + return _access_s(file, W_OK) == 0; + +#else + + return access(file, W_OK) == 0; + +#endif + +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +unsigned int File::bufferSize() +{ + return 1024; +} + +void File::setValid(bool valid) +{ + d->valid = valid; +} + diff --git a/external/taglib/source/toolkit/tfile.h b/external/taglib/source/toolkit/tfile.h new file mode 100644 index 0000000..bdc4f12 --- /dev/null +++ b/external/taglib/source/toolkit/tfile.h @@ -0,0 +1,323 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILE_H +#define TAGLIB_FILE_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tag.h" +#include "tbytevector.h" +#include "tiostream.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + class PropertyMap; + + //! A file class with some useful methods for tag manipulation + + /*! + * This class is a basic file class with some methods that are particularly + * useful for tag editors. It has methods to take advantage of + * ByteVector and a binary search method for finding patterns in a file. + */ + + class TAGLIB_EXPORT File + { + public: + /*! + * Position in the file used for seeking. + */ + enum Position { + //! Seek from the beginning of the file. + Beginning, + //! Seek from the current position in the file. + Current, + //! Seek from the end of the file. + End + }; + + /*! + * Specify which tags to strip either explicitly, or on save. + */ + enum StripTags { + StripNone, // +#else +# include +# include +#endif + +using namespace TagLib; + +namespace +{ +#ifdef _WIN32 + + // Uses Win32 native API instead of POSIX API to reduce the resource consumption. + + typedef FileName FileNameHandle; + typedef HANDLE FileHandle; + + const FileHandle InvalidFileHandle = INVALID_HANDLE_VALUE; + + FileHandle openFile(const FileName &path, bool readOnly) + { + const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE); + +#if defined (PLATFORM_WINRT) + return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL); +#else + return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); +#endif + } + + FileHandle openFile(const int fileDescriptor, bool readOnly) + { + return InvalidFileHandle; + } + + void closeFile(FileHandle file) + { + CloseHandle(file); + } + + size_t readFile(FileHandle file, ByteVector &buffer) + { + DWORD length; + if(ReadFile(file, buffer.data(), static_cast(buffer.size()), &length, NULL)) + return static_cast(length); + else + return 0; + } + + size_t writeFile(FileHandle file, const ByteVector &buffer) + { + DWORD length; + if(WriteFile(file, buffer.data(), static_cast(buffer.size()), &length, NULL)) + return static_cast(length); + else + return 0; + } + +#else // _WIN32 + + struct FileNameHandle : public std::string + { + FileNameHandle(FileName name) : std::string(name) {} + operator FileName () const { return c_str(); } + }; + + typedef FILE* FileHandle; + + const FileHandle InvalidFileHandle = 0; + + FileHandle openFile(const FileName &path, bool readOnly) + { + return fopen(path, readOnly ? "rb" : "rb+"); + } + + FileHandle openFile(const int fileDescriptor, bool readOnly) + { + return fdopen(fileDescriptor, readOnly ? "rb" : "rb+"); + } + + void closeFile(FileHandle file) + { + fclose(file); + } + + size_t readFile(FileHandle file, ByteVector &buffer) + { + return fread(buffer.data(), sizeof(char), buffer.size(), file); + } + + size_t writeFile(FileHandle file, const ByteVector &buffer) + { + return fwrite(buffer.data(), sizeof(char), buffer.size(), file); + } + +#endif // _WIN32 +} // namespace + +class FileStream::FileStreamPrivate +{ +public: + FileStreamPrivate(const FileName &fileName) + : file(InvalidFileHandle) + , name(fileName) + , readOnly(true) + { + } + + FileHandle file; + FileNameHandle name; + bool readOnly; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +FileStream::FileStream(FileName fileName, bool openReadOnly) + : d(new FileStreamPrivate(fileName)) +{ + // First try with read / write mode, if that fails, fall back to read only. + + if(!openReadOnly) + d->file = openFile(fileName, false); + + if(d->file != InvalidFileHandle) + d->readOnly = false; + else + d->file = openFile(fileName, true); + + if(d->file == InvalidFileHandle) +# ifdef _WIN32 + debug("Could not open file " + fileName.toString()); +# else + debug("Could not open file " + String(static_cast(d->name))); +# endif +} + +FileStream::FileStream(int fileDescriptor, bool openReadOnly) + : d(new FileStreamPrivate("")) +{ + // First try with read / write mode, if that fails, fall back to read only. + + if(!openReadOnly) + d->file = openFile(fileDescriptor, false); + + if(d->file != InvalidFileHandle) + d->readOnly = false; + else + d->file = openFile(fileDescriptor, true); + + if(d->file == InvalidFileHandle) + debug("Could not open file using file descriptor"); +} + +FileStream::~FileStream() +{ + if(isOpen()) + closeFile(d->file); + + delete d; +} + +FileName FileStream::name() const +{ + return d->name; +} + +ByteVector FileStream::readBlock(unsigned long length) +{ + if(!isOpen()) { + debug("FileStream::readBlock() -- invalid file."); + return ByteVector(); + } + + if(length == 0) + return ByteVector(); + + const unsigned long streamLength = static_cast(FileStream::length()); + if(length > bufferSize() && length > streamLength) + length = streamLength; + + ByteVector buffer(static_cast(length)); + + const size_t count = readFile(d->file, buffer); + buffer.resize(static_cast(count)); + + return buffer; +} + +void FileStream::writeBlock(const ByteVector &data) +{ + if(!isOpen()) { + debug("FileStream::writeBlock() -- invalid file."); + return; + } + + if(readOnly()) { + debug("FileStream::writeBlock() -- read only file."); + return; + } + + writeFile(d->file, data); +} + +void FileStream::insert(const ByteVector &data, unsigned long start, unsigned long replace) +{ + if(!isOpen()) { + debug("FileStream::insert() -- invalid file."); + return; + } + + if(readOnly()) { + debug("FileStream::insert() -- read only file."); + return; + } + + if(data.size() == replace) { + seek(start); + writeBlock(data); + return; + } + if(data.size() < replace) { + seek(start); + writeBlock(data); + removeBlock(start + data.size(), replace - data.size()); + return; + } + + // Woohoo! Faster (about 20%) than id3lib at last. I had to get hardcore + // and avoid TagLib's high level API for rendering just copying parts of + // the file that don't contain tag data. + // + // Now I'll explain the steps in this ugliness: + + // First, make sure that we're working with a buffer that is longer than + // the *difference* in the tag sizes. We want to avoid overwriting parts + // that aren't yet in memory, so this is necessary. + + unsigned long bufferLength = bufferSize(); + + while(data.size() - replace > bufferLength) + bufferLength += bufferSize(); + + // Set where to start the reading and writing. + + long readPosition = start + replace; + long writePosition = start; + + ByteVector buffer = data; + ByteVector aboutToOverwrite(static_cast(bufferLength)); + + while(true) { + // Seek to the current read position and read the data that we're about + // to overwrite. Appropriately increment the readPosition. + + seek(readPosition); + const unsigned int bytesRead = static_cast(readFile(d->file, aboutToOverwrite)); + aboutToOverwrite.resize(bytesRead); + readPosition += bufferLength; + + // Check to see if we just read the last block. We need to call clear() + // if we did so that the last write succeeds. + + if(bytesRead < bufferLength) + clear(); + + // Seek to the write position and write our buffer. Increment the + // writePosition. + + seek(writePosition); + writeBlock(buffer); + + // We hit the end of the file. + + if(bytesRead == 0) + break; + + writePosition += buffer.size(); + + // Make the current buffer the data that we read in the beginning. + + buffer = aboutToOverwrite; + } +} + +void FileStream::removeBlock(unsigned long start, unsigned long length) +{ + if(!isOpen()) { + debug("FileStream::removeBlock() -- invalid file."); + return; + } + + unsigned long bufferLength = bufferSize(); + + long readPosition = start + length; + long writePosition = start; + + ByteVector buffer(static_cast(bufferLength)); + + for(unsigned int bytesRead = -1; bytesRead != 0;) { + seek(readPosition); + bytesRead = static_cast(readFile(d->file, buffer)); + readPosition += bytesRead; + + // Check to see if we just read the last block. We need to call clear() + // if we did so that the last write succeeds. + + if(bytesRead < buffer.size()) { + clear(); + buffer.resize(bytesRead); + } + + seek(writePosition); + writeFile(d->file, buffer); + + writePosition += bytesRead; + } + + truncate(writePosition); +} + +bool FileStream::readOnly() const +{ + return d->readOnly; +} + +bool FileStream::isOpen() const +{ + return (d->file != InvalidFileHandle); +} + +void FileStream::seek(long offset, Position p) +{ + if(!isOpen()) { + debug("FileStream::seek() -- invalid file."); + return; + } + +#ifdef _WIN32 + + if(p != Beginning && p != Current && p != End) { + debug("FileStream::seek() -- Invalid Position value."); + return; + } + + LARGE_INTEGER liOffset; + liOffset.QuadPart = offset; + + if(!SetFilePointerEx(d->file, liOffset, NULL, static_cast(p))) { + debug("FileStream::seek() -- Failed to set the file pointer."); + } + +#else + + int whence; + switch(p) { + case Beginning: + whence = SEEK_SET; + break; + case Current: + whence = SEEK_CUR; + break; + case End: + whence = SEEK_END; + break; + default: + debug("FileStream::seek() -- Invalid Position value."); + return; + } + + fseek(d->file, offset, whence); + +#endif +} + +void FileStream::clear() +{ +#ifdef _WIN32 + + // NOP + +#else + + clearerr(d->file); + +#endif +} + +long FileStream::tell() const +{ +#ifdef _WIN32 + + const LARGE_INTEGER zero = {}; + LARGE_INTEGER position; + + if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) && + position.QuadPart <= LONG_MAX) { + return static_cast(position.QuadPart); + } + else { + debug("FileStream::tell() -- Failed to get the file pointer."); + return 0; + } + +#else + + return ftell(d->file); + +#endif +} + +long FileStream::length() +{ + if(!isOpen()) { + debug("FileStream::length() -- invalid file."); + return 0; + } + +#ifdef _WIN32 + + LARGE_INTEGER fileSize; + + if(GetFileSizeEx(d->file, &fileSize) && fileSize.QuadPart <= LONG_MAX) { + return static_cast(fileSize.QuadPart); + } + else { + debug("FileStream::length() -- Failed to get the file size."); + return 0; + } + +#else + + const long curpos = tell(); + + seek(0, End); + const long endpos = tell(); + + seek(curpos, Beginning); + + return endpos; + +#endif +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void FileStream::truncate(long length) +{ +#ifdef _WIN32 + + const long currentPos = tell(); + + seek(length); + + if(!SetEndOfFile(d->file)) { + debug("FileStream::truncate() -- Failed to truncate the file."); + } + + seek(currentPos); + +#else + + fflush(d->file); + const int error = ftruncate(fileno(d->file), length); + if(error != 0) + debug("FileStream::truncate() -- Couldn't truncate the file."); + +#endif +} + +unsigned int FileStream::bufferSize() +{ + return 1024; +} diff --git a/external/taglib/source/toolkit/tfilestream.h b/external/taglib/source/toolkit/tfilestream.h new file mode 100644 index 0000000..aa4d71b --- /dev/null +++ b/external/taglib/source/toolkit/tfilestream.h @@ -0,0 +1,159 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_FILESTREAM_H +#define TAGLIB_FILESTREAM_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" +#include "tiostream.h" + +namespace TagLib { + + class String; + class Tag; + class AudioProperties; + + //! A file class with some useful methods for tag manipulation + + /*! + * This class is a basic file class with some methods that are particularly + * useful for tag editors. It has methods to take advantage of + * ByteVector and a binary search method for finding patterns in a file. + */ + + class TAGLIB_EXPORT FileStream : public IOStream + { + public: + /*! + * Construct a File object and opens the \a file. \a file should be a + * be a C-string in the local file system encoding. + */ + FileStream(FileName file, bool openReadOnly = false); + + /*! + * Construct a File object and opens the \a file using file descriptor. + */ + FileStream(int fileDescriptor, bool openReadOnly = false); + + /*! + * Destroys this FileStream instance. + */ + virtual ~FileStream(); + + /*! + * Returns the file name in the local file system encoding. + */ + FileName name() const; + + /*! + * Reads a block of size \a length at the current get pointer. + */ + ByteVector readBlock(unsigned long length); + + /*! + * Attempts to write the block \a data at the current get pointer. If the + * file is currently only opened read only -- i.e. readOnly() returns true -- + * this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator + * for a ByteVector. And even this function is significantly slower than + * doing output with a char[]. + */ + void writeBlock(const ByteVector &data); + + /*! + * Insert \a data at position \a start in the file overwriting \a replace + * bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file + * after the insertion point. + */ + void insert(const ByteVector &data, unsigned long start = 0, unsigned long replace = 0); + + /*! + * Removes a block of the file starting a \a start and continuing for + * \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ + void removeBlock(unsigned long start = 0, unsigned long length = 0); + + /*! + * Returns true if the file is read only (or if the file can not be opened). + */ + bool readOnly() const; + + /*! + * Since the file can currently only be opened as an argument to the + * constructor (sort-of by design), this returns if that open succeeded. + */ + bool isOpen() const; + + /*! + * Move the I/O pointer to \a offset in the file from position \a p. This + * defaults to seeking from the beginning of the file. + * + * \see Position + */ + void seek(long offset, Position p = Beginning); + + /*! + * Reset the end-of-file and error flags on the file. + */ + void clear(); + + /*! + * Returns the current offset within the file. + */ + long tell() const; + + /*! + * Returns the length of the file. + */ + long length(); + + /*! + * Truncates the file to a \a length. + */ + void truncate(long length); + + protected: + + /*! + * Returns the buffer size that is used for internal buffering. + */ + static unsigned int bufferSize(); + + private: + class FileStreamPrivate; + FileStreamPrivate *d; + }; + +} + +#endif diff --git a/external/taglib/source/toolkit/tiostream.cpp b/external/taglib/source/toolkit/tiostream.cpp new file mode 100644 index 0000000..de0bd50 --- /dev/null +++ b/external/taglib/source/toolkit/tiostream.cpp @@ -0,0 +1,114 @@ +/*************************************************************************** + copyright : (C) 2011 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef _WIN32 +# include +# include +#endif + +#include "tiostream.h" + +using namespace TagLib; + +#ifdef _WIN32 + +namespace +{ + std::wstring ansiToUnicode(const char *str) + { + const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); + if(len == 0) + return std::wstring(); + + std::wstring wstr(len - 1, L'\0'); + MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len); + + return wstr; + } +} + +// m_name is no longer used, but kept for backward compatibility. + +FileName::FileName(const wchar_t *name) : + m_name(), + m_wname(name) +{ +} + +FileName::FileName(const char *name) : + m_name(), + m_wname(ansiToUnicode(name)) +{ +} + +FileName::FileName(const FileName &name) : + m_name(), + m_wname(name.m_wname) +{ +} + +FileName::operator const wchar_t *() const +{ + return m_wname.c_str(); +} + +FileName::operator const char *() const +{ + return m_name.c_str(); +} + +const std::wstring &FileName::wstr() const +{ + return m_wname; +} + +const std::string &FileName::str() const +{ + return m_name; +} + +String FileName::toString() const +{ + return String(m_wname.c_str()); +} + +#endif // _WIN32 + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +IOStream::IOStream() +{ +} + +IOStream::~IOStream() +{ +} + +void IOStream::clear() +{ +} + diff --git a/external/taglib/source/toolkit/tiostream.h b/external/taglib/source/toolkit/tiostream.h new file mode 100644 index 0000000..1105316 --- /dev/null +++ b/external/taglib/source/toolkit/tiostream.h @@ -0,0 +1,170 @@ +/*************************************************************************** + copyright : (C) 2011 by Lukas Lalinsky + email : lalinsky@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_IOSTREAM_H +#define TAGLIB_IOSTREAM_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" + +namespace TagLib { + +#ifdef _WIN32 + class TAGLIB_EXPORT FileName + { + public: + FileName(const wchar_t *name); + FileName(const char *name); + + FileName(const FileName &name); + + operator const wchar_t *() const; + operator const char *() const; + + const std::wstring &wstr() const; + const std::string &str() const; + + String toString() const; + + private: + const std::string m_name; + const std::wstring m_wname; + }; +#else + typedef const char *FileName; +#endif + + //! An abstract class that provides operations on a sequence of bytes + + class TAGLIB_EXPORT IOStream + { + public: + /*! + * Position in the file used for seeking. + */ + enum Position { + //! Seek from the beginning of the file. + Beginning, + //! Seek from the current position in the file. + Current, + //! Seek from the end of the file. + End + }; + + IOStream(); + + /*! + * Destroys this IOStream instance. + */ + virtual ~IOStream(); + + /*! + * Returns the stream name in the local file system encoding. + */ + virtual FileName name() const = 0; + + /*! + * Reads a block of size \a length at the current get pointer. + */ + virtual ByteVector readBlock(unsigned long length) = 0; + + /*! + * Attempts to write the block \a data at the current get pointer. If the + * file is currently only opened read only -- i.e. readOnly() returns true -- + * this attempts to reopen the file in read/write mode. + * + * \note This should be used instead of using the streaming output operator + * for a ByteVector. And even this function is significantly slower than + * doing output with a char[]. + */ + virtual void writeBlock(const ByteVector &data) = 0; + + /*! + * Insert \a data at position \a start in the file overwriting \a replace + * bytes of the original content. + * + * \note This method is slow since it requires rewriting all of the file + * after the insertion point. + */ + virtual void insert(const ByteVector &data, + unsigned long start = 0, unsigned long replace = 0) = 0; + + /*! + * Removes a block of the file starting a \a start and continuing for + * \a length bytes. + * + * \note This method is slow since it involves rewriting all of the file + * after the removed portion. + */ + virtual void removeBlock(unsigned long start = 0, unsigned long length = 0) = 0; + + /*! + * Returns true if the file is read only (or if the file can not be opened). + */ + virtual bool readOnly() const = 0; + + /*! + * Since the file can currently only be opened as an argument to the + * constructor (sort-of by design), this returns if that open succeeded. + */ + virtual bool isOpen() const = 0; + + /*! + * Move the I/O pointer to \a offset in the stream from position \a p. This + * defaults to seeking from the beginning of the stream. + * + * \see Position + */ + virtual void seek(long offset, Position p = Beginning) = 0; + + /*! + * Reset the end-of-stream and error flags on the stream. + */ + virtual void clear(); + + /*! + * Returns the current offset within the stream. + */ + virtual long tell() const = 0; + + /*! + * Returns the length of the stream. + */ + virtual long length() = 0; + + /*! + * Truncates the stream to a \a length. + */ + virtual void truncate(long length) = 0; + + private: + IOStream(const IOStream &); + IOStream &operator=(const IOStream &); + }; + +} + +#endif diff --git a/external/taglib/source/toolkit/tlist.h b/external/taglib/source/toolkit/tlist.h new file mode 100644 index 0000000..377b824 --- /dev/null +++ b/external/taglib/source/toolkit/tlist.h @@ -0,0 +1,270 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_LIST_H +#define TAGLIB_LIST_H + +#include "taglib.h" + +#include + +namespace TagLib { + + //! A generic, implicitly shared list. + + /*! + * This is basic generic list that's somewhere between a std::list and a + * QValueList. This class is implicitly shared. For example: + * + * \code + * + * TagLib::List l = someOtherIntList; + * + * \endcode + * + * The above example is very cheap. This also makes lists suitable for the + * return types of functions. The above example will just copy a pointer rather + * than copying the data in the list. When your \e shared list's data changes, + * only \e then will the data be copied. + */ + + template class List + { + public: +#ifndef DO_NOT_DOCUMENT + typedef typename std::list::iterator Iterator; + typedef typename std::list::const_iterator ConstIterator; +#endif + + /*! + * Constructs an empty list. + */ + List(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List(const List &l); + + /*! + * Destroys this List instance. If auto deletion is enabled and this list + * contains a pointer type all of the members are also deleted. + */ + virtual ~List(); + + /*! + * Returns an STL style iterator to the beginning of the list. See + * std::list::const_iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style constant iterator to the beginning of the list. See + * std::list::iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the list. See + * std::list::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style constant iterator to the end of the list. See + * std::list::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts a copy of \a value before \a it. + */ + Iterator insert(Iterator it, const T &value); + + /*! + * Inserts the \a value into the list. This assumes that the list is + * currently sorted. If \a unique is true then the value will not + * be inserted if it is already in the list. + */ + List &sortedInsert(const T &value, bool unique = false); + + /*! + * Appends \a item to the end of the list and returns a reference to the + * list. + */ + List &append(const T &item); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + List &append(const List &l); + + /*! + * Prepends \a item to the beginning list and returns a reference to the + * list. + */ + List &prepend(const T &item); + + /*! + * Prepends all of the items in \a l to the beginning list and returns a + * reference to the list. + */ + List &prepend(const List &l); + + /*! + * Clears the list. If auto deletion is enabled and this list contains a + * pointer type the members are also deleted. + * + * \see setAutoDelete() + */ + List &clear(); + + /*! + * Returns the number of elements in the list. + * + * \see isEmpty() + */ + unsigned int size() const; + + /*! + * Returns whether or not the list is empty. + * + * \see size() + */ + bool isEmpty() const; + + /*! + * Find the first occurrence of \a value. + */ + Iterator find(const T &value); + + /*! + * Find the first occurrence of \a value. + */ + ConstIterator find(const T &value) const; + + /*! + * Returns true if the list contains \a value. + */ + bool contains(const T &value) const; + + /*! + * Erase the item at \a it from the list. + */ + Iterator erase(Iterator it); + + /*! + * Returns a reference to the first item in the list. + */ + const T &front() const; + + /*! + * Returns a reference to the first item in the list. + */ + T &front(); + + /*! + * Returns a reference to the last item in the list. + */ + const T &back() const; + + /*! + * Returns a reference to the last item in the list. + */ + T &back(); + + /*! + * Auto delete the members of the list when the last reference to the list + * passes out of scope. This will have no effect on lists which do not + * contain a pointer type. + * + * \note This relies on partial template instantiation -- most modern C++ + * compilers should now support this. + */ + void setAutoDelete(bool autoDelete); + + /*! + * Returns a reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + T &operator[](unsigned int i); + + /*! + * Returns a const reference to item \a i in the list. + * + * \warning This method is slow. Use iterators to loop through the list. + */ + const T &operator[](unsigned int i) const; + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + List &operator=(const List &l); + + /*! + * Exchanges the content of this list by the content of \a l. + */ + void swap(List &l); + + /*! + * Compares this list with \a l and returns true if all of the elements are + * the same. + */ + bool operator==(const List &l) const; + + /*! + * Compares this list with \a l and returns true if the lists differ. + */ + bool operator!=(const List &l) const; + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class ListPrivate; + ListPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tlist.tcc" + +#endif diff --git a/external/taglib/source/toolkit/tlist.tcc b/external/taglib/source/toolkit/tlist.tcc new file mode 100644 index 0000000..478f098 --- /dev/null +++ b/external/taglib/source/toolkit/tlist.tcc @@ -0,0 +1,323 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include "trefcounter.h" + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +// The functionality of List::setAutoDelete() is implemented here partial +// template specialization. This is implemented in such a way that calling +// setAutoDelete() on non-pointer types will simply have no effect. + +// A base for the generic and specialized private class types. New +// non-templatized members should be added here. + +// BIC change to RefCounter +class ListPrivateBase : public RefCounterOld +{ +public: + ListPrivateBase() : autoDelete(false) {} + bool autoDelete; +}; + +// A generic implementation + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + void clear() { + list.clear(); + } + std::list list; +}; + +// A partial specialization for all pointer types that implements the +// setAutoDelete() functionality. + +template +template class List::ListPrivate : public ListPrivateBase +{ +public: + ListPrivate() : ListPrivateBase() {} + ListPrivate(const std::list &l) : ListPrivateBase(), list(l) {} + ~ListPrivate() { + clear(); + } + void clear() { + if(autoDelete) { + typename std::list::const_iterator it = list.begin(); + for(; it != list.end(); ++it) + delete *it; + } + list.clear(); + } + std::list list; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +template +List::List() : + d(new ListPrivate()) +{ +} + +template +List::List(const List &l) : d(l.d) +{ + d->ref(); +} + +template +List::~List() +{ + if(d->deref()) + delete d; +} + +template +typename List::Iterator List::begin() +{ + detach(); + return d->list.begin(); +} + +template +typename List::ConstIterator List::begin() const +{ + return d->list.begin(); +} + +template +typename List::Iterator List::end() +{ + detach(); + return d->list.end(); +} + +template +typename List::ConstIterator List::end() const +{ + return d->list.end(); +} + +template +typename List::Iterator List::insert(Iterator it, const T &item) +{ + detach(); + return d->list.insert(it, item); +} + +template +List &List::sortedInsert(const T &value, bool unique) +{ + detach(); + Iterator it = begin(); + while(it != end() && *it < value) + ++it; + if(unique && it != end() && *it == value) + return *this; + insert(it, value); + return *this; +} + +template +List &List::append(const T &item) +{ + detach(); + d->list.push_back(item); + return *this; +} + +template +List &List::append(const List &l) +{ + detach(); + d->list.insert(d->list.end(), l.begin(), l.end()); + return *this; +} + +template +List &List::prepend(const T &item) +{ + detach(); + d->list.push_front(item); + return *this; +} + +template +List &List::prepend(const List &l) +{ + detach(); + d->list.insert(d->list.begin(), l.begin(), l.end()); + return *this; +} + +template +List &List::clear() +{ + detach(); + d->clear(); + return *this; +} + +template +unsigned int List::size() const +{ + return static_cast(d->list.size()); +} + +template +bool List::isEmpty() const +{ + return d->list.empty(); +} + +template +typename List::Iterator List::find(const T &value) +{ + detach(); + return std::find(d->list.begin(), d->list.end(), value); +} + +template +typename List::ConstIterator List::find(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value); +} + +template +bool List::contains(const T &value) const +{ + return std::find(d->list.begin(), d->list.end(), value) != d->list.end(); +} + +template +typename List::Iterator List::erase(Iterator it) +{ + return d->list.erase(it); +} + +template +const T &List::front() const +{ + return d->list.front(); +} + +template +T &List::front() +{ + detach(); + return d->list.front(); +} + +template +const T &List::back() const +{ + return d->list.back(); +} + +template +void List::setAutoDelete(bool autoDelete) +{ + d->autoDelete = autoDelete; +} + +template +T &List::back() +{ + detach(); + return d->list.back(); +} + +template +T &List::operator[](unsigned int i) +{ + Iterator it = d->list.begin(); + std::advance(it, i); + + return *it; +} + +template +const T &List::operator[](unsigned int i) const +{ + ConstIterator it = d->list.begin(); + std::advance(it, i); + + return *it; +} + +template +List &List::operator=(const List &l) +{ + List(l).swap(*this); + return *this; +} + +template +void List::swap(List &l) +{ + using std::swap; + + swap(d, l.d); +} + +template +bool List::operator==(const List &l) const +{ + return d->list == l.d->list; +} + +template +bool List::operator!=(const List &l) const +{ + return d->list != l.d->list; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void List::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new ListPrivate(d->list); + } +} + +} // namespace TagLib diff --git a/external/taglib/source/toolkit/tmap.h b/external/taglib/source/toolkit/tmap.h new file mode 100644 index 0000000..2f920d2 --- /dev/null +++ b/external/taglib/source/toolkit/tmap.h @@ -0,0 +1,212 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_MAP_H +#define TAGLIB_MAP_H + +#include + +#include "taglib.h" + +namespace TagLib { + + //! A generic, implicitly shared map. + + /*! + * This implements a standard map container that associates a key with a value + * and has fast key-based lookups. This map is also implicitly shared making + * it suitable for pass-by-value usage. + */ + + template class Map + { + public: +#ifndef DO_NOT_DOCUMENT +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + // Some STL implementations get snippy over the use of the + // class keyword to distinguish different templates; Sun Studio + // in particular finds multiple specializations in certain rare + // cases and complains about that. GCC doesn't seem to mind, + // and uses the typedefs further below without the class keyword. + // Not all the specializations of Map can use the class keyword + // (when T is not actually a class type), so don't apply this + // generally. + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#else + typedef typename std::map::iterator Iterator; + typedef typename std::map::const_iterator ConstIterator; +#endif +#endif + + /*! + * Constructs an empty Map. + */ + Map(); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map(const Map &m); + + /*! + * Destroys this instance of the Map. + */ + virtual ~Map(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::iterator for the semantics. + */ + Iterator begin(); + + /*! + * Returns an STL style iterator to the beginning of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator begin() const; + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::iterator for the semantics. + */ + Iterator end(); + + /*! + * Returns an STL style iterator to the end of the map. See + * std::map::const_iterator for the semantics. + */ + ConstIterator end() const; + + /*! + * Inserts \a value under \a key in the map. If a value for \a key already + * exists it will be overwritten. + */ + Map &insert(const Key &key, const T &value); + + /*! + * Removes all of the elements from elements from the map. This however + * will not delete pointers if the mapped type is a pointer type. + */ + Map &clear(); + + /*! + * The number of elements in the map. + * + * \see isEmpty() + */ + unsigned int size() const; + + /*! + * Returns true if the map is empty. + * + * \see size() + */ + bool isEmpty() const; + + /*! + * Find the first occurrence of \a key. + */ + Iterator find(const Key &key); + + /*! + * Find the first occurrence of \a key. + */ + ConstIterator find(const Key &key) const; + + /*! + * Returns true if the map contains an instance of \a key. + */ + bool contains(const Key &key) const; + + /*! + * Erase the item at \a it from the list. + */ + Map &erase(Iterator it); + + /*! + * Erase the item with \a key from the list. + */ + Map &erase(const Key &key); + + /*! + * Returns the value associated with \a key. + * + * If the map does not contain \a key, it returns defaultValue. + * If no defaultValue is specified, it returns a default-constructed value. + */ + const T value(const Key &key, const T &defaultValue = T()) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + const T &operator[](const Key &key) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note This has undefined behavior if the key is not present in the map. + */ + T &operator[](const Key &key); + + /*! + * Make a shallow, implicitly shared, copy of \a m. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + Map &operator=(const Map &m); + + /*! + * Exchanges the content of this map by the content of \a m. + */ + void swap(Map &m); + + protected: + /* + * If this List is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: +#ifndef DO_NOT_DOCUMENT + template class MapPrivate; + MapPrivate *d; +#endif + }; + +} + +// Since GCC doesn't support the "export" keyword, we have to include the +// implementation. + +#include "tmap.tcc" + +#endif diff --git a/external/taglib/source/toolkit/tmap.tcc b/external/taglib/source/toolkit/tmap.tcc new file mode 100644 index 0000000..18eec11 --- /dev/null +++ b/external/taglib/source/toolkit/tmap.tcc @@ -0,0 +1,206 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "trefcounter.h" + +namespace TagLib { + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +// BIC change to RefCounter +template +template +class Map::MapPrivate : public RefCounterOld +{ +public: + MapPrivate() : RefCounterOld() {} +#ifdef WANT_CLASS_INSTANTIATION_OF_MAP + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} + std::map map; +#else + MapPrivate(const std::map& m) : RefCounterOld(), map(m) {} + std::map map; +#endif +}; + +template +Map::Map() : + d(new MapPrivate()) +{ +} + +template +Map::Map(const Map &m) : d(m.d) +{ + d->ref(); +} + +template +Map::~Map() +{ + if(d->deref()) + delete(d); +} + +template +typename Map::Iterator Map::begin() +{ + detach(); + return d->map.begin(); +} + +template +typename Map::ConstIterator Map::begin() const +{ + return d->map.begin(); +} + +template +typename Map::Iterator Map::end() +{ + detach(); + return d->map.end(); +} + +template +typename Map::ConstIterator Map::end() const +{ + return d->map.end(); +} + +template +Map &Map::insert(const Key &key, const T &value) +{ + detach(); + d->map[key] = value; + return *this; +} + +template +Map &Map::clear() +{ + detach(); + d->map.clear(); + return *this; +} + +template +bool Map::isEmpty() const +{ + return d->map.empty(); +} + +template +typename Map::Iterator Map::find(const Key &key) +{ + detach(); + return d->map.find(key); +} + +template +typename Map::ConstIterator Map::find(const Key &key) const +{ + return d->map.find(key); +} + +template +bool Map::contains(const Key &key) const +{ + return d->map.find(key) != d->map.end(); +} + +template +Map &Map::erase(Iterator it) +{ + detach(); + d->map.erase(it); + return *this; +} + +template +Map &Map::erase(const Key &key) +{ + detach(); + d->map.erase(key); + return *this; +} + +template +unsigned int Map::size() const +{ + return static_cast(d->map.size()); +} + +template +const T Map::value(const Key &key, const T &defaultValue) const +{ + ConstIterator it = d->map.find(key); + return it != d->map.end() ? it->second : defaultValue; +} + +template +const T &Map::operator[](const Key &key) const +{ + return d->map[key]; +} + +template +T &Map::operator[](const Key &key) +{ + detach(); + return d->map[key]; +} + +template +Map &Map::operator=(const Map &m) +{ + Map(m).swap(*this); + return *this; +} + +template +void Map::swap(Map &m) +{ + using std::swap; + + swap(d, m.d); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +template +void Map::detach() +{ + if(d->count() > 1) { + d->deref(); + d = new MapPrivate(d->map); + } +} + +} // namespace TagLib diff --git a/external/taglib/source/toolkit/tpropertymap.cpp b/external/taglib/source/toolkit/tpropertymap.cpp new file mode 100644 index 0000000..e1b9746 --- /dev/null +++ b/external/taglib/source/toolkit/tpropertymap.cpp @@ -0,0 +1,194 @@ +/*************************************************************************** + copyright : (C) 2012 by Michael Helmling + email : helmling@mathematik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "tpropertymap.h" +using namespace TagLib; + + +PropertyMap::PropertyMap() +{ +} + +PropertyMap::PropertyMap(const PropertyMap &m) : SimplePropertyMap(m), unsupported(m.unsupported) +{ +} + +PropertyMap::PropertyMap(const SimplePropertyMap &m) +{ + for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){ + String key = it->first.upper(); + if(!key.isEmpty()) + insert(it->first, it->second); + else + unsupported.append(it->first); + } +} + +PropertyMap::~PropertyMap() +{ +} + +bool PropertyMap::insert(const String &key, const StringList &values) +{ + String realKey = key.upper(); + Iterator result = SimplePropertyMap::find(realKey); + if(result == end()) + SimplePropertyMap::insert(realKey, values); + else + SimplePropertyMap::operator[](realKey).append(values); + return true; +} + +bool PropertyMap::replace(const String &key, const StringList &values) +{ + String realKey = key.upper(); + SimplePropertyMap::erase(realKey); + SimplePropertyMap::insert(realKey, values); + return true; +} + +PropertyMap::Iterator PropertyMap::find(const String &key) +{ + return SimplePropertyMap::find(key.upper()); +} + +PropertyMap::ConstIterator PropertyMap::find(const String &key) const +{ + return SimplePropertyMap::find(key.upper()); +} + +bool PropertyMap::contains(const String &key) const +{ + return SimplePropertyMap::contains(key.upper()); +} + +bool PropertyMap::contains(const PropertyMap &other) const +{ + for(ConstIterator it = other.begin(); it != other.end(); ++it) { + if(!SimplePropertyMap::contains(it->first)) + return false; + if ((*this)[it->first] != it->second) + return false; + } + return true; +} + +PropertyMap &PropertyMap::erase(const String &key) +{ + SimplePropertyMap::erase(key.upper()); + return *this; +} + +PropertyMap &PropertyMap::erase(const PropertyMap &other) +{ + for(ConstIterator it = other.begin(); it != other.end(); ++it) + erase(it->first); + return *this; +} + +PropertyMap &PropertyMap::merge(const PropertyMap &other) +{ + for(PropertyMap::ConstIterator it = other.begin(); it != other.end(); ++it) + insert(it->first, it->second); + unsupported.append(other.unsupported); + return *this; +} + +const StringList PropertyMap::value(const String &key, + const StringList &defaultValue) const +{ + return SimplePropertyMap::value(key.upper(), defaultValue); +} + +const StringList &PropertyMap::operator[](const String &key) const +{ + return SimplePropertyMap::operator[](key.upper()); +} + +StringList &PropertyMap::operator[](const String &key) +{ + return SimplePropertyMap::operator[](key.upper()); +} + +bool PropertyMap::operator==(const PropertyMap &other) const +{ + for(ConstIterator it = other.begin(); it != other.end(); ++it) { + ConstIterator thisFind = find(it->first); + if( thisFind == end() || (thisFind->second != it->second) ) + return false; + } + for(ConstIterator it = begin(); it != end(); ++it) { + ConstIterator otherFind = other.find(it->first); + if( otherFind == other.end() || (otherFind->second != it->second) ) + return false; + } + return unsupported == other.unsupported; +} + +bool PropertyMap::operator!=(const PropertyMap &other) const +{ + return !(*this == other); +} + +String PropertyMap::toString() const +{ + String ret; + + for(ConstIterator it = begin(); it != end(); ++it) + ret += it->first+"="+it->second.toString(", ") + "\n"; + if(!unsupported.isEmpty()) + ret += "Unsupported Data: " + unsupported.toString(", ") + "\n"; + return ret; +} + +void PropertyMap::removeEmpty() +{ + PropertyMap m; + for(ConstIterator it = begin(); it != end(); ++it) { + if(!it->second.isEmpty()) + m.insert(it->first, it->second); + } + *this = m; +} + +StringList &PropertyMap::unsupportedData() +{ + return unsupported; +} + +const StringList &PropertyMap::unsupportedData() const +{ + return unsupported; +} + +#ifdef _MSC_VER +// When building with shared libraries and tests, MSVC will fail with +// "already defined in test_opus.obj" as soon as operator[] of +// Ogg::FieldListMap is used because this will instantiate the same template +// Map. Therefore this template is instantiated here +// and declared extern in the headers using it. +template class TagLib::Map; +#endif diff --git a/external/taglib/source/toolkit/tpropertymap.h b/external/taglib/source/toolkit/tpropertymap.h new file mode 100644 index 0000000..de49786 --- /dev/null +++ b/external/taglib/source/toolkit/tpropertymap.h @@ -0,0 +1,256 @@ +/*************************************************************************** + copyright : (C) 2012 by Michael Helmling + email : helmling@mathematik.uni-kl.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_PROPERTYMAP_H_ +#define TAGLIB_PROPERTYMAP_H_ + +#include "tmap.h" +#include "tstringlist.h" + +#ifdef _MSC_VER +// Explained at end of tpropertymap.cpp +extern template class TAGLIB_EXPORT TagLib::Map; +#endif + +namespace TagLib { + + typedef Map SimplePropertyMap; + + //! A map for format-independent tag representations. + + /*! + * This map implements a generic representation of textual audio metadata + * ("tags") realized as pairs of a case-insensitive key + * and a nonempty list of corresponding values, each value being an arbitrary + * unicode String. + * + * Note that most metadata formats pose additional conditions on the tag keys. The + * most popular ones (Vorbis, APE, ID3v2) should support all ASCII only words of + * length between 2 and 16. + * + * This class can contain any tags, but here is a list of "well-known" tags that + * you might want to use: + * + * Basic tags: + * + * - TITLE + * - ALBUM + * - ARTIST + * - ALBUMARTIST + * - SUBTITLE + * - TRACKNUMBER + * - DISCNUMBER + * - DATE + * - ORIGINALDATE + * - GENRE + * - COMMENT + * + * Sort names: + * + * - TITLESORT + * - ALBUMSORT + * - ARTISTSORT + * - ALBUMARTISTSORT + * - COMPOSERSORT + * + * Credits: + * + * - COMPOSER + * - LYRICIST + * - CONDUCTOR + * - REMIXER + * - PERFORMER:\ + * + * Other tags: + * + * - ISRC + * - ASIN + * - BPM + * - COPYRIGHT + * - ENCODEDBY + * - MOOD + * - COMMENT + * - MEDIA + * - LABEL + * - CATALOGNUMBER + * - BARCODE + * - RELEASECOUNTRY + * - RELEASESTATUS + * - RELEASETYPE + * + * MusicBrainz identifiers: + * + * - MUSICBRAINZ_TRACKID + * - MUSICBRAINZ_ALBUMID + * - MUSICBRAINZ_RELEASEGROUPID + * - MUSICBRAINZ_RELEASETRACKID + * - MUSICBRAINZ_WORKID + * - MUSICBRAINZ_ARTISTID + * - MUSICBRAINZ_ALBUMARTISTID + * - ACOUSTID_ID + * - ACOUSTID_FINGERPRINT + * - MUSICIP_PUID + * + */ + + class TAGLIB_EXPORT PropertyMap: public SimplePropertyMap + { + public: + + typedef SimplePropertyMap::Iterator Iterator; + typedef SimplePropertyMap::ConstIterator ConstIterator; + + PropertyMap(); + + PropertyMap(const PropertyMap &m); + + /*! + * Creates a PropertyMap initialized from a SimplePropertyMap. Copies all + * entries from \a m that have valid keys. + * Invalid keys will be appended to the unsupportedData() list. + */ + PropertyMap(const SimplePropertyMap &m); + + virtual ~PropertyMap(); + + /*! + * Inserts \a values under \a key in the map. If \a key already exists, + * then \a values will be appended to the existing StringList. + * The returned value indicates success, i.e. whether \a key is a + * valid key. + */ + bool insert(const String &key, const StringList &values); + + /*! + * Replaces any existing values for \a key with the given \a values, + * and simply insert them if \a key did not exist before. + * The returned value indicates success, i.e. whether \a key is a + * valid key. + */ + bool replace(const String &key, const StringList &values); + + /*! + * Find the first occurrence of \a key. + */ + Iterator find(const String &key); + + /*! + * Find the first occurrence of \a key. + */ + ConstIterator find(const String &key) const; + + /*! + * Returns true if the map contains values for \a key. + */ + bool contains(const String &key) const; + + /*! + * Returns true if this map contains all keys of \a other + * and the values coincide for that keys. Does not take + * the unsupportedData list into account. + */ + bool contains(const PropertyMap &other) const; + + /*! + * Erase the \a key and its values from the map. + */ + PropertyMap &erase(const String &key); + + /*! + * Erases from this map all keys that appear in \a other. + */ + PropertyMap &erase(const PropertyMap &other); + + /*! + * Merge the contents of \a other into this PropertyMap. + * If a key is contained in both maps, the values of the second + * are appended to that of the first. + * The unsupportedData() lists are concatenated as well. + */ + PropertyMap &merge(const PropertyMap &other); + + /*! + * Returns the value associated with \a key. + * + * If the map does not contain \a key, it returns defaultValue. + * If no defaultValue is specified, it returns an empty string list. + */ + const StringList value(const String &key, + const StringList &defaultValue = StringList()) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty + * StringList is returned without error. + */ + const StringList &operator[](const String &key) const; + + /*! + * Returns a reference to the value associated with \a key. + * + * \note: If \a key is not contained in the map, an empty + * StringList is returned. You can also directly add entries + * by using this function as an lvalue. + */ + StringList &operator[](const String &key); + + /*! + * Returns true if and only if \a other has the same contents as this map. + */ + bool operator==(const PropertyMap &other) const; + + /*! + * Returns false if and only \a other has the same contents as this map. + */ + bool operator!=(const PropertyMap &other) const; + + /*! + * If a PropertyMap is read from a File object using File::properties(), + * the StringList returned from this function will represent metadata + * that could not be parsed into the PropertyMap representation. This could + * be e.g. binary data, unknown ID3 frames, etc. + * You can remove items from the returned list, which tells TagLib to remove + * those unsupported elements if you call File::setProperties() with the + * same PropertyMap as argument. + */ + StringList &unsupportedData(); + const StringList &unsupportedData() const; + + /*! + * Removes all entries which have an empty value list. + */ + void removeEmpty(); + + String toString() const; + + private: + + + StringList unsupported; + }; + +} +#endif /* TAGLIB_PROPERTYMAP_H_ */ diff --git a/external/taglib/source/toolkit/trefcounter.cpp b/external/taglib/source/toolkit/trefcounter.cpp new file mode 100644 index 0000000..bbbac0b --- /dev/null +++ b/external/taglib/source/toolkit/trefcounter.cpp @@ -0,0 +1,96 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "trefcounter.h" + +#if defined(HAVE_GCC_ATOMIC) +# define ATOMIC_INT int +# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1) +# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1) +#elif defined(HAVE_WIN_ATOMIC) +# if !defined(NOMINMAX) +# define NOMINMAX +# endif +# include +# define ATOMIC_INT long +# define ATOMIC_INC(x) InterlockedIncrement(&x) +# define ATOMIC_DEC(x) InterlockedDecrement(&x) +#elif defined(HAVE_MAC_ATOMIC) +# include +# define ATOMIC_INT int32_t +# define ATOMIC_INC(x) OSAtomicIncrement32Barrier(&x) +# define ATOMIC_DEC(x) OSAtomicDecrement32Barrier(&x) +#elif defined(HAVE_IA64_ATOMIC) +# include +# define ATOMIC_INT int +# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1) +# define ATOMIC_DEC(x) __sync_sub_and_fetch(&x, 1) +#else +# define ATOMIC_INT int +# define ATOMIC_INC(x) (++x) +# define ATOMIC_DEC(x) (--x) +#endif + +namespace TagLib +{ + + class RefCounter::RefCounterPrivate + { + public: + RefCounterPrivate() : + refCount(1) {} + + volatile ATOMIC_INT refCount; + }; + + RefCounter::RefCounter() : + d(new RefCounterPrivate()) + { + } + + RefCounter::~RefCounter() + { + delete d; + } + + void RefCounter::ref() + { + ATOMIC_INC(d->refCount); + } + + bool RefCounter::deref() + { + return (ATOMIC_DEC(d->refCount) == 0); + } + + int RefCounter::count() const + { + return static_cast(d->refCount); + } +} // namespace TagLib diff --git a/external/taglib/source/toolkit/trefcounter.h b/external/taglib/source/toolkit/trefcounter.h new file mode 100644 index 0000000..db97c53 --- /dev/null +++ b/external/taglib/source/toolkit/trefcounter.h @@ -0,0 +1,114 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_REFCOUNTER_H +#define TAGLIB_REFCOUNTER_H + +#include "taglib_export.h" +#include "taglib.h" + +#ifdef __APPLE__ +# define OSATOMIC_DEPRECATED 0 +# include +# define TAGLIB_ATOMIC_MAC +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef NOMINMAX +# define NOMINMAX +# endif +# include +# define TAGLIB_ATOMIC_WIN +#elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ + && (defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(__x86_64) || defined(__ia64)) \ + && !defined(__INTEL_COMPILER) +# define TAGLIB_ATOMIC_GCC +#elif defined(__ia64) && defined(__INTEL_COMPILER) +# include +# define TAGLIB_ATOMIC_GCC +#endif + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen to skip this class. +/*! + * \internal + * This is just used as a base class for shared classes in TagLib. + * + * \warning This is not part of the TagLib public API! + */ +namespace TagLib +{ + + class TAGLIB_EXPORT RefCounter + { + public: + RefCounter(); + virtual ~RefCounter(); + + void ref(); + bool deref(); + int count() const; + + private: + class RefCounterPrivate; + RefCounterPrivate *d; + }; + + // BIC this old class is needed by tlist.tcc and tmap.tcc + class RefCounterOld + { + public: + RefCounterOld() : refCount(1) {} + +#ifdef TAGLIB_ATOMIC_MAC + void ref() { OSAtomicIncrement32Barrier(const_cast(&refCount)); } + bool deref() { return ! OSAtomicDecrement32Barrier(const_cast(&refCount)); } + int32_t count() { return refCount; } + private: + volatile int32_t refCount; +#elif defined(TAGLIB_ATOMIC_WIN) + void ref() { InterlockedIncrement(&refCount); } + bool deref() { return ! InterlockedDecrement(&refCount); } + long count() { return refCount; } + private: + volatile long refCount; +#elif defined(TAGLIB_ATOMIC_GCC) + void ref() { __sync_add_and_fetch(&refCount, 1); } + bool deref() { return ! __sync_sub_and_fetch(&refCount, 1); } + int count() { return refCount; } + private: + volatile int refCount; +#else + void ref() { refCount++; } + bool deref() { return ! --refCount; } + int count() { return refCount; } + private: + unsigned int refCount; +#endif + }; + +} + +#endif // DO_NOT_DOCUMENT +#endif + diff --git a/external/taglib/source/toolkit/tstring.cpp b/external/taglib/source/toolkit/tstring.cpp new file mode 100644 index 0000000..669cd0e --- /dev/null +++ b/external/taglib/source/toolkit/tstring.cpp @@ -0,0 +1,743 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "tstring.h" + +namespace +{ + using namespace TagLib; + + // Returns the native format of std::wstring. + String::Type wcharByteOrder() + { + if(Utils::systemByteOrder() == Utils::LittleEndian) + return String::UTF16LE; + return String::UTF16BE; + } + + // Converts a Latin-1 string into UTF-16(without BOM/CPU byte order) + // and copies it to the internal buffer. + void copyFromLatin1(std::wstring &data, const char *s, size_t length) + { + data.resize(length); + + for(size_t i = 0; i < length; ++i) + data[i] = static_cast(s[i]); + } + + // Converts a UTF-8 string into UTF-16(without BOM/CPU byte order) + // and copies it to the internal buffer. + void copyFromUTF8(std::wstring &data, const char *s, size_t length) + { + data.resize(length); + + try { + const std::wstring::iterator dstEnd = utf8::utf8to16(s, s + length, data.begin()); + data.resize(dstEnd - data.begin()); + } + catch(const utf8::exception &e) { + const String message(e.what()); + debug("String::copyFromUTF8() - UTF8-CPP error: " + message); + data.clear(); + } + } + + // Helper functions to read a UTF-16 character from an array. + template + unsigned short nextUTF16(const T **p); + + template <> + unsigned short nextUTF16(const wchar_t **p) + { + return static_cast(*(*p)++); + } + + template <> + unsigned short nextUTF16(const char **p) + { + union { + unsigned short w; + char c[2]; + } u; + u.c[0] = *(*p)++; + u.c[1] = *(*p)++; + return u.w; + } + + // Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into + // UTF-16(without BOM/CPU byte order) and copies it to the internal buffer. + template + void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t) + { + bool swap; + if(t == String::UTF16) { + if(length < 1) { + debug("String::copyFromUTF16() - Invalid UTF16 string. Too short to have a BOM."); + return; + } + + const unsigned short bom = nextUTF16(&s); + if(bom == 0xfeff) + swap = false; // Same as CPU endian. No need to swap bytes. + else if(bom == 0xfffe) + swap = true; // Not same as CPU endian. Need to swap bytes. + else { + debug("String::copyFromUTF16() - Invalid UTF16 string. BOM is broken."); + return; + } + + length--; + } + else { + swap = (t != wcharByteOrder()); + } + + data.resize(length); + for(size_t i = 0; i < length; ++i) { + const unsigned short c = nextUTF16(&s); + if(swap) + data[i] = Utils::byteSwap(c); + else + data[i] = c; + } + } +} // namespace + +namespace TagLib { + +class String::StringPrivate : public RefCounter +{ +public: + StringPrivate() + {} + + /*! + * Stores string in UTF-16. The byte order depends on the CPU endian. + */ + TagLib::wstring data; + + /*! + * This is only used to hold the the most recent value of toCString(). + */ + std::string cstring; +}; + +String String::null; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +String::String() : + d(new StringPrivate()) +{ +} + +String::String(const String &s) : + d(s.d) +{ + d->ref(); +} + +String::String(const std::string &s, Type t) : + d(new StringPrivate()) +{ + if(t == Latin1) + copyFromLatin1(d->data, s.c_str(), s.length()); + else if(t == String::UTF8) + copyFromUTF8(d->data, s.c_str(), s.length()); + else { + debug("String::String() -- std::string should not contain UTF16."); + } +} + +String::String(const wstring &s, Type t) : + d(new StringPrivate()) +{ + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + // This looks ugly but needed for the compatibility with TagLib1.8. + // Should be removed in TabLib2.0. + if (t == UTF16BE) + t = wcharByteOrder(); + else if (t == UTF16LE) + t = (wcharByteOrder() == UTF16LE ? UTF16BE : UTF16LE); + + copyFromUTF16(d->data, s.c_str(), s.length(), t); + } + else { + debug("String::String() -- TagLib::wstring should not contain Latin1 or UTF-8."); + } +} + +String::String(const wchar_t *s, Type t) : + d(new StringPrivate()) +{ + if(t == UTF16 || t == UTF16BE || t == UTF16LE) { + // This looks ugly but needed for the compatibility with TagLib1.8. + // Should be removed in TabLib2.0. + if (t == UTF16BE) + t = wcharByteOrder(); + else if (t == UTF16LE) + t = (wcharByteOrder() == UTF16LE ? UTF16BE : UTF16LE); + + copyFromUTF16(d->data, s, ::wcslen(s), t); + } + else { + debug("String::String() -- const wchar_t * should not contain Latin1 or UTF-8."); + } +} + +String::String(const char *s, Type t) : + d(new StringPrivate()) +{ + if(t == Latin1) + copyFromLatin1(d->data, s, ::strlen(s)); + else if(t == String::UTF8) + copyFromUTF8(d->data, s, ::strlen(s)); + else { + debug("String::String() -- const char * should not contain UTF16."); + } +} + +String::String(wchar_t c, Type t) : + d(new StringPrivate()) +{ + if(t == UTF16 || t == UTF16BE || t == UTF16LE) + copyFromUTF16(d->data, &c, 1, t); + else { + debug("String::String() -- wchar_t should not contain Latin1 or UTF-8."); + } +} + +String::String(char c, Type t) : + d(new StringPrivate()) +{ + if(t == Latin1) + copyFromLatin1(d->data, &c, 1); + else if(t == String::UTF8) + copyFromUTF8(d->data, &c, 1); + else { + debug("String::String() -- char should not contain UTF16."); + } +} + +String::String(const ByteVector &v, Type t) : + d(new StringPrivate()) +{ + if(v.isEmpty()) + return; + + if(t == Latin1) + copyFromLatin1(d->data, v.data(), v.size()); + else if(t == UTF8) + copyFromUTF8(d->data, v.data(), v.size()); + else + copyFromUTF16(d->data, v.data(), v.size() / 2, t); + + // If we hit a null in the ByteVector, shrink the string again. + d->data.resize(::wcslen(d->data.c_str())); +} + +//////////////////////////////////////////////////////////////////////////////// + +String::~String() +{ + if(d->deref()) + delete d; +} + +std::string String::to8Bit(bool unicode) const +{ + const ByteVector v = data(unicode ? UTF8 : Latin1); + return std::string(v.data(), v.size()); +} + +TagLib::wstring String::toWString() const +{ + return d->data; +} + +const char *String::toCString(bool unicode) const +{ + d->cstring = to8Bit(unicode); + return d->cstring.c_str(); +} + +const wchar_t *String::toCWString() const +{ + return d->data.c_str(); +} + +String::Iterator String::begin() +{ + detach(); + return d->data.begin(); +} + +String::ConstIterator String::begin() const +{ + return d->data.begin(); +} + +String::Iterator String::end() +{ + detach(); + return d->data.end(); +} + +String::ConstIterator String::end() const +{ + return d->data.end(); +} + +int String::find(const String &s, int offset) const +{ + return static_cast(d->data.find(s.d->data, offset)); +} + +int String::rfind(const String &s, int offset) const +{ + return static_cast(d->data.rfind(s.d->data, offset)); +} + +StringList String::split(const String &separator) const +{ + StringList list; + for(int index = 0;;) { + int sep = find(separator, index); + if(sep < 0) { + list.append(substr(index, size() - index)); + break; + } + list.append(substr(index, sep - index)); + index = sep + separator.size(); + } + return list; +} + +bool String::startsWith(const String &s) const +{ + if(s.length() > length()) + return false; + + return substr(0, s.length()) == s; +} + +String String::substr(unsigned int position, unsigned int n) const +{ + if(position == 0 && n >= size()) + return *this; + return String(d->data.substr(position, n)); +} + +String &String::append(const String &s) +{ + detach(); + d->data += s.d->data; + return *this; +} + +String & String::clear() +{ + *this = String(); + return *this; +} + +String String::upper() const +{ + String s; + s.d->data.reserve(size()); + + for(ConstIterator it = begin(); it != end(); ++it) { + if(*it >= 'a' && *it <= 'z') + s.d->data.push_back(*it + 'A' - 'a'); + else + s.d->data.push_back(*it); + } + + return s; +} + +unsigned int String::size() const +{ + return static_cast(d->data.size()); +} + +unsigned int String::length() const +{ + return size(); +} + +bool String::isEmpty() const +{ + return d->data.empty(); +} + +bool String::isNull() const +{ + return d == null.d; +} + +ByteVector String::data(Type t) const +{ + switch(t) + { + case Latin1: + { + ByteVector v(size(), 0); + char *p = v.data(); + + for(ConstIterator it = begin(); it != end(); ++it) + *p++ = static_cast(*it); + + return v; + } + case UTF8: + { + ByteVector v(size() * 4, 0); + + try { + const ByteVector::Iterator dstEnd = utf8::utf16to8(begin(), end(), v.begin()); + v.resize(static_cast(dstEnd - v.begin())); + } + catch(const utf8::exception &e) { + const String message(e.what()); + debug("String::data() - UTF8-CPP error: " + message); + v.clear(); + } + + return v; + } + case UTF16: + { + ByteVector v(2 + size() * 2, 0); + char *p = v.data(); + + // We use little-endian encoding here and need a BOM. + + *p++ = '\xff'; + *p++ = '\xfe'; + + for(ConstIterator it = begin(); it != end(); ++it) { + *p++ = static_cast(*it & 0xff); + *p++ = static_cast(*it >> 8); + } + + return v; + } + case UTF16BE: + { + ByteVector v(size() * 2, 0); + char *p = v.data(); + + for(ConstIterator it = begin(); it != end(); ++it) { + *p++ = static_cast(*it >> 8); + *p++ = static_cast(*it & 0xff); + } + + return v; + } + case UTF16LE: + { + ByteVector v(size() * 2, 0); + char *p = v.data(); + + for(ConstIterator it = begin(); it != end(); ++it) { + *p++ = static_cast(*it & 0xff); + *p++ = static_cast(*it >> 8); + } + + return v; + } + default: + { + debug("String::data() - Invalid Type value."); + return ByteVector(); + } + } +} + +int String::toInt() const +{ + return toInt(0); +} + +int String::toInt(bool *ok) const +{ + const wchar_t *begin = d->data.c_str(); + wchar_t *end; + errno = 0; + const long value = ::wcstol(begin, &end, 10); + + // Has wcstol() consumed the entire string and not overflowed? + if(ok) { + *ok = (errno == 0 && end > begin && *end == L'\0'); + *ok = (*ok && value > INT_MIN && value < INT_MAX); + } + + return static_cast(value); +} + +String String::stripWhiteSpace() const +{ + static const wchar_t *WhiteSpaceChars = L"\t\n\f\r "; + + const size_t pos1 = d->data.find_first_not_of(WhiteSpaceChars); + if(pos1 == std::wstring::npos) + return String(); + + const size_t pos2 = d->data.find_last_not_of(WhiteSpaceChars); + return substr(static_cast(pos1), static_cast(pos2 - pos1 + 1)); +} + +bool String::isLatin1() const +{ + for(ConstIterator it = begin(); it != end(); ++it) { + if(*it >= 256) + return false; + } + return true; +} + +bool String::isAscii() const +{ + for(ConstIterator it = begin(); it != end(); ++it) { + if(*it >= 128) + return false; + } + return true; +} + +String String::number(int n) // static +{ + return Utils::formatString("%d", n); +} + +wchar_t &String::operator[](int i) +{ + detach(); + return d->data[i]; +} + +const wchar_t &String::operator[](int i) const +{ + return d->data[i]; +} + +bool String::operator==(const String &s) const +{ + return (d == s.d || d->data == s.d->data); +} + +bool String::operator!=(const String &s) const +{ + return !(*this == s); +} + +bool String::operator==(const char *s) const +{ + const wchar_t *p = toCWString(); + + while(*p != L'\0' || *s != '\0') { + if(*p++ != static_cast(*s++)) + return false; + } + return true; +} + +bool String::operator!=(const char *s) const +{ + return !(*this == s); +} + +bool String::operator==(const wchar_t *s) const +{ + return (d->data == s); +} + +bool String::operator!=(const wchar_t *s) const +{ + return !(*this == s); +} + +String &String::operator+=(const String &s) +{ + detach(); + + d->data += s.d->data; + return *this; +} + +String &String::operator+=(const wchar_t *s) +{ + detach(); + + d->data += s; + return *this; +} + +String &String::operator+=(const char *s) +{ + detach(); + + for(int i = 0; s[i] != 0; i++) + d->data += static_cast(s[i]); + return *this; +} + +String &String::operator+=(wchar_t c) +{ + detach(); + + d->data += c; + return *this; +} + +String &String::operator+=(char c) +{ + detach(); + + d->data += static_cast(c); + return *this; +} + +String &String::operator=(const String &s) +{ + String(s).swap(*this); + return *this; +} + +String &String::operator=(const std::string &s) +{ + String(s).swap(*this); + return *this; +} + +String &String::operator=(const wstring &s) +{ + String(s).swap(*this); + return *this; +} + +String &String::operator=(const wchar_t *s) +{ + String(s).swap(*this); + return *this; +} + +String &String::operator=(char c) +{ + String(c).swap(*this); + return *this; +} + +String &String::operator=(wchar_t c) +{ + String(c, wcharByteOrder()).swap(*this); + return *this; +} + +String &String::operator=(const char *s) +{ + String(s).swap(*this); + return *this; +} + +String &String::operator=(const ByteVector &v) +{ + String(v).swap(*this); + return *this; +} + +void String::swap(String &s) +{ + using std::swap; + + swap(d, s.d); +} + +bool String::operator<(const String &s) const +{ + return (d->data < s.d->data); +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void String::detach() +{ + if(d->count() > 1) + String(d->data.c_str()).swap(*this); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +const String::Type String::WCharByteOrder = wcharByteOrder(); +} // namespace TagLib + +//////////////////////////////////////////////////////////////////////////////// +// related non-member functions +//////////////////////////////////////////////////////////////////////////////// + +const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2) +{ + TagLib::String s(s1); + s.append(s2); + return s; +} + +const TagLib::String operator+(const char *s1, const TagLib::String &s2) +{ + TagLib::String s(s1); + s.append(s2); + return s; +} + +const TagLib::String operator+(const TagLib::String &s1, const char *s2) +{ + TagLib::String s(s1); + s.append(s2); + return s; +} + +std::ostream &operator<<(std::ostream &s, const TagLib::String &str) +{ + s << str.to8Bit(); + return s; +} + diff --git a/external/taglib/source/toolkit/tstring.h b/external/taglib/source/toolkit/tstring.h new file mode 100644 index 0000000..7028aab --- /dev/null +++ b/external/taglib/source/toolkit/tstring.h @@ -0,0 +1,580 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRING_H +#define TAGLIB_STRING_H + +#include "taglib_export.h" +#include "taglib.h" +#include "tbytevector.h" + +#include +#include + +/*! + * \relates TagLib::String + * + * Converts a QString to a TagLib::String without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + */ + +#if defined(QT_VERSION) && (QT_VERSION >= 0x040000) +#define QStringToTString(s) TagLib::String(s.toUtf8().data(), TagLib::String::UTF8) +#else +#define QStringToTString(s) TagLib::String(s.utf8().data(), TagLib::String::UTF8) +#endif + +/*! + * \relates TagLib::String + * + * Converts a TagLib::String to a QString without a requirement to link to Qt. + * + * \note consider conversion via usual char-by-char for loop to avoid UTF16->UTF8->UTF16 + * conversion happening in the background + * + */ + +#define TStringToQString(s) QString::fromUtf8(s.toCString(true)) + +namespace TagLib { + + class StringList; + + //! A \e wide string class suitable for unicode. + + /*! + * This is an implicitly shared \e wide string. For storage it uses + * TagLib::wstring, but as this is an implementation detail this of + * course could change. Strings are stored internally as UTF-16(without BOM/ + * CPU byte order) + * + * The use of implicit sharing means that copying a string is cheap, the only + * \e cost comes into play when the copy is modified. Prior to that the string + * just has a pointer to the data of the \e parent String. This also makes + * this class suitable as a function return type. + * + * In addition to adding implicit sharing, this class keeps track of four + * possible encodings, which are the four supported by the ID3v2 standard. + */ + + class TAGLIB_EXPORT String + { + public: + +#ifndef DO_NOT_DOCUMENT + typedef TagLib::wstring::iterator Iterator; + typedef TagLib::wstring::const_iterator ConstIterator; +#endif + + /** + * The four types of string encodings supported by the ID3v2 specification. + * ID3v1 is assumed to be Latin1 and Ogg Vorbis comments use UTF8. + */ + enum Type { + /*! + * IS08859-1, or Latin1 encoding. 8 bit characters. + */ + Latin1 = 0, + /*! + * UTF16 with a byte order mark. 16 bit characters. + */ + UTF16 = 1, + /*! + * UTF16 big endian. 16 bit characters. This is the encoding used + * internally by TagLib. + */ + UTF16BE = 2, + /*! + * UTF8 encoding. Characters are usually 8 bits but can be up to 32. + */ + UTF8 = 3, + /*! + * UTF16 little endian. 16 bit characters. + */ + UTF16LE = 4 + }; + + /*! + * Constructs an empty String. + */ + String(); + + /*! + * Make a shallow, implicitly shared, copy of \a s. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + String(const String &s); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const std::string &s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. + */ + String(const wstring &s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a s. + * + * /note If \a t is UTF16LE, the byte order of \a s will be swapped regardless + * of the CPU byte order. If UTF16BE, it will not be swapped. This behavior + * will be changed in TagLib2.0. + */ + String(const wchar_t *s, Type t = UTF16BE); + + /*! + * Makes a deep copy of the data in \a c. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(char c, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a c. + */ + String(wchar_t c, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a s. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + String(const char *s, Type t = Latin1); + + /*! + * Makes a deep copy of the data in \a v. + */ + String(const ByteVector &v, Type t = Latin1); + + /*! + * Destroys this String instance. + */ + virtual ~String(); + + /*! + * Returns a deep copy of this String as an std::string. The returned string + * is encoded in UTF8 if \a unicode is true, otherwise Latin1. + * + * \see toCString() + */ + std::string to8Bit(bool unicode = false) const; + + /*! + * Returns a deep copy of this String as a wstring. The returned string is + * encoded in UTF-16 (without BOM/CPU byte order), not UTF-32 even if wchar_t + * is 32-bit wide. + * + * \see toCWString() + */ + wstring toWString() const; + + /*! + * Creates and returns a standard C-style (null-terminated) version of this + * String. The returned string is encoded in UTF8 if \a unicode is true, + * otherwise Latin1. + * + * The returned string is still owned by this String and should not be deleted + * by the user. + * + * The returned pointer remains valid until this String instance is destroyed + * or toCString() is called again. + * + * \warning This however has the side effect that the returned string will remain + * in memory in addition to other memory that is consumed by this + * String instance. So, this method should not be used on large strings or + * where memory is critical. Consider using to8Bit() instead to avoid it. + * + * \see to8Bit() + */ + const char *toCString(bool unicode = false) const; + + /*! + * Returns a standard C-style (null-terminated) wide character version of + * this String. The returned string is encoded in UTF-16 (without BOM/CPU byte + * order), not UTF-32 even if wchar_t is 32-bit wide. + * + * The returned string is still owned by this String and should not be deleted + * by the user. + * + * The returned pointer remains valid until this String instance is destroyed + * or any other method of this String is called. + * + * \note This returns a pointer to the String's internal data without any + * conversions. + * + * \see toWString() + */ + const wchar_t *toCWString() const; + + /*! + * Returns an iterator pointing to the beginning of the string. + */ + Iterator begin(); + + /*! + * Returns a const iterator pointing to the beginning of the string. + */ + ConstIterator begin() const; + + /*! + * Returns an iterator pointing to the end of the string (the position + * after the last character). + */ + Iterator end(); + + /*! + * Returns a const iterator pointing to the end of the string (the position + * after the last character). + */ + ConstIterator end() const; + + /*! + * Finds the first occurrence of pattern \a s in this string starting from + * \a offset. If the pattern is not found, -1 is returned. + */ + int find(const String &s, int offset = 0) const; + + /*! + * Finds the last occurrence of pattern \a s in this string, searched backwards, + * either from the end of the string or starting from \a offset. If the pattern + * is not found, -1 is returned. + */ + int rfind(const String &s, int offset = -1) const; + + /*! + * Splits the string on each occurrence of \a separator. + */ + StringList split(const String &separator = " ") const; + + /*! + * Returns true if the strings starts with the substring \a s. + */ + bool startsWith(const String &s) const; + + /*! + * Extract a substring from this string starting at \a position and + * continuing for \a n characters. + */ + String substr(unsigned int position, unsigned int n = 0xffffffff) const; + + /*! + * Append \a s to the current string and return a reference to the current + * string. + */ + String &append(const String &s); + + /*! + * Clears the string. + */ + String &clear(); + + /*! + * Returns an upper case version of the string. + * + * \warning This only works for the characters in US-ASCII, i.e. A-Z. + */ + String upper() const; + + /*! + * Returns the size of the string. + */ + unsigned int size() const; + + /*! + * Returns the length of the string. Equivalent to size(). + */ + unsigned int length() const; + + /*! + * Returns true if the string is empty. + * + * \see isNull() + */ + bool isEmpty() const; + + /*! + * Returns true if this string is null -- i.e. it is a copy of the + * String::null string. + * + * \note A string can be empty and not null. So do not use this method to + * check if the string is empty. + * + * \see isEmpty() + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED bool isNull() const; + + /*! + * Returns a ByteVector containing the string's data. If \a t is Latin1 or + * UTF8, this will return a vector of 8 bit characters, otherwise it will use + * 16 bit characters. + * + * \note If \a t is UTF16, the returned data is encoded in little-endian + * format and has a BOM. + * + * \note The returned data is not null terminated. + */ + ByteVector data(Type t) const; + + /*! + * Convert the string to an integer. + * + * Returns the integer if the conversion was successful or 0 if the + * string does not represent a number. + */ + // BIC: merge with the method below + int toInt() const; + + /*! + * Convert the string to an integer. + * + * If the conversion was successful, it sets the value of \a *ok to + * true and returns the integer. Otherwise it sets \a *ok to false + * and the result is undefined. + */ + int toInt(bool *ok) const; + + /*! + * Returns a string with the leading and trailing whitespace stripped. + */ + String stripWhiteSpace() const; + + /*! + * Returns true if the file only uses characters required by Latin1. + */ + bool isLatin1() const; + + /*! + * Returns true if the file only uses characters required by (7-bit) ASCII. + */ + bool isAscii() const; + + /*! + * Converts the base-10 integer \a n to a string. + */ + static String number(int n); + + /*! + * Returns a reference to the character at position \a i. + */ + wchar_t &operator[](int i); + + /*! + * Returns a const reference to the character at position \a i. + */ + const wchar_t &operator[](int i) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const String &s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const String &s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const char *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const char *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns true if the strings match. + */ + bool operator==(const wchar_t *s) const; + + /*! + * Compares each character of the String with each character of \a s and + * returns false if the strings match. + */ + bool operator!=(const wchar_t *s) const; + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const String &s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const wchar_t* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(const char* s); + + /*! + * Appends \a s to the end of the String. + */ + String &operator+=(wchar_t c); + + /*! + * Appends \a c to the end of the String. + */ + String &operator+=(char c); + + /*! + * Performs a shallow, implicitly shared, copy of \a s, overwriting the + * String's current data. + */ + String &operator=(const String &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const std::string &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wstring &s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const wchar_t *s); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(char c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(wchar_t c); + + /*! + * Performs a deep copy of the data in \a s. + */ + String &operator=(const char *s); + + /*! + * Performs a deep copy of the data in \a v. + */ + String &operator=(const ByteVector &v); + + /*! + * Exchanges the content of the String by the content of \a s. + */ + void swap(String &s); + + /*! + * To be able to use this class in a Map, this operator needed to be + * implemented. Returns true if \a s is less than this string in a byte-wise + * comparison. + */ + bool operator<(const String &s) const; + + /*! + * A null string provided for convenience. + * + * \warning Do not modify this variable. It will mess up the internal state + * of TagLib. + * + * \deprecated + */ + // BIC: remove + TAGLIB_DEPRECATED static String null; + + protected: + /*! + * If this String is being shared via implicit sharing, do a deep copy of the + * data and separate from the shared members. This should be called by all + * non-const subclass members. + */ + void detach(); + + private: + /*! + * \deprecated This variable is no longer used, but NEVER remove this. It + * may lead to a linkage error. + */ + // BIC: remove + TAGLIB_DEPRECATED static const Type WCharByteOrder; + + class StringPrivate; + StringPrivate *d; + }; +} + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const char *s1, const TagLib::String &s2); + +/*! + * \relates TagLib::String + * + * Concatenates \a s1 and \a s2 and returns the result as a string. + */ +TAGLIB_EXPORT const TagLib::String operator+(const TagLib::String &s1, const char *s2); + + +/*! + * \relates TagLib::String + * + * Send the string to an output stream. + */ +TAGLIB_EXPORT std::ostream &operator<<(std::ostream &s, const TagLib::String &str); + +#endif diff --git a/external/taglib/source/toolkit/tstringlist.cpp b/external/taglib/source/toolkit/tstringlist.cpp new file mode 100644 index 0000000..3237091 --- /dev/null +++ b/external/taglib/source/toolkit/tstringlist.cpp @@ -0,0 +1,123 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tstringlist.h" + +using namespace TagLib; + +class StringListPrivate +{ + +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +StringList StringList::split(const String &s, const String &pattern) +{ + StringList l; + + int previousOffset = 0; + for(int offset = s.find(pattern); offset != -1; offset = s.find(pattern, offset + 1)) { + l.append(s.substr(previousOffset, offset - previousOffset)); + previousOffset = offset + 1; + } + + l.append(s.substr(previousOffset, s.size() - previousOffset)); + + return l; +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +StringList::StringList() +{ + +} + +StringList::StringList(const StringList &l) : List(l) +{ + +} + +StringList::StringList(const String &s) +{ + append(s); +} + +StringList::StringList(const ByteVectorList &bl, String::Type t) +{ + ByteVectorList::ConstIterator i = bl.begin(); + for(;i != bl.end(); i++) { + append(String(*i, t)); + } +} + +StringList::~StringList() +{ + +} + +String StringList::toString(const String &separator) const +{ + String s; + + ConstIterator it = begin(); + ConstIterator itEnd = end(); + + while(it != itEnd) { + s += *it; + it++; + if(it != itEnd) + s += separator; + } + + return s; +} + +StringList &StringList::append(const String &s) +{ + List::append(s); + return *this; +} + +StringList &StringList::append(const StringList &l) +{ + List::append(l); + return *this; +} + +//////////////////////////////////////////////////////////////////////////////// +// related functions +//////////////////////////////////////////////////////////////////////////////// + +std::ostream &operator<<(std::ostream &s, const StringList &l) +{ + s << l.toString(); + return s; +} diff --git a/external/taglib/source/toolkit/tstringlist.h b/external/taglib/source/toolkit/tstringlist.h new file mode 100644 index 0000000..ddf0f04 --- /dev/null +++ b/external/taglib/source/toolkit/tstringlist.h @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2002 - 2008 by Scott Wheeler + email : wheeler@kde.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_STRINGLIST_H +#define TAGLIB_STRINGLIST_H + +#include "tstring.h" +#include "tlist.h" +#include "tbytevectorlist.h" +#include "taglib_export.h" + +#include + +namespace TagLib { + + //! A list of strings + + /*! + * This is a specialization of the List class with some members convention for + * string operations. + */ + + class TAGLIB_EXPORT StringList : public List + { + public: + + /*! + * Constructs an empty StringList. + */ + StringList(); + + /*! + * Make a shallow, implicitly shared, copy of \a l. Because this is + * implicitly shared, this method is lightweight and suitable for + * pass-by-value usage. + */ + StringList(const StringList &l); + + /*! + * Constructs a StringList with \a s as a member. + */ + StringList(const String &s); + + /*! + * Makes a deep copy of the data in \a vl. + * + * \note This should only be used with the 8-bit codecs Latin1 and UTF8, when + * used with other codecs it will simply print a warning and exit. + */ + StringList(const ByteVectorList &vl, String::Type t = String::Latin1); + + /*! + * Destroys this StringList instance. + */ + virtual ~StringList(); + + /*! + * Concatenate the list of strings into one string separated by \a separator. + */ + String toString(const String &separator = " ") const; + + /*! + * Appends \a s to the end of the list and returns a reference to the + * list. + */ + StringList &append(const String &s); + + /*! + * Appends all of the values in \a l to the end of the list and returns a + * reference to the list. + */ + StringList &append(const StringList &l); + + /*! + * Splits the String \a s into several strings at \a pattern. This will not include + * the pattern in the returned strings. + */ + static StringList split(const String &s, const String &pattern); + + private: + class StringListPrivate; + StringListPrivate *d; + }; + +} + +/*! + * \related TagLib::StringList + * Send the StringList to an output stream. + */ +std::ostream TAGLIB_EXPORT &operator<<(std::ostream &s, const TagLib::StringList &l); + +#endif diff --git a/external/taglib/source/toolkit/tutils.h b/external/taglib/source/toolkit/tutils.h new file mode 100644 index 0000000..6d96cd1 --- /dev/null +++ b/external/taglib/source/toolkit/tutils.h @@ -0,0 +1,243 @@ +/*************************************************************************** + copyright : (C) 2013 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TUTILS_H +#define TAGLIB_TUTILS_H + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined(HAVE_MSC_BYTESWAP) +# include +#elif defined(HAVE_GLIBC_BYTESWAP) +# include +#elif defined(HAVE_MAC_BYTESWAP) +# include +#elif defined(HAVE_OPENBSD_BYTESWAP) +# include +#endif + +#include +#include +#include +#include + +namespace TagLib +{ + namespace Utils + { + namespace + { + + /*! + * Reverses the order of bytes in an 16-bit integer. + */ + inline unsigned short byteSwap(unsigned short x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap16(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_ushort(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_16(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt16(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap16(x); + +#else + + return ((x >> 8) & 0xff) | ((x & 0xff) << 8); + +#endif + } + + /*! + * Reverses the order of bytes in an 32-bit integer. + */ + inline unsigned int byteSwap(unsigned int x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap32(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_ulong(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_32(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt32(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap32(x); + +#else + + return ((x & 0xff000000u) >> 24) + | ((x & 0x00ff0000u) >> 8) + | ((x & 0x0000ff00u) << 8) + | ((x & 0x000000ffu) << 24); + +#endif + } + + /*! + * Reverses the order of bytes in an 64-bit integer. + */ + inline unsigned long long byteSwap(unsigned long long x) + { +#if defined(HAVE_GCC_BYTESWAP) + + return __builtin_bswap64(x); + +#elif defined(HAVE_MSC_BYTESWAP) + + return _byteswap_uint64(x); + +#elif defined(HAVE_GLIBC_BYTESWAP) + + return __bswap_64(x); + +#elif defined(HAVE_MAC_BYTESWAP) + + return OSSwapInt64(x); + +#elif defined(HAVE_OPENBSD_BYTESWAP) + + return swap64(x); + +#else + + return ((x & 0xff00000000000000ull) >> 56) + | ((x & 0x00ff000000000000ull) >> 40) + | ((x & 0x0000ff0000000000ull) >> 24) + | ((x & 0x000000ff00000000ull) >> 8) + | ((x & 0x00000000ff000000ull) << 8) + | ((x & 0x0000000000ff0000ull) << 24) + | ((x & 0x000000000000ff00ull) << 40) + | ((x & 0x00000000000000ffull) << 56); + +#endif + } + + /*! + * Returns a formatted string just like standard sprintf(), but makes use of + * safer functions such as snprintf() if available. + */ + inline String formatString(const char *format, ...) + { + // Sufficient buffer size for the current internal uses. + // Consider changing this value when you use this function. + + static const size_t BufferSize = 128; + + va_list args; + va_start(args, format); + + char buf[BufferSize]; + int length; + +#if defined(HAVE_VSNPRINTF) + + length = vsnprintf(buf, BufferSize, format, args); + +#elif defined(HAVE_VSPRINTF_S) + + length = vsprintf_s(buf, format, args); + +#else + + // The last resort. May cause a buffer overflow. + + length = vsprintf(buf, format, args); + if(length >= BufferSize) { + debug("Utils::formatString() - Buffer overflow! Returning an empty string."); + length = -1; + } + +#endif + + va_end(args); + + if(length > 0) + return String(buf); + else + return String(); + } + + /*! + * The types of byte order of the running system. + */ + enum ByteOrder + { + //! Little endian systems. + LittleEndian, + //! Big endian systems. + BigEndian + }; + + /*! + * Returns the byte order of the system. + */ + inline ByteOrder systemByteOrder() + { + union { + int i; + char c; + } u; + + u.i = 1; + if(u.c == 1) + return LittleEndian; + else + return BigEndian; + } + } + } +} + +#endif + +#endif diff --git a/external/taglib/source/toolkit/tzlib.cpp b/external/taglib/source/toolkit/tzlib.cpp new file mode 100644 index 0000000..4b348df --- /dev/null +++ b/external/taglib/source/toolkit/tzlib.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + copyright : (C) 2016 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_ZLIB +# include +# include +# include +#endif + +#include "tzlib.h" + +using namespace TagLib; + +bool zlib::isAvailable() +{ +#ifdef HAVE_ZLIB + + return true; + +#else + + return false; + +#endif +} + +ByteVector zlib::decompress(const ByteVector &data) +{ +#ifdef HAVE_ZLIB + + z_stream stream = {}; + + if(inflateInit(&stream) != Z_OK) { + debug("zlib::decompress() - Failed to initialize zlib."); + return ByteVector(); + } + + ByteVector inData = data; + + stream.avail_in = static_cast(inData.size()); + stream.next_in = reinterpret_cast(inData.data()); + + const unsigned int chunkSize = 1024; + + ByteVector outData; + + do { + const size_t offset = outData.size(); + outData.resize(outData.size() + chunkSize); + + stream.avail_out = static_cast(chunkSize); + stream.next_out = reinterpret_cast(outData.data() + offset); + + const int result = inflate(&stream, Z_NO_FLUSH); + + if(result == Z_STREAM_ERROR || + result == Z_NEED_DICT || + result == Z_DATA_ERROR || + result == Z_MEM_ERROR) + { + if(result != Z_STREAM_ERROR) + inflateEnd(&stream); + + debug("zlib::decompress() - Error reading compressed stream."); + return ByteVector(); + } + + outData.resize(outData.size() - stream.avail_out); + } while(stream.avail_out == 0); + + inflateEnd(&stream); + + return outData; + +#else + + return ByteVector(); + +#endif +} diff --git a/external/taglib/source/toolkit/tzlib.h b/external/taglib/source/toolkit/tzlib.h new file mode 100644 index 0000000..dab7828 --- /dev/null +++ b/external/taglib/source/toolkit/tzlib.h @@ -0,0 +1,54 @@ +/*************************************************************************** + copyright : (C) 2016 by Tsuda Kageyu + email : tsuda.kageyu@gmail.com + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TZLIB_H +#define TAGLIB_TZLIB_H + +#include + +// THIS FILE IS NOT A PART OF THE TAGLIB API + +#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header + +namespace TagLib { + + namespace zlib { + + /*! + * Returns whether or not zlib is installed and ready to use. + */ + bool TAGLIB_EXPORT isAvailable(); + + /*! + * Decompress \a data by zlib. + */ + ByteVector decompress(const ByteVector &data); + + } +} + +#endif + +#endif diff --git a/external/taglib/source/trueaudio/trueaudiofile.cpp b/external/taglib/source/trueaudio/trueaudiofile.cpp new file mode 100644 index 0000000..e4de436 --- /dev/null +++ b/external/taglib/source/trueaudio/trueaudiofile.cpp @@ -0,0 +1,310 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "trueaudiofile.h" +#include "id3v1tag.h" +#include "id3v2tag.h" +#include "id3v2header.h" + +using namespace TagLib; + +namespace +{ + enum { TrueAudioID3v2Index = 0, TrueAudioID3v1Index = 1 }; +} + +class TrueAudio::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Location(-1), + properties(0) {} + + ~FilePrivate() + { + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + long ID3v2Location; + long ID3v2OriginalSize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool TrueAudio::File::isSupported(IOStream *stream) +{ + // A TrueAudio file has to start with "TTA". An ID3v2 tag may precede. + + const ByteVector id = Utils::readHeader(stream, 3, true); + return (id == "TTA"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TrueAudio::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +TrueAudio::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +TrueAudio::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate(frameFactory)) +{ + if(isOpen()) + read(readProperties); +} + +TrueAudio::File::~File() +{ + delete d; +} + +TagLib::Tag *TrueAudio::File::tag() const +{ + return &d->tag; +} + +PropertyMap TrueAudio::File::properties() const +{ + return d->tag.properties(); +} + +void TrueAudio::File::removeUnsupportedProperties(const StringList &unsupported) +{ + d->tag.removeUnsupportedProperties(unsupported); +} + +PropertyMap TrueAudio::File::setProperties(const PropertyMap &properties) +{ + if(ID3v1Tag()) + ID3v1Tag()->setProperties(properties); + + return ID3v2Tag(true)->setProperties(properties); +} + +TrueAudio::Properties *TrueAudio::File::audioProperties() const +{ + return d->properties; +} + +void TrueAudio::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +bool TrueAudio::File::save() +{ + if(readOnly()) { + debug("TrueAudio::File::save() -- File is read only."); + return false; + } + + // Update ID3v2 tag + + if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) { + + // ID3v2 tag is not empty. Update the old one or create a new one. + + if(d->ID3v2Location < 0) + d->ID3v2Location = 0; + + const ByteVector data = ID3v2Tag()->render(); + insert(data, d->ID3v2Location, d->ID3v2OriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->ID3v2OriginalSize); + + d->ID3v2OriginalSize = data.size(); + } + else { + + // ID3v2 tag is empty. Remove the old one. + + if(d->ID3v2Location >= 0) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->ID3v2OriginalSize; + + d->ID3v2Location = -1; + d->ID3v2OriginalSize = 0; + } + } + + // Update ID3v1 tag + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + if(d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + } + } + + return true; +} + +ID3v1::Tag *TrueAudio::File::ID3v1Tag(bool create) +{ + return d->tag.access(TrueAudioID3v1Index, create); +} + +ID3v2::Tag *TrueAudio::File::ID3v2Tag(bool create) +{ + return d->tag.access(TrueAudioID3v2Index, create); +} + +void TrueAudio::File::strip(int tags) +{ + if(tags & ID3v1) + d->tag.set(TrueAudioID3v1Index, 0); + + if(tags & ID3v2) + d->tag.set(TrueAudioID3v2Index, 0); + + if(!ID3v1Tag()) + ID3v2Tag(true); +} + +bool TrueAudio::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +bool TrueAudio::File::hasID3v2Tag() const +{ + return (d->ID3v2Location >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TrueAudio::File::read(bool readProperties) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = Utils::findID3v2(this); + + if(d->ID3v2Location >= 0) { + d->tag.set(TrueAudioID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory)); + d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize(); + } + + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(TrueAudioID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + if(d->ID3v1Location < 0) + ID3v2Tag(true); + + // Look for TrueAudio metadata + + if(readProperties) { + + long streamLength; + + if(d->ID3v1Location >= 0) + streamLength = d->ID3v1Location; + else + streamLength = length(); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location + d->ID3v2OriginalSize); + streamLength -= (d->ID3v2Location + d->ID3v2OriginalSize); + } + else { + seek(0); + } + + d->properties = new Properties(readBlock(TrueAudio::HeaderSize), streamLength); + } +} diff --git a/external/taglib/source/trueaudio/trueaudiofile.h b/external/taglib/source/trueaudio/trueaudiofile.h new file mode 100644 index 0000000..1f664d2 --- /dev/null +++ b/external/taglib/source/trueaudio/trueaudiofile.h @@ -0,0 +1,259 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOFILE_H +#define TAGLIB_TRUEAUDIOFILE_H + +#include "tfile.h" +#include "trueaudioproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + + //! An implementation of TrueAudio metadata + + /*! + * This is implementation of TrueAudio metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream + * properties from the file. + */ + + namespace TrueAudio { + + //! An implementation of TagLib::File with TrueAudio specific methods + + /*! + * This implements and provides an interface for TrueAudio files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to TrueAudio files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a TrueAudio file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a file. If \a readProperties is true + * the file's audio properties will also be read. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(FileName file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs a TrueAudio file from \a stream. If \a readProperties is true + * the file's audio properties will also be read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + * + * If this file contains and ID3v2 tag the frames will be created using + * \a frameFactory. + * + * \note In the current implementation, \a propertiesStyle is ignored. + */ + File(IOStream *stream, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both ID3v1 and v2 tags, only ID3v2 will be + * converted to the PropertyMap. + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Creates in ID3v2 tag if necessary. If an ID3v1 tag exists, it will + * be updated as well, within the limitations of ID3v1. + */ + PropertyMap setProperties(const PropertyMap &); + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Returns the TrueAudio::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + * \deprecated This value should be passed in via the constructor + */ + TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v2 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file + * on disk actually has an ID3v2 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v2Tag() + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an ID3v2 tag. + * + * \see ID3v2Tag() + */ + bool hasID3v2Tag() const; + + /*! + * Returns whether or not the given \a stream can be opened as a TrueAudio + * file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/trueaudio/trueaudioproperties.cpp b/external/taglib/source/trueaudio/trueaudioproperties.cpp new file mode 100644 index 0000000..0aab241 --- /dev/null +++ b/external/taglib/source/trueaudio/trueaudioproperties.cpp @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "trueaudioproperties.h" +#include "trueaudiofile.h" + +using namespace TagLib; + +class TrueAudio::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0), + sampleFrames(0) {} + + int version; + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; + unsigned int sampleFrames; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TrueAudio::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(data, streamLength); +} + +TrueAudio::Properties::~Properties() +{ + delete d; +} + +int TrueAudio::Properties::length() const +{ + return lengthInSeconds(); +} + +int TrueAudio::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int TrueAudio::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int TrueAudio::Properties::bitrate() const +{ + return d->bitrate; +} + +int TrueAudio::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int TrueAudio::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int TrueAudio::Properties::channels() const +{ + return d->channels; +} + +unsigned int TrueAudio::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +int TrueAudio::Properties::ttaVersion() const +{ + return d->version; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TrueAudio::Properties::read(const ByteVector &data, long streamLength) +{ + if(data.size() < 4) { + debug("TrueAudio::Properties::read() -- data is too short."); + return; + } + + if(!data.startsWith("TTA")) { + debug("TrueAudio::Properties::read() -- invalid header signature."); + return; + } + + unsigned int pos = 3; + + d->version = data[pos] - '0'; + pos += 1; + + // According to http://en.true-audio.com/TTA_Lossless_Audio_Codec_-_Format_Description + // TTA2 headers are in development, and have a different format + if(1 == d->version) { + if(data.size() < 18) { + debug("TrueAudio::Properties::read() -- data is too short."); + return; + } + + // Skip the audio format + pos += 2; + + d->channels = data.toShort(pos, false); + pos += 2; + + d->bitsPerSample = data.toShort(pos, false); + pos += 2; + + d->sampleRate = data.toUInt(pos, false); + pos += 4; + + d->sampleFrames = data.toUInt(pos, false); + pos += 4; + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } + } +} diff --git a/external/taglib/source/trueaudio/trueaudioproperties.h b/external/taglib/source/trueaudio/trueaudioproperties.h new file mode 100644 index 0000000..d25c7a7 --- /dev/null +++ b/external/taglib/source/trueaudio/trueaudioproperties.h @@ -0,0 +1,133 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOPROPERTIES_H +#define TAGLIB_TRUEAUDIOPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace TrueAudio { + + class File; + + static const unsigned int HeaderSize = 18; + + //! An implementation of audio property reading for TrueAudio + + /*! + * This reads the data from an TrueAudio stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of TrueAudio::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this TrueAudio::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns the total number of sample frames + */ + unsigned int sampleFrames() const; + + /*! + * Returns the major version number. + */ + int ttaVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(const ByteVector &data, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/wavpack/wavpackfile.cpp b/external/taglib/source/wavpack/wavpackfile.cpp new file mode 100644 index 0000000..56b9939 --- /dev/null +++ b/external/taglib/source/wavpack/wavpackfile.cpp @@ -0,0 +1,284 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include "wavpackfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" + +using namespace TagLib; + +namespace +{ + enum { WavAPEIndex, WavID3v1Index }; +} + +class WavPack::File::FilePrivate +{ +public: + FilePrivate() : + APELocation(-1), + APESize(0), + ID3v1Location(-1), + properties(0) {} + + ~FilePrivate() + { + delete properties; + } + + long APELocation; + long APESize; + + long ID3v1Location; + + TagUnion tag; + + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// static members +//////////////////////////////////////////////////////////////////////////////// + +bool WavPack::File::isSupported(IOStream *stream) +{ + // A WavPack file has to start with "wvpk". + + const ByteVector id = Utils::readHeader(stream, 4, false); + return (id == "wvpk"); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::File::File(FileName file, bool readProperties, Properties::ReadStyle) : + TagLib::File(file), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +WavPack::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : + TagLib::File(stream), + d(new FilePrivate()) +{ + if(isOpen()) + read(readProperties); +} + +WavPack::File::~File() +{ + delete d; +} + +TagLib::Tag *WavPack::File::tag() const +{ + return &d->tag; +} + +PropertyMap WavPack::File::properties() const +{ + return d->tag.properties(); +} + +void WavPack::File::removeUnsupportedProperties(const StringList &unsupported) +{ + d->tag.removeUnsupportedProperties(unsupported); +} + +PropertyMap WavPack::File::setProperties(const PropertyMap &properties) +{ + if(ID3v1Tag()) + ID3v1Tag()->setProperties(properties); + + return APETag(true)->setProperties(properties); +} + +WavPack::Properties *WavPack::File::audioProperties() const +{ + return d->properties; +} + +bool WavPack::File::save() +{ + if(readOnly()) { + debug("WavPack::File::save() -- File is read only."); + return false; + } + + // Update ID3v1 tag + + if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) { + + // ID3v1 tag is not empty. Update the old one or create a new one. + + if(d->ID3v1Location >= 0) { + seek(d->ID3v1Location); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + } + + writeBlock(ID3v1Tag()->render()); + } + else { + + // ID3v1 tag is empty. Remove the old one. + + if(d->ID3v1Location >= 0) { + truncate(d->ID3v1Location); + d->ID3v1Location = -1; + } + } + + // Update APE tag + + if(APETag() && !APETag()->isEmpty()) { + + // APE tag is not empty. Update the old one or create a new one. + + if(d->APELocation < 0) { + if(d->ID3v1Location >= 0) + d->APELocation = d->ID3v1Location; + else + d->APELocation = length(); + } + + const ByteVector data = APETag()->render(); + insert(data, d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location += (static_cast(data.size()) - d->APESize); + + d->APESize = data.size(); + } + else { + + // APE tag is empty. Remove the old one. + + if(d->APELocation >= 0) { + removeBlock(d->APELocation, d->APESize); + + if(d->ID3v1Location >= 0) + d->ID3v1Location -= d->APESize; + + d->APELocation = -1; + d->APESize = 0; + } + } + + return true; +} + +ID3v1::Tag *WavPack::File::ID3v1Tag(bool create) +{ + return d->tag.access(WavID3v1Index, create); +} + +APE::Tag *WavPack::File::APETag(bool create) +{ + return d->tag.access(WavAPEIndex, create); +} + +void WavPack::File::strip(int tags) +{ + if(tags & ID3v1) + d->tag.set(WavID3v1Index, 0); + + if(tags & APE) + d->tag.set(WavAPEIndex, 0); + + if(!ID3v1Tag()) + APETag(true); +} + +bool WavPack::File::hasID3v1Tag() const +{ + return (d->ID3v1Location >= 0); +} + +bool WavPack::File::hasAPETag() const +{ + return (d->APELocation >= 0); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void WavPack::File::read(bool readProperties) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = Utils::findID3v1(this); + + if(d->ID3v1Location >= 0) + d->tag.set(WavID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); + + // Look for an APE tag + + d->APELocation = Utils::findAPE(this, d->ID3v1Location); + + if(d->APELocation >= 0) { + d->tag.set(WavAPEIndex, new APE::Tag(this, d->APELocation)); + d->APESize = APETag()->footer()->completeTagSize(); + d->APELocation = d->APELocation + APE::Footer::size() - d->APESize; + } + + if(d->ID3v1Location < 0) + APETag(true); + + // Look for WavPack audio properties + + if(readProperties) { + + long streamLength; + + if(d->APELocation >= 0) + streamLength = d->APELocation; + else if(d->ID3v1Location >= 0) + streamLength = d->ID3v1Location; + else + streamLength = length(); + + d->properties = new Properties(this, streamLength); + } +} diff --git a/external/taglib/source/wavpack/wavpackfile.h b/external/taglib/source/wavpack/wavpackfile.h new file mode 100644 index 0000000..ccc4ef6 --- /dev/null +++ b/external/taglib/source/wavpack/wavpackfile.h @@ -0,0 +1,223 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVFILE_H +#define TAGLIB_WVFILE_H + +#include "tfile.h" +#include "taglib_export.h" +#include "wavpackproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of WavPack metadata + + /*! + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace WavPack { + + //! An implementation of TagLib::File with WavPack specific methods + + /*! + * This implements and provides an interface for WavPack files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WavPack files. + */ + + class TAGLIB_EXPORT File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Constructs a WavPack file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored + */ + File(FileName file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Constructs an WavPack file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * If the file contains both an APE and an ID3v1 tag, only APE + * will be converted to the PropertyMap. + */ + PropertyMap properties() const; + + void removeUnsupportedProperties(const StringList &properties); + + /*! + * Implements the unified property interface -- import function. + * Creates an APE tag if it does not exists and calls setProperties() on + * that. Any existing ID3v1 tag will be updated as well. + */ + PropertyMap setProperties(const PropertyMap&); + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file + * on disk actually has an ID3v1 tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasID3v1Tag() + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this may return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * an APE tag if one does not exist and returns a valid pointer. + * + * \note This may return a valid pointer regardless of whether or not the + * file on disk has an APE tag. Use hasAPETag() to check if the file + * on disk actually has an APE tag. + * + * \note The Tag is still owned by the MPEG::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + * + * \see hasAPETag() + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void strip(int tags = AllTags); + + /*! + * Returns whether or not the file on disk actually has an ID3v1 tag. + * + * \see ID3v1Tag() + */ + bool hasID3v1Tag() const; + + /*! + * Returns whether or not the file on disk actually has an APE tag. + * + * \see APETag() + */ + bool hasAPETag() const; + + /*! + * Check if the given \a stream can be opened as a WavPack file. + * + * \note This method is designed to do a quick check. The result may + * not necessarily be correct. + */ + static bool isSupported(IOStream *stream); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/wavpack/wavpackproperties.cpp b/external/taglib/source/wavpack/wavpackproperties.cpp new file mode 100644 index 0000000..1dd2a05 --- /dev/null +++ b/external/taglib/source/wavpack/wavpackproperties.cpp @@ -0,0 +1,374 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include +#include +#include + +#include "wavpackproperties.h" +#include "wavpackfile.h" + +// Implementation of this class is based on the information at: +// http://www.wavpack.com/file_format.txt + +using namespace TagLib; + +class WavPack::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0), + lossless(false), + sampleFrames(0) {} + + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; + bool lossless; + unsigned int sampleFrames; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::Properties::Properties(const ByteVector &, long, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + debug("WavPack::Properties::Properties() -- This constructor is no longer used."); +} + +WavPack::Properties::Properties(File *file, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file, streamLength); +} + +WavPack::Properties::~Properties() +{ + delete d; +} + +int WavPack::Properties::length() const +{ + return lengthInSeconds(); +} + +int WavPack::Properties::lengthInSeconds() const +{ + return d->length / 1000; +} + +int WavPack::Properties::lengthInMilliseconds() const +{ + return d->length; +} + +int WavPack::Properties::bitrate() const +{ + return d->bitrate; +} + +int WavPack::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int WavPack::Properties::channels() const +{ + return d->channels; +} + +int WavPack::Properties::version() const +{ + return d->version; +} + +int WavPack::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +bool WavPack::Properties::isLossless() const +{ + return d->lossless; +} + +unsigned int WavPack::Properties::sampleFrames() const +{ + return d->sampleFrames; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +#define BYTES_STORED 3 +#define MONO_FLAG 4 +#define HYBRID_FLAG 8 +#define DSD_FLAG 0x80000000 // block is encoded DSD (1-bit PCM) + +#define SHIFT_LSB 13 +#define SHIFT_MASK (0x1fL << SHIFT_LSB) + +#define SRATE_LSB 23 +#define SRATE_MASK (0xfL << SRATE_LSB) + +#define MIN_STREAM_VERS 0x402 +#define MAX_STREAM_VERS 0x410 + +#define INITIAL_BLOCK 0x800 +#define FINAL_BLOCK 0x1000 + +#define ID_DSD_BLOCK 0x0e +#define ID_OPTIONAL_DATA 0x20 +#define ID_UNIQUE 0x3f +#define ID_ODD_SIZE 0x40 +#define ID_LARGE 0x80 +#define ID_SAMPLE_RATE (ID_OPTIONAL_DATA | 0x7) + +namespace +{ + const unsigned int sampleRates[] = { + 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000, 192000, 0 }; + + /*! + * Given a WavPack \a block (complete, but not including the 32-byte header), + * parse the metadata blocks until an \a id block is found and return the + * contained data, or zero if no such block is found. + * Supported values for \a id are ID_SAMPLE_RATE and ID_DSD_BLOCK. + */ + int getMetaDataChunk(const ByteVector &block, unsigned char id) + { + if(id != ID_SAMPLE_RATE && id != ID_DSD_BLOCK) + return 0; + + const int blockSize = static_cast(block.size()); + int index = 0; + + while(index + 1 < blockSize) { + const unsigned char metaId = static_cast(block[index]); + int metaBc = static_cast(block[index + 1]) << 1; + index += 2; + + if(metaId & ID_LARGE) { + if(index + 2 > blockSize) + return 0; + + metaBc += (static_cast(static_cast(block[index])) << 9) + + (static_cast(static_cast(block[index + 1])) << 17); + index += 2; + } + + if(index + metaBc > blockSize) + return 0; + + // if we got a sample rate, return it + + if(id == ID_SAMPLE_RATE && (metaId & ID_UNIQUE) == ID_SAMPLE_RATE && metaBc == 4) { + int sampleRate = static_cast(static_cast(block[index])); + sampleRate |= static_cast(static_cast(block[index + 1])) << 8; + sampleRate |= static_cast(static_cast(block[index + 2])) << 16; + + // only use 4th byte if it's really there + + if(!(metaId & ID_ODD_SIZE)) + sampleRate |= static_cast(static_cast(block[index + 3]) & 0x7f) << 24; + + return sampleRate; + } + + // if we got DSD block, return the specified rate shift amount + + if(id == ID_DSD_BLOCK && (metaId & ID_UNIQUE) == ID_DSD_BLOCK && metaBc > 0) { + const unsigned char rateShift = static_cast(block[index]); + if(rateShift <= 31) + return rateShift; + } + + index += metaBc; + } + + return 0; + } + + /*! + * Given a WavPack block (complete, but not including the 32-byte header), + * parse the metadata blocks until an ID_SAMPLE_RATE block is found and + * return the non-standard sample rate contained there, or zero if no such + * block is found. + */ + int getNonStandardRate(const ByteVector &block) + { + return getMetaDataChunk(block, ID_SAMPLE_RATE); + } + + /*! + * Given a WavPack block (complete, but not including the 32-byte header), + * parse the metadata blocks until a DSD audio data block is found and return + * the sample-rate shift value contained there, or zero if no such block is + * found. The nominal sample rate of DSD audio files (found in the header) + * must be left-shifted by this amount to get the actual "byte" sample rate. + * Note that 8-bit bytes are the "atoms" of the DSD audio coding (for + * decoding, seeking, etc), so the shifted rate must be further multiplied by + * 8 to get the actual DSD bit sample rate. + */ + int getDsdRateShifter(const ByteVector &block) + { + return getMetaDataChunk(block, ID_DSD_BLOCK); + } + +} // namespace + +void WavPack::Properties::read(File *file, long streamLength) +{ + long offset = 0; + + while(true) { + file->seek(offset); + const ByteVector data = file->readBlock(32); + + if(data.size() < 32) { + debug("WavPack::Properties::read() -- data is too short."); + break; + } + + if(!data.startsWith("wvpk")) { + debug("WavPack::Properties::read() -- Block header not found."); + break; + } + + const unsigned int blockSize = data.toUInt(4, false); + const unsigned int sampleFrames = data.toUInt(12, false); + const unsigned int blockSamples = data.toUInt(20, false); + const unsigned int flags = data.toUInt(24, false); + unsigned int sampleRate = sampleRates[(flags & SRATE_MASK) >> SRATE_LSB]; + + if(!blockSamples) { // ignore blocks with no samples + offset += blockSize + 8; + continue; + } + + if(blockSize < 24 || blockSize > 1048576) { + debug("WavPack::Properties::read() -- Invalid block header found."); + break; + } + + // For non-standard sample rates or DSD audio files, we must read and parse the block + // to actually determine the sample rate. + + if(!sampleRate || (flags & DSD_FLAG)) { + const unsigned int adjustedBlockSize = blockSize - 24; + const ByteVector block = file->readBlock(adjustedBlockSize); + + if(block.size() < adjustedBlockSize) { + debug("WavPack::Properties::read() -- block is too short."); + break; + } + + if(!sampleRate) + sampleRate = static_cast(getNonStandardRate(block)); + + if(sampleRate && (flags & DSD_FLAG)) + sampleRate <<= getDsdRateShifter(block); + } + + if(flags & INITIAL_BLOCK) { + d->version = data.toShort(8, false); + if(d->version < MIN_STREAM_VERS || d->version > MAX_STREAM_VERS) + break; + + d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 - ((flags & SHIFT_MASK) >> SHIFT_LSB); + d->sampleRate = static_cast(sampleRate); + d->lossless = !(flags & HYBRID_FLAG); + d->sampleFrames = sampleFrames; + } + + d->channels += (flags & MONO_FLAG) ? 1 : 2; + + if(flags & FINAL_BLOCK) + break; + + offset += blockSize + 8; + } + + if(d->sampleFrames == ~0u) + d->sampleFrames = seekFinalIndex(file, streamLength); + + if(d->sampleFrames > 0 && d->sampleRate > 0) { + const double length = d->sampleFrames * 1000.0 / d->sampleRate; + d->length = static_cast(length + 0.5); + d->bitrate = static_cast(streamLength * 8.0 / length + 0.5); + } +} + +unsigned int WavPack::Properties::seekFinalIndex(File *file, long streamLength) +{ + long offset = streamLength; + + while (offset >= 32) { + offset = file->rfind("wvpk", offset - 4); + + if(offset == -1) + return 0; + + file->seek(offset); + const ByteVector data = file->readBlock(32); + if(data.size() < 32) + return 0; + + const unsigned int blockSize = data.toUInt(4, false); + const unsigned int blockIndex = data.toUInt(16, false); + const unsigned int blockSamples = data.toUInt(20, false); + const unsigned int flags = data.toUInt(24, false); + const int version = data.toShort(8, false); + + // try not to trigger on a spurious "wvpk" in WavPack binary block data + + if(version < MIN_STREAM_VERS || version > MAX_STREAM_VERS || (blockSize & 1) || + blockSize < 24 || blockSize >= 1048576 || blockSamples > 131072) + continue; + + if (blockSamples && (flags & FINAL_BLOCK)) + return blockIndex + blockSamples; + } + + return 0; +} diff --git a/external/taglib/source/wavpack/wavpackproperties.h b/external/taglib/source/wavpack/wavpackproperties.h new file mode 100644 index 0000000..e6acdcc --- /dev/null +++ b/external/taglib/source/wavpack/wavpackproperties.h @@ -0,0 +1,149 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_WVPROPERTIES_H +#define TAGLIB_WVPROPERTIES_H + +#include "taglib_export.h" +#include "audioproperties.h" + +namespace TagLib { + + namespace WavPack { + + class File; + + static const unsigned int HeaderSize = 32; + + //! An implementation of audio property reading for WavPack + + /*! + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ + + class TAGLIB_EXPORT Properties : public AudioProperties + { + public: + /*! + * Create an instance of WavPack::Properties with the data read from the + * ByteVector \a data. + * + * \deprecated This constructor will be dropped in favor of the one below + * in a future version. + */ + TAGLIB_DEPRECATED Properties(const ByteVector &data, long streamLength, + ReadStyle style = Average); + + /*! + * Create an instance of WavPack::Properties. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this WavPack::Properties instance. + */ + virtual ~Properties(); + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \note This method is just an alias of lengthInSeconds(). + * + * \deprecated + */ + TAGLIB_DEPRECATED virtual int length() const; + + /*! + * Returns the length of the file in seconds. The length is rounded down to + * the nearest whole second. + * + * \see lengthInMilliseconds() + */ + // BIC: make virtual + int lengthInSeconds() const; + + /*! + * Returns the length of the file in milliseconds. + * + * \see lengthInSeconds() + */ + // BIC: make virtual + int lengthInMilliseconds() const; + + /*! + * Returns the average bit rate of the file in kb/s. + */ + virtual int bitrate() const; + + /*! + * Returns the sample rate in Hz. 0 means unknown or custom. + */ + virtual int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + virtual int channels() const; + + /*! + * Returns the number of bits per audio sample. + */ + int bitsPerSample() const; + + /*! + * Returns whether or not the file is lossless encoded. + */ + bool isLossless() const; + + /*! + * Returns the total number of audio samples in file. + */ + unsigned int sampleFrames() const; + + /*! + * Returns WavPack version. + */ + int version() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(File *file, long streamLength); + unsigned int seekFinalIndex(File *file, long streamLength); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/xm/xmfile.cpp b/external/taglib/source/xm/xmfile.cpp new file mode 100644 index 0000000..61a554c --- /dev/null +++ b/external/taglib/source/xm/xmfile.cpp @@ -0,0 +1,649 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#include "tstringlist.h" +#include "tdebug.h" +#include "xmfile.h" +#include "modfileprivate.h" +#include "tpropertymap.h" + +#include +#include + +using namespace TagLib; +using namespace XM; + +namespace +{ + +/*! + * The Reader classes are helpers to make handling of the stripped XM + * format more easy. In the stripped XM format certain header sizes might + * be smaller than one would expect. The fields that are not included + * are then just some predefined valued (e.g. 0). + * + * Using these classes this code: + * + * if(headerSize >= 4) { + * if(!readU16L(value1)) ERROR(); + * if(headerSize >= 8) { + * if(!readU16L(value2)) ERROR(); + * if(headerSize >= 12) { + * if(!readString(value3, 22)) ERROR(); + * ... + * } + * } + * } + * + * Becomes: + * + * StructReader header; + * header.u16L(value1).u16L(value2).string(value3, 22). ...; + * if(header.read(*this, headerSize) < std::min(header.size(), headerSize)) + * ERROR(); + * + * Maybe if this is useful to other formats these classes can be moved to + * their own public files. + */ +class Reader +{ +public: + virtual ~Reader() + { + } + + /*! + * Reads associated values from \a file, but never reads more + * then \a limit bytes. + */ + virtual unsigned int read(TagLib::File &file, unsigned int limit) = 0; + + /*! + * Returns the number of bytes this reader would like to read. + */ + virtual unsigned int size() const = 0; +}; + +class SkipReader : public Reader +{ +public: + SkipReader(unsigned int size) : m_size(size) + { + } + + unsigned int read(TagLib::File &file, unsigned int limit) + { + unsigned int count = std::min(m_size, limit); + file.seek(count, TagLib::File::Current); + return count; + } + + unsigned int size() const + { + return m_size; + } + +private: + unsigned int m_size; +}; + +template +class ValueReader : public Reader +{ +public: + ValueReader(T &value) : value(value) + { + } + +protected: + T &value; +}; + +class StringReader : public ValueReader +{ +public: + StringReader(String &string, unsigned int size) : + ValueReader(string), m_size(size) + { + } + + unsigned int read(TagLib::File &file, unsigned int limit) + { + ByteVector data = file.readBlock(std::min(m_size, limit)); + unsigned int count = data.size(); + int index = data.find(static_cast(0)); + if(index > -1) { + data.resize(index); + } + data.replace('\xff', ' '); + value = data; + return count; + } + + unsigned int size() const + { + return m_size; + } + +private: + unsigned int m_size; +}; + +class ByteReader : public ValueReader +{ +public: + ByteReader(unsigned char &byte) : ValueReader(byte) {} + + unsigned int read(TagLib::File &file, unsigned int limit) + { + ByteVector data = file.readBlock(std::min(1U,limit)); + if(data.size() > 0) { + value = data[0]; + } + return data.size(); + } + + unsigned int size() const + { + return 1; + } +}; + +template +class NumberReader : public ValueReader +{ +public: + NumberReader(T &value, bool bigEndian) : + ValueReader(value), bigEndian(bigEndian) + { + } + +protected: + bool bigEndian; +}; + +class U16Reader : public NumberReader +{ +public: + U16Reader(unsigned short &value, bool bigEndian) + : NumberReader(value, bigEndian) {} + + unsigned int read(TagLib::File &file, unsigned int limit) + { + ByteVector data = file.readBlock(std::min(2U,limit)); + value = data.toUShort(bigEndian); + return data.size(); + } + + unsigned int size() const + { + return 2; + } +}; + +class U32Reader : public NumberReader +{ +public: + U32Reader(unsigned long &value, bool bigEndian = true) : + NumberReader(value, bigEndian) + { + } + + unsigned int read(TagLib::File &file, unsigned int limit) + { + ByteVector data = file.readBlock(std::min(4U,limit)); + value = data.toUInt(bigEndian); + return data.size(); + } + + unsigned int size() const + { + return 4; + } +}; + +class StructReader : public Reader +{ +public: + StructReader() + { + m_readers.setAutoDelete(true); + } + + /*! + * Add a nested reader. This reader takes ownership. + */ + StructReader &reader(Reader *reader) + { + m_readers.append(reader); + return *this; + } + + /*! + * Don't read anything but skip \a size bytes. + */ + StructReader &skip(unsigned int size) + { + m_readers.append(new SkipReader(size)); + return *this; + } + + /*! + * Read a string of \a size characters (bytes) into \a string. + */ + StructReader &string(String &string, unsigned int size) + { + m_readers.append(new StringReader(string, size)); + return *this; + } + + /*! + * Read a byte into \a byte. + */ + StructReader &byte(unsigned char &byte) + { + m_readers.append(new ByteReader(byte)); + return *this; + } + + /*! + * Read a unsigned 16 Bit integer into \a number. The byte order + * is controlled by \a bigEndian. + */ + StructReader &u16(unsigned short &number, bool bigEndian) + { + m_readers.append(new U16Reader(number, bigEndian)); + return *this; + } + + /*! + * Read a unsigned 16 Bit little endian integer into \a number. + */ + StructReader &u16L(unsigned short &number) + { + return u16(number, false); + } + + /*! + * Read a unsigned 16 Bit big endian integer into \a number. + */ + StructReader &u16B(unsigned short &number) + { + return u16(number, true); + } + + /*! + * Read a unsigned 32 Bit integer into \a number. The byte order + * is controlled by \a bigEndian. + */ + StructReader &u32(unsigned long &number, bool bigEndian) + { + m_readers.append(new U32Reader(number, bigEndian)); + return *this; + } + + /*! + * Read a unsigned 32 Bit little endian integer into \a number. + */ + StructReader &u32L(unsigned long &number) + { + return u32(number, false); + } + + /*! + * Read a unsigned 32 Bit big endian integer into \a number. + */ + StructReader &u32B(unsigned long &number) + { + return u32(number, true); + } + + unsigned int size() const + { + unsigned int size = 0; + for(List::ConstIterator i = m_readers.begin(); + i != m_readers.end(); ++ i) { + size += (*i)->size(); + } + return size; + } + + unsigned int read(TagLib::File &file, unsigned int limit) + { + unsigned int sumcount = 0; + for(List::ConstIterator i = m_readers.begin(); + limit > 0 && i != m_readers.end(); ++ i) { + unsigned int count = (*i)->read(file, limit); + limit -= count; + sumcount += count; + } + return sumcount; + } + +private: + List m_readers; +}; + +} // namespace + +class XM::File::FilePrivate +{ +public: + FilePrivate(AudioProperties::ReadStyle propertiesStyle) + : properties(propertiesStyle) + { + } + + Mod::Tag tag; + XM::Properties properties; +}; + +XM::File::File(FileName file, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(file), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +XM::File::File(IOStream *stream, bool readProperties, + AudioProperties::ReadStyle propertiesStyle) : + Mod::FileBase(stream), + d(new FilePrivate(propertiesStyle)) +{ + if(isOpen()) + read(readProperties); +} + +XM::File::~File() +{ + delete d; +} + +Mod::Tag *XM::File::tag() const +{ + return &d->tag; +} + +PropertyMap XM::File::properties() const +{ + return d->tag.properties(); +} + +PropertyMap XM::File::setProperties(const PropertyMap &properties) +{ + return d->tag.setProperties(properties); +} + +XM::Properties *XM::File::audioProperties() const +{ + return &d->properties; +} + +bool XM::File::save() +{ + if(readOnly()) { + debug("XM::File::save() - Cannot save to a read only file."); + return false; + } + + seek(17); + writeString(d->tag.title(), 20); + + seek(38); + writeString(d->tag.trackerName(), 20); + + seek(60); + unsigned long headerSize = 0; + if(!readU32L(headerSize)) + return false; + + seek(70); + unsigned short patternCount = 0; + unsigned short instrumentCount = 0; + if(!readU16L(patternCount) || !readU16L(instrumentCount)) + return false; + + long pos = 60 + headerSize; // should be long long in taglib2. + + // need to read patterns again in order to seek to the instruments: + for(unsigned short i = 0; i < patternCount; ++ i) { + seek(pos); + unsigned long patternHeaderLength = 0; + if(!readU32L(patternHeaderLength) || patternHeaderLength < 4) + return false; + + seek(pos + 7); + unsigned short dataSize = 0; + if (!readU16L(dataSize)) + return false; + + pos += patternHeaderLength + dataSize; + } + + const StringList lines = d->tag.comment().split("\n"); + unsigned int sampleNameIndex = instrumentCount; + for(unsigned short i = 0; i < instrumentCount; ++ i) { + seek(pos); + unsigned long instrumentHeaderSize = 0; + if(!readU32L(instrumentHeaderSize) || instrumentHeaderSize < 4) + return false; + + seek(pos + 4); + const unsigned int len = std::min(22UL, instrumentHeaderSize - 4U); + if(i >= lines.size()) + writeString(String(), len); + else + writeString(lines[i], len); + + unsigned short sampleCount = 0; + if(instrumentHeaderSize >= 29U) { + seek(pos + 27); + if(!readU16L(sampleCount)) + return false; + } + + unsigned long sampleHeaderSize = 0; + if(sampleCount > 0) { + seek(pos + 29); + if(instrumentHeaderSize < 33U || !readU32L(sampleHeaderSize)) + return false; + } + + pos += instrumentHeaderSize; + + for(unsigned short j = 0; j < sampleCount; ++ j) { + if(sampleHeaderSize > 4U) { + seek(pos); + unsigned long sampleLength = 0; + if(!readU32L(sampleLength)) + return false; + + if(sampleHeaderSize > 18U) { + seek(pos + 18); + const unsigned int len = std::min(sampleHeaderSize - 18U, 22UL); + if(sampleNameIndex >= lines.size()) + writeString(String(), len); + else + writeString(lines[sampleNameIndex ++], len); + } + } + pos += sampleHeaderSize; + } + } + + return true; +} + +void XM::File::read(bool) +{ + if(!isOpen()) + return; + + seek(0); + ByteVector magic = readBlock(17); + // it's all 0x00 for stripped XM files: + READ_ASSERT(magic == "Extended Module: " || magic == ByteVector(17, 0)); + + READ_STRING(d->tag.setTitle, 20); + READ_BYTE_AS(escape); + // in stripped XM files this is 0x00: + READ_ASSERT(escape == 0x1A || escape == 0x00); + + READ_STRING(d->tag.setTrackerName, 20); + READ_U16L(d->properties.setVersion); + + READ_U32L_AS(headerSize); + READ_ASSERT(headerSize >= 4); + + unsigned short length = 0; + unsigned short restartPosition = 0; + unsigned short channels = 0; + unsigned short patternCount = 0; + unsigned short instrumentCount = 0; + unsigned short flags = 0; + unsigned short tempo = 0; + unsigned short bpmSpeed = 0; + + StructReader header; + header.u16L(length) + .u16L(restartPosition) + .u16L(channels) + .u16L(patternCount) + .u16L(instrumentCount) + .u16L(flags) + .u16L(tempo) + .u16L(bpmSpeed); + + unsigned int count = header.read(*this, headerSize - 4U); + unsigned int size = std::min(headerSize - 4U, static_cast(header.size())); + + READ_ASSERT(count == size); + + d->properties.setLengthInPatterns(length); + d->properties.setRestartPosition(restartPosition); + d->properties.setChannels(channels); + d->properties.setPatternCount(patternCount); + d->properties.setInstrumentCount(instrumentCount); + d->properties.setFlags(flags); + d->properties.setTempo(tempo); + d->properties.setBpmSpeed(bpmSpeed); + + seek(60 + headerSize); + + // read patterns: + for(unsigned short i = 0; i < patternCount; ++ i) { + READ_U32L_AS(patternHeaderLength); + READ_ASSERT(patternHeaderLength >= 4); + + unsigned char packingType = 0; + unsigned short rowCount = 0; + unsigned short dataSize = 0; + StructReader pattern; + pattern.byte(packingType).u16L(rowCount).u16L(dataSize); + + unsigned int count = pattern.read(*this, patternHeaderLength - 4U); + READ_ASSERT(count == std::min(patternHeaderLength - 4U, (unsigned long)pattern.size())); + + seek(patternHeaderLength - (4 + count) + dataSize, Current); + } + + StringList instrumentNames; + StringList sampleNames; + unsigned int sumSampleCount = 0; + + // read instruments: + for(unsigned short i = 0; i < instrumentCount; ++ i) { + READ_U32L_AS(instrumentHeaderSize); + READ_ASSERT(instrumentHeaderSize >= 4); + + String instrumentName; + unsigned char instrumentType = 0; + unsigned short sampleCount = 0; + + StructReader instrument; + instrument.string(instrumentName, 22).byte(instrumentType).u16L(sampleCount); + + // 4 for instrumentHeaderSize + unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U); + READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4)); + + long offset = 0; + if(sampleCount > 0) { + unsigned long sampleHeaderSize = 0; + sumSampleCount += sampleCount; + // wouldn't know which header size to assume otherwise: + READ_ASSERT(instrumentHeaderSize >= count + 4 && readU32L(sampleHeaderSize)); + // skip unhandled header proportion: + seek(instrumentHeaderSize - count - 4, Current); + + for(unsigned short j = 0; j < sampleCount; ++ j) { + unsigned long sampleLength = 0; + unsigned long loopStart = 0; + unsigned long loopLength = 0; + unsigned char volume = 0; + unsigned char finetune = 0; + unsigned char sampleType = 0; + unsigned char panning = 0; + unsigned char noteNumber = 0; + unsigned char compression = 0; + String sampleName; + StructReader sample; + sample.u32L(sampleLength) + .u32L(loopStart) + .u32L(loopLength) + .byte(volume) + .byte(finetune) + .byte(sampleType) + .byte(panning) + .byte(noteNumber) + .byte(compression) + .string(sampleName, 22); + + unsigned int count = sample.read(*this, sampleHeaderSize); + READ_ASSERT(count == std::min(sampleHeaderSize, (unsigned long)sample.size())); + // skip unhandled header proportion: + seek(sampleHeaderSize - count, Current); + + offset += sampleLength; + sampleNames.append(sampleName); + } + } + else { + offset = instrumentHeaderSize - count; + } + instrumentNames.append(instrumentName); + seek(offset, Current); + } + + d->properties.setSampleCount(sumSampleCount); + String comment(instrumentNames.toString("\n")); + if(!sampleNames.isEmpty()) { + comment += "\n"; + comment += sampleNames.toString("\n"); + } + d->tag.setComment(comment); +} diff --git a/external/taglib/source/xm/xmfile.h b/external/taglib/source/xm/xmfile.h new file mode 100644 index 0000000..9211078 --- /dev/null +++ b/external/taglib/source/xm/xmfile.h @@ -0,0 +1,112 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XMFILE_H +#define TAGLIB_XMFILE_H + +#include "tfile.h" +#include "audioproperties.h" +#include "taglib_export.h" +#include "modfilebase.h" +#include "modtag.h" +#include "xmproperties.h" + +namespace TagLib { + + namespace XM { + + class TAGLIB_EXPORT File : public Mod::FileBase { + public: + /*! + * Constructs an Extended Module file from \a file. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + */ + File(FileName file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Constructs an Extended Module file from \a stream. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. The audio properties are always + * read. + * + * \note TagLib will *not* take ownership of the stream, the caller is + * responsible for deleting it after the File object. + */ + File(IOStream *stream, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = + AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + Mod::Tag *tag() const; + + /*! + * Implements the unified property interface -- export function. + * Forwards to Mod::Tag::properties(). + */ + PropertyMap properties() const; + + /*! + * Implements the unified property interface -- import function. + * Forwards to Mod::Tag::setProperties(). + */ + PropertyMap setProperties(const PropertyMap &); + + /*! + * Returns the XM::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + XM::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note Saving Extended Module tags is not supported. + */ + bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/external/taglib/source/xm/xmproperties.cpp b/external/taglib/source/xm/xmproperties.cpp new file mode 100644 index 0000000..93d8498 --- /dev/null +++ b/external/taglib/source/xm/xmproperties.cpp @@ -0,0 +1,195 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + + +#include "xmproperties.h" + +using namespace TagLib; +using namespace XM; + +class XM::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate() : + lengthInPatterns(0), + channels(0), + version(0), + restartPosition(0), + patternCount(0), + instrumentCount(0), + sampleCount(0), + flags(0), + tempo(0), + bpmSpeed(0) + { + } + + unsigned short lengthInPatterns; + int channels; + unsigned short version; + unsigned short restartPosition; + unsigned short patternCount; + unsigned short instrumentCount; + unsigned int sampleCount; + unsigned short flags; + unsigned short tempo; + unsigned short bpmSpeed; +}; + +XM::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : + AudioProperties(propertiesStyle), + d(new PropertiesPrivate()) +{ +} + +XM::Properties::~Properties() +{ + delete d; +} + +int XM::Properties::length() const +{ + return 0; +} + +int XM::Properties::lengthInSeconds() const +{ + return 0; +} + +int XM::Properties::lengthInMilliseconds() const +{ + return 0; +} + +int XM::Properties::bitrate() const +{ + return 0; +} + +int XM::Properties::sampleRate() const +{ + return 0; +} + +int XM::Properties::channels() const +{ + return d->channels; +} + +unsigned short XM::Properties::lengthInPatterns() const +{ + return d->lengthInPatterns; +} + +unsigned short XM::Properties::version() const +{ + return d->version; +} + +unsigned short XM::Properties::restartPosition() const +{ + return d->restartPosition; +} + +unsigned short XM::Properties::patternCount() const +{ + return d->patternCount; +} + +unsigned short XM::Properties::instrumentCount() const +{ + return d->instrumentCount; +} + +unsigned int XM::Properties::sampleCount() const +{ + return d->sampleCount; +} + +unsigned short XM::Properties::flags() const +{ + return d->flags; +} + +unsigned short XM::Properties::tempo() const +{ + return d->tempo; +} + +unsigned short XM::Properties::bpmSpeed() const +{ + return d->bpmSpeed; +} + +void XM::Properties::setLengthInPatterns(unsigned short lengthInPatterns) +{ + d->lengthInPatterns = lengthInPatterns; +} + +void XM::Properties::setChannels(int channels) +{ + d->channels = channels; +} + +void XM::Properties::setVersion(unsigned short version) +{ + d->version = version; +} + +void XM::Properties::setRestartPosition(unsigned short restartPosition) +{ + d->restartPosition = restartPosition; +} + +void XM::Properties::setPatternCount(unsigned short patternCount) +{ + d->patternCount = patternCount; +} + +void XM::Properties::setInstrumentCount(unsigned short instrumentCount) +{ + d->instrumentCount = instrumentCount; +} + +void XM::Properties::setSampleCount(unsigned int sampleCount) +{ + d->sampleCount = sampleCount; +} + +void XM::Properties::setFlags(unsigned short flags) +{ + d->flags = flags; +} + +void XM::Properties::setTempo(unsigned short tempo) +{ + d->tempo = tempo; +} + +void XM::Properties::setBpmSpeed(unsigned short bpmSpeed) +{ + d->bpmSpeed = bpmSpeed; +} diff --git a/external/taglib/source/xm/xmproperties.h b/external/taglib/source/xm/xmproperties.h new file mode 100644 index 0000000..24a5221 --- /dev/null +++ b/external/taglib/source/xm/xmproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2011 by Mathias Panzenböck + email : grosser.meister.morti@gmx.net + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * + * 02110-1301 USA * + * * + * Alternatively, this file is available under the Mozilla Public * + * License Version 1.1. You may obtain a copy of the License at * + * http://www.mozilla.org/MPL/ * + ***************************************************************************/ + +#ifndef TAGLIB_XMPROPERTIES_H +#define TAGLIB_XMPROPERTIES_H + +#include "taglib.h" +#include "tstring.h" +#include "audioproperties.h" + +namespace TagLib { + namespace XM { + class TAGLIB_EXPORT Properties : public AudioProperties { + friend class File; + public: + /*! Flag bits. */ + enum { + LinearFreqTable = 1 // otherwise its the amiga freq. table + }; + + Properties(AudioProperties::ReadStyle propertiesStyle); + virtual ~Properties(); + + int length() const; + int lengthInSeconds() const; + int lengthInMilliseconds() const; + int bitrate() const; + int sampleRate() const; + int channels() const; + + unsigned short lengthInPatterns() const; + unsigned short version() const; + unsigned short restartPosition() const; + unsigned short patternCount() const; + unsigned short instrumentCount() const; + unsigned int sampleCount() const; + unsigned short flags() const; + unsigned short tempo() const; + unsigned short bpmSpeed() const; + + void setChannels(int channels); + + void setLengthInPatterns(unsigned short lengthInPatterns); + void setVersion(unsigned short version); + void setRestartPosition(unsigned short restartPosition); + void setPatternCount(unsigned short patternCount); + void setInstrumentCount(unsigned short instrumentCount); + void setSampleCount(unsigned int sampleCount); + void setFlags(unsigned short flags); + void setTempo(unsigned short tempo); + void setBpmSpeed(unsigned short bpmSpeed); + + private: + Properties(const Properties&); + Properties &operator=(const Properties&); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/itemz-daemon/Makefile b/itemz-daemon/Makefile new file mode 100644 index 0000000..3d42ded --- /dev/null +++ b/itemz-daemon/Makefile @@ -0,0 +1,27 @@ +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target ?= ps4_elf_sce +TargetFile=daemon.elf + +include $(ORBISDEV)/make/ps4sdk.mk + +LinkerFlags += -lfuse -lkernel_stub -lSceLibcInternal_stub -lSceSysmodule_stub -lSceSystemService_stub -lSceNet_stub -lSceUserService_stub -lScePigletv2VSH_stub -lSceVideoOut_stub -lSceImeDialog_stub -lSceGnmDriver_stub -lorbis -lorbisGl -lScePad_stub -lSceCommonDialog_stub -lSceMsgDialog_stub -lSceAudioOut_stub -lSceIme_stub -lSceAppInstUtil_stub -lSceBgft_stub -lSceSysUtil_stub -lSceHttp_stub -lSceSsl_stub -lSceNetCtl_stub -lfreetype-gl -lSceFreeTypeOl_stub -lkernel_sys_stub -lSceLncUtil_stub -lSQLite -lSceSysCore_stub + +CompilerFlags += -Wno-implicit-function-declaration -Wno-int-to-pointer-cast -D_FILE_OFFSET_BITS=64 -D__Freebsd__ -D__PS4__ -D__ORBIS__ -fstack-protector-all + +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -I$(ORBISDEV)/usr/include/orbis +IncludePath += -I$(ORBISDEV)/usr/include/orbis/freetype-gl + + +oelf: + orbis-elf-create bin/daemon.elf bin/daemon.oelf >/dev/null 2>&1 + + +AUTH_INFO = 000000000000000000000000001C004000FF000000000080000000000000000000000000000000000000008000400040000000000000008000000000000000080040FFFF000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +eboot: + python2 $(ORBISDEV)/bin/make_fself.py --auth-info $(AUTH_INFO) bin/daemon.oelf bin/eboot.bin +pkg_build: + cp bin/eboot.bin pkg/eboot.bin && cd pkg && pkgTool pkg_build Project.gp4 . && cp *.pkg ../bin/ diff --git a/itemz-daemon/include/defines.h b/itemz-daemon/include/defines.h new file mode 100644 index 0000000..63face2 --- /dev/null +++ b/itemz-daemon/include/defines.h @@ -0,0 +1,180 @@ +#pragma once + +/* + ES2_goodness, a GLES2 playground on EGL + + 2019-2021 masterzorag & LM + + here follows the parts: +*/ + +// nfs or local stdio +//#define USE_NFS (1) +#if defined (USE_NFS) +#include +#endif + +// common +#include +#include +#include +#include +#include "net.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#include //sceKernelIccSetBuzzer + +#define HOME_TITLE_ID "ITEM00001" +#define PS_BUTTON 0x10000 +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING 0x8094000c +#define SCE_SYSMODULE_INTERNAL_COMMON_DIALOG 0x80000018 +#define SCE_SYSMODULE_INTERNAL_SYSUTIL 0x80000018 +#define SCE_LNC_ERROR_APP_NOT_FOUND 0x80940031 // Usually happens if you to launch an app not in app.db +#define SCE_LNC_UTIL_ERROR_ALREADY_INITIALIZED 0x80940018 +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING 0x8094000c +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED 0x80940010 +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED 0x80940011 +#define SCE_LNC_UTIL_ERROR_APP_ALREADY_RESUMED 0x8094001e +#define SCE_LNC_UTIL_ERROR_APP_ALREADY_SUSPENDED 0x8094001d +#define SCE_LNC_UTIL_ERROR_APP_NOT_IN_BACKGROUND 0x80940015 +#define SCE_LNC_UTIL_ERROR_APPHOME_EBOOTBIN_NOT_FOUND 0x80940008 +#define SCE_LNC_UTIL_ERROR_APPHOME_PARAMSFO_NOT_FOUND 0x80940009 +#define SCE_LNC_UTIL_ERROR_CANNOT_RESUME_INITIAL_USER_NEEDED 0x80940012 +#define SCE_LNC_UTIL_ERROR_DEVKIT_EXPIRED 0x8094000b +#define SCE_LNC_UTIL_ERROR_IN_LOGOUT_PROCESSING 0x8094001a +#define SCE_LNC_UTIL_ERROR_IN_SPECIAL_RESUME 0x8094001b +#define SCE_LNC_UTIL_ERROR_INVALID_PARAM 0x80940005 +#define SCE_LNC_UTIL_ERROR_INVALID_STATE 0x80940019 +#define SCE_LNC_UTIL_ERROR_INVALID_TITLE_ID 0x8094001c +#define SCE_LNC_UTIL_ERROR_LAUNCH_DISABLED_BY_MEMORY_MODE 0x8094000d +#define SCE_LNC_UTIL_ERROR_NO_APP_INFO 0x80940004 +#define SCE_LNC_UTIL_ERROR_NO_LOGIN_USER 0x8094000a +#define SCE_LNC_UTIL_ERROR_NO_SESSION_MEMORY 0x80940002 +#define SCE_LNC_UTIL_ERROR_NO_SFOKEY_IN_APP_INFO 0x80940014 +#define SCE_LNC_UTIL_ERROR_NO_SHELL_UI 0x8094000e +#define SCE_LNC_UTIL_ERROR_NOT_ALLOWED 0x8094000f +#define SCE_LNC_UTIL_ERROR_NOT_INITIALIZED 0x80940001 +#define SCE_LNC_UTIL_ERROR_OPTICAL_DISC_DRIVE 0x80940013 +#define SCE_LNC_UTIL_ERROR_SETUP_FS_SANDBOX 0x80940006 +#define SCE_LNC_UTIL_ERROR_SUSPEND_BLOCK_TIMEOUT 0x80940017 +#define SCE_LNC_UTIL_ERROR_VIDEOOUT_NOT_SUPPORTED 0x80940016 +#define SCE_LNC_UTIL_ERROR_WAITING_READY_FOR_SUSPEND_TIMEOUT 0x80940021 +#define SCE_SYSCORE_ERROR_LNC_INVALID_STATE 0x80aa000a +#define SCE_LNC_UTIL_ERROR_NOT_INITIALIZED 0x80940001 +#define SCE_SYSMODULE_INTERNAL_SYS_CORE 0x80000004 +#define SCE_SYSMODULE_INTERNAL_NETCTL 0x80000009 +#define SCE_SYSMODULE_INTERNAL_HTTP 0x8000000A +#define SCE_SYSMODULE_INTERNAL_SSL 0x8000000B +#define SCE_SYSMODULE_INTERNAL_NP_COMMON 0x8000000C +#define SCE_SYSMODULE_INTERNAL_SYSTEM_SERVICE 0x80000010 +#define SCE_SYSMODULE_INTERNAL_USER_SERVICE 0x80000011 +#define SCE_SYSMODULE_INTERNAL_APPINSTUTIL 0x80000014 +#define SCE_SYSMODULE_INTERNAL_NET 0x8000001C +#define SCE_SYSMODULE_INTERNAL_IPMI 0x8000001D +#define SCE_SYSMODULE_INTERNAL_VIDEO_OUT 0x80000022 +#define SCE_SYSMODULE_INTERNAL_BGFT 0x8000002A +#define SCE_SYSMODULE_INTERNAL_PRECOMPILED_SHADERS 0x80000064 + +#define BUILD_YEAR_CH0 (__DATE__[ 7]) +#define BUILD_YEAR_CH1 (__DATE__[ 8]) +#define BUILD_YEAR_CH2 (__DATE__[ 9]) +#define BUILD_YEAR_CH3 (__DATE__[10]) + + +#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') + + +#define BUILD_MONTH_CH0 \ + ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0') + +#define BUILD_MONTH_CH1 \ + ( \ + (BUILD_MONTH_IS_JAN) ? '1' : \ + (BUILD_MONTH_IS_FEB) ? '2' : \ + (BUILD_MONTH_IS_MAR) ? '3' : \ + (BUILD_MONTH_IS_APR) ? '4' : \ + (BUILD_MONTH_IS_MAY) ? '5' : \ + (BUILD_MONTH_IS_JUN) ? '6' : \ + (BUILD_MONTH_IS_JUL) ? '7' : \ + (BUILD_MONTH_IS_AUG) ? '8' : \ + (BUILD_MONTH_IS_SEP) ? '9' : \ + (BUILD_MONTH_IS_OCT) ? '0' : \ + (BUILD_MONTH_IS_NOV) ? '1' : \ + (BUILD_MONTH_IS_DEC) ? '2' : \ + /* error default */ '?' \ + ) + +#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +#define BUILD_DAY_CH1 (__DATE__[ 5]) + + + +// Example of __TIME__ string: "21:06:19" +// 01234567 + +#define BUILD_HOUR_CH0 (__TIME__[0]) +#define BUILD_HOUR_CH1 (__TIME__[1]) + +#define BUILD_MIN_CH0 (__TIME__[3]) +#define BUILD_MIN_CH1 (__TIME__[4]) + +#define BUILD_SEC_CH0 (__TIME__[6]) +#define BUILD_SEC_CH1 (__TIME__[7]) + + +#if VERSION_MAJOR > 100 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 100) + '0'), \ + (((VERSION_MAJOR % 100) / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#elif VERSION_MAJOR > 10 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#else + +#define VERSION_MAJOR_INIT \ + (VERSION_MAJOR + '0') + +#endif + +#if VERSION_MINOR > 100 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 100) + '0'), \ + (((VERSION_MINOR % 100) / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#elif VERSION_MINOR > 10 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#else + +#define VERSION_MINOR_INIT \ + (VERSION_MINOR + '0') +#endif diff --git a/itemz-daemon/include/ftp.h b/itemz-daemon/include/ftp.h new file mode 100644 index 0000000..a40b515 --- /dev/null +++ b/itemz-daemon/include/ftp.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Sergi Granell (xerpi) + */ + +#ifndef FTPS4_H +#define FTPS4_H + +#include "defines.h" +#include +#include + +typedef void (*ftps4_log_cb_t)(const char*); +#define PATH_MAX 1024 +/* Returns PS4's IP and FTP port. 0 on success */ +bool ftps4_init(const char* ip, unsigned short int port); +void ftps4_set_file_buf_size(unsigned int size); + +/* Extended functionality */ + +#define FTPS4_EOL "\r\n" + +typedef enum { + FTP_DATA_CONNECTION_NONE, + FTP_DATA_CONNECTION_ACTIVE, + FTP_DATA_CONNECTION_PASSIVE, +} DataConnectionType; + +typedef struct ftps4_client_info { + /* Client number */ + int num; + /* Thread UID */ + ScePthread thid; + /* Control connection socket FD */ + int ctrl_sockfd; + /* Data connection attributes */ + int data_sockfd; + DataConnectionType data_con_type; + struct sockaddr_in data_sockaddr; + /* PASV mode client socket */ + struct sockaddr_in pasv_sockaddr; + int pasv_sockfd; + /* Remote client net info */ + struct sockaddr_in addr; + /* Receive buffer attributes */ + int n_recv; + char recv_buffer[512]; + /* Points to the character after the first space */ + const char* recv_cmd_args; + /* Current working directory */ + char cur_path[PATH_MAX]; + /* Rename path */ + char rename_path[PATH_MAX]; + /* Client list */ + struct ftps4_client_info* next; + struct ftps4_client_info* prev; + /* Offset for transfer resume */ + unsigned int restore_point; +} ftps4_client_info_t; + + +typedef void (*cmd_dispatch_func)(ftps4_client_info_t* client); // Command handler + +int ftps4_ext_add_command(const char* cmd, cmd_dispatch_func func); +int ftps4_ext_del_command(const char* cmd); +void ftps4_ext_client_send_ctrl_msg(ftps4_client_info_t* client, const char* msg); +void ftps4_ext_client_send_data_msg(ftps4_client_info_t* client, const char* str); +void ftps4_gen_ftp_fullpath(ftps4_client_info_t* client, char* path, size_t path_size); + +bool StartFTP(); +void ShutdownFTP(); +void check_ftp_addr_change(); +#endif \ No newline at end of file diff --git a/itemz-daemon/include/fuse/Makefile.am b/itemz-daemon/include/fuse/Makefile.am new file mode 100644 index 0000000..663e164 --- /dev/null +++ b/itemz-daemon/include/fuse/Makefile.am @@ -0,0 +1,17 @@ +## Process this file with automake to produce Makefile.in + +fuseincludedir=$(includedir)/fuse + +fuseinclude_HEADERS = \ + fuse.h \ + fuse_compat.h \ + fuse_common.h \ + fuse_common_compat.h \ + fuse_lowlevel.h \ + fuse_lowlevel_compat.h \ + fuse_opt.h \ + cuse_lowlevel.h + +include_HEADERS = old/fuse.h ulockmgr.h + +noinst_HEADERS = fuse_kernel.h diff --git a/itemz-daemon/include/fuse/Makefile.in b/itemz-daemon/include/fuse/Makefile.in new file mode 100644 index 0000000..7cbd333 --- /dev/null +++ b/itemz-daemon/include/fuse/Makefile.in @@ -0,0 +1,516 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = include +DIST_COMMON = $(fuseinclude_HEADERS) $(include_HEADERS) \ + $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(fuseincludedir)" \ + "$(DESTDIR)$(includedir)" +HEADERS = $(fuseinclude_HEADERS) $(include_HEADERS) $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INIT_D_PATH = @INIT_D_PATH@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MOUNT_FUSE_PATH = @MOUNT_FUSE_PATH@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +UDEV_RULES_PATH = @UDEV_RULES_PATH@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +libfuse_libs = @libfuse_libs@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs2 = @subdirs2@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +fuseincludedir = $(includedir)/fuse +fuseinclude_HEADERS = \ + fuse.h \ + fuse_compat.h \ + fuse_common.h \ + fuse_common_compat.h \ + fuse_lowlevel.h \ + fuse_lowlevel_compat.h \ + fuse_opt.h \ + cuse_lowlevel.h + +include_HEADERS = old/fuse.h ulockmgr.h +noinst_HEADERS = fuse_kernel.h +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu include/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status include/config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-fuseincludeHEADERS: $(fuseinclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(fuseincludedir)" || $(MKDIR_P) "$(DESTDIR)$(fuseincludedir)" + @list='$(fuseinclude_HEADERS)'; test -n "$(fuseincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(fuseincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(fuseincludedir)" || exit $$?; \ + done + +uninstall-fuseincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(fuseinclude_HEADERS)'; test -n "$(fuseincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(fuseincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(fuseincludedir)" && rm -f $$files +install-includeHEADERS: $(include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)" + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \ + done + +uninstall-includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(includedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(includedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) config.h +installdirs: + for dir in "$(DESTDIR)$(fuseincludedir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-fuseincludeHEADERS install-includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-fuseincludeHEADERS uninstall-includeHEADERS + +.MAKE: all install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool ctags distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-fuseincludeHEADERS install-html \ + install-html-am install-includeHEADERS install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-fuseincludeHEADERS \ + uninstall-includeHEADERS + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/itemz-daemon/include/fuse/config.h b/itemz-daemon/include/fuse/config.h new file mode 100644 index 0000000..b914b0e --- /dev/null +++ b/itemz-daemon/include/fuse/config.h @@ -0,0 +1,90 @@ +/* include/config.h. Generated from config.h.in by configure. */ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `fork' function. */ +#define HAVE_FORK 1 + +/* Define if you have the iconv() function and it works. */ +#define HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `setxattr' function. */ +/* #undef HAVE_SETXATTR */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if `st_atim' is a member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_ATIM */ + +/* Define to 1 if `st_atimespec' is a member of `struct stat'. */ +#define HAVE_STRUCT_STAT_ST_ATIMESPEC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST const + +/* Don't update /etc/mtab */ +/* #undef IGNORE_MTAB */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "fuse" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "fuse" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "fuse 2.8.6" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "fuse" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.8.6" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +#define VERSION "2.8.6" diff --git a/itemz-daemon/include/fuse/config.h.in b/itemz-daemon/include/fuse/config.h.in new file mode 100644 index 0000000..4181f89 --- /dev/null +++ b/itemz-daemon/include/fuse/config.h.in @@ -0,0 +1,89 @@ +/* include/config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `fdatasync' function. */ +#undef HAVE_FDATASYNC + +/* Define to 1 if you have the `fork' function. */ +#undef HAVE_FORK + +/* Define if you have the iconv() function and it works. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `setxattr' function. */ +#undef HAVE_SETXATTR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if `st_atim' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_ATIM + +/* Define to 1 if `st_atimespec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_ATIMESPEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define as const if the declaration of iconv() needs const. */ +#undef ICONV_CONST + +/* Don't update /etc/mtab */ +#undef IGNORE_MTAB + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION diff --git a/itemz-daemon/include/fuse/cuse_lowlevel.h b/itemz-daemon/include/fuse/cuse_lowlevel.h new file mode 100644 index 0000000..e147fa2 --- /dev/null +++ b/itemz-daemon/include/fuse/cuse_lowlevel.h @@ -0,0 +1,87 @@ +/* + CUSE: Character device in Userspace + Copyright (C) 2008-2009 SUSE Linux Products GmbH + Copyright (C) 2008-2009 Tejun Heo + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. + + Read example/cusexmp.c for usages. +*/ + +#ifndef _CUSE_LOWLEVEL_H_ +#define _CUSE_LOWLEVEL_H_ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 29 +#endif + +#include "fuse_lowlevel.h" + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) /* use unrestricted ioctl */ + +struct fuse_session; + +struct cuse_info { + unsigned dev_major; + unsigned dev_minor; + unsigned dev_info_argc; + const char **dev_info_argv; + unsigned flags; +}; + +/* + * Most ops behave almost identically to the matching fuse_lowlevel + * ops except that they don't take @ino. + * + * init_done : called after initialization is complete + * read/write : always direct IO, simultaneous operations allowed + * ioctl : might be in unrestricted mode depending on ci->flags + */ +struct cuse_lowlevel_ops { + void (*init) (void *userdata, struct fuse_conn_info *conn); + void (*init_done) (void *userdata); + void (*destroy) (void *userdata); + void (*open) (fuse_req_t req, struct fuse_file_info *fi); + void (*read) (fuse_req_t req, size_t size, off_t off, + struct fuse_file_info *fi); + void (*write) (fuse_req_t req, const char *buf, size_t size, off_t off, + struct fuse_file_info *fi); + void (*flush) (fuse_req_t req, struct fuse_file_info *fi); + void (*release) (fuse_req_t req, struct fuse_file_info *fi); + void (*fsync) (fuse_req_t req, int datasync, struct fuse_file_info *fi); + void (*ioctl) (fuse_req_t req, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz); + void (*poll) (fuse_req_t req, struct fuse_file_info *fi, + struct fuse_pollhandle *ph); +}; + +struct fuse_session *cuse_lowlevel_new(struct fuse_args *args, + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + void *userdata); + +struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[], + const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, + int *multithreaded, void *userdata); + +void cuse_lowlevel_teardown(struct fuse_session *se); + +int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci, + const struct cuse_lowlevel_ops *clop, void *userdata); + +#ifdef __cplusplus +} +#endif + +#endif /* _CUSE_LOWLEVEL_H_ */ diff --git a/itemz-daemon/include/fuse/fuse.h b/itemz-daemon/include/fuse/fuse.h new file mode 100644 index 0000000..651d1ed --- /dev/null +++ b/itemz-daemon/include/fuse/fuse.h @@ -0,0 +1,906 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_H_ +#define _FUSE_H_ + +#define SPECNAMELEN 63 + +/** @file + * + * This file defines the library interface of FUSE + * + * IMPORTANT: you should define FUSE_USE_VERSION before including this + * header. To use the newest API define it to 26 (recommended for any + * new application), to use the old API define it to 21 (default) 22 + * or 25, to use the even older 1.X API define it to 11. + */ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 21 +#endif + +#include "fuse_common.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------- * + * Basic FUSE API * + * ----------------------------------------------------------- */ + +/** Handle for a FUSE filesystem */ +struct fuse; + +/** Structure containing a raw command */ +struct fuse_cmd; + +/** Function to add an entry in a readdir() operation + * + * @param buf the buffer passed to the readdir() operation + * @param name the file name of the directory entry + * @param stat file attributes, can be NULL + * @param off offset of the next entry or zero + * @return 1 if buffer is full, zero otherwise + */ +typedef int (*fuse_fill_dir_t) (void *buf, const char *name, + const struct stat *stbuf, off_t off); + +/* Used by deprecated getdir() method */ +typedef struct fuse_dirhandle *fuse_dirh_t; +typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type, + ino_t ino); + +/** + * The file system operations: + * + * Most of these should work very similarly to the well known UNIX + * file system operations. A major exception is that instead of + * returning an error in 'errno', the operation should return the + * negated error value (-errno) directly. + * + * All methods are optional, but some are essential for a useful + * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, + * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, + * init and destroy are special purpose methods, without which a full + * featured filesystem can still be implemented. + * + * Almost all operations take a path which can be of any length. + * + * Changed in fuse 2.8.0 (regardless of API version) + * Previously, paths were limited to a length of PATH_MAX. + * + * See http://fuse.sourceforge.net/wiki/ for more information. There + * is also a snapshot of the relevant wiki pages in the doc/ folder. + */ +struct fuse_operations { + /** Get file attributes. + * + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are + * ignored. The 'st_ino' field is ignored except if the 'use_ino' + * mount option is given. + */ + int (*getattr) (const char *, struct stat *); + + /** Read the target of a symbolic link + * + * The buffer should be filled with a null terminated string. The + * buffer size argument includes the space for the terminating + * null character. If the linkname is too long to fit in the + * buffer, it should be truncated. The return value should be 0 + * for success. + */ + int (*readlink) (const char *, char *, size_t); + + /* Deprecated, use readdir() instead */ + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + + /** Create a file node + * + * This is called for creation of all non-directory, non-symlink + * nodes. If the filesystem defines a create() method, then for + * regular files that will be called instead. + */ + int (*mknod) (const char *, mode_t, dev_t); + + /** Create a directory + * + * Note that the mode argument may not have the type specification + * bits set, i.e. S_ISDIR(mode) can be false. To obtain the + * correct directory type bits use mode|S_IFDIR + * */ + int (*mkdir) (const char *, mode_t); + + /** Remove a file */ + int (*unlink) (const char *); + + /** Remove a directory */ + int (*rmdir) (const char *); + + /** Create a symbolic link */ + int (*symlink) (const char *, const char *); + + /** Rename a file */ + int (*rename) (const char *, const char *); + + /** Create a hard link to a file */ + int (*link) (const char *, const char *); + + /** Change the permission bits of a file */ + int (*chmod) (const char *, mode_t); + + /** Change the owner and group of a file */ + int (*chown) (const char *, uid_t, gid_t); + + /** Change the size of a file */ + int (*truncate) (const char *, off_t); + + /** Change the access and/or modification times of a file + * + * Deprecated, use utimens() instead. + */ + int (*utime) (const char *, struct utimbuf *); + + /** File open operation + * + * No creation (O_CREAT, O_EXCL) and by default also no + * truncation (O_TRUNC) flags will be passed to open(). If an + * application specifies O_TRUNC, fuse first calls truncate() + * and then open(). Only if 'atomic_o_trunc' has been + * specified and kernel version is 2.6.24 or later, O_TRUNC is + * passed on to open. + * + * Unless the 'default_permissions' mount option is given, + * open should check if the operation is permitted for the + * given flags. Optionally open may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to all file operations. + * + * Changed in version 2.2 + */ + int (*open) (const char *, struct fuse_file_info *); + + /** Read data from an open file + * + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 + */ + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info *); + + /** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info *); + + /** Get file system statistics + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + * + * Replaced 'struct statfs' parameter with 'struct statvfs' in + * version 2.5 + */ + int (*statfs) (const char *, struct statvfs *); + + /** Possibly flush cached data + * + * BIG NOTE: This is not equivalent to fsync(). It's not a + * request to sync dirty data. + * + * Flush is called on each close() of a file descriptor. So if a + * filesystem wants to return write errors in close() and the file + * has cached dirty data, this is a good place to write back data + * and return any errors. Since many applications ignore close() + * errors this is not always useful. + * + * NOTE: The flush() method may be called more than once for each + * open(). This happens if more than one file descriptor refers + * to an opened file due to dup(), dup2() or fork() calls. It is + * not possible to determine if a flush is final, so each flush + * should be treated equally. Multiple write-flush sequences are + * relatively rare, so this shouldn't be a problem. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * Changed in version 2.2 + */ + int (*flush) (const char *, struct fuse_file_info *); + + /** Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + * + * Changed in version 2.2 + */ + int (*release) (const char *, struct fuse_file_info *); + + /** Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Changed in version 2.2 + */ + int (*fsync) (const char *, int, struct fuse_file_info *); + + /** Set extended attributes */ + int (*setxattr) (const char *, const char *, const char *, size_t, int); + + /** Get extended attributes */ + int (*getxattr) (const char *, const char *, char *, size_t); + + /** List extended attributes */ + int (*listxattr) (const char *, char *, size_t); + + /** Remove extended attributes */ + int (*removexattr) (const char *, const char *); + + /** Open directory + * + * Unless the 'default_permissions' mount option is given, + * this method should check if opendir is permitted for this + * directory. Optionally opendir may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to readdir, closedir and fsyncdir. + * + * Introduced in version 2.3 + */ + int (*opendir) (const char *, struct fuse_file_info *); + + /** Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. + * + * The filesystem may choose between two modes of operation: + * + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. + * + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + * + * Introduced in version 2.3 + */ + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info *); + + /** Release directory + * + * Introduced in version 2.3 + */ + int (*releasedir) (const char *, struct fuse_file_info *); + + /** Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data + * + * Introduced in version 2.3 + */ + int (*fsyncdir) (const char *, int, struct fuse_file_info *); + + /** + * Initialize filesystem + * + * The return value will passed in the private_data field of + * fuse_context to all file operations and as a parameter to the + * destroy() method. + * + * Introduced in version 2.3 + * Changed in version 2.6 + */ + void *(*init) (struct fuse_conn_info *conn); + + /** + * Clean up filesystem + * + * Called on filesystem exit. + * + * Introduced in version 2.3 + */ + void (*destroy) (void *); + + /** + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 + */ + int (*access) (const char *, int); + + /** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + */ + int (*create) (const char *, mode_t, struct fuse_file_info *); + + /** + * Change the size of an open file + * + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the truncate() method will be + * called instead. + * + * Introduced in version 2.5 + */ + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); + + /** + * Get attributes from an open file + * + * This method is called instead of the getattr() method if the + * file information is available. + * + * Currently this is only called after the create() method if that + * is implemented (see above). Later it may be called for + * invocations of fstat() too. + * + * Introduced in version 2.5 + */ + int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); + + /** + * Perform POSIX file locking operation + * + * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. + * + * For the meaning of fields in 'struct flock' see the man page + * for fcntl(2). The l_whence field will always be set to + * SEEK_SET. + * + * For checking lock ownership, the 'fuse_file_info->owner' + * argument must be used. + * + * For F_GETLK operation, the library will first check currently + * held locks, and if a conflicting lock is found it will return + * information without calling this method. This ensures, that + * for local locks the l_pid field is correctly filled in. The + * results may not be accurate in case of race conditions and in + * the presence of hard links, but it's unlikly that an + * application would rely on accurate GETLK results in these + * cases. If a conflicting lock is not found, this method will be + * called, and the filesystem may fill out l_pid by a meaningful + * value, or it may leave this field zero. + * + * For F_SETLK and F_SETLKW the l_pid field will be set to the pid + * of the process performing the locking operation. + * + * Note: if this method is not implemented, the kernel will still + * allow file locking to work locally. Hence it is only + * interesting for network filesystems and similar. + * + * Introduced in version 2.6 + */ + int (*lock) (const char *, struct fuse_file_info *, int cmd, + struct flock *); + + /** + * Change the access and modification times of a file with + * nanosecond resolution + * + * Introduced in version 2.6 + */ + int (*utimens) (const char *, const struct timespec tv[2]); + + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 + */ + int (*bmap) (const char *, size_t blocksize, uint64_t *idx); + + /** + * Flag indicating, that the filesystem can accept a NULL path + * as the first argument for the following operations: + * + * read, write, flush, release, fsync, readdir, releasedir, + * fsyncdir, ftruncate, fgetattr and lock + */ + unsigned int flag_nullpath_ok : 1; + + /** + * Reserved flags, don't set + */ + unsigned int flag_reserved : 31; + + /** + * Ioctl + * + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in + * 64bit environment. The size and direction of data is + * determined by _IOC_*() decoding of cmd. For _IOC_NONE, + * data will be NULL, for _IOC_WRITE data is out area, for + * _IOC_READ in area and if both are set in/out area. In all + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. + * + * Introduced in version 2.8 + */ + int (*ioctl) (const char *, int cmd, void *arg, + struct fuse_file_info *, unsigned int flags, void *data); + + /** + * Poll for IO readiness events + * + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Introduced in version 2.8 + */ + int (*poll) (const char *, struct fuse_file_info *, + struct fuse_pollhandle *ph, unsigned *reventsp); +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + void (*mount_done) (int); +}; + +/** Extra context that may be needed by some filesystems + * + * The uid, gid and pid fields are not filled in case of a writepage + * operation. + */ +struct fuse_context { + /** Pointer to the fuse object */ + struct fuse *fuse; + + /** User ID of the calling process */ + uid_t uid; + + /** Group ID of the calling process */ + gid_t gid; + + /** Thread ID of the calling process */ + pid_t pid; + + /** Private filesystem data */ + void *private_data; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +}; + +/** + * Main function of FUSE. + * + * This is for the lazy. This is all that has to be called from the + * main() function. + * + * This function does the following: + * - parses command line options (-d -s and -h) + * - passes relevant mount options to the fuse_mount() + * - installs signal handlers for INT, HUP, TERM and PIPE + * - registers an exit handler to unmount the filesystem on program exit + * - creates a fuse handle + * - registers the operations + * - calls either the single-threaded or the multi-threaded event loop + * + * Note: this is currently implemented as a macro. + * + * @param argc the argument counter passed to the main() function + * @param argv the argument vector passed to the main() function + * @param op the file system operation + * @param user_data user data supplied in the context during the init() method + * @return 0 on success, nonzero on failure + */ +/* + int fuse_main(int argc, char *argv[], const struct fuse_operations *op, + void *user_data); +*/ +#define fuse_main(argc, argv, op, user_data) \ + fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) + +/* ----------------------------------------------------------- * + * More detailed API * + * ----------------------------------------------------------- */ + +/** + * Create a new FUSE filesystem. + * + * @param ch the communication channel + * @param args argument vector + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return the created FUSE handle + */ +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, size_t op_size, + void *user_data); + +/** + * Destroy the FUSE handle. + * + * The communication channel attached to the handle is also destroyed. + * + * NOTE: This function does not unmount the filesystem. If this is + * needed, call fuse_unmount() before calling this function. + * + * @param f the FUSE handle + */ +void fuse_destroy(struct fuse *f); + +/** + * FUSE event loop. + * + * Requests from the kernel are processed, and the appropriate + * operations are called. + * + * @param f the FUSE handle + * @return 0 if no error occurred, -1 otherwise + */ +int fuse_loop(struct fuse *f); + +/** + * Exit from event loop + * + * @param f the FUSE handle + */ +void fuse_exit(struct fuse *f); + +/** + * FUSE event loop with multiple threads + * + * Requests from the kernel are processed, and the appropriate + * operations are called. Request are processed in parallel by + * distributing them between multiple threads. + * + * Calling this function requires the pthreads library to be linked to + * the application. + * + * @param f the FUSE handle + * @return 0 if no error occurred, -1 otherwise + */ +int fuse_loop_mt(struct fuse *f); + +/** + * Get the current context + * + * The context is only valid for the duration of a filesystem + * operation, and thus must not be stored and used later. + * + * @return the context + */ +struct fuse_context *fuse_get_context(void); + +/** + * Get the current supplementary group IDs for the current request + * + * Similar to the getgroups(2) system call, except the return value is + * always the total number of group IDs, even if it is larger than the + * specified size. + * + * The current fuse kernel module in linux (as of 2.6.30) doesn't pass + * the group list to userspace, hence this function needs to parse + * "/proc/$TID/task/$TID/status" to get the group IDs. + * + * This feature may not be supported on all operating systems. In + * such a case this function will return -ENOSYS. + * + * @param size size of given array + * @param list array of group IDs to be filled in + * @return the total number of supplementary group IDs or -errno on failure + */ +int fuse_getgroups(int size, gid_t list[]); + +/** + * Check if the current request has already been interrupted + * + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_interrupted(void); + +/** + * Obsolete, doesn't do anything + * + * @return -EINVAL + */ +int fuse_invalidate(struct fuse *f, const char *path); + +/* Deprecated, don't use */ +int fuse_is_lib_option(const char *opt); + +/** + * The real main function + * + * Do not call this directly, use fuse_main() + */ +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, + size_t op_size, void *user_data); + +/* + * Stacking API + */ + +/** + * Fuse filesystem object + * + * This is opaque object represents a filesystem layer + */ +struct fuse_fs; + +/* + * These functions call the relevant filesystem operation, and return + * the result. + * + * If the operation is not defined, they return -ENOSYS, with the + * exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir, + * fuse_fs_releasedir and fuse_fs_statfs, which return 0. + */ + +int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf); +int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf, + struct fuse_file_info *fi); +int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, + const char *newpath); +int fuse_fs_unlink(struct fuse_fs *fs, const char *path); +int fuse_fs_rmdir(struct fuse_fs *fs, const char *path); +int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, + const char *path); +int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath); +int fuse_fs_release(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_open(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_read(struct fuse_fs *fs, const char *path, char *buf, size_t size, + off_t off, struct fuse_file_info *fi); +int fuse_fs_write(struct fuse_fs *fs, const char *path, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); +int fuse_fs_fsync(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi); +int fuse_fs_flush(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf); +int fuse_fs_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf, + fuse_fill_dir_t filler, off_t off, + struct fuse_file_info *fi); +int fuse_fs_fsyncdir(struct fuse_fs *fs, const char *path, int datasync, + struct fuse_file_info *fi); +int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, + struct fuse_file_info *fi); +int fuse_fs_lock(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, int cmd, struct flock *lock); +int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid); +int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size); +int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size, + struct fuse_file_info *fi); +int fuse_fs_utimens(struct fuse_fs *fs, const char *path, + const struct timespec tv[2]); +int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask); +int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, + size_t len); +int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, + dev_t rdev); +int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, + const char *value, size_t size, int flags); +int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, + char *value, size_t size); +int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, + size_t size); +int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, + const char *name); +int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, + uint64_t *idx); +int fuse_fs_ioctl(struct fuse_fs *fs, const char *path, int cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, void *data); +int fuse_fs_poll(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi, struct fuse_pollhandle *ph, + unsigned *reventsp); +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); +void fuse_fs_destroy(struct fuse_fs *fs); + +int fuse_notify_poll(struct fuse_pollhandle *ph); + +/** + * Create a new fuse filesystem object + * + * This is usually called from the factory of a fuse module to create + * a new instance of a filesystem. + * + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return a new filesystem object + */ +struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, + void *user_data); + +/** + * Filesystem module + * + * Filesystem modules are registered with the FUSE_REGISTER_MODULE() + * macro. + * + * If the "-omodules=modname:..." option is present, filesystem + * objects are created and pushed onto the stack with the 'factory' + * function. + */ +struct fuse_module { + /** + * Name of filesystem + */ + const char *name; + + /** + * Factory for creating filesystem objects + * + * The function may use and remove options from 'args' that belong + * to this module. + * + * For now the 'fs' vector always contains exactly one filesystem. + * This is the filesystem which will be below the newly created + * filesystem in the stack. + * + * @param args the command line arguments + * @param fs NULL terminated filesystem object vector + * @return the new filesystem object + */ + struct fuse_fs *(*factory)(struct fuse_args *args, + struct fuse_fs *fs[]); + + struct fuse_module *next; + struct fusemod_so *so; + int ctr; +}; + +/** + * Register a filesystem module + * + * This function is used by FUSE_REGISTER_MODULE and there's usually + * no need to call it directly + */ +void fuse_register_module(struct fuse_module *mod); + +/** + * Register filesystem module + * + * For the parameters, see description of the fields in 'struct + * fuse_module' + */ +#define FUSE_REGISTER_MODULE(name_, factory_) \ + static __attribute__((constructor)) void name_ ## _register(void) \ + { \ + static struct fuse_module mod = \ + { #name_, factory_, NULL, NULL, 0 }; \ + fuse_register_module(&mod); \ + } + + +/* ----------------------------------------------------------- * + * Advanced API for event handling, don't worry about this... * + * ----------------------------------------------------------- */ + +/* NOTE: the following functions are deprecated, and will be removed + from the 3.0 API. Use the lowlevel session functions instead */ + +/** Function type used to process commands */ +typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *); + +/** This is the part of fuse_main() before the event loop */ +struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + char **mountpoint, int *multithreaded, + void *user_data); + +/** This is the part of fuse_main() after the event loop */ +void fuse_teardown(struct fuse *fuse, char *mountpoint); + +/** Read a single command. If none are read, return NULL */ +struct fuse_cmd *fuse_read_cmd(struct fuse *f); + +/** Process a single command */ +void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd); + +/** Multi threaded event loop, which calls the custom command + processor function */ +int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); + +/** Return the exited flag, which indicates if fuse_exit() has been + called */ +int fuse_exited(struct fuse *f); + +/** This function is obsolete and implemented as a no-op */ +void fuse_set_getcontext_func(struct fuse_context *(*func)(void)); + +/** Get session from fuse object */ +struct fuse_session *fuse_get_session(struct fuse *f); + +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +/* ----------------------------------------------------------- * + * For DRFP * + * ------------------------------------------------------------*/ +#define DRFP_MNTDONE_RELATIVE (1) +#define DRFP_MNTDONE_ABSOLUTE (2) + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_H_ */ diff --git a/itemz-daemon/include/fuse/fuse_common.h b/itemz-daemon/include/fuse/fuse_common.h new file mode 100644 index 0000000..e8e14f5 --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_common.h @@ -0,0 +1,271 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/** @file */ + +#if !defined(_FUSE_H_) && !defined(_FUSE_LOWLEVEL_H_) +#error "Never include directly; use or instead." +#endif + +#ifndef _FUSE_COMMON_H_ +#define _FUSE_COMMON_H_ + +#include "fuse_opt.h" +#include + +/** Major version of FUSE library interface */ +#define FUSE_MAJOR_VERSION 2 + +/** Minor version of FUSE library interface */ +#define FUSE_MINOR_VERSION 8 + +#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min)) +#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Information about open files + * + * Changed in version 2.5 + */ +struct fuse_file_info { + /** Open flags. Available in open() and release() */ + int flags; + + /** Old file handle, don't use */ + unsigned long fh_old; + + /** In case of a write operation indicates if this was caused by a + writepage */ + int writepage; + + /** Can be filled in by open, to use direct I/O on this file. + Introduced in version 2.4 */ + unsigned int direct_io : 1; + + /** Can be filled in by open, to indicate, that cached file data + need not be invalidated. Introduced in version 2.4 */ + unsigned int keep_cache : 1; + + /** Indicates a flush operation. Set in flush operation, also + maybe set in highlevel lock operation and lowlevel release + operation. Introduced in version 2.6 */ + unsigned int flush : 1; + + /** Can be filled in by open, to indicate that the file is not + seekable. Introduced in version 2.8 */ + unsigned int nonseekable : 1; + +/* +Modified by Y.ITO, 07/27/2016 + +--------------- +Copyright (c) 2016 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ + /** Padding. Do not use*/ + unsigned int padding : 12; + + /** Known count to be issued with the same read size */ + unsigned int ra_hint : 8; + + /** heuristic from vfs */ + unsigned int seq_count : 8; + + /** File handle. May be filled in by filesystem in open(). + Available in all other file operations */ + uint64_t fh; + + /** Lock owner id. Available in locking operations and flush */ + uint64_t lock_owner; +}; + +/** + * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' + * + * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests + * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking + * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag + * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB + * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations + */ +#define FUSE_CAP_ASYNC_READ (1 << 0) +#define FUSE_CAP_POSIX_LOCKS (1 << 1) +#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_CAP_EXPORT_SUPPORT (1 << 4) +#define FUSE_CAP_BIG_WRITES (1 << 5) +#define FUSE_CAP_DONT_MASK (1 << 6) + +/** + * Ioctl flags + * + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed + * FUSE_IOCTL_RETRY: retry with new iovecs + * + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs + */ +#define FUSE_IOCTL_COMPAT (1 << 0) +#define FUSE_IOCTL_UNRESTRICTED (1 << 1) +#define FUSE_IOCTL_RETRY (1 << 2) + +#define FUSE_IOCTL_MAX_IOV 256 + +/** + * Connection information, passed to the ->init() method + * + * Some of the elements are read-write, these can be changed to + * indicate the value requested by the filesystem. The requested + * value must usually be smaller than the indicated value. + */ +struct fuse_conn_info { + /** + * Major version of the protocol (read-only) + */ + unsigned proto_major; + + /** + * Minor version of the protocol (read-only) + */ + unsigned proto_minor; + + /** + * Is asynchronous read supported (read-write) + */ + unsigned async_read; + + /** + * Maximum size of the write buffer + */ + unsigned max_write; + + /** + * Maximum readahead + */ + unsigned max_readahead; + + /** + * Capability flags, that the kernel supports + */ + unsigned capable; + + /** + * Capability flags, that the filesystem wants to enable + */ + unsigned want; + + /** + * For future use. + */ + unsigned reserved[25]; +}; + +struct fuse_session; +struct fuse_chan; +struct fuse_pollhandle; + +/** + * Create a FUSE mountpoint + * + * Returns a control file descriptor suitable for passing to + * fuse_new() + * + * @param mountpoint the mount point path + * @param args argument vector + * @return the communication channel on success, NULL on failure + */ +struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args); + +/** + * Umount a FUSE mountpoint + * + * @param mountpoint the mount point path + * @param ch the communication channel + */ +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); + +/** + * Parse common options + * + * The following options are parsed: + * + * '-f' foreground + * '-d' '-odebug' foreground, but keep the debug option + * '-s' single threaded + * '-h' '--help' help + * '-ho' help without header + * '-ofsname=..' file system name, if not present, then set to the program + * name + * + * All parameters may be NULL + * + * @param args argument vector + * @param mountpoint the returned mountpoint, should be freed after use + * @param multithreaded set to 1 unless the '-s' option is present + * @param foreground set to 1 if one of the relevant options is present + * @return 0 on success, -1 on failure + */ +int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint, + int *multithreaded, int *foreground); + +/** + * Go into the background + * + * @param foreground if true, stay in the foreground + * @return 0 on success, -1 on failure + */ +int fuse_daemonize(int foreground); + +/** + * Get the version of the library + * + * @return the version + */ +int fuse_version(void); + +/** + * Destroy poll handle + * + * @param ph the poll handle + */ +void fuse_pollhandle_destroy(struct fuse_pollhandle *ph); + +/* ----------------------------------------------------------- * + * Signal handling * + * ----------------------------------------------------------- */ + +/** + * Exit session on HUP, TERM and INT signals and ignore PIPE signal + * + * Stores session in a global variable. May only be called once per + * process until fuse_remove_signal_handlers() is called. + * + * @param se the session to exit + * @return 0 on success, -1 on failure + */ +int fuse_set_signal_handlers(struct fuse_session *se); + +/** + * Restore default signal handlers + * + * Resets global session. After this fuse_set_signal_handlers() may + * be called again. + * + * @param se the same session as given in fuse_set_signal_handlers() + */ +void fuse_remove_signal_handlers(struct fuse_session *se); +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_COMMON_H_ */ diff --git a/itemz-daemon/include/fuse/fuse_common_compat.h b/itemz-daemon/include/fuse/fuse_common_compat.h new file mode 100644 index 0000000..a3edfde --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_common_compat.h @@ -0,0 +1,33 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_file_info_compat { + int flags; + unsigned long fh; + int writepage; + unsigned int direct_io : 1; + unsigned int keep_cache : 1; +}; +/* +Modified by Y.OGATA, 03/16/2012 + +--------------- +Copyright (c) 2012 Sony Interactive Entertainment Inc. All Rights Reserved. +--------------- + +*/ +int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args, const struct fuse_operations *op); + +int fuse_mount_compat22(const char *mountpoint, const char *opts); + +int fuse_mount_compat1(const char *mountpoint, const char *args[]); + +void fuse_unmount_compat22(const char *mountpoint); diff --git a/itemz-daemon/include/fuse/fuse_compat.h b/itemz-daemon/include/fuse/fuse_compat.h new file mode 100644 index 0000000..225276f --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_compat.h @@ -0,0 +1,201 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_operations_compat25 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, struct fuse_file_info *); + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info *); + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info *); + int (*statfs) (const char *, struct statvfs *); + int (*flush) (const char *, struct fuse_file_info *); + int (*release) (const char *, struct fuse_file_info *); + int (*fsync) (const char *, int, struct fuse_file_info *); + int (*setxattr) (const char *, const char *, const char *, size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); + int (*opendir) (const char *, struct fuse_file_info *); + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info *); + int (*releasedir) (const char *, struct fuse_file_info *); + int (*fsyncdir) (const char *, int, struct fuse_file_info *); + void *(*init) (void); + void (*destroy) (void *); + int (*access) (const char *, int); + int (*create) (const char *, mode_t, struct fuse_file_info *); + int (*ftruncate) (const char *, off_t, struct fuse_file_info *); + int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *); +}; + +struct fuse *fuse_new_compat25(int fd, struct fuse_args *args, + const struct fuse_operations_compat25 *op, + size_t op_size); + +int fuse_main_real_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size); + +struct fuse *fuse_setup_compat25(int argc, char *argv[], + const struct fuse_operations_compat25 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd); + +void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint); + +#ifndef __FreeBSD__ +#include + +struct fuse_operations_compat22 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, struct fuse_file_info_compat *); + int (*read) (const char *, char *, size_t, off_t, + struct fuse_file_info_compat *); + int (*write) (const char *, const char *, size_t, off_t, + struct fuse_file_info_compat *); + int (*statfs) (const char *, struct statfs *); + int (*flush) (const char *, struct fuse_file_info_compat *); + int (*release) (const char *, struct fuse_file_info_compat *); + int (*fsync) (const char *, int, struct fuse_file_info_compat *); + int (*setxattr) (const char *, const char *, const char *, size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); + int (*opendir) (const char *, struct fuse_file_info_compat *); + int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t, + struct fuse_file_info_compat *); + int (*releasedir) (const char *, struct fuse_file_info_compat *); + int (*fsyncdir) (const char *, int, struct fuse_file_info_compat *); + void *(*init) (void); + void (*destroy) (void *); +}; + +struct fuse *fuse_new_compat22(int fd, const char *opts, + const struct fuse_operations_compat22 *op, + size_t op_size); + +struct fuse *fuse_setup_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size, char **mountpoint, + int *multithreaded, int *fd); + +int fuse_main_real_compat22(int argc, char *argv[], + const struct fuse_operations_compat22 *op, + size_t op_size); + +typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type); +struct fuse_operations_compat2 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, int); + int (*read) (const char *, char *, size_t, off_t); + int (*write) (const char *, const char *, size_t, off_t); + int (*statfs) (const char *, struct statfs *); + int (*flush) (const char *); + int (*release) (const char *, int); + int (*fsync) (const char *, int); + int (*setxattr) (const char *, const char *, const char *, + size_t, int); + int (*getxattr) (const char *, const char *, char *, size_t); + int (*listxattr) (const char *, char *, size_t); + int (*removexattr) (const char *, const char *); +}; + +int fuse_main_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op); + +struct fuse *fuse_new_compat2(int fd, const char *opts, + const struct fuse_operations_compat2 *op); + +struct fuse *fuse_setup_compat2(int argc, char *argv[], + const struct fuse_operations_compat2 *op, + char **mountpoint, int *multithreaded, int *fd); + +struct fuse_statfs_compat1 { + long block_size; + long blocks; + long blocks_free; + long files; + long files_free; + long namelen; +}; + +struct fuse_operations_compat1 { + int (*getattr) (const char *, struct stat *); + int (*readlink) (const char *, char *, size_t); + int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat); + int (*mknod) (const char *, mode_t, dev_t); + int (*mkdir) (const char *, mode_t); + int (*unlink) (const char *); + int (*rmdir) (const char *); + int (*symlink) (const char *, const char *); + int (*rename) (const char *, const char *); + int (*link) (const char *, const char *); + int (*chmod) (const char *, mode_t); + int (*chown) (const char *, uid_t, gid_t); + int (*truncate) (const char *, off_t); + int (*utime) (const char *, struct utimbuf *); + int (*open) (const char *, int); + int (*read) (const char *, char *, size_t, off_t); + int (*write) (const char *, const char *, size_t, off_t); + int (*statfs) (struct fuse_statfs_compat1 *); + int (*release) (const char *, int); + int (*fsync) (const char *, int); +}; + +#define FUSE_DEBUG_COMPAT1 (1 << 1) + +struct fuse *fuse_new_compat1(int fd, int flags, + const struct fuse_operations_compat1 *op); + +void fuse_main_compat1(int argc, char *argv[], + const struct fuse_operations_compat1 *op); + +#endif /* __FreeBSD__ */ diff --git a/itemz-daemon/include/fuse/fuse_kernel.h b/itemz-daemon/include/fuse/fuse_kernel.h new file mode 100644 index 0000000..bd73630 --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_kernel.h @@ -0,0 +1,593 @@ +/* + This file defines the kernel interface of FUSE + Copyright (C) 2001-2008 Miklos Szeredi + + This program can be distributed under the terms of the GNU GPL. + See the file COPYING. + + This -- and only this -- header file may also be distributed under + the terms of the BSD Licence as follows: + + Copyright (C) 2001-2007 Miklos Szeredi. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +/* + * This file defines the kernel interface of FUSE + * + * Protocol changelog: + * + * 7.9: + * - new fuse_getattr_in input argument of GETATTR + * - add lk_flags in fuse_lk_in + * - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in + * - add blksize field to fuse_attr + * - add file flags field to fuse_read_in and fuse_write_in + * + * 7.10 + * - add nonseekable open flag + * + * 7.11 + * - add IOCTL message + * - add unsolicited notification support + * - add POLL message and NOTIFY_POLL notification + * + * 7.12 + * - add umask flag to input argument of open, mknod and mkdir + * - add notification messages for invalidation of inodes and + * directory entries + */ + +#ifndef _LINUX_FUSE_H +#define _LINUX_FUSE_H + +#include +#define __u64 uint64_t +#define __s64 int64_t +#define __u32 uint32_t +#define __s32 int32_t + +/* + * Version negotiation: + * + * Both the kernel and userspace send the version they support in the + * INIT request and reply respectively. + * + * If the major versions match then both shall use the smallest + * of the two minor versions for communication. + * + * If the kernel supports a larger major version, then userspace shall + * reply with the major version it supports, ignore the rest of the + * INIT message and expect a new INIT message from the kernel with a + * matching major version. + * + * If the library supports a larger major version, then it shall fall + * back to the major protocol version sent by the kernel for + * communication and reply with that major version (and an arbitrary + * supported minor version). + */ + +/** Version number of this interface */ +#define FUSE_KERNEL_VERSION 7 + +/** Minor version number of this interface */ +#define FUSE_KERNEL_MINOR_VERSION 12 + +/** The node ID of the root inode */ +#define FUSE_ROOT_ID 1 + +/* Make sure all structures are padded to 64bit boundary, so 32bit + userspace works under 64bit kernels */ + +struct fuse_attr { + __u64 ino; + __u64 size; + __u64 blocks; + __u64 atime; + __u64 mtime; + __u64 ctime; + __u32 atimensec; + __u32 mtimensec; + __u32 ctimensec; + __u32 mode; + __u32 nlink; + __u32 uid; + __u32 gid; + __u32 rdev; + __u32 blksize; + __u32 padding; +}; + +struct fuse_kstatfs { + __u64 blocks; + __u64 bfree; + __u64 bavail; + __u64 files; + __u64 ffree; + __u32 bsize; + __u32 namelen; + __u32 frsize; + __u32 padding; + __u32 spare[6]; +}; + +struct fuse_file_lock { + __u64 start; + __u64 end; + __u32 type; + __u32 pid; /* tgid */ +}; + +/** + * Bitmasks for fuse_setattr_in.valid + */ +#define FATTR_MODE (1 << 0) +#define FATTR_UID (1 << 1) +#define FATTR_GID (1 << 2) +#define FATTR_SIZE (1 << 3) +#define FATTR_ATIME (1 << 4) +#define FATTR_MTIME (1 << 5) +#define FATTR_FH (1 << 6) +#define FATTR_ATIME_NOW (1 << 7) +#define FATTR_MTIME_NOW (1 << 8) +#define FATTR_LOCKOWNER (1 << 9) + +/** + * Flags returned by the OPEN request + * + * FOPEN_DIRECT_IO: bypass page cache for this open file + * FOPEN_KEEP_CACHE: don't invalidate the data cache on open + * FOPEN_NONSEEKABLE: the file is not seekable + */ +#define FOPEN_DIRECT_IO (1 << 0) +#define FOPEN_KEEP_CACHE (1 << 1) +#define FOPEN_NONSEEKABLE (1 << 2) + +/** + * INIT request/reply flags + * + * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_DONT_MASK: don't apply umask to file mode on create operations + */ +#define FUSE_ASYNC_READ (1 << 0) +#define FUSE_POSIX_LOCKS (1 << 1) +#define FUSE_FILE_OPS (1 << 2) +#define FUSE_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_EXPORT_SUPPORT (1 << 4) +#define FUSE_BIG_WRITES (1 << 5) +#define FUSE_DONT_MASK (1 << 6) + +/** + * CUSE INIT request/reply flags + * + * CUSE_UNRESTRICTED_IOCTL: use unrestricted ioctl + */ +#define CUSE_UNRESTRICTED_IOCTL (1 << 0) + +/** + * Release flags + */ +#define FUSE_RELEASE_FLUSH (1 << 0) + +/** + * Getattr flags + */ +#define FUSE_GETATTR_FH (1 << 0) + +/** + * Lock flags + */ +#define FUSE_LK_FLOCK (1 << 0) + +/** + * WRITE flags + * + * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed + * FUSE_WRITE_LOCKOWNER: lock_owner field is valid + */ +#define FUSE_WRITE_CACHE (1 << 0) +#define FUSE_WRITE_LOCKOWNER (1 << 1) + +/** + * Read flags + */ +#define FUSE_READ_LOCKOWNER (1 << 1) + +/** + * Ioctl flags + * + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed + * FUSE_IOCTL_RETRY: retry with new iovecs + * + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs + */ +#define FUSE_IOCTL_COMPAT (1 << 0) +#define FUSE_IOCTL_UNRESTRICTED (1 << 1) +#define FUSE_IOCTL_RETRY (1 << 2) + +#define FUSE_IOCTL_MAX_IOV 256 + +/** + * Poll flags + * + * FUSE_POLL_SCHEDULE_NOTIFY: request poll notify + */ +#define FUSE_POLL_SCHEDULE_NOTIFY (1 << 0) + +enum fuse_opcode { + FUSE_LOOKUP = 1, + FUSE_FORGET = 2, /* no reply */ + FUSE_GETATTR = 3, + FUSE_SETATTR = 4, + FUSE_READLINK = 5, + FUSE_SYMLINK = 6, + FUSE_MKNOD = 8, + FUSE_MKDIR = 9, + FUSE_UNLINK = 10, + FUSE_RMDIR = 11, + FUSE_RENAME = 12, + FUSE_LINK = 13, + FUSE_OPEN = 14, + FUSE_READ = 15, + FUSE_WRITE = 16, + FUSE_STATFS = 17, + FUSE_RELEASE = 18, + FUSE_FSYNC = 20, + FUSE_SETXATTR = 21, + FUSE_GETXATTR = 22, + FUSE_LISTXATTR = 23, + FUSE_REMOVEXATTR = 24, + FUSE_FLUSH = 25, + FUSE_INIT = 26, + FUSE_OPENDIR = 27, + FUSE_READDIR = 28, + FUSE_RELEASEDIR = 29, + FUSE_FSYNCDIR = 30, + FUSE_GETLK = 31, + FUSE_SETLK = 32, + FUSE_SETLKW = 33, + FUSE_ACCESS = 34, + FUSE_CREATE = 35, + FUSE_INTERRUPT = 36, + FUSE_BMAP = 37, + FUSE_DESTROY = 38, + FUSE_IOCTL = 39, + FUSE_POLL = 40, + + /* CUSE specific operations */ + CUSE_INIT = 4096, +}; + +enum fuse_notify_code { + FUSE_NOTIFY_POLL = 1, + FUSE_NOTIFY_INVAL_INODE = 2, + FUSE_NOTIFY_INVAL_ENTRY = 3, + FUSE_NOTIFY_CODE_MAX, +}; + +/* The read buffer is required to be at least 8k, but may be much larger */ +#define FUSE_MIN_READ_BUFFER 8192 + +#define FUSE_COMPAT_ENTRY_OUT_SIZE 120 + +struct fuse_entry_out { + __u64 nodeid; /* Inode ID */ + __u64 generation; /* Inode generation: nodeid:gen must + be unique for the fs's lifetime */ + __u64 entry_valid; /* Cache timeout for the name */ + __u64 attr_valid; /* Cache timeout for the attributes */ + __u32 entry_valid_nsec; + __u32 attr_valid_nsec; + struct fuse_attr attr; +}; + +struct fuse_forget_in { + __u64 nlookup; +}; + +struct fuse_getattr_in { + __u32 getattr_flags; + __u32 dummy; + __u64 fh; +}; + +#define FUSE_COMPAT_ATTR_OUT_SIZE 96 + +struct fuse_attr_out { + __u64 attr_valid; /* Cache timeout for the attributes */ + __u32 attr_valid_nsec; + __u32 dummy; + struct fuse_attr attr; +}; + +#define FUSE_COMPAT_MKNOD_IN_SIZE 8 + +struct fuse_mknod_in { + __u32 mode; + __u32 rdev; + __u32 umask; + __u32 padding; +}; + +struct fuse_mkdir_in { + __u32 mode; + __u32 umask; +}; + +struct fuse_rename_in { + __u64 newdir; +}; + +struct fuse_link_in { + __u64 oldnodeid; +}; + +struct fuse_setattr_in { + __u32 valid; + __u32 padding; + __u64 fh; + __u64 size; + __u64 lock_owner; + __u64 atime; + __u64 mtime; + __u64 unused2; + __u32 atimensec; + __u32 mtimensec; + __u32 unused3; + __u32 mode; + __u32 unused4; + __u32 uid; + __u32 gid; + __u32 unused5; +}; + +struct fuse_open_in { + __u32 flags; + __u32 unused; +}; + +struct fuse_create_in { + __u32 flags; + __u32 mode; + __u32 umask; + __u32 padding; +}; + +struct fuse_open_out { + __u64 fh; + __u32 open_flags; + __u32 padding; +}; + +struct fuse_release_in { + __u64 fh; + __u32 flags; + __u32 release_flags; + __u64 lock_owner; +}; + +struct fuse_flush_in { + __u64 fh; + __u32 unused; + __u32 padding; + __u64 lock_owner; +}; + +struct fuse_read_in { + __u64 fh; + __u64 offset; + __u32 size; + __u32 read_flags; + __u64 lock_owner; + __u32 flags; + __u32 padding; +}; + +#define FUSE_COMPAT_WRITE_IN_SIZE 24 + +struct fuse_write_in { + __u64 fh; + __u64 offset; + __u32 size; + __u32 write_flags; + __u64 lock_owner; + __u32 flags; + __u32 padding; +}; + +struct fuse_write_out { + __u32 size; + __u32 padding; +}; + +#define FUSE_COMPAT_STATFS_SIZE 48 + +struct fuse_statfs_out { + struct fuse_kstatfs st; +}; + +struct fuse_fsync_in { + __u64 fh; + __u32 fsync_flags; + __u32 padding; +}; + +struct fuse_setxattr_in { + __u32 size; + __u32 flags; +}; + +struct fuse_getxattr_in { + __u32 size; + __u32 padding; +}; + +struct fuse_getxattr_out { + __u32 size; + __u32 padding; +}; + +struct fuse_lk_in { + __u64 fh; + __u64 owner; + struct fuse_file_lock lk; + __u32 lk_flags; + __u32 padding; +}; + +struct fuse_lk_out { + struct fuse_file_lock lk; +}; + +struct fuse_access_in { + __u32 mask; + __u32 padding; +}; + +struct fuse_init_in { + __u32 major; + __u32 minor; + __u32 max_readahead; + __u32 flags; +}; + +struct fuse_init_out { + __u32 major; + __u32 minor; + __u32 max_readahead; + __u32 flags; + __u32 unused; + __u32 max_write; +}; + +#define CUSE_INIT_INFO_MAX 4096 + +struct cuse_init_in { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; +}; + +struct cuse_init_out { + __u32 major; + __u32 minor; + __u32 unused; + __u32 flags; + __u32 max_read; + __u32 max_write; + __u32 dev_major; /* chardev major */ + __u32 dev_minor; /* chardev minor */ + __u32 spare[10]; +}; + +struct fuse_interrupt_in { + __u64 unique; +}; + +struct fuse_bmap_in { + __u64 block; + __u32 blocksize; + __u32 padding; +}; + +struct fuse_bmap_out { + __u64 block; +}; + +struct fuse_ioctl_in { + __u64 fh; + __u32 flags; + __u32 cmd; + __u64 arg; + __u32 in_size; + __u32 out_size; +}; + +struct fuse_ioctl_out { + __s32 result; + __u32 flags; + __u32 in_iovs; + __u32 out_iovs; +}; + +struct fuse_poll_in { + __u64 fh; + __u64 kh; + __u32 flags; + __u32 padding; +}; + +struct fuse_poll_out { + __u32 revents; + __u32 padding; +}; + +struct fuse_notify_poll_wakeup_out { + __u64 kh; +}; + +struct fuse_in_header { + __u32 len; + __u32 opcode; + __u64 unique; + __u64 nodeid; + __u32 uid; + __u32 gid; + __u32 pid; + __u32 padding; +}; + +struct fuse_out_header { + __u32 len; + __s32 error; + __u64 unique; +}; + +struct fuse_dirent { + __u64 ino; + __u64 off; + __u32 namelen; + __u32 type; + char name[0]; +}; + +#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name) +#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1)) +#define FUSE_DIRENT_SIZE(d) \ + FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen) + +struct fuse_notify_inval_inode_out { + __u64 ino; + __s64 off; + __s64 len; +}; + +struct fuse_notify_inval_entry_out { + __u64 parent; + __u32 namelen; + __u32 padding; +}; + +#endif /* _LINUX_FUSE_H */ diff --git a/itemz-daemon/include/fuse/fuse_lowlevel.h b/itemz-daemon/include/fuse/fuse_lowlevel.h new file mode 100644 index 0000000..f553f26 --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_lowlevel.h @@ -0,0 +1,1556 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_LOWLEVEL_H_ +#define _FUSE_LOWLEVEL_H_ + +/** @file + * + * Low level API + * + * IMPORTANT: you should define FUSE_USE_VERSION before including this + * header. To use the newest API define it to 26 (recommended for any + * new application), to use the old API define it to 24 (default) or + * 25 + */ + +#ifndef FUSE_USE_VERSION +#define FUSE_USE_VERSION 26 +#endif + +#include "fuse_common.h" + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------- * + * Miscellaneous definitions * + * ----------------------------------------------------------- */ + +/** The node ID of the root inode */ +#define FUSE_ROOT_ID 1 + +/** Inode number type */ +typedef unsigned long fuse_ino_t; + +/** Request pointer type */ +typedef struct fuse_req *fuse_req_t; + +/** + * Session + * + * This provides hooks for processing requests, and exiting + */ +struct fuse_session; + +/** + * Channel + * + * A communication channel, providing hooks for sending and receiving + * messages + */ +struct fuse_chan; + +/** Directory entry parameters supplied to fuse_reply_entry() */ +struct fuse_entry_param { + /** Unique inode number + * + * In lookup, zero means negative entry (from version 2.5) + * Returning ENOENT also means negative entry, but by setting zero + * ino the kernel may cache negative entries for entry_timeout + * seconds. + */ + fuse_ino_t ino; + + /** Generation number for this entry. + * + * The ino/generation pair should be unique for the filesystem's + * lifetime. It must be non-zero, otherwise FUSE will treat it as an + * error. + */ + unsigned long generation; + + /** Inode attributes. + * + * Even if attr_timeout == 0, attr must be correct. For example, + * for open(), FUSE uses attr.st_size from lookup() to determine + * how many bytes to request. If this value is not correct, + * incorrect data will be returned. + */ + struct stat attr; + + /** Validity timeout (in seconds) for the attributes */ + double attr_timeout; + + /** Validity timeout (in seconds) for the name */ + double entry_timeout; +}; + +/** Additional context associated with requests */ +struct fuse_ctx { + /** User ID of the calling process */ + uid_t uid; + + /** Group ID of the calling process */ + gid_t gid; + + /** Thread ID of the calling process */ + pid_t pid; + + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +}; + +/* 'to_set' flags in setattr */ +#define FUSE_SET_ATTR_MODE (1 << 0) +#define FUSE_SET_ATTR_UID (1 << 1) +#define FUSE_SET_ATTR_GID (1 << 2) +#define FUSE_SET_ATTR_SIZE (1 << 3) +#define FUSE_SET_ATTR_ATIME (1 << 4) +#define FUSE_SET_ATTR_MTIME (1 << 5) +#define FUSE_SET_ATTR_ATIME_NOW (1 << 7) +#define FUSE_SET_ATTR_MTIME_NOW (1 << 8) + +/* ----------------------------------------------------------- * + * Request methods and replies * + * ----------------------------------------------------------- */ + +/** + * Low level filesystem operations + * + * Most of the methods (with the exception of init and destroy) + * receive a request handle (fuse_req_t) as their first argument. + * This handle must be passed to one of the specified reply functions. + * + * This may be done inside the method invocation, or after the call + * has returned. The request handle is valid until one of the reply + * functions is called. + * + * Other pointer arguments (name, fuse_file_info, etc) are not valid + * after the call has returned, so if they are needed later, their + * contents have to be copied. + * + * The filesystem sometimes needs to handle a return value of -ENOENT + * from the reply function, which means, that the request was + * interrupted, and the reply discarded. For example if + * fuse_reply_open() return -ENOENT means, that the release method for + * this file will not be called. + */ +struct fuse_lowlevel_ops { + /** + * Initialize filesystem + * + * Called before any other filesystem method + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ + void (*init) (void *userdata, struct fuse_conn_info *conn); + + /** + * Clean up filesystem + * + * Called on filesystem exit + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ + void (*destroy) (void *userdata); + + /** + * Look up a directory entry by name and get its attributes. + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name the name to look up + */ + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Forget about an inode + * + * The nlookup parameter indicates the number of lookups + * previously performed on this inode. + * + * If the filesystem implements inode lifetimes, it is recommended + * that inodes acquire a single reference on each lookup, and lose + * nlookup references on each forget. + * + * The filesystem may ignore forget calls, if the inodes don't + * need to have a limited lifetime. + * + * On unmount it is not guaranteed, that all referenced inodes + * will receive a forget message. + * + * Valid replies: + * fuse_reply_none + * + * @param req request handle + * @param ino the inode number + * @param nlookup the number of lookups to forget + */ + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + + /** + * Get file attributes + * + * Valid replies: + * fuse_reply_attr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi for future use, currently always NULL + */ + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Set file attributes + * + * In the 'attr' argument only members indicated by the 'to_set' + * bitmask contain valid values. Other members contain undefined + * values. + * + * If the setattr was invoked from the ftruncate() system call + * under Linux kernel versions 2.6.15 or later, the fi->fh will + * contain the value set by the open method or will be undefined + * if the open method didn't set any value. Otherwise (not + * ftruncate call, or kernel version earlier than 2.6.15) the fi + * parameter will be NULL. + * + * Valid replies: + * fuse_reply_attr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param attr the attributes + * @param to_set bit mask of attributes which should be set + * @param fi file information, or NULL + * + * Changed in version 2.5: + * file information filled in for ftruncate + */ + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi); + + /** + * Read symbolic link + * + * Valid replies: + * fuse_reply_readlink + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + */ + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + + /** + * Create file node + * + * Create a regular file, character device, block device, fifo or + * socket node. + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param rdev the device number (only valid if created file is a device) + */ + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + + /** + * Create a directory + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode with which to create the new file + */ + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + + /** + * Remove a file + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to remove + */ + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Remove a directory + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to remove + */ + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + + /** + * Create a symbolic link + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param link the contents of the symbolic link + * @param parent inode number of the parent directory + * @param name to create + */ + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + + /** Rename a file + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the old parent directory + * @param name old name + * @param newparent inode number of the new parent directory + * @param newname new name + */ + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + + /** + * Create a hard link + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param ino the old inode number + * @param newparent inode number of the new parent directory + * @param newname new name to create + */ + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + + /** + * Open a file + * + * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and + * O_TRUNC) are available in fi->flags. + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). + * + * Filesystem may also implement stateless file I/O and not store + * anything in fi->fh. + * + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. + * + * Valid replies: + * fuse_reply_open + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Read data + * + * Read should send exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the file + * has been opened in 'direct_io' mode, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_iov + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size number of bytes to read + * @param off offset to read from + * @param fi file information + */ + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + + /** + * Write data + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the file has + * been opened in 'direct_io' mode, in which case the return value + * of the write system call will reflect the return value of this + * operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * Valid replies: + * fuse_reply_write + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param buf data to write + * @param size number of bytes to write + * @param off offset to write to + * @param fi file information + */ + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); + + /** + * Flush method + * + * This is called on each close() of the opened file. + * + * Since file descriptors can be duplicated (dup, dup2, fork), for + * one open call there may be many flush calls. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * NOTE: the name of the method is misleading, since (unlike + * fsync) the filesystem is not forced to flush pending writes. + * One reason to flush data, is if the filesystem wants to return + * write errors. + * + * If the filesystem supports file locking operations (setlk, + * getlk) it should remove all locks belonging to 'fi->owner'. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open call there will be exactly one release call. + * + * The filesystem may reply with an error, but error values are + * not returned to close() or munmap() which triggered the + * release. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * fi->flags will contain the same flags as for open. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param datasync flag indicating if only data should be flushed + * @param fi file information + */ + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + + /** + * Open a directory + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other directory + * stream operations (readdir, releasedir, fsyncdir). + * + * Filesystem may also implement stateless directory I/O and not + * store anything in fi->fh, though that makes it impossible to + * implement standard conforming directory stream operations in + * case the contents of the directory can change between opendir + * and releasedir. + * + * Valid replies: + * fuse_reply_open + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Read directory + * + * Send a buffer filled using fuse_add_direntry(), with size not + * exceeding the requested size. Send an empty buffer on end of + * stream. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum number of bytes to send + * @param off offset to continue reading the directory stream + * @param fi file information + */ + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + + /** + * Release an open directory + * + * For every opendir call there will be exactly one releasedir + * call. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + */ + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + + /** + * Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the directory + * contents should be flushed, not the meta data. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param datasync flag indicating if only data should be flushed + * @param fi file information + */ + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + + /** + * Get file system statistics + * + * Valid replies: + * fuse_reply_statfs + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number, zero means "undefined" + */ + void (*statfs) (fuse_req_t req, fuse_ino_t ino); + + /** + * Set an extended attribute + * + * Valid replies: + * fuse_reply_err + */ + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + + /** + * Get an extended attribute + * + * If size is zero, the size of the value should be sent with + * fuse_reply_xattr. + * + * If the size is non-zero, and the value fits in the buffer, the + * value should be sent with fuse_reply_buf. + * + * If the size is too small for the value, the ERANGE error should + * be sent. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_xattr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param name of the extended attribute + * @param size maximum size of the value to send + */ + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + + /** + * List extended attribute names + * + * If size is zero, the total size of the attribute list should be + * sent with fuse_reply_xattr. + * + * If the size is non-zero, and the null character separated + * attribute list fits in the buffer, the list should be sent with + * fuse_reply_buf. + * + * If the size is too small for the list, the ERANGE error should + * be sent. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_xattr + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param size maximum size of the list to send + */ + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + + /** + * Remove an extended attribute + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param name of the extended attribute + */ + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + + /** + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param mask requested access mode + */ + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + + /** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * Open flags (with the exception of O_NOCTTY) are available in + * fi->flags. + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). + * + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_create + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param fi file information + */ + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi); + + /** + * Test for a POSIX file lock + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_lock + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param lock the region/type to test + */ + void (*getlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock); + + /** + * Acquire, modify or release a POSIX file lock + * + * For POSIX threads (NPTL) there's a 1-1 relation between pid and + * owner, but otherwise this is not always the case. For checking + * lock ownership, 'fi->owner' must be used. The l_pid field in + * 'struct flock' should only be used to fill in this field in + * getlk(). + * + * Note: if the locking methods are not implemented, the kernel + * will still allow file locking to work locally. Hence these are + * only interesting for network filesystems and similar. + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param lock the region/type to test + * @param sleep locking operation may sleep + */ + void (*setlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, + struct flock *lock, int sleep); + + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_bmap + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param blocksize unit of block index + * @param idx block index within file + */ + void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t idx); + + /** + * Ioctl + * + * Note: For unrestricted ioctls (not allowed for FUSE + * servers), data in and out areas can be discovered by giving + * iovs and setting FUSE_IOCTL_RETRY in @flags. For + * restricted ioctls, kernel prepares in/out data area + * according to the information encoded in cmd. + * + * Introduced in version 2.8 + * + * Valid replies: + * fuse_reply_ioctl_retry + * fuse_reply_ioctl + * fuse_reply_ioctl_iov + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param cmd ioctl command + * @param arg ioctl argument + * @param fi file information + * @param flags for FUSE_IOCTL_* flags + * @param in_buf data fetched from the caller + * @param in_bufsz number of fetched bytes + * @param out_bufsz maximum size of output data + */ + void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg, + struct fuse_file_info *fi, unsigned flags, + const void *in_buf, size_t in_bufsz, size_t out_bufsz); + + /** + * Poll for IO readiness + * + * Introduced in version 2.8 + * + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_lowelevel_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Valid replies: + * fuse_reply_poll + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param ph poll handle to be used for notification + */ + void (*poll) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, + struct fuse_pollhandle *ph); +}; + +/** + * Reply with an error code or success + * + * Possible requests: + * all except forget + * + * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr, + * removexattr and setlk may send a zero code + * + * @param req request handle + * @param err the positive error value, or zero for success + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_err(fuse_req_t req, int err); + +/** + * Don't send reply + * + * Possible requests: + * forget + * + * @param req request handle + */ +void fuse_reply_none(fuse_req_t req); + +/** + * Reply with a directory entry + * + * Possible requests: + * lookup, mknod, mkdir, symlink, link + * + * @param req request handle + * @param e the entry parameters + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e); + +/** + * Reply with a directory entry and open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * create + * + * @param req request handle + * @param e the entry parameters + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, + const struct fuse_file_info *fi); + +/** + * Reply with attributes + * + * Possible requests: + * getattr, setattr + * + * @param req request handle + * @param attr the attributes + * @param attr_timeout validity timeout (in seconds) for the attributes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_attr(fuse_req_t req, const struct stat *attr, + double attr_timeout); + +/** + * Reply with the contents of a symbolic link + * + * Possible requests: + * readlink + * + * @param req request handle + * @param link symbolic link contents + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_readlink(fuse_req_t req, const char *link); + +/** + * Reply with open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * open, opendir + * + * @param req request handle + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi); + +/** + * Reply with number of bytes written + * + * Possible requests: + * write + * + * @param req request handle + * @param count the number of bytes written + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_write(fuse_req_t req, size_t count); + +/** + * Reply with data + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param buf buffer containing data + * @param size the size of data in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); + +/** + * Reply with data vector + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param iov the vector containing the data + * @param count the size of vector + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count); + +/** + * Reply with filesystem statistics + * + * Possible requests: + * statfs + * + * @param req request handle + * @param stbuf filesystem statistics + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf); + +/** + * Reply with needed buffer size + * + * Possible requests: + * getxattr, listxattr + * + * @param req request handle + * @param count the buffer size needed in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_xattr(fuse_req_t req, size_t count); + +/** + * Reply with file lock information + * + * Possible requests: + * getlk + * + * @param req request handle + * @param lock the lock information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_lock(fuse_req_t req, struct flock *lock); + +/** + * Reply with block index + * + * Possible requests: + * bmap + * + * @param req request handle + * @param idx block index within device + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_bmap(fuse_req_t req, uint64_t idx); + +/* ----------------------------------------------------------- * + * Filling a buffer in readdir * + * ----------------------------------------------------------- */ + +/** + * Add a directory entry to the buffer + * + * Buffer needs to be large enough to hold the entry. If it's not, + * then the entry is not filled in but the size of the entry is still + * returned. The caller can check this by comparing the bufsize + * parameter with the returned entry size. If the entry size is + * larger than the buffer size, the operation failed. + * + * From the 'stbuf' argument the st_ino field and bits 12-15 of the + * st_mode field are used. The other fields are ignored. + * + * Note: offsets do not necessarily represent physical offsets, and + * could be any marker, that enables the implementation to find a + * specific point in the directory stream. + * + * @param req request handle + * @param buf the point where the new entry will be added to the buffer + * @param bufsize remaining size of the buffer + * @param name the name of the entry + * @param stbuf the file attributes + * @param off the offset of the next entry + * @return the space needed for the entry + */ +size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize, + const char *name, const struct stat *stbuf, + off_t off); + +/** + * Reply to ask for data fetch and output buffer preparation. ioctl + * will be retried with the specified input data fetched and output + * buffer prepared. + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param in_iov iovec specifying data to fetch from the caller + * @param in_count number of entries in in_iov + * @param out_iov iovec specifying addresses to write output to + * @param out_count number of entries in out_iov + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_ioctl_retry(fuse_req_t req, + const struct iovec *in_iov, size_t in_count, + const struct iovec *out_iov, size_t out_count); + +/** + * Reply to finish ioctl + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param buf buffer containing output data + * @param size length of output data + */ +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size); + +/** + * Reply to finish ioctl with iov buffer + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param iov the vector containing the data + * @param count the size of vector + */ +int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, + int count); + +/** + * Reply with poll result event mask + * + * @param req request handle + * @param revents poll result event mask + */ +int fuse_reply_poll(fuse_req_t req, unsigned revents); + +/* ----------------------------------------------------------- * + * Notification * + * ----------------------------------------------------------- */ + +/** + * Notify IO readiness event + * + * For more information, please read comment for poll operation. + * + * @param ph poll handle to notify IO readiness event for + */ +int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph); + +/** + * Notify to invalidate cache for an inode + * + * @param ch the channel through which to send the invalidation + * @param ino the inode number + * @param off the offset in the inode where to start invalidating + * or negative to invalidate attributes only + * @param len the amount of cache to invalidate or 0 for all + * @return zero for success, -errno for failure + */ +int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, + off_t off, off_t len); + +/** + * Notify to invalidate parent attributes and the dentry matching + * parent/name + * + * @param ch the channel through which to send the invalidation + * @param parent inode number + * @param name file name + * @param namelen strlen() of file name + * @return zero for success, -errno for failure + */ +int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, + const char *name, size_t namelen); + +/* ----------------------------------------------------------- * + * Utility functions * + * ----------------------------------------------------------- */ + +/** + * Get the userdata from the request + * + * @param req request handle + * @return the user data passed to fuse_lowlevel_new() + */ +void *fuse_req_userdata(fuse_req_t req); + +/** + * Get the context from the request + * + * The pointer returned by this function will only be valid for the + * request's lifetime + * + * @param req request handle + * @return the context structure + */ +const struct fuse_ctx *fuse_req_ctx(fuse_req_t req); + +/** + * Get the current supplementary group IDs for the specified request + * + * Similar to the getgroups(2) system call, except the return value is + * always the total number of group IDs, even if it is larger than the + * specified size. + * + * The current fuse kernel module in linux (as of 2.6.30) doesn't pass + * the group list to userspace, hence this function needs to parse + * "/proc/$TID/task/$TID/status" to get the group IDs. + * + * This feature may not be supported on all operating systems. In + * such a case this function will return -ENOSYS. + * + * @param req request handle + * @param size size of given array + * @param list array of group IDs to be filled in + * @return the total number of supplementary group IDs or -errno on failure + */ +int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]); + +/** + * Callback function for an interrupt + * + * @param req interrupted request + * @param data user data + */ +typedef void (*fuse_interrupt_func_t)(fuse_req_t req, void *data); + +/** + * Register/unregister callback for an interrupt + * + * If an interrupt has already happened, then the callback function is + * called from within this function, hence it's not possible for + * interrupts to be lost. + * + * @param req request handle + * @param func the callback function or NULL for unregister + * @param data user data passed to the callback function + */ +void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, + void *data); + +/** + * Check if a request has already been interrupted + * + * @param req request handle + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_req_interrupted(fuse_req_t req); + +/* ----------------------------------------------------------- * + * Filesystem setup * + * ----------------------------------------------------------- */ + +/* Deprecated, don't use */ +int fuse_lowlevel_is_lib_option(const char *opt); + +/** + * Create a low level session + * + * @param args argument vector + * @param op the low level filesystem operations + * @param op_size sizeof(struct fuse_lowlevel_ops) + * @param userdata user data + * @return the created session object, or NULL on failure + */ +struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata); + +/* ----------------------------------------------------------- * + * Session interface * + * ----------------------------------------------------------- */ + +/** + * Session operations + * + * This is used in session creation + */ +struct fuse_session_ops { + /** + * Hook to process a request (mandatory) + * + * @param data user data passed to fuse_session_new() + * @param buf buffer containing the raw request + * @param len request length + * @param ch channel on which the request was received + */ + void (*process) (void *data, const char *buf, size_t len, + struct fuse_chan *ch); + + /** + * Hook for session exit and reset (optional) + * + * @param data user data passed to fuse_session_new() + * @param val exited status (1 - exited, 0 - not exited) + */ + void (*exit) (void *data, int val); + + /** + * Hook for querying the current exited status (optional) + * + * @param data user data passed to fuse_session_new() + * @return 1 if exited, 0 if not exited + */ + int (*exited) (void *data); + + /** + * Hook for cleaning up the channel on destroy (optional) + * + * @param data user data passed to fuse_session_new() + */ + void (*destroy) (void *data); +}; + +/** + * Create a new session + * + * @param op session operations + * @param data user data + * @return new session object, or NULL on failure + */ +struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data); + +/** + * Assign a channel to a session + * + * Note: currently only a single channel may be assigned. This may + * change in the future + * + * If a session is destroyed, the assigned channel is also destroyed + * + * @param se the session + * @param ch the channel + */ +void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch); + +/** + * Remove a channel from a session + * + * If the channel is not assigned to a session, then this is a no-op + * + * @param ch the channel to remove + */ +void fuse_session_remove_chan(struct fuse_chan *ch); + +/** + * Iterate over the channels assigned to a session + * + * The iterating function needs to start with a NULL channel, and + * after that needs to pass the previously returned channel to the + * function. + * + * @param se the session + * @param ch the previous channel, or NULL + * @return the next channel, or NULL if no more channels exist + */ +struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, + struct fuse_chan *ch); + +/** + * Process a raw request + * + * @param se the session + * @param buf buffer containing the raw request + * @param len request length + * @param ch channel on which the request was received + */ +void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, + struct fuse_chan *ch); + +/** + * Destroy a session + * + * @param se the session + */ +void fuse_session_destroy(struct fuse_session *se); + +/** + * Exit a session + * + * @param se the session + */ +void fuse_session_exit(struct fuse_session *se); + +/** + * Reset the exited status of a session + * + * @param se the session + */ +void fuse_session_reset(struct fuse_session *se); + +/** + * Query the exited status of a session + * + * @param se the session + * @return 1 if exited, 0 if not exited + */ +int fuse_session_exited(struct fuse_session *se); + +/** + * Get the user data provided to the session + * + * @param se the session + * @return the user data + */ +void *fuse_session_data(struct fuse_session *se); + +/** + * Enter a single threaded event loop + * + * @param se the session + * @return 0 on success, -1 on error + */ +int fuse_session_loop(struct fuse_session *se); + +/** + * Enter a multi-threaded event loop + * + * @param se the session + * @return 0 on success, -1 on error + */ +int fuse_session_loop_mt(struct fuse_session *se); + +/* ----------------------------------------------------------- * + * Channel interface * + * ----------------------------------------------------------- */ + +/** + * Channel operations + * + * This is used in channel creation + */ +struct fuse_chan_ops { + /** + * Hook for receiving a raw request + * + * @param ch pointer to the channel + * @param buf the buffer to store the request in + * @param size the size of the buffer + * @return the actual size of the raw request, or -1 on error + */ + int (*receive)(struct fuse_chan **chp, char *buf, size_t size); + + /** + * Hook for sending a raw reply + * + * A return value of -ENOENT means, that the request was + * interrupted, and the reply was discarded + * + * @param ch the channel + * @param iov vector of blocks + * @param count the number of blocks in vector + * @return zero on success, -errno on failure + */ + int (*send)(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + + /** + * Destroy the channel + * + * @param ch the channel + */ + void (*destroy)(struct fuse_chan *ch); +}; + +/** + * Create a new channel + * + * @param op channel operations + * @param fd file descriptor of the channel + * @param bufsize the minimal receive buffer size + * @param data user data + * @return the new channel object, or NULL on failure + */ +struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd, + size_t bufsize, void *data); + +/** + * Query the file descriptor of the channel + * + * @param ch the channel + * @return the file descriptor passed to fuse_chan_new() + */ +int fuse_chan_fd(struct fuse_chan *ch); + +/** + * Query the minimal receive buffer size + * + * @param ch the channel + * @return the buffer size passed to fuse_chan_new() + */ +size_t fuse_chan_bufsize(struct fuse_chan *ch); + +/** + * Query the user data + * + * @param ch the channel + * @return the user data passed to fuse_chan_new() + */ +void *fuse_chan_data(struct fuse_chan *ch); + +/** + * Query the session to which this channel is assigned + * + * @param ch the channel + * @return the session, or NULL if the channel is not assigned + */ +struct fuse_session *fuse_chan_session(struct fuse_chan *ch); + +/** + * Receive a raw request + * + * A return value of -ENODEV means, that the filesystem was unmounted + * + * @param ch pointer to the channel + * @param buf the buffer to store the request in + * @param size the size of the buffer + * @return the actual size of the raw request, or -errno on error + */ +int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size); + +/** + * Send a raw reply + * + * A return value of -ENOENT means, that the request was + * interrupted, and the reply was discarded + * + * @param ch the channel + * @param iov vector of blocks + * @param count the number of blocks in vector + * @return zero on success, -errno on failure + */ +int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + +/** + * Destroy a channel + * + * @param ch the channel + */ +void fuse_chan_destroy(struct fuse_chan *ch); + + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_LOWLEVEL_H_ */ diff --git a/itemz-daemon/include/fuse/fuse_lowlevel_compat.h b/itemz-daemon/include/fuse/fuse_lowlevel_compat.h new file mode 100644 index 0000000..aba45e6 --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_lowlevel_compat.h @@ -0,0 +1,155 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +/* these definitions provide source compatibility to prior versions. + Do not include this file directly! */ + +struct fuse_lowlevel_ops_compat25 { + void (*init) (void *userdata); + void (*destroy) (void *userdata); + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi); + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); + void (*statfs) (fuse_req_t req); + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi); +}; + +struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args, + const struct fuse_lowlevel_ops_compat25 *op, + size_t op_size, void *userdata); + +size_t fuse_dirent_size(size_t namelen); + +char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf, + off_t off); + +#ifndef __FreeBSD__ + +#include + +struct fuse_lowlevel_ops_compat { + void (*init) (void *userdata); + void (*destroy) (void *userdata); + void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup); + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info_compat *fi); + void (*readlink) (fuse_req_t req, fuse_ino_t ino); + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info_compat *fi); + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info_compat *fi); + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info_compat *fi); + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info_compat *fi); + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info_compat *fi); + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info_compat *fi); + void (*statfs) (fuse_req_t req); + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info_compat *fi); +}; + +int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf); + +int fuse_reply_open_compat(fuse_req_t req, + const struct fuse_file_info_compat *fi); + +struct fuse_session *fuse_lowlevel_new_compat(const char *opts, + const struct fuse_lowlevel_ops_compat *op, + size_t op_size, void *userdata); + +#endif /* __FreeBSD__ */ + +struct fuse_chan_ops_compat24 { + int (*receive)(struct fuse_chan *ch, char *buf, size_t size); + int (*send)(struct fuse_chan *ch, const struct iovec iov[], + size_t count); + void (*destroy)(struct fuse_chan *ch); +}; + +struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op, + int fd, size_t bufsize, void *data); + +int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size); +struct fuse_chan *fuse_kern_chan_new(int fd); diff --git a/itemz-daemon/include/fuse/fuse_opt.h b/itemz-daemon/include/fuse/fuse_opt.h new file mode 100644 index 0000000..8c08d77 --- /dev/null +++ b/itemz-daemon/include/fuse/fuse_opt.h @@ -0,0 +1,270 @@ +/* + FUSE: Filesystem in Userspace + Copyright (C) 2001-2007 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#ifndef _FUSE_OPT_H_ +#define _FUSE_OPT_H_ + +/** @file + * + * This file defines the option parsing interface of FUSE + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Option description + * + * This structure describes a single option, and and action associated + * with it, in case it matches. + * + * More than one such match may occur, in which case the action for + * each match is executed. + * + * There are three possible actions in case of a match: + * + * i) An integer (int or unsigned) variable determined by 'offset' is + * set to 'value' + * + * ii) The processing function is called, with 'value' as the key + * + * iii) An integer (any) or string (char *) variable determined by + * 'offset' is set to the value of an option parameter + * + * 'offset' should normally be either set to + * + * - 'offsetof(struct foo, member)' actions i) and iii) + * + * - -1 action ii) + * + * The 'offsetof()' macro is defined in the header. + * + * The template determines which options match, and also have an + * effect on the action. Normally the action is either i) or ii), but + * if a format is present in the template, then action iii) is + * performed. + * + * The types of templates are: + * + * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only + * themselves. Invalid values are "--" and anything beginning + * with "-o" + * + * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or + * the relevant option in a comma separated option list + * + * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) + * which have a parameter + * + * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform + * action iii). + * + * 5) "-x ", etc. Matches either "-xparam" or "-x param" as + * two separate arguments + * + * 6) "-x %s", etc. Combination of 4) and 5) + * + * If the format is "%s", memory is allocated for the string unlike + * with scanf(). + */ +struct fuse_opt { + /** Matching template and optional parameter formatting */ + const char *templ; + + /** + * Offset of variable within 'data' parameter of fuse_opt_parse() + * or -1 + */ + unsigned long offset; + + /** + * Value to set the variable to, or to be passed as 'key' to the + * processing function. Ignored if template has a format + */ + int value; +}; + +/** + * Key option. In case of a match, the processing function will be + * called with the specified key. + */ +#define FUSE_OPT_KEY(templ, key) { templ, -1U, key } + +/** + * Last option. An array of 'struct fuse_opt' must end with a NULL + * template value + */ +#define FUSE_OPT_END { NULL, 0, 0 } + +/** + * Argument list + */ +struct fuse_args { + /** Argument count */ + int argc; + + /** Argument vector. NULL terminated */ + char **argv; + + /** Is 'argv' allocated? */ + int allocated; +}; + +/** + * Initializer for 'struct fuse_args' + */ +#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } + +/** + * Key value passed to the processing function if an option did not + * match any template + */ +#define FUSE_OPT_KEY_OPT -1 + +/** + * Key value passed to the processing function for all non-options + * + * Non-options are the arguments beginning with a charater other than + * '-' or all arguments after the special '--' option + */ +#define FUSE_OPT_KEY_NONOPT -2 + +/** + * Special key value for options to keep + * + * Argument is not passed to processing function, but behave as if the + * processing function returned 1 + */ +#define FUSE_OPT_KEY_KEEP -3 + +/** + * Special key value for options to discard + * + * Argument is not passed to processing function, but behave as if the + * processing function returned zero + */ +#define FUSE_OPT_KEY_DISCARD -4 + +/** + * Processing function + * + * This function is called if + * - option did not match any 'struct fuse_opt' + * - argument is a non-option + * - option did match and offset was set to -1 + * + * The 'arg' parameter will always contain the whole argument or + * option including the parameter if exists. A two-argument option + * ("-x foo") is always converted to single arguemnt option of the + * form "-xfoo" before this function is called. + * + * Options of the form '-ofoo' are passed to this function without the + * '-o' prefix. + * + * The return value of this function determines whether this argument + * is to be inserted into the output argument vector, or discarded. + * + * @param data is the user data passed to the fuse_opt_parse() function + * @param arg is the whole argument or option + * @param key determines why the processing function was called + * @param outargs the current output argument list + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept + */ +typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, + struct fuse_args *outargs); + +/** + * Option parsing function + * + * If 'args' was returned from a previous call to fuse_opt_parse() or + * it was constructed from + * + * A NULL 'args' is equivalent to an empty argument vector + * + * A NULL 'opts' is equivalent to an 'opts' array containing a single + * end marker + * + * A NULL 'proc' is equivalent to a processing function always + * returning '1' + * + * @param args is the input and output argument list + * @param data is the user data + * @param opts is the option description array + * @param proc is the processing function + * @return -1 on error, 0 on success + */ +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc); + +/** + * Add an option to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt(char **opts, const char *opt); + +/** + * Add an option, escaping commas, to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt_escaped(char **opts, const char *opt); + +/** + * Add an argument to a NULL terminated argument vector + * + * @param args is the structure containing the current argument list + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_arg(struct fuse_args *args, const char *arg); + +/** + * Add an argument at the specified position in a NULL terminated + * argument vector + * + * Adds the argument to the N-th position. This is useful for adding + * options at the beggining of the array which must not come after the + * special '--' option. + * + * @param args is the structure containing the current argument list + * @param pos is the position at which to add the argument + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); + +/** + * Free the contents of argument list + * + * The structure itself is not freed + * + * @param args is the structure containing the argument list + */ +void fuse_opt_free_args(struct fuse_args *args); + + +/** + * Check if an option matches + * + * @param opts is the option description array + * @param opt is the option to match + * @return 1 if a match is found, 0 if not + */ +int fuse_opt_match(const struct fuse_opt opts[], const char *opt); + +#ifdef __cplusplus +} +#endif + +#endif /* _FUSE_OPT_H_ */ diff --git a/itemz-daemon/include/fuse/old/fuse.h b/itemz-daemon/include/fuse/old/fuse.h new file mode 100644 index 0000000..3db0945 --- /dev/null +++ b/itemz-daemon/include/fuse/old/fuse.h @@ -0,0 +1,9 @@ +/* + This header is for compatibility with older software using FUSE. + + Please use 'pkg-config --cflags fuse' to set include path. The + correct usage is still '#include ', not '#include + '. +*/ + +#include "fuse/fuse.h" diff --git a/itemz-daemon/include/fuse/ulockmgr.h b/itemz-daemon/include/fuse/ulockmgr.h new file mode 100644 index 0000000..ad55579 --- /dev/null +++ b/itemz-daemon/include/fuse/ulockmgr.h @@ -0,0 +1,24 @@ +/* + libulockmgr: Userspace Lock Manager Library + Copyright (C) 2006 Miklos Szeredi + + This program can be distributed under the terms of the GNU LGPLv2. + See the file COPYING.LIB. +*/ + +#include +#include +#include + +/** + * Perform POSIX locking operation + * + * @param fd the file descriptor + * @param cmd the locking command (F_GETFL, F_SETLK or F_SETLKW) + * @param lock the lock parameters + * @param owner the lock owner ID cookie + * @param owner_len length of the lock owner ID cookie + * @return 0 on success -errno on error + */ +int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner, + size_t owner_len); diff --git a/itemz-daemon/include/jsmn.h b/itemz-daemon/include/jsmn.h new file mode 100644 index 0000000..a2a0b6c --- /dev/null +++ b/itemz-daemon/include/jsmn.h @@ -0,0 +1,468 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif +#define JSMN_STATIC 1 +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/itemz-daemon/include/log.h b/itemz-daemon/include/log.h new file mode 100644 index 0000000..99d9e52 --- /dev/null +++ b/itemz-daemon/include/log.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2020 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See `log.c` for details. + */ + +#ifndef LOG_H +#define LOG_H + +#include +#include +#include +#include + +#define LOG_VERSION "0.1.0" + +typedef struct { + va_list ap; + const char* fmt; + const char* file; + struct tm* time; + void* udata; + int line; + int level; +} log_Event; + +typedef void (*log_LogFn)(log_Event* ev); +typedef void (*log_LockFn)(bool lock, void* udata); + +enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL }; + +#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) +#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define log_info(...) log_log(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define log_warn(...) log_log(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) +#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) +#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) + +const char* log_level_string(int level); +void log_set_lock(log_LockFn fn, void* udata); +void log_set_level(int level); +void log_set_quiet(bool enable); +int log_add_callback(log_LogFn fn, void* udata, int level); +int log_add_fp(FILE* fp, int level); + +void log_log(int level, const char* file, int line, const char* fmt, ...); + +#endif \ No newline at end of file diff --git a/itemz-daemon/include/md5.h b/itemz-daemon/include/md5.h new file mode 100644 index 0000000..3c3b3bb --- /dev/null +++ b/itemz-daemon/include/md5.h @@ -0,0 +1,50 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * See md5.c for more information. + */ + +#ifdef HAVE_OPENSSL +#include +#elif !defined(_MD5_H) +#define _MD5_H + +/* Any 32-bit or wider unsigned integer data type will do */ +typedef unsigned int MD5_u32plus; + +#define DIFFERENT_HASH true +#define SAME_HASH false + +#define MD5_HASH_LENGTH (16) + +typedef struct { + MD5_u32plus lo, hi; + MD5_u32plus a, b, c, d; + unsigned char buffer[64]; + MD5_u32plus block[16]; +} MD5_CTX; + +extern void MD5_Init(MD5_CTX *ctx); +extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); +extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); + +#endif diff --git a/itemz-daemon/include/net.h b/itemz-daemon/include/net.h new file mode 100644 index 0000000..712d567 --- /dev/null +++ b/itemz-daemon/include/net.h @@ -0,0 +1,836 @@ +#ifndef _SCE_SSL_H_ +#define _SCE_SSL_H_ + +#pragma once +#include +#include "defines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ORBIS_NET_CTL_INFO_DEVICE 1 +#define ORBIS_NET_CTL_INFO_ETHER_ADDR 2 +#define ORBIS_NET_CTL_INFO_MTU 3 +#define ORBIS_NET_CTL_INFO_LINK 4 +#define ORBIS_NET_CTL_INFO_BSSID 5 +#define ORBIS_NET_CTL_INFO_SSID 6 +#define ORBIS_NET_CTL_INFO_WIFI_SECURITY 7 +#define ORBIS_NET_CTL_INFO_RSSI_DBM 8 +#define ORBIS_NET_CTL_INFO_RSSI_PERCENTAGE 9 +#define ORBIS_NET_CTL_INFO_CHANNEL 10 +#define ORBIS_NET_CTL_INFO_IP_CONFIG 11 +#define ORBIS_NET_CTL_INFO_DHCP_HOSTNAME 12 +#define ORBIS_NET_CTL_INFO_PPPOE_AUTH_NAME 13 +#define ORBIS_NET_CTL_INFO_IP_ADDRESS 14 +#define ORBIS_NET_CTL_INFO_NETMASK 15 +#define ORBIS_NET_CTL_INFO_DEFAULT_ROUTE 16 +#define ORBIS_NET_CTL_INFO_PRIMARY_DNS 17 +#define ORBIS_NET_CTL_INFO_SECONDARY_DNS 18 +#define ORBIS_NET_CTL_INFO_HTTP_PROXY_CONFIG 19 +#define ORBIS_NET_CTL_INFO_HTTP_PROXY_SERVER 20 +#define ORBIS_NET_CTL_INFO_HTTP_PROXY_PORT 21 +#define ORBIS_NET_CTL_INFO_RESERVED1 22 +#define ORBIS_NET_CTL_INFO_RESERVED2 23 + +typedef union OrbisNetCtlInfo { + uint32_t device; + char ether_addr[6]; + uint32_t mtu; + uint32_t link; + char bssid[6]; + char ssid[33]; + uint32_t wifi_security; + uint8_t rssi_dbm; + uint8_t rssi_percentage; + uint8_t channel; + uint32_t ip_config; + char dhcp_hostname[256]; + char pppoe_auth_name[128]; + char ip_address[16]; + char netmask[16]; + char default_route[16]; + char primary_dns[16]; + char secondary_dns[16]; + uint32_t http_proxy_config; + char http_proxy_server[256]; + uint16_t http_proxy_port; +} OrbisNetCtlInfo; + +int sceNetCtlGetInfo(int, void *); +int sceNetCtlInit(); + +// Empty Comment +void CA_MGMT_allocCertDistinguishedName(); +// Empty Comment +void CA_MGMT_certDistinguishedNameCompare(); +// Empty Comment +void CA_MGMT_convertKeyBlobToPKCS8Key(); +// Empty Comment +void CA_MGMT_convertKeyDER(); +// Empty Comment +void CA_MGMT_convertKeyPEM(); +// Empty Comment +void CA_MGMT_convertPKCS8KeyToKeyBlob(); +// Empty Comment +void CA_MGMT_convertProtectedPKCS8KeyToKeyBlob(); +// Empty Comment +void CA_MGMT_decodeCertificate(); +// Empty Comment +void CA_MGMT_enumAltName(); +// Empty Comment +void CA_MGMT_enumCrl(); +// Empty Comment +void CA_MGMT_extractAllCertDistinguishedName(); +// Empty Comment +void CA_MGMT_extractBasicConstraint(); +// Empty Comment +void CA_MGMT_extractCertASN1Name(); +// Empty Comment +void CA_MGMT_extractCertTimes(); +// Empty Comment +void CA_MGMT_extractKeyBlobEx(); +// Empty Comment +void CA_MGMT_extractKeyBlobTypeEx(); +// Empty Comment +void CA_MGMT_extractPublicKeyInfo(); +// Empty Comment +void CA_MGMT_extractSerialNum(); +// Empty Comment +void CA_MGMT_extractSignature(); +// Empty Comment +void CA_MGMT_free(); +// Empty Comment +void CA_MGMT_freeCertDistinguishedName(); +// Empty Comment +void CA_MGMT_freeCertDistinguishedNameOnStack(); +// Empty Comment +void CA_MGMT_freeCertificate(); +// Empty Comment +void CA_MGMT_freeKeyBlob(); +// Empty Comment +void CA_MGMT_freeSearchDetails(); +// Empty Comment +void CA_MGMT_getCertSignAlgoType(); +// Empty Comment +void CA_MGMT_keyBlobToDER(); +// Empty Comment +void CA_MGMT_keyBlobToPEM(); +// Empty Comment +void CA_MGMT_makeKeyBlobEx(); +// Empty Comment +void CA_MGMT_rawVerifyOID(); +// Empty Comment +void CA_MGMT_reorderChain(); +// Empty Comment +void CA_MGMT_returnCertificatePrints(); +// Empty Comment +void CA_MGMT_verifyCertWithKeyBlob(); +// Empty Comment +void CA_MGMT_verifySignature(); +// Empty Comment +void CERT_checkCertificateIssuer(); +// Empty Comment +void CERT_checkCertificateIssuer2(); +// Empty Comment +void CERT_checkCertificateIssuerSerialNumber(); +// Empty Comment +void CERT_CompSubjectAltNames(); +// Empty Comment +void CERT_CompSubjectAltNames2(); +// Empty Comment +void CERT_CompSubjectAltNamesExact(); +// Empty Comment +void CERT_CompSubjectCommonName(); +// Empty Comment +void CERT_CompSubjectCommonName2(); +// Empty Comment +void CERT_ComputeBufferHash(); +// Empty Comment +void CERT_decryptRSASignature(); +// Empty Comment +void CERT_decryptRSASignatureBuffer(); +// Empty Comment +void CERT_enumerateAltName(); +// Empty Comment +void CERT_enumerateAltName2(); +// Empty Comment +void CERT_enumerateCRL(); +// Empty Comment +void CERT_enumerateCRL2(); +// Empty Comment +void CERT_enumerateCRLAux(); +// Empty Comment +void CERT_extractAllDistinguishedNames(); +// Empty Comment +void CERT_extractDistinguishedNames(); +// Empty Comment +void CERT_extractDistinguishedNames2(); +// Empty Comment +void CERT_extractDistinguishedNamesFromName(); +// Empty Comment +void CERT_extractRSAKey(); +// Empty Comment +void CERT_extractSerialNum(); +// Empty Comment +void CERT_extractSerialNum2(); +// Empty Comment +void CERT_extractValidityTime(); +// Empty Comment +void CERT_extractValidityTime2(); +// Empty Comment +void CERT_getCertExtension(); +// Empty Comment +void CERT_getCertificateExtensions(); +// Empty Comment +void CERT_getCertificateExtensions2(); +// Empty Comment +void CERT_getCertificateIssuerSerialNumber(); +// Empty Comment +void CERT_getCertificateIssuerSerialNumber2(); +// Empty Comment +void CERT_getCertificateKeyUsage(); +// Empty Comment +void CERT_getCertificateKeyUsage2(); +// Empty Comment +void CERT_getCertificateSubject(); +// Empty Comment +void CERT_getCertificateSubject2(); +// Empty Comment +void CERT_getCertSignAlgoType(); +// Empty Comment +void CERT_GetCertTime(); +// Empty Comment +void CERT_getNumberOfChild(); +// Empty Comment +void CERT_getRSASignatureAlgo(); +// Empty Comment +void CERT_getSignatureItem(); +// Empty Comment +void CERT_getSubjectCommonName(); +// Empty Comment +void CERT_getSubjectCommonName2(); +// Empty Comment +void CERT_isRootCertificate(); +// Empty Comment +void CERT_isRootCertificate2(); +// Empty Comment +void CERT_rawVerifyOID(); +// Empty Comment +void CERT_rawVerifyOID2(); +// Empty Comment +void CERT_setKeyFromSubjectPublicKeyInfo(); +// Empty Comment +void CERT_setKeyFromSubjectPublicKeyInfoCert(); +// Empty Comment +void CERT_STORE_addCertAuthority(); +// Empty Comment +void CERT_STORE_addIdentity(); +// Empty Comment +void CERT_STORE_addIdentityNakedKey(); +// Empty Comment +void CERT_STORE_addIdentityPSK(); +// Empty Comment +void CERT_STORE_addIdentityWithCertificateChain(); +// Empty Comment +void CERT_STORE_addTrustPoint(); +// Empty Comment +void CERT_STORE_createStore(); +// Empty Comment +void CERT_STORE_findCertBySubject(); +// Empty Comment +void CERT_STORE_findIdentityByTypeFirst(); +// Empty Comment +void CERT_STORE_findIdentityByTypeNext(); +// Empty Comment +void CERT_STORE_findIdentityCertChainFirst(); +// Empty Comment +void CERT_STORE_findIdentityCertChainNext(); +// Empty Comment +void CERT_STORE_findPskByIdentity(); +// Empty Comment +void CERT_STORE_releaseStore(); +// Empty Comment +void CERT_STORE_traversePskListHead(); +// Empty Comment +void CERT_STORE_traversePskListNext(); +// Empty Comment +void CERT_validateCertificate(); +// Empty Comment +void CERT_validateCertificateWithConf(); +// Empty Comment +void CERT_VerifyCertificatePolicies(); +// Empty Comment +void CERT_VerifyCertificatePolicies2(); +// Empty Comment +void CERT_verifySignature(); +// Empty Comment +void CERT_VerifyValidityTime(); +// Empty Comment +void CERT_VerifyValidityTime2(); +// Empty Comment +void CERT_VerifyValidityTimeWithConf(); +// Empty Comment +void CRYPTO_initAsymmetricKey(); +// Empty Comment +void CRYPTO_uninitAsymmetricKey(); +// Empty Comment +void GC_createInstanceIDs(); +// Empty Comment +void getCertSigAlgo(); +// Empty Comment +void MOCANA_freeMocana(); +// Empty Comment +void MOCANA_initMocana(); +// Empty Comment +void RSA_verifySignature(); +// Empty Comment +void sceSslClose(); +// Empty Comment +void sceSslConnect(); +// Empty Comment +void sceSslCreateSslConnection(); +// Empty Comment +void sceSslDeleteSslConnection(); +// Empty Comment +void sceSslDisableOption(); +// Empty Comment +void sceSslDisableOptionInternal(); +// Empty Comment +void sceSslDisableOptionInternalInsecure(); +// Empty Comment +void sceSslEnableOption(); +// Empty Comment +void sceSslEnableOptionInternal(); +// Empty Comment +void sceSslFreeCaCerts(); +// Empty Comment +void sceSslFreeCaList(); +// Empty Comment +void sceSslFreeSslCertName(); +// Empty Comment +void sceSslGetCaCerts(); +// Empty Comment +void sceSslGetCaList(); +// Empty Comment +void sceSslGetIssuerName(); +// Empty Comment +void sceSslGetMemoryPoolStats(); +// Empty Comment +void sceSslGetNameEntryCount(); +// Empty Comment +void sceSslGetNameEntryInfo(); +// Empty Comment +void sceSslGetNanoSSLModuleId(); +// Empty Comment +void sceSslGetNotAfter(); +// Empty Comment +void sceSslGetNotBefore(); +// Empty Comment +void sceSslGetSerialNumber(); +// Empty Comment +void sceSslGetSslError(); +// Empty Comment +void sceSslGetSubjectName(); +// Empty Comment +int sceSslInit(size_t poolSize); +// Empty Comment +void sceSslLoadCert(); +// Empty Comment +void sceSslLoadRootCACert(); +// Empty Comment +void sceSslRecv(); +// Empty Comment +void sceSslSend(); +// Empty Comment +void sceSslSetSslVersion(); +// Empty Comment +void sceSslSetVerifyCallback(); +// Empty Comment +void sceSslShowMemoryStat(); +// Empty Comment +int sceSslTerm(); +// Empty Comment +void sceSslUnloadCert(); +// Empty Comment +void SSL_acceptConnection(); +// Empty Comment +void SSL_acceptConnectionCommon(); +// Empty Comment +void SSL_assignCertificateStore(); +// Empty Comment +void SSL_ASYNC_acceptConnection(); +// Empty Comment +void SSL_ASYNC_closeConnection(); +// Empty Comment +void SSL_ASYNC_connect(); +// Empty Comment +void SSL_ASYNC_connectCommon(); +// Empty Comment +void SSL_ASYNC_getRecvBuffer(); +// Empty Comment +void SSL_ASYNC_getSendBuffer(); +// Empty Comment +void SSL_ASYNC_init(); +// Empty Comment +void SSL_ASYNC_initServer(); +// Empty Comment +void SSL_ASYNC_recvMessage(); +// Empty Comment +void SSL_ASYNC_recvMessage2(); +// Empty Comment +void SSL_ASYNC_sendMessage(); +// Empty Comment +void SSL_ASYNC_sendMessagePending(); +// Empty Comment +void SSL_ASYNC_start(); +// Empty Comment +void SSL_closeConnection(); +// Empty Comment +void SSL_connect(); +// Empty Comment +void SSL_connectWithCfgParam(); +// Empty Comment +void SSL_enableCiphers(); +// Empty Comment +void SSL_findConnectionInstance(); +// Empty Comment +void SSL_getCipherInfo(); +// Empty Comment +void SSL_getClientRandom(); +// Empty Comment +void SSL_getClientSessionInfo(); +// Empty Comment +void SSL_getCookie(); +// Empty Comment +void SSL_getInstanceFromSocket(); +// Empty Comment +void SSL_getNextSessionId(); +// Empty Comment +void SSL_getServerRandom(); +// Empty Comment +void SSL_getSessionCache(); +// Empty Comment +void SSL_getSessionFlags(); +// Empty Comment +void SSL_getSessionInfo(); +// Empty Comment +void SSL_getSessionStatus(); +// Empty Comment +void SSL_getSocketId(); +// Empty Comment +void SSL_getSSLTLSVersion(); +// Empty Comment +void SSL_init(); +// Empty Comment +void SSL_initiateRehandshake(); +// Empty Comment +void SSL_initServerCert(); +// Empty Comment +void SSL_ioctl(); +// Empty Comment +void SSL_isSessionSSL(); +// Empty Comment +void SSL_lockSessionCacheMutex(); +// Empty Comment +void SSL_lookupAlert(); +// Empty Comment +void SSL_negotiateConnection(); +// Empty Comment +void SSL_recv(); +// Empty Comment +void SSL_recvPending(); +// Empty Comment +void SSL_releaseTables(); +// Empty Comment +void SSL_retrieveServerNameList(); +// Empty Comment +void SSL_rngFun(); +// Empty Comment +void SSL_send(); +// Empty Comment +void SSL_sendAlert(); +// Empty Comment +void SSL_sendPending(); +// Empty Comment +void SSL_setCookie(); +// Empty Comment +void SSL_setServerCert(); +// Empty Comment +void SSL_setServerNameList(); +// Empty Comment +void SSL_setSessionFlags(); +// Empty Comment +void SSL_shutdown(); +// Empty Comment +void SSL_sslSettings(); +// Empty Comment +void SSL_validateCertParam(); +// Empty Comment +void VLONG_freeVlongQueue(); + + +typedef void* OrbisHttpEpollHandle; + +#define ORBIS_HTTP_NB_EVENT_IN 0x00000001 +#define ORBIS_HTTP_NB_EVENT_OUT 0x00000002 +#define ORBIS_HTTP_NB_EVENT_SOCK_ERR 0x00000008 +#define ORBIS_HTTP_NB_EVENT_HUP 0x00000010 +#define ORBIS_HTTP_NB_EVENT_ICM 0x00000020 +#define ORBIS_HTTP_NB_EVENT_RESOLVED 0x00010000 +#define ORBIS_HTTP_NB_EVENT_RESOLVER_ERR 0x00020000 + +typedef struct OrbisHttpNBEvent { + uint32_t events; + uint32_t eventDetail; + int id; + void* userArg; +} OrbisHttpNBEvent; + + +#define ORBIS_HTTP_DEFAULT_RESOLVER_TIMEOUT (0) // libnet default +#define ORBIS_HTTP_DEFAULT_RESOLVER_RETRY (0) // libnet default +#define ORBIS_HTTP_DEFAULT_CONNECT_TIMEOUT (30* 1000 * 1000U) +#define ORBIS_HTTP_DEFAULT_SEND_TIMEOUT (120* 1000 * 1000U) +#define ORBIS_HTTP_DEFAULT_RECV_TIMEOUT (120* 1000 * 1000U) +#define ORBIS_HTTP_DEFAULT_RECV_BLOCK_SIZE (1500U) +#define ORBIS_HTTP_DEFAULT_RESPONSE_HEADER_MAX (5000U) +#define ORBIS_HTTP_DEFAULT_REDIRECT_MAX (6U) +#define ORBIS_HTTP_DEFAULT_TRY_AUTH_MAX (6U) + +#define ORBIS_HTTP_TRUE (int)(1) +#define ORBIS_HTTP_FALSE (int)(0) + +#define ORBIS_HTTP_ENABLE ORBIS_HTTP_TRUE +#define ORBIS_HTTP_DISABLE ORBIS_HTTP_FALSE + +#define ORBIS_HTTP_USERNAME_MAX_SIZE 256 +#define ORBIS_HTTP_PASSWORD_MAX_SIZE 256 + + +#define ORBIS_HTTP_TRUE (int)(1) +#define ORBIS_HTTP_FALSE (int)(0) + +#define ORBIS_HTTP_ENABLE ORBIS_HTTP_TRUE +#define ORBIS_HTTP_DISABLE ORBIS_HTTP_FALSE + +#define ORBIS_HTTP_USERNAME_MAX_SIZE 256 +#define ORBIS_HTTP_PASSWORD_MAX_SIZE 256 + + +typedef enum{ + ORBIS_HTTP_VERSION_1_0=1, + ORBIS_HTTP_VERSION_1_1 +} OrbisHttpHttpVersion; + +typedef enum{ + ORBIS_HTTP_PROXY_AUTO, + ORBIS_HTTP_PROXY_MANUAL +} OrbisHttpProxyMode; + +typedef enum{ + ORBIS_HTTP_HEADER_OVERWRITE, + ORBIS_HTTP_HEADER_ADD +} OrbisHttpAddHeaderMode; + +typedef enum{ + ORBIS_HTTP_AUTH_BASIC, + ORBIS_HTTP_AUTH_DIGEST, + ORBIS_HTTP_AUTH_RESERVED0, + ORBIS_HTTP_AUTH_RESERVED1, + ORBIS_HTTP_AUTH_RESERVED2 +} OrbisHttpAuthType; + +typedef enum { + ORBIS_HTTP_CONTENTLEN_EXIST, + ORBIS_HTTP_CONTENTLEN_NOT_FOUND, + ORBIS_HTTP_CONTENTLEN_CHUNK_ENC +} OrbisHttpContentLengthType; + +typedef enum { + ORBIS_HTTP_REQUEST_STATUS_CONNECTION_RESERVED, + ORBIS_HTTP_REQUEST_STATUS_RESOLVING_NAME, + ORBIS_HTTP_REQUEST_STATUS_NAME_RESOLVED, + ORBIS_HTTP_REQUEST_STATUS_CONNECTING, + ORBIS_HTTP_REQUEST_STATUS_CONNECTED, + ORBIS_HTTP_REQUEST_STATUS_TLS_CONNECTING, + ORBIS_HTTP_REQUEST_STATUS_TLS_CONNECTED, + ORBIS_HTTP_REQUEST_STATUS_SENDING_REQUEST, + ORBIS_HTTP_REQUEST_STATUS_REQUEST_SENT, + ORBIS_HTTP_REQUEST_STATUS_RECEIVING_HEADER, + ORBIS_HTTP_REQUEST_STATUS_HEADER_RECEIVED, +} OrbisHttpRequestStatus; + + +#define ORBIS_HTTP_INVALID_ID 0 + + +typedef int (*OrbisHttpAuthInfoCallback)( + int request, + OrbisHttpAuthType authType, + const char *realm, + char *username, + char *password, + int isNeedEntity, + uint8_t **entityBody, + size_t *entitySize, + int *isSave, + void *userArg); + +typedef int (*OrbisHttpRedirectCallback)( + int request, + int32_t statusCode, + int32_t *method, + const char *location, + void *userArg); + +typedef void (*OrbisHttpRequestStatusCallback)( + int request, + OrbisHttpRequestStatus requestStatus, + void *userArg); + +typedef struct OrbisHttpMemoryPoolStats{ + size_t poolSize; + size_t maxInuseSize; + size_t currentInuseSize; + int32_t reserved; +} OrbisHttpMemoryPoolStats; + + + +// Empty Comment +int sceHttpAbortRequest(int reqId); +// Empty Comment +void sceHttpAbortRequestForce(); +// Empty Comment +int sceHttpAbortWaitRequest(OrbisHttpEpollHandle eh); +// Empty Comment +void sceHttpAddCookie(); +// Empty Comment +int sceHttpAddRequestHeader(int id, const char *name, const char *value, uint32_t mode); +// Empty Comment +void sceHttpAddRequestHeaderRaw(); +// Empty Comment +void sceHttpAuthCacheExport(); +// Empty Comment +int sceHttpAuthCacheFlush(int libhttpCtxId); +// Empty Comment +void sceHttpAuthCacheImport(); +// Empty Comment +void sceHttpCookieExport(); +// Empty Comment +void sceHttpCookieFlush(); +// Empty Comment +void sceHttpCookieImport(); +// Empty Comment +int sceHttpCreateConnection(int tmplId, const char *serverName, const char *scheme, uint16_t port, int isEnableKeepalive); +// Empty Comment +int sceHttpCreateConnectionWithURL(int tmplId, const char *url, int isEnableKeepalive); +// Empty Comment +int sceHttpCreateEpoll(int libhttpCtxId, OrbisHttpEpollHandle* eh); +// Empty Comment +int sceHttpCreateRequest(int connId, int method, const char *path, uint64_t contentLength); +// Empty Comment +int sceHttpCreateRequest2(int connId, const char* method, const char *path, uint64_t contentLength); +// Empty Comment +int sceHttpCreateRequestWithURL(int connId, int method, const char *url, uint64_t contentLength); +// Empty Comment +int sceHttpCreateRequestWithURL2(int connId, const char* method, const char *url, uint64_t contentLength); +// Empty Comment +int sceHttpCreateTemplate(int libhttpCtxId, const char *userAgent, int httpVer, int isAutoProxyConf); +// Empty Comment +void sceHttpDbgGetConnectionStat(); +// Empty Comment +void sceHttpDbgGetRequestStat(); +// Empty Comment +void sceHttpDbgSetPrintf(); +// Empty Comment +void sceHttpDbgShowConnectionStat(); +// Empty Comment +void sceHttpDbgShowMemoryPoolStat(); +// Empty Comment +void sceHttpDbgShowRequestStat(); +// Empty Comment +void sceHttpDbgShowStat(); +// Empty Comment +int sceHttpDeleteConnection(int connId); +// Empty Comment +int sceHttpDeleteRequest(int reqId); +// Empty Comment +int sceHttpDeleteTemplate(int tmplId); +// Empty Comment +int sceHttpDestroyEpoll(int libhttpCtxId, OrbisHttpEpollHandle eh); +// Empty Comment +void sceHttpGetAcceptEncodingGZIPEnabled(); +// Empty Comment +int sceHttpGetAllResponseHeaders(int reqId, char **header, size_t *headerSize); +// Empty Comment +int sceHttpGetAuthEnabled(int id, int *isEnable); +// Empty Comment +int sceHttpGetAutoRedirect(int id, int *isEnable); +// Empty Comment +void sceHttpGetCookie(); +// Empty Comment +void sceHttpGetCookieEnabled(); +// Empty Comment +void sceHttpGetCookieStats(); +// Empty Comment +int sceHttpGetEpoll(int id, OrbisHttpEpollHandle* eh, void **userArg); +// Empty Comment +void sceHttpGetEpollId(); +// Empty Comment +int sceHttpGetLastErrno(int reqId, int* errNum); +// Empty Comment +int sceHttpGetMemoryPoolStats(int libhttpCtxId, OrbisHttpMemoryPoolStats* currentStat); +// Empty Comment +int sceHttpGetNonblock(int id, int *isEnable); +// Empty Comment +int sceHttpGetResponseContentLength(int reqId, int* result, uint64_t *contentLength); +// Empty Comment +int sceHttpGetStatusCode(int reqId, int *statusCode); +// Empty Comment +int sceHttpInit(int libnetMemId, int libsslCtxId, size_t poolSize); +// Empty Comment +int sceHttpParseResponseHeader(const char *header, size_t headerLen, const char *fieldStr, const char **fieldValue, size_t *valueLen); +// Empty Comment +int sceHttpParseStatusLine(const char *statusLine, size_t lineLen, int *httpMajorVer, int *httpMinorVer, int *responseCode, const char **reasonPhras); +// Empty Comment +int sceHttpReadData(int reqId, void *data, size_t size); +// Empty Comment +int sceHttpRedirectCacheFlush(int libhttpCtxId); +// Empty Comment +int sceHttpRemoveRequestHeader(int id, const char *name); +// Empty Comment +void sceHttpRequestGetAllHeaders(); +// Empty Comment +void sceHttpsDisableOption(); +// Empty Comment +void sceHttpsDisableOptionPrivate(); +// Empty Comment +void sceHttpsEnableOption(); +// Empty Comment +void sceHttpsEnableOptionPrivate(); +// Empty Comment +int sceHttpSendRequest(int reqId, const void *postData, size_t size); +// Empty Comment +void sceHttpSetAcceptEncodingGZIPEnabled(); +// Empty Comment +int sceHttpSetAuthEnabled(int id, int isEnable); +// Empty Comment +int sceHttpSetAuthInfoCallback(int id, OrbisHttpAuthInfoCallback cbfunc, void *userArg); +// Empty Comment +int sceHttpSetAutoRedirect(int id, int isEnable); +// Empty Comment +int sceHttpSetChunkedTransferEnabled(int id, int isEnable); +// Empty Comment +int sceHttpSetConnectTimeOut(int id, uint32_t usec); +// Empty Comment +void sceHttpSetCookieEnabled(); +// Empty Comment +void sceHttpSetCookieMaxNum(); +// Empty Comment +void sceHttpSetCookieMaxNumPerDomain(); +// Empty Comment +void sceHttpSetCookieMaxSize(); +// Empty Comment +void sceHttpSetCookieRecvCallback(); +// Empty Comment +void sceHttpSetCookieSendCallback(); +// Empty Comment +void sceHttpSetCookieTotalMaxSize(); +// Empty Comment +void sceHttpSetDefaultAcceptEncodingGZIPEnabled(); +// Empty Comment +void sceHttpSetEpoll(); +// Empty Comment +void sceHttpSetEpollId(); +// Empty Comment +int sceHttpSetInflateGZIPEnabled(int id, int isEnable); +// Empty Comment +int sceHttpSetNonblock(int id, int isEnable); +// Empty Comment +void sceHttpSetPolicyOption(); +// Empty Comment +void sceHttpSetPriorityOption(); +// Empty Comment +void sceHttpSetProxy(); +// Empty Comment +void sceHttpSetRecvBlockSize(); +// Empty Comment +int sceHttpSetRecvTimeOut(int id, uint32_t usec); +// Empty Comment +int sceHttpSetRedirectCallback(int id, OrbisHttpRedirectCallback cbfunc, void *userArg); +// Empty Comment +int sceHttpSetRequestContentLength(int id, uint64_t contentLength); +// Empty Comment +int sceHttpSetResolveRetry(int id, int retry); +// Empty Comment +int sceHttpSetResolveTimeOut(int id, uint32_t usec); +// Empty Comment +int sceHttpSetResponseHeaderMaxSize(int id, size_t headerSize); +// Empty Comment +int sceHttpSetSendTimeOut(int id, uint32_t usec); +// Empty Comment +void sceHttpsFreeCaList(); +// Empty Comment +void sceHttpsGetCaList(); +// Empty Comment +void sceHttpsGetSslError(); +// Empty Comment +void sceHttpsLoadCert(); +typedef int (*HttpsCallback)(int libsslCtxId, unsigned int verifyErr, void* const sslCert[], int certNum, void* userArg); +int sceHttpsSetSslCallback(int id, HttpsCallback cbfunc, void* userArg); +// Empty Comment +void sceHttpsSetSslVersion(); +// Empty Comment +void sceHttpsUnloadCert(); +// Empty Comment +int sceHttpTerm(int libhttpCtxId); +// Empty Comment +int sceHttpTryGetNonblock(int id, int *isEnable); +// Empty Comment +int sceHttpTrySetNonblock(int id, int isEnable); +// Empty Comment +int sceHttpUnsetEpoll(int id); +// Empty Comment +void sceHttpUriBuild(); +// Empty Comment +void sceHttpUriCopy(); +// Empty Comment +void sceHttpUriEscape(); +// Empty Comment +void sceHttpUriMerge(); +// Empty Comment +void sceHttpUriParse(); +// Empty Comment +void sceHttpUriSweepPath(); +// Empty Comment +void sceHttpUriUnescape(); +// Empty Comment +int sceHttpWaitRequest(OrbisHttpEpollHandle eh, OrbisHttpNBEvent* nbev, int maxevents, int timeout); + +void sceNetCtlTerm(); + +int sceNetPoolCreate( + const char *name, + int size, + int flags +); +int sceNetInit(); + +#endif + + +struct sockaddr_in networkAdress(uint16_t port); +int networkListen(const char* soc_path); +int networkAccept(int socket); +int networkReceiveData(int socket, uint8_t* buffer, int32_t size); +int networkSendData(int socket, uint8_t* buffer, int32_t size); +int networkSendDebugData(uint8_t* buffer, int32_t size); +int networkCloseConnection(int socket); +int networkCloseDebugConnection(); + + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/itemz-daemon/include/utils.h b/itemz-daemon/include/utils.h new file mode 100644 index 0000000..e2f46d5 --- /dev/null +++ b/itemz-daemon/include/utils.h @@ -0,0 +1,331 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "defines.h" +#include "log.h" + +#define SYS_dynlib_get_info 593 +#define SYS_dynlib_get_info_ex 608 + +#define SYS_PROC_ALLOC 1 +#define SYS_PROC_FREE 2 +#define SYS_PROC_PROTECT 3 +#define SYS_PROC_VM_MAP 4 +#define SYS_PROC_INSTALL 5 +#define SYS_PROC_CALL 6 +#define SYS_PROC_ELF 7 +#define SYS_PROC_INFO 8 +#define SYS_PROC_THRINFO 9 + +#define SYS_CONSOLE_CMD_REBOOT 1 +#define SYS_CONSOLE_CMD_PRINT 2 +#define SYS_CONSOLE_CMD_JAILBREAK 3 +#define SYS_CONSOLE_CMD_ISLOADED 6 + +#define DIM(x) (sizeof(x)/sizeof(*(x))) +#define KB(x) ((size_t) (x) << 10) +#define MB(x) ((size_t) (x) << 20) + +#define STAT_DB "/data/itemzflow_daemon/stats.db" +#define DAEMON_LOG_PS4 "/data/itemzflow_daemon/daemon.log" +#define DAEMON_LOG_USB "/mnt/usb0/itemzflow/daemon.log" +bool touch_file(char* destfile); +enum IPC_Errors +{ + INVALID = -1, + NO_ERROR = 0, + OPERATION_FAILED = 1 +}; + +enum cmd +{ + SHUTDOWN_DAEMON = 0, + CONNECTION_TEST = 1, + ENABLE_HOME_REDIRECT = 2, + DISABLE_HOME_REDIRECT = 3, + GAME_GET_MINS = 4, + GAME_GET_START_TIME = 5, + CRITICAL_SUSPEND = 6, + INSTALL_IF_UPDATE = 7, + RESTART_FTP_SERVICE = 8, + DEAMON_UPDATE = 100 +}; + + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + + +struct clientArgs { + char* ip; + int socket; + int cl_nmb; +}; + +enum Flag +{ + Flag_None = 0, + SkipLaunchCheck = 1, + SkipResumeCheck = 1, + SkipSystemUpdateCheck = 2, + RebootPatchInstall = 4, + VRMode = 8, + NonVRMode = 16 +}; + +typedef struct _LncAppParam +{ + uint32_t sz; + uint32_t user_id; + uint32_t app_opt; + uint64_t crash_report; + enum Flag check_flag; +} +LncAppParam; + +typedef struct OrbisUserServiceLoginUserIdList { + int32_t userId[4]; +} OrbisUserServiceLoginUserIdList; + +typedef struct OrbisUserServiceInitializeParams { + int32_t priority; +} OrbisUserServiceInitializeParams; + +void* syscall1( + uint64_t number, + void* arg1 +); + +void* syscall2( + uint64_t number, + void* arg1, + void* arg2 +); + +void* syscall3( + uint64_t number, + void* arg1, + void* arg2, + void* arg3 +); + +void* syscall4( + uint64_t number, + void* arg1, + void* arg2, + void* arg3, + void* arg4 +); + +void* syscall5( + uint64_t number, + void* arg1, + void* arg2, + void* arg3, + void* arg4, + void* arg5 +); + +int64_t sys_dynlib_load_prx(char* prxPath, int* moduleID); +int64_t sys_dynlib_unload_prx(int64_t prxID); +int64_t sys_dynlib_dlsym(int64_t moduleHandle, const char* functionName, void* destFuncOffset); + +bool rejail(); +bool jailbreak(const char* prx_path); +bool full_init(); +bool isRestMode(); +bool IsOn(); +void notify(char* message); + +extern int DaemonSocket; + +#define networkSendMessage(socket, format, ...)\ +do {\ + char msgBuffer[512];\ + int msgSize = sprintf(msgBuffer, format, ##__VA_ARGS__);\ + sceNetSend(socket, msgBuffer, msgSize, 0);\ +} while(0) + +void handleIPC(struct clientArgs* client, uint8_t* buffer, uint32_t length); +void *IPC_loop(void* args); +void* ipc_client(void* args); +bool check_update_from_url(const char* url); +bool create_stat_db(const char* path); +bool open_stat_db(const char* path); +bool update_game_time_played(const char* tid); +int sceUserServiceGetForegroundUser(int *userid); +int32_t sceSystemServiceHideSplashScreen(); +uint32_t sceLncUtilLaunchApp(const char* tid, int opt, LncAppParam* param); +void print_memory(); +int sceSystemServiceLoadExec(const char* eboot, int idc); +const char* Language_GetName(int m_Code); +int sceSystemServiceGetAppIdOfMiniApp(); +int sceSystemServiceGetAppIdOfBigApp(); +int sceLncUtilGetAppId(const char* TID); +int sceLncUtilGetAppTitleId(int appid, char* tid_out); +int scePadSetProcessPrivilege(int privilege); // 0 = no privilege, 1 = privilege +int sceLncUtilInitialize(); +bool if_exists(const char* path); +int sceSystemServiceRegisterDaemon(); +void loadModulesVanilla(); +int backtrace(void** buffer, int size); +int pthread_getthreadid_np(); +int get_game_time_played(const char* tid); +time_t get_game_start_date(const char* tid); +void DumpHex(const void* data, size_t size); +uint32_t pkginstall(const char *path, bool is_if_update); + +#define SWAP32(x) \ + ((uint32_t)( \ + (((uint32_t)(x) & UINT32_C(0x000000FF)) << 24) | \ + (((uint32_t)(x) & UINT32_C(0x0000FF00)) << 8) | \ + (((uint32_t)(x) & UINT32_C(0x00FF0000)) >> 8) | \ + (((uint32_t)(x) & UINT32_C(0xFF000000)) >> 24) \ + )) + +#define BE32(x) SWAP32(x) + +struct _SceBgftDownloadRegisterErrorInfo { + /* TODO */ + uint8_t buf[0x100]; +}; + +enum bgft_task_option_t { + BGFT_TASK_OPTION_NONE = 0x0, + BGFT_TASK_OPTION_DELETE_AFTER_UPLOAD = 0x1, + BGFT_TASK_OPTION_INVISIBLE = 0x2, + BGFT_TASK_OPTION_ENABLE_PLAYGO = 0x4, + BGFT_TASK_OPTION_FORCE_UPDATE = 0x8, + BGFT_TASK_OPTION_REMOTE = 0x10, + BGFT_TASK_OPTION_COPY_CRASH_REPORT_FILES = 0x20, + BGFT_TASK_OPTION_DISABLE_INSERT_POPUP = 0x40, + BGFT_TASK_OPTION_DISABLE_CDN_QUERY_PARAM = 0x10000, +}; + +struct bgft_download_param { + int user_id; + int entitlement_type; + const char* id; + const char* content_url; + const char* content_ex_url; + const char* content_name; + const char* icon_path; + const char* sku_id; + enum bgft_task_option_t option; + const char* playgo_scenario_id; + const char* release_date; + const char* package_type; + const char* package_sub_type; + unsigned long package_size; +}; + + + +struct bgft_download_param_ex { + struct bgft_download_param param; + unsigned int slot; +}; + + + +struct bgft_task_progress_internal { + unsigned int bits; + int error_result; + unsigned long length; + unsigned long transferred; + unsigned long length_total; + unsigned long transferred_total; + unsigned int num_index; + unsigned int num_total; + unsigned int rest_sec; + unsigned int rest_sec_total; + int preparing_percent; + int local_copy_percent; +}; + + +struct bgft_init_params { + void *heap; + size_t heapSize; +}; + +struct bgft_download_task_progress_info { + unsigned int bits; + int error_result; + unsigned long length; + unsigned long transferred; + unsigned long length_total; + unsigned long transferred_total; + unsigned int num_index; + unsigned int num_total; + unsigned int rest_sec; + unsigned int rest_sec_total; + int preparing_percent; + int local_copy_percent; +}; + +struct _SceBgftTaskProgress { + unsigned int bits; + int error_result; + unsigned long length; + unsigned long transferred; + unsigned long lengthTotal; + unsigned long transferredTotal; + unsigned int numIndex; + unsigned int numTotal; + unsigned int restSec; + unsigned int restSecTotal; + int preparingPercent; + int localCopyPercent; +}; + +typedef struct _SceBgftTaskProgress SceBgftTaskProgress; +typedef int SceBgftTaskId; +#define SCE_BGFT_INVALID_TASK_ID (-1) + +bool app_inst_util_is_exists(const char* title_id, bool* exists); + +#if defined(__cplusplus) +extern "C" { +#endif +int sceBgftServiceDownloadStartTask(SceBgftTaskId taskId); +int sceBgftServiceDownloadStartTaskAll(void); +int sceBgftServiceDownloadPauseTask(SceBgftTaskId taskId); +int sceBgftServiceDownloadPauseTaskAll(void); +int sceBgftServiceDownloadResumeTask(SceBgftTaskId taskId); +int sceBgftServiceDownloadResumeTaskAll(void); +int sceBgftServiceDownloadStopTask(SceBgftTaskId taskId); +int sceBgftServiceDownloadStopTaskAll(void); +int sceAppInstUtilTerminate(); +int sceBgftServiceDownloadGetProgress(SceBgftTaskId taskId, SceBgftTaskProgress* progress); + + +int sceBgftFinalize(void); + +bool app_inst_util_init(void); +int sceAppInstUtilInitialize(void); +int sceAppInstUtilAppInstallPkg(const char* file_path, void* reserved); +int sceAppInstUtilGetTitleIdFromPkg(const char* pkg_path, char* title_id, int* is_app); +int sceAppInstUtilCheckAppSystemVer(const char* title_id, uint64_t buf, uint64_t bufs); +int sceAppInstUtilAppPrepareOverwritePkg(const char* pkg_path); +int sceAppInstUtilGetPrimaryAppSlot(const char* title_id, int* slot); +int sceAppInstUtilAppUnInstall(const char* title_id); +int sceAppInstUtilAppGetSize(const char* title_id, uint64_t* buf); +int sceBgftServiceInit(struct bgft_init_params* params); +int sceBgftServiceIntDownloadRegisterTaskByStorageEx(struct bgft_download_param_ex* params, int* task_id); +int sceBgftServiceDownloadStartTask(int task_id); +int sceBgftServiceTerm(void); +#if defined(__cplusplus) +} +#endif +bool copy_dir(const char* sourcedir,const char* destdir); +bool rmtree(const char path[]); +bool copyRegFile(const char* source, const char* dest); +void* initialize_userland_fuse(); +long CalcAppsize(char *path); \ No newline at end of file diff --git a/itemz-daemon/source/asm.s b/itemz-daemon/source/asm.s new file mode 100644 index 0000000..78cd9d5 --- /dev/null +++ b/itemz-daemon/source/asm.s @@ -0,0 +1,105 @@ +.intel_syntax noprefix +.text + +.global kernelRdmsr +.global cpu_enable_wp +.global cpu_disable_wp +.global call_not_RESOLVED_Exception + +kernelRdmsr: + mov ecx, edi + rdmsr + shl rdx, 32 + or rax, rdx + ret + +cpu_enable_wp: + mov rax, cr0 + or rax, 0x10000 + mov cr0, rax + ret + +cpu_disable_wp: + mov rax, cr0 + and rax, ~0x10000 + mov cr0, rax + ret + + .intel_syntax noprefix +.text + +.global syscall, syscall1, syscall2, syscall3, syscall4 ,Sysctl, Fork + + +Fork: + push rbp + mov rbp,rsp + + mov rax,2 + syscall + + leave + ret + +Sysctl: + push rbp + mov rbp,rsp + + mov rax,202 + mov r10, rcx + syscall + + leave + ret + + + +syscall: + mov rax,0 + mov r10,rcx + syscall + jb err + ret + +syscall1: + mov rax,rdi + mov rdi,rsi + syscall + ret + +syscall2: + mov rax,rdi + mov rdi,rsi + mov rsi,rdx + syscall + ret + +syscall3: + mov rax,rdi + mov rdi,rsi + mov rsi,rdx + mov rdx,rcx + syscall + ret + +syscall4: + mov rax,rdi + mov rdi,rsi + mov rsi,rdx + mov rdx,rcx + mov r10,r8 + syscall + ret + + +err: + push rax + call __error + pop rcx + mov [rax], ecx + mov rax,-1 + mov rdx,-1 + ret + + + diff --git a/itemz-daemon/source/ftp.c b/itemz-daemon/source/ftp.c new file mode 100644 index 0000000..358d820 --- /dev/null +++ b/itemz-daemon/source/ftp.c @@ -0,0 +1,1287 @@ +#include "ftp.h" +#include "defines.h" +#include +#include "net.h" +#include +#include +#include + +#define UNUSED(x) (void)(x) +#define NET_INIT_SIZE (64 * 1024) +#define DEFAULT_FILE_BUF_SIZE (4 * 1024 * 1024) + +#define FTP_DEFAULT_PATH "/" + +#define MAX_COMMANDS 32 +char ip_address[20]; + + +typedef struct SceNetEtherAddr { + uint8_t data[6]; +} SceNetEtherAddr; + +typedef union SceNetCtlInfo { + uint32_t device; + SceNetEtherAddr ether_addr; + uint32_t mtu; + uint32_t link; + SceNetEtherAddr bssid; + char ssid[33]; + uint32_t wifi_security; + int32_t rssi_dbm; + uint8_t rssi_percentage; + uint8_t channel; + uint32_t ip_config; + char dhcp_hostname[256]; + char pppoe_auth_name[128]; + char ip_address[16]; + char netmask[16]; + char default_route[16]; + char primary_dns[16]; + char secondary_dns[16]; + uint32_t http_proxy_config; + char http_proxy_server[256]; + uint16_t http_proxy_port; +} SceNetCtlInfo; + +static struct { + const char* cmd; + cmd_dispatch_func func; + int valid; +} command_dispatchers[MAX_COMMANDS]; + +static int ftp_initialized = 0; +static unsigned int file_buf_size; +static struct in_addr ps4_addr; +static unsigned short int ps4_port; +static ScePthread server_thid; +static int server_sockfd; +static int number_clients = 0; +static ftps4_client_info_t* client_list = NULL; +static ScePthreadMutex client_list_mtx; + +#define client_send_ctrl_msg(cl, str) \ + sceNetSend(cl->ctrl_sockfd, str, strlen(str), 0) + +static void cmd_installpkg_func(ftps4_client_info_t *client) +{ + int ret = -1; + client_send_ctrl_msg(client, "Installing PKG ..." FTPS4_EOL); + log_info("[FTP] Installing PKG ..."); + if((ret = pkginstall("/user/app/temp.pkg", false)) < 0){ + notify("[FTP] Failed to install PKG see log for error message"); + log_info("[FTP] Failed to install PKG with code: %i", ret); + client_send_ctrl_msg(client, "500 installpkg command failed!" FTPS4_EOL); + + } + else{ + log_info("[FTP] PKG installing"); + notify("[FTP] PKG is now installing ..."); + client_send_ctrl_msg(client, "200 installpkg command successful!" FTPS4_EOL); + + } +} +static inline void client_send_data_msg(ftps4_client_info_t* client, const char* str) +{ + if (client->data_con_type == FTP_DATA_CONNECTION_ACTIVE) { + sceNetSend(client->data_sockfd, str, strlen(str), 0); + } + else { + sceNetSend(client->pasv_sockfd, str, strlen(str), 0); + } +} + +static inline int client_recv_data_raw(ftps4_client_info_t* client, void* buf, unsigned int len) +{ + if (client->data_con_type == FTP_DATA_CONNECTION_ACTIVE) { + return sceNetRecv(client->data_sockfd, buf, len, 0); + } + else { + return sceNetRecv(client->pasv_sockfd, buf, len, 0); + } +} + +static inline void client_send_data_raw(ftps4_client_info_t* client, const void* buf, unsigned int len) +{ + if (client->data_con_type == FTP_DATA_CONNECTION_ACTIVE) { + sceNetSend(client->data_sockfd, buf, len, 0); + } + else { + sceNetSend(client->pasv_sockfd, buf, len, 0); + } +} + +static int file_exists(const char* path) +{ + struct stat s; + return (stat(path, &s) >= 0); +} + +static void cmd_NOOP_func(ftps4_client_info_t* client) +{ + client_send_ctrl_msg(client, "200 No operation ;)" FTPS4_EOL); +} + +static void cmd_USER_func(ftps4_client_info_t* client) +{ + client_send_ctrl_msg(client, "331 Username OK, need password b0ss." FTPS4_EOL); +} + +static void cmd_PASS_func(ftps4_client_info_t* client) +{ + client_send_ctrl_msg(client, "230 User logged in!" FTPS4_EOL); +} + +static void cmd_QUIT_func(ftps4_client_info_t* client) +{ + client_send_ctrl_msg(client, "221 Goodbye senpai :'(" FTPS4_EOL); +} + +static void cmd_SYST_func(ftps4_client_info_t* client) +{ + client_send_ctrl_msg(client, "215 UNIX Type: L8" FTPS4_EOL); +} + +static void cmd_PASV_func(ftps4_client_info_t* client) +{ + int ret; + UNUSED(ret); + + char cmd[512]; + unsigned int namelen; + struct sockaddr_in picked; + + /* Create data mode socket name */ + char data_socket_name[64]; + sprintf(data_socket_name, "FTPS4_client_%i_data_socket", + client->num); + + /* Create the data socket */ + client->data_sockfd = sceNetSocket(data_socket_name, + AF_INET, + SOCK_STREAM, + 0); + + log_debug("[FTP Module] PASV data socket fd: %d", client->data_sockfd); + + /* Fill the data socket address */ + client->data_sockaddr.sin_len = sizeof(client->data_sockaddr); + client->data_sockaddr.sin_family = AF_INET; + client->data_sockaddr.sin_addr.s_addr = sceNetHtonl(0); + /* Let the PS4 choose a port */ + client->data_sockaddr.sin_port = sceNetHtons(0); + + /* Bind the data socket address to the data socket */ + ret = sceNetBind(client->data_sockfd, + (struct sockaddr*)&client->data_sockaddr, + sizeof(client->data_sockaddr)); + log_debug("[FTP Module] sceNetBind(): 0x%08X", ret); + + /* Start listening */ + ret = sceNetListen(client->data_sockfd, 128); + log_debug("[FTP Module] sceNetListen(): 0x%08X", ret); + + /* Get the port that the PS4 has chosen */ + namelen = sizeof(picked); + sceNetGetsockname(client->data_sockfd, (struct sockaddr*)&picked, + &namelen); + + log_debug("[FTP Module] PASV mode port: 0x%04X", picked.sin_port); + + /* Build the command */ + sprintf(cmd, "227 Entering Passive Mode (%hhu,%hhu,%hhu,%hhu,%hhu,%hhu)" FTPS4_EOL, + (ps4_addr.s_addr >> 0) & 0xFF, + (ps4_addr.s_addr >> 8) & 0xFF, + (ps4_addr.s_addr >> 16) & 0xFF, + (ps4_addr.s_addr >> 24) & 0xFF, + (picked.sin_port >> 0) & 0xFF, + (picked.sin_port >> 8) & 0xFF); + + client_send_ctrl_msg(client, cmd); + + /* Set the data connection type to passive! */ + client->data_con_type = FTP_DATA_CONNECTION_PASSIVE; +} + +static void cmd_PORT_func(ftps4_client_info_t* client) +{ + unsigned char data_ip[4]; + unsigned char porthi, portlo; + unsigned short data_port; + char ip_str[16]; + struct in_addr data_addr; + int n; + + if (!client->recv_cmd_args) { + client_send_ctrl_msg(client, "500 Syntax error, command unrecognized." FTPS4_EOL); + return; + } + + n = sscanf(client->recv_cmd_args, "%hhu,%hhu,%hhu,%hhu,%hhu,%hhu", + &data_ip[0], &data_ip[1], &data_ip[2], &data_ip[3], + &porthi, &portlo); + if (n != 6) { + client_send_ctrl_msg(client, "500 Syntax error, command unrecognized." FTPS4_EOL); + return; + } + + data_port = portlo + porthi * 256; + + /* Convert to an X.X.X.X IP string */ + sprintf(ip_str, "%d.%d.%d.%d", + data_ip[0], data_ip[1], data_ip[2], data_ip[3]); + + /* Convert the IP to a struct in_addr */ + sceNetInetPton(AF_INET, ip_str, &data_addr); + + log_debug("[FTP Module] PORT connection to client's IP: %s Port: %d", ip_str, data_port); + + /* Create data mode socket name */ + char data_socket_name[64]; + sprintf(data_socket_name, "FTPS4_client_%i_data_socket", + client->num); + + /* Create data mode socket */ + client->data_sockfd = sceNetSocket(data_socket_name, + AF_INET, + SOCK_STREAM, + 0); + + log_debug("[FTP Module] Client %i data socket fd: %d", client->num, + client->data_sockfd); + + /* Prepare socket address for the data connection */ + client->data_sockaddr.sin_len = sizeof(client->data_sockaddr); + client->data_sockaddr.sin_family = AF_INET; + client->data_sockaddr.sin_addr = data_addr; + client->data_sockaddr.sin_port = sceNetHtons(data_port); + + /* Set the data connection type to active! */ + client->data_con_type = FTP_DATA_CONNECTION_ACTIVE; + + client_send_ctrl_msg(client, "200 PORT command successful!" FTPS4_EOL); +} + +static void client_open_data_connection(ftps4_client_info_t* client) +{ + int ret; + UNUSED(ret); + + unsigned int addrlen; + + if (client->data_con_type == FTP_DATA_CONNECTION_ACTIVE) { + /* Connect to the client using the data socket */ + ret = sceNetConnect(client->data_sockfd, + (struct sockaddr*)&client->data_sockaddr, + sizeof(client->data_sockaddr)); + + log_debug("[FTP Module] sceNetConnect(): 0x%08X", ret); + } + else { + /* Listen to the client using the data socket */ + addrlen = sizeof(client->pasv_sockaddr); + client->pasv_sockfd = sceNetAccept(client->data_sockfd, + (struct sockaddr*)&client->pasv_sockaddr, + &addrlen); + log_debug("[FTP Module] PASV client fd: 0x%08X", client->pasv_sockfd); + } +} + +static void client_close_data_connection(ftps4_client_info_t* client) +{ + sceNetSocketClose(client->data_sockfd); + /* In passive mode we have to close the client pasv socket too */ + if (client->data_con_type == FTP_DATA_CONNECTION_PASSIVE) { + sceNetSocketClose(client->pasv_sockfd); + } + client->data_con_type = FTP_DATA_CONNECTION_NONE; +} + +static char file_type_char(mode_t mode) +{ + return S_ISBLK(mode) ? 'b' : + S_ISCHR(mode) ? 'c' : + S_ISREG(mode) ? '-' : + S_ISDIR(mode) ? 'd' : + S_ISFIFO(mode) ? 'p' : + S_ISSOCK(mode) ? 's' : + S_ISLNK(mode) ? 'l' : ' '; +} + +static int gen_list_format(char* out, int n, mode_t file_mode, unsigned long long file_size, + const struct tm file_tm, const char* file_name, const char* link_name, const struct tm cur_tm) +{ + static const char num_to_month[][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + char yt[6]; + + if (cur_tm.tm_year == file_tm.tm_year) { + snprintf(yt, sizeof(yt), "%02d:%02d", file_tm.tm_hour, file_tm.tm_min); + } + else { + snprintf(yt, sizeof(yt), "%04d", 1900 + file_tm.tm_year); + } + +#define LIST_FMT "%c%c%c%c%c%c%c%c%c%c 1 ps4 ps4 %llu %s %2d %s %s" +#define LIST_ARGS \ + file_type_char(file_mode), \ + file_mode & 0400 ? 'r' : '-', \ + file_mode & 0200 ? 'w' : '-', \ + file_mode & 0100 ? (S_ISDIR(file_mode) ? 's' : 'x') : (S_ISDIR(file_mode) ? 'S' : '-'), \ + file_mode & 040 ? 'r' : '-', \ + file_mode & 020 ? 'w' : '-', \ + file_mode & 010 ? (S_ISDIR(file_mode) ? 's' : 'x') : (S_ISDIR(file_mode) ? 'S' : '-'), \ + file_mode & 04 ? 'r' : '-', \ + file_mode & 02 ? 'w' : '-', \ + file_mode & 01 ? (S_ISDIR(file_mode) ? 's' : 'x') : (S_ISDIR(file_mode) ? 'S' : '-'), \ + file_size, \ + num_to_month[file_tm.tm_mon%12], \ + file_tm.tm_mday, \ + yt, \ + file_name + + if (!S_ISLNK(file_mode) || link_name[0] == '\0') { + return snprintf(out, n, LIST_FMT FTPS4_EOL, LIST_ARGS); + } + else { + return snprintf(out, n, LIST_FMT " -> %s" FTPS4_EOL, LIST_ARGS, link_name); + } + +#undef LIST_ARGS +#undef LIST_FMT +} + +static void send_LIST(ftps4_client_info_t* client, const char* path) +{ + char buffer[512]; + uint8_t* dentbuf; + size_t dentbufsize; + int dfd, dentsize, err, readlinkerr; + struct dirent* dent, * dend; + struct stat st; + time_t cur_time; + struct tm tm, cur_tm; + + if (stat(path, &st) < 0) { + client_send_ctrl_msg(client, "550 Invalid directory." FTPS4_EOL); + return; + } + + dentbufsize = st.st_blksize; + log_debug("[FTP Module] dent buffer size = %lx", dentbufsize); + + dfd = open(path, O_RDONLY, 0); + if (dfd < 0) { + client_send_ctrl_msg(client, "550 Invalid directory." FTPS4_EOL); + return; + } + + dentbuf = (uint8_t*)malloc(dentbufsize); + memset(dentbuf, 0, dentbufsize); + + client_send_ctrl_msg(client, "150 Opening ASCII mode data transfer for LIST." FTPS4_EOL); + + client_open_data_connection(client); + + time(&cur_time); + gmtime_s(&cur_time, &cur_tm); + + while ((dentsize = getdents(dfd, (char*)dentbuf, dentbufsize)) > 0) { + dent = (struct dirent*)dentbuf; + dend = (struct dirent*)(&dentbuf[dentsize]); + + while (dent != dend) { + if (dent->d_name[0] != '\0') { + char full_path[PATH_MAX]; + snprintf(full_path, sizeof(full_path), "%s/%s", path, dent->d_name); + + err = stat(full_path, &st); + + if (err == 0) { + char link_path[PATH_MAX]; + if (S_ISLNK(st.st_mode)) { + if ((readlinkerr = readlink(full_path, link_path, sizeof(link_path))) > 0) { + link_path[readlinkerr] = 0; + } + else { + link_path[0] = 0; + } + } + + gmtime_s(&st.st_ctim.tv_sec, &tm); + gen_list_format(buffer, sizeof(buffer), + st.st_mode, + st.st_size, + tm, + dent->d_name, + S_ISLNK(st.st_mode) && link_path[0] != '\0' ? link_path : NULL, + cur_tm); + + client_send_data_msg(client, buffer); + memset(buffer, 0, sizeof(buffer)); + } + else { + log_debug("[FTP Module] %s stat returned %d", full_path, errno); + } + } + else { + log_debug("[FTP Module] got empty dent"); + } + dent = (struct dirent*)((void*)dent + dent->d_reclen); + } + memset(dentbuf, 0, dentbufsize); + } + + close(dfd); + free(dentbuf); + + log_debug("[FTP Module] Done sending LIST"); + + client_close_data_connection(client); + client_send_ctrl_msg(client, "226 Transfer complete." FTPS4_EOL); +} + +static void cmd_LIST_func(ftps4_client_info_t* client) +{ + char list_path[PATH_MAX]; + int list_cur_path = 1; + int n = !client->recv_cmd_args + ? 0 + : sscanf(client->recv_cmd_args, "%[^\r\n\t]", list_path); + + if (n > 0 && file_exists(list_path)) + list_cur_path = 0; + + if (list_cur_path) + send_LIST(client, client->cur_path); + else + send_LIST(client, list_path); +} + +static void cmd_NLST_func(ftps4_client_info_t* client) +{ + cmd_LIST_func(client); +} + +static void cmd_PWD_func(ftps4_client_info_t* client) +{ + char msg[PATH_MAX]; + snprintf(msg, sizeof(msg), "257 \"%s\" is the current directory." FTPS4_EOL, client->cur_path); + client_send_ctrl_msg(client, msg); +} + +static void dir_up(char* path) +{ + char* pch; + size_t len_in = strlen(path); + if (len_in == 1) { + root: + strcpy(path, "/"); + return; + } + pch = strrchr(path, '/'); + if (pch == path) + goto root; + *pch = '\0'; +} + +static void cmd_CWD_func(ftps4_client_info_t* client) +{ + char cmd_path[PATH_MAX]; + char tmp_path[PATH_MAX]; + int pd; + int n = !client->recv_cmd_args + ? 0 + : sscanf(client->recv_cmd_args, "%[^\r\n\t]", cmd_path); + + if (n < 1) { + client_send_ctrl_msg(client, "500 Syntax error, command unrecognized." FTPS4_EOL); + } + else { + if (strcmp(cmd_path, "/") == 0) { + strcpy(client->cur_path, cmd_path); + } + else if (strcmp(cmd_path, "..") == 0) { + dir_up(client->cur_path); + } + else { + if (cmd_path[0] == '/') { /* Full path */ + strcpy(tmp_path, cmd_path); + } + else { /* Change dir relative to current dir */ + if (strcmp(client->cur_path, "/") == 0) + snprintf(tmp_path, sizeof(tmp_path), "%s%s", client->cur_path, cmd_path); + else + snprintf(tmp_path, sizeof(tmp_path), "%s/%s", client->cur_path, cmd_path); + } + + /* If the path is not "/", check if it exists */ + if (strcmp(tmp_path, "/") != 0) { + /* Check if the path exists */ + pd = open(tmp_path, O_RDONLY, 0); + if (pd < 0) { + client_send_ctrl_msg(client, "550 Invalid directory." FTPS4_EOL); + return; + } + close(pd); + } + strcpy(client->cur_path, tmp_path); + } + client_send_ctrl_msg(client, "250 Requested file action okay, completed." FTPS4_EOL); + } +} + +static void cmd_TYPE_func(ftps4_client_info_t* client) +{ + char data_type; + char format_control[8]; + int n_args = !client->recv_cmd_args + ? 0 + : sscanf(client->recv_cmd_args, "%c %s", &data_type, format_control); + + if (n_args > 0) { + switch (data_type) { + case 'A': + case 'I': + client_send_ctrl_msg(client, "200 Okay" FTPS4_EOL); + break; + case 'E': + case 'L': + default: + client_send_ctrl_msg(client, "504 Error: bad parameters?" FTPS4_EOL); + break; + } + } + else { + client_send_ctrl_msg(client, "504 Error: bad parameters?" FTPS4_EOL); + } +} + +static void cmd_CDUP_func(ftps4_client_info_t* client) +{ + dir_up(client->cur_path); + client_send_ctrl_msg(client, "200 Command okay." FTPS4_EOL); +} + +static void send_file(ftps4_client_info_t* client, const char* path) +{ + unsigned char* buffer; + int fd; + unsigned int bytes_read; + + log_debug("[FTP Module] Opening: %s", path); + + if ((fd = open(path, O_RDONLY, 0)) >= 0) { + + lseek(fd, client->restore_point, SEEK_SET); + + buffer = malloc(file_buf_size); + if (buffer == NULL) { + client_send_ctrl_msg(client, "550 Could not allocate memory." FTPS4_EOL); + return; + } + + client_open_data_connection(client); + client_send_ctrl_msg(client, "150 Opening Image mode data transfer." FTPS4_EOL); + + while ((bytes_read = read(fd, buffer, file_buf_size)) > 0) { + client_send_data_raw(client, buffer, bytes_read); + } + + close(fd); + free(buffer); + client->restore_point = 0; + client_send_ctrl_msg(client, "226 Transfer completed." FTPS4_EOL); + client_close_data_connection(client); + + } + else { + client_send_ctrl_msg(client, "550 File not found." FTPS4_EOL); + } +} + +/* This function generates a FTP full-path valid path with the input path (relative or absolute) + * from RETR, STOR, DELE, RMD, MKD, RNFR and RNTO commands */ +static void gen_ftp_fullpath(ftps4_client_info_t* client, char* path, size_t path_size) +{ + char cmd_path[PATH_MAX]; + int n = !client->recv_cmd_args + ? 0 + : sscanf(client->recv_cmd_args, "%[^\r\n\t]", cmd_path); + + if (n < 1) { + client_send_ctrl_msg(client, "500 Syntax error, command unrecognized." FTPS4_EOL); + return; + } + + if (cmd_path[0] == '/') { + /* Full path */ + strncpy(path, cmd_path, path_size); + } + else { + /* The file is relative to current dir, so + * append the file to the current path */ + snprintf(path, path_size, "%s/%s", client->cur_path, cmd_path); + } +} + +static void cmd_RETR_func(ftps4_client_info_t* client) +{ + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + send_file(client, dest_path); + +} + +static void receive_file(ftps4_client_info_t* client, const char* path) +{ + unsigned char* buffer; + int fd; + unsigned int bytes_recv; + + log_debug("[FTP Module] Opening: %s", path); + + int mode = O_CREAT | O_RDWR; + /* if we resume broken - append missing part + * else - overwrite file */ + if (client->restore_point) { + mode = mode | O_APPEND; + } + else { + mode = mode | O_TRUNC; + } + + if ((fd = open(path, mode, 0777)) >= 0) { + + buffer = malloc(file_buf_size); + if (buffer == NULL) { + client_send_ctrl_msg(client, "550 Could not allocate memory." FTPS4_EOL); + return; + } + + client_open_data_connection(client); + client_send_ctrl_msg(client, "150 Opening Image mode data transfer." FTPS4_EOL); + + while ((bytes_recv = client_recv_data_raw(client, buffer, file_buf_size)) > 0) { + write(fd, buffer, bytes_recv); + } + + close(fd); + free(buffer); + client->restore_point = 0; + if (bytes_recv == 0) { + client_send_ctrl_msg(client, "226 Transfer completed." FTPS4_EOL); + } + else { + unlink(path); + client_send_ctrl_msg(client, "426 Connection closed; transfer aborted." FTPS4_EOL); + } + client_close_data_connection(client); + + } + else { + client_send_ctrl_msg(client, "550 File not found." FTPS4_EOL); + } +} + +static void cmd_STOR_func(ftps4_client_info_t* client) +{ + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + receive_file(client, dest_path); +} + +static void delete_file(ftps4_client_info_t* client, const char* path) +{ + log_debug("[FTP Module] Deleting: %s", path); + + if (unlink(path) >= 0) { + client_send_ctrl_msg(client, "226 File deleted." FTPS4_EOL); + } + else { + client_send_ctrl_msg(client, "550 Could not delete the file." FTPS4_EOL); + } +} + +static void cmd_DELE_func(ftps4_client_info_t* client) +{ + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + delete_file(client, dest_path); +} + +static void delete_dir(ftps4_client_info_t* client, const char* path) +{ + int ret; + log_debug("[FTP Module] Deleting: %s", path); + ret = rmdir(path); + if (ret >= 0) { + client_send_ctrl_msg(client, "226 Directory deleted." FTPS4_EOL); + } + else if (errno == 66) { /* ENOTEMPTY */ + client_send_ctrl_msg(client, "550 Directory is not empty." FTPS4_EOL); + } + else { + client_send_ctrl_msg(client, "550 Could not delete the directory." FTPS4_EOL); + } +} + +static void cmd_RMD_func(ftps4_client_info_t* client) +{ + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + delete_dir(client, dest_path); +} + +static void create_dir(ftps4_client_info_t* client, const char* path) +{ + log_debug("[FTP Module] Creating: %s", path); + + if (mkdir(path, 0777) >= 0) { + client_send_ctrl_msg(client, "226 Directory created." FTPS4_EOL); + } + else { + client_send_ctrl_msg(client, "550 Could not create the directory." FTPS4_EOL); + } +} + +static void cmd_MKD_func(ftps4_client_info_t* client) +{ + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + create_dir(client, dest_path); +} + +static void cmd_RNFR_func(ftps4_client_info_t* client) +{ + char from_path[PATH_MAX]; + /* Get the origin filename */ + gen_ftp_fullpath(client, from_path, sizeof(from_path)); + + /* Check if the file exists */ + if (!file_exists(from_path)) { + client_send_ctrl_msg(client, "550 The file doesn't exist." FTPS4_EOL); + return; + } + /* The file to be renamed is the received path */ + strcpy(client->rename_path, from_path); + client_send_ctrl_msg(client, "350 I need the destination name b0ss." FTPS4_EOL); +} + +static void cmd_RNTO_func(ftps4_client_info_t* client) +{ + char path_to[PATH_MAX]; + /* Get the destination filename */ + gen_ftp_fullpath(client, path_to, sizeof(path_to)); + + log_debug("[FTP Module] Renaming: %s to %s", client->rename_path, path_to); + + if (rename(client->rename_path, path_to) < 0) { + client_send_ctrl_msg(client, "550 Error renaming the file." FTPS4_EOL); + } + + client_send_ctrl_msg(client, "226 Rename completed." FTPS4_EOL); +} + +static void cmd_SIZ3_func(ftps4_client_info_t* client) +{ + struct stat s; + char path[PATH_MAX]; + char cmd[64]; + /* Get the filename to retrieve its size */ + gen_ftp_fullpath(client, path, sizeof(path)); + + /* Check if the file exists */ + if (stat(path, &s) < 0) { + client_send_ctrl_msg(client, "550 The file doesn't exist." FTPS4_EOL); + return; + } + /* Send the size of the file */ + sprintf(cmd, "213 %lld" FTPS4_EOL, s.st_size); + client_send_ctrl_msg(client, cmd); +} + +static void cmd_REST_func(ftps4_client_info_t* client) +{ + char cmd[64]; + sscanf(client->recv_buffer, "%*[^ ] %d", &client->restore_point); + sprintf(cmd, "350 Resuming at %d" FTPS4_EOL, client->restore_point); + client_send_ctrl_msg(client, cmd); +} + +static void cmd_FEAT_func(ftps4_client_info_t* client) +{ + /*So client would know that we support resume */ + client_send_ctrl_msg(client, "211-extensions" FTPS4_EOL); + client_send_ctrl_msg(client, "REST STREAM" FTPS4_EOL); + client_send_ctrl_msg(client, "211 end" FTPS4_EOL); +} + +static void cmd_APPE_func(ftps4_client_info_t* client) +{ + /* set restore point to not 0 + restore point numeric value only matters if we RETR file from ps4. + If we STOR or APPE, it is only used to indicate that we want to resume + a broken transfer */ + client->restore_point = -1; + char dest_path[PATH_MAX]; + gen_ftp_fullpath(client, dest_path, sizeof(dest_path)); + receive_file(client, dest_path); +} + +static cmd_dispatch_func get_dispatch_func(const char* cmd) +{ + int i; + // Check for commands + for (i = 0; i < MAX_COMMANDS; i++) { + if (command_dispatchers[i].valid) { + if (strcmp(cmd, command_dispatchers[i].cmd) == 0) { + return command_dispatchers[i].func; + } + } + } + return NULL; +} + +static void client_list_add(ftps4_client_info_t* client) +{ + /* Add the client at the front of the client list */ + scePthreadMutexLock(&client_list_mtx); + + if (client_list == NULL) { /* List is empty */ + client_list = client; + client->prev = NULL; + client->next = NULL; + } + else { + client->next = client_list; + client->next->prev = client; + client->prev = NULL; + client_list = client; + } + client->restore_point = 0; + number_clients++; + + scePthreadMutexUnlock(&client_list_mtx); +} + +static void client_list_delete(ftps4_client_info_t* client) +{ + /* Remove the client from the client list */ + scePthreadMutexLock(&client_list_mtx); + + if (client->prev) { + client->prev->next = client->next; + } + if (client->next) { + client->next->prev = client->prev; + } + if (client == client_list) { + client_list = client->next; + } + + number_clients--; + + scePthreadMutexUnlock(&client_list_mtx); +} + +static void client_list_thread_end() +{ + ftps4_client_info_t* it, * next; + ScePthread client_thid; + const int data_abort_flags = 0x01 | + 0x02; + + /* Iterate over the client list and close their sockets */ + scePthreadMutexLock(&client_list_mtx); + + it = client_list; + + while (it) { + next = it->next; + client_thid = it->thid; + + /* Abort the client's control socket, only abort + * receiving data so we can still send control messages */ + sceNetSocketAbort(it->ctrl_sockfd, + 0x01); + + /* If there's an open data connection, abort it */ + if (it->data_con_type != FTP_DATA_CONNECTION_NONE) { + sceNetSocketAbort(it->data_sockfd, data_abort_flags); + if (it->data_con_type == FTP_DATA_CONNECTION_PASSIVE) { + sceNetSocketAbort(it->pasv_sockfd, data_abort_flags); + } + } + + /* Wait until the client threads ends */ + scePthreadJoin(client_thid, NULL); + + it = next; + } + + scePthreadMutexUnlock(&client_list_mtx); +} + +static void* client_thread(void* arg) +{ + char cmd[16]; + cmd_dispatch_func dispatch_func; + ftps4_client_info_t* client = (ftps4_client_info_t*)arg; + + log_debug("[FTP Module] Client thread %i started!", client->num); + + client_send_ctrl_msg(client, "220 FTPS4 Server ready." FTPS4_EOL); + + while (1) { + memset(client->recv_buffer, 0, sizeof(client->recv_buffer)); + + client->n_recv = sceNetRecv(client->ctrl_sockfd, client->recv_buffer, sizeof(client->recv_buffer), 0); + if (client->n_recv > 0) { + + /* The command is the first chars until the first space */ + sscanf(client->recv_buffer, "%s", cmd); + + client->recv_cmd_args = strchr(client->recv_buffer, ' '); + if (client->recv_cmd_args) + client->recv_cmd_args++; /* Skip the space */ + + /* Wait 1 ms before sending any data */ + sceKernelUsleep(1 * 1000); + + if ((dispatch_func = get_dispatch_func(cmd))) { + dispatch_func(client); + } + else { + client_send_ctrl_msg(client, "502 Sorry, command not implemented. :(" FTPS4_EOL); + } + + } + else if (client->n_recv == 0) { + /* Value 0 means connection closed by the remote peer */ + log_info("Connection closed by the client %i.", client->num); + /* Delete itself from the client list */ + client_list_delete(client); + break; + } + else if (client->n_recv == 0x80410104) { + /* Socket aborted (ftps4_fini() called) */ + log_info("Client %i socket aborted.", client->num); + break; + } + else { + /* Other errors */ + log_info("Client %i socket error: 0x%08X", client->num, client->n_recv); + client_list_delete(client); + break; + } + } + + /* Close the client's socket */ + sceNetSocketClose(client->ctrl_sockfd); + + /* If there's an open data connection, close it */ + if (client->data_con_type != FTP_DATA_CONNECTION_NONE) { + sceNetSocketClose(client->data_sockfd); + if (client->data_con_type == FTP_DATA_CONNECTION_PASSIVE) { + sceNetSocketClose(client->pasv_sockfd); + } + } + + log_debug("[FTP Module] Client thread %i exiting!", client->num); + + free(client); + + scePthreadExit(NULL); + return NULL; +} + +static void* server_thread(void* arg) +{ + int ret, enable; + UNUSED(ret); + + struct sockaddr_in serveraddr; + + log_debug("[FTP Module] Server thread started!"); + + /* Create server socket */ + server_sockfd = sceNetSocket("FTPS4_server_sock", + AF_INET, + SOCK_STREAM, + 0); + + log_debug("[FTP Module] Server socket fd: %d", server_sockfd); + + enable = 1; + sceNetSetsockopt(server_sockfd, 0xffff, 0x04, &enable, sizeof(enable)); + + /* Fill the server's address */ + serveraddr.sin_len = sizeof(serveraddr); + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = sceNetHtonl(0); + serveraddr.sin_port = sceNetHtons(ps4_port); + + /* Bind the server's address to the socket */ + ret = sceNetBind(server_sockfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)); + log_debug("[FTP Module] sceNetBind(): 0x%08X", ret); + + /* Start listening */ + ret = sceNetListen(server_sockfd, 128); + log_debug("[FTP Module] sceNetListen(): 0x%08X", ret); + + while (1) { + /* Accept clients */ + struct sockaddr_in clientaddr; + int client_sockfd; + unsigned int addrlen = sizeof(clientaddr); + + log_debug("[FTP Module] Waiting for incoming connections..."); + + client_sockfd = sceNetAccept(server_sockfd, (struct sockaddr*)&clientaddr, &addrlen); + if (client_sockfd >= 0) { + log_debug("[FTP Module] New connection, client fd: 0x%08X", client_sockfd); + + /* Get the client's IP address */ + char remote_ip[16]; + sceNetInetNtop(AF_INET, + &clientaddr.sin_addr.s_addr, + remote_ip, + sizeof(remote_ip)); + + log_info("Client %i connected, IP: %s port: %i", + number_clients, remote_ip, clientaddr.sin_port); + + /* Allocate the ftps4_client_info_t struct for the new client */ + ftps4_client_info_t* client = malloc(sizeof(*client)); + client->num = number_clients; + client->ctrl_sockfd = client_sockfd; + client->data_con_type = FTP_DATA_CONNECTION_NONE; + strcpy(client->cur_path, FTP_DEFAULT_PATH); + memcpy(&client->addr, &clientaddr, sizeof(client->addr)); + + /* Add the new client to the client list */ + client_list_add(client); + + /* Create a new thread for the client */ + char client_thread_name[64]; + sprintf(client_thread_name, "FTPS4_client_%i_thread", + number_clients); + + /* Create a new thread for the client */ + scePthreadCreate(&client->thid, NULL, client_thread, client, client_thread_name); + + log_debug("[FTP Module] Client %i thread UID: 0x%08X", number_clients, client->thid); + + number_clients++; + } + else if (client_sockfd == 0x80410104) { + log_info("Server socket aborted."); + break; + } + else { + /* if sceNetAccept returns < 0, it means that the listening + * socket has been closed, this means that we want to + * finish the server thread */ + log_debug("[FTP Module] Server socket closed, 0x%08X", client_sockfd); + break; + } + } + + log_debug("[FTP Module] Server thread exiting!"); + + /* Causing a crash? */ + /*scePthreadExit(NULL);*/ + return NULL; +} + +#define add_command(name) ftps4_ext_add_command(#name, cmd_##name##_func) +bool ftps4_init(const char* ip, unsigned short int port) +{ + int i; + + if (ftp_initialized) { + return false; + } + + file_buf_size = DEFAULT_FILE_BUF_SIZE; + + /* Save the listening port of the PS4 to a global variable */ + ps4_port = port; + + /* Save the IP of the PS4 to a global variable */ + sceNetInetPton(AF_INET, ip, &ps4_addr); + + /* Create the client list mutex */ + scePthreadMutexInit(&client_list_mtx, NULL, "FTPS4_client_list_mutex"); + log_debug("[FTP Module] Client list mutex UID: 0x%08X", client_list_mtx); + + for (i = 0; i < MAX_COMMANDS; i++) { + command_dispatchers[i].valid = 0; + } + + /* Add commands */ + add_command(NOOP); + add_command(USER); + add_command(installpkg); + add_command(PASS); + add_command(QUIT); + add_command(SYST); + add_command(PASV); + add_command(PORT); + add_command(LIST); + add_command(NLST); + add_command(PWD); + add_command(CWD); + add_command(TYPE); + add_command(CDUP); + add_command(RETR); + add_command(STOR); + add_command(DELE); + add_command(RMD); + add_command(MKD); + add_command(RNFR); + add_command(RNTO); + add_command(SIZ3); //size + add_command(REST); + add_command(FEAT); + add_command(APPE); + + /* Create server thread */ + scePthreadCreate(&server_thid, NULL, server_thread, NULL, "FTPS4_server_thread"); + log_debug("[FTP Module] Server thread UID: 0x%08X", server_thid); + + ftp_initialized = 1; + + return true; +} + +void ftps4_fini() +{ + if (ftp_initialized) { + /* Necessary to get sceNetAccept to notice the close on PS4? */ + sceNetSocketAbort(server_sockfd, 0); + /* In order to "stop" the blocking sceNetAccept, + * we have to close the server socket; this way + * the accept call will return an error */ + sceNetSocketClose(server_sockfd); + + /* Wait until the server threads ends */ + scePthreadJoin(server_thid, NULL); + + /* To close the clients we have to do the same: + * we have to iterate over all the clients + * and shutdown their sockets */ + client_list_thread_end(); + + /* Delete the client list mutex */ + scePthreadMutexDestroy(client_list_mtx); + + client_list = NULL; + number_clients = 0; + + ftp_initialized = 0; + } +} + +int ftps4_is_initialized() +{ + return ftp_initialized; +} + +void ftps4_set_file_buf_size(unsigned int size) +{ + file_buf_size = size; +} + +int ftps4_ext_add_command(const char* cmd, cmd_dispatch_func func) +{ + int i; + for (i = 0; i < MAX_COMMANDS; i++) { + if (!command_dispatchers[i].valid) { + command_dispatchers[i].cmd = cmd; + command_dispatchers[i].func = func; + command_dispatchers[i].valid = 1; + return 1; + } + } + return 0; +} + +int ftps4_ext_del_command(const char* cmd) +{ + int i; + for (i = 0; i < MAX_COMMANDS; i++) { + if (strcmp(cmd, command_dispatchers[i].cmd) == 0) { + command_dispatchers[i].valid = 0; + return 1; + } + } + return 0; +} + +void ftps4_ext_client_send_ctrl_msg(ftps4_client_info_t* client, const char* msg) +{ + client_send_ctrl_msg(client, msg); +} + +void ftps4_ext_client_send_data_msg(ftps4_client_info_t* client, const char* str) +{ + client_send_data_msg(client, str); +} + +void ftps4_gen_ftp_fullpath(ftps4_client_info_t* client, char* path, size_t path_size) +{ + gen_ftp_fullpath(client, path, path_size); +} + +int get_ip_address(char* ip_address) +{ + int ret; + SceNetCtlInfo info; + + ret = sceNetCtlInit(); + if (ret < 0) + goto error; + + ret = sceNetCtlGetInfo(14, &info); + if (ret < 0) + goto error; + + memcpy(ip_address, info.ip_address, sizeof(info.ip_address)); + + sceNetCtlTerm(); + + return ret; + +error: + ip_address = NULL; + return -1; +} +bool ftp_started = false; + +bool StartFTP() { + ftp_started = false; + if (get_ip_address(&ip_address[0]) < 0) + return false; + + return (ftp_started = ftps4_init(&ip_address[0], 21)); +} +void ShutdownFTP() { + ftps4_fini(); +} +void check_ftp_addr_change(){ + + char func_ip_address[16]; + if (get_ip_address(&func_ip_address[0]) < 0 || !ftp_started) + return; + + if (strcmp(&ip_address[0], &func_ip_address[0]) != 0) { + log_debug("[FTP Module] IP Address changed, restarting FTP server"); + ShutdownFTP(); + StartFTP(); + } +} diff --git a/itemz-daemon/source/fuse.c b/itemz-daemon/source/fuse.c new file mode 100644 index 0000000..50ae070 --- /dev/null +++ b/itemz-daemon/source/fuse.c @@ -0,0 +1,185 @@ +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define FUSE_USE_VERSION 26 +#include "fuse/fuse.h" +#include +#include +#include + +static int +fs_readdir(const char *path, void *data, fuse_fill_dir_t filler, + off_t off, struct fuse_file_info *ffi) +{ + log_info("readdir: %s", path); + + filler(data, ".", NULL, 0); + filler(data, "..", NULL, 0); + filler(data, "file", NULL, 0); + return 0; +} + +static int +fs_read(const char *path, char *buf, size_t size, off_t off, + struct fuse_file_info *ffi) +{ + size_t len; + log_info("read: %s", path); + const char *file_contents = "fuse filesystem example\n"; + + len = strlen(file_contents); + + if (off < len) { + if (off + size > len) + size = len - off; + memcpy(buf, file_contents + off, size); + } else + size = 0; + + return size; +} + +static int +fs_open(const char *path, struct fuse_file_info *ffi) +{ + log_info("open: %s", path); + if (strncmp(path, "/hostapp/file", 10) != 0) + return -ENOENT; + + if ((ffi->flags & 3) != O_RDONLY) + return -EACCES; + + return 0; +} + +static int +fs_getattr(const char *path, struct stat *st) +{ + log_info("getattr: %s", path); + + st->st_blksize = 512; + st->st_mode = 0755; + st->st_nlink = 2; + st->st_uid = getuid(); + st->st_gid = getgid(); + st->st_atime = st->st_mtime = st->st_ctime = time(NULL); + st->st_ino = 1; + + if (strcmp(path, "/file") == 0) { + st->st_mode = 0644; + st->st_blksize = 512; + st->st_nlink = 1; + st->st_size = 5; + } + + return 0; +} + +struct fuse_operations fsops = { + .readdir = fs_readdir, + .read = fs_read, + .open = fs_open, + .getattr = fs_getattr, +}; + +//char* argv[] = { "fuse", "-f", "/host", "-o", "subtype=dummy" }; + +int fuse_ret = -1; +int (*fuse_main_real_2)(int argc, char *argv[], const struct fuse_operations *op, size_t op_size, void *user_data); +int sceKernelSetBesteffort(int besteffort, int priority); + +char* argv[] = { "dummy", "/hostapp", "-o", "allow_other", "-o", "rw", "-o", "use_ino", "-o", "direct_io", "-o", "attr_timeout=0.0", "-o", "max_read=65536", "-f", NULL }; + +int sceKernelLoadStartModule( + const char *moduleFileName, + size_t args, + const void *argp, + uint32_t flags, + int*, + int *pRes +); +int sceKernelDlsym( + int handle, + const char *symbol, + void **addrp +); + +void* kpayload(struct thread *td) +{ + + void* kernel_base = &((uint8_t*)kernelRdmsr(0xC0000082))[-0x1C0]; + uint8_t* kernel_ptr = (uint8_t*)kernel_base; + + cpu_disable_wp(); + +int *ksuser_enabled=(int *)(kernel_base+0x2300B88); + struct vfsconf *p=(struct vfsconf *)(kernel_base + 0x19FC380 ); + //suser_enabled in priv_check_cred + *ksuser_enabled=1; + //add jail friendly for fuse file system + p->vfc_flags=0x00400000 | 0x00080000; + //avoid enforce_dev_perms checks + //*kfuse_enforce_dev_perms=0; + //default prison_priv_check to 0 + kernel_ptr[0x3B219E]=0; + + //skip devkit/testkit/dipsw check in fuse_loader + kernel_ptr[0x49DDDE] = 0xEB; + kernel_ptr[0x49DDDF] = 0x1B; + + //skip sceSblACMgrIsSyscoreProcess check in fuse_open_device + kernel_ptr[0x4A28EE] = 0xEB; + kernel_ptr[0x4A28EF] = 0x0; + + //skip sceSblACMgrIsDebuggerProcess/sceSblACMgrIsSyscoreProcess check in fuse_close_device + kernel_ptr[0x4A29E2] = 0xEB; + + //skip sceSblACMgrIsDebuggerProcess/sceSblACMgrIsSyscoreProcess check in fuse_poll_device + kernel_ptr[0x4A2F34] = 0xEB; + + // skip sceSblACMgrIsSyscoreProcess check in fuse_vfsop_mount + kernel_ptr[0x4A30F7] = 0xEB; + kernel_ptr[0x4A30F8] = 0x04; + + // skip sceSblACMgrIsMinisyscore/unknown check in fuse_vfsop_unmount + kernel_ptr[0x4A384C] = 0xEB; + kernel_ptr[0x4A384D] = 0x00; + + // skip sceSblACMgrIsSystemUcred check in fuse_vfsop_statfs + kernel_ptr[0x4A3BED] = 0xEB; + kernel_ptr[0x4A3BEE] = 0x04; + + kernel_ptr[0x4A27FC]=0xB6; + + // patch kernel + + cpu_enable_wp(); + + int (*fuse_loader)(void* m, int op, void* arg)=(void *)(kernel_base + 0x49DDB0); + fuse_loader(NULL, 0, NULL); + + + return NULL; +} + + +void* initialize_userland_fuse() +{ + //syscall(11, &kpayload); + log_info("Starting FUSE ..."); + sceKernelSetBesteffort(903, 255); // set best cpu effort to highest for IO + + fuse_ret = fuse_main(15, argv, &fsops, NULL); + log_error("[ERROR] fuse: fuse_main returned %d", fuse_ret); + notify("Fuse failed to Start (see logs)"); + return (void*)(uintptr_t)fuse_ret; +} \ No newline at end of file diff --git a/itemz-daemon/source/log.c b/itemz-daemon/source/log.c new file mode 100644 index 0000000..46f1bc1 --- /dev/null +++ b/itemz-daemon/source/log.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2020 rxi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "log.h" + +#define MAX_CALLBACKS 32 + +typedef struct { + log_LogFn fn; + void* udata; + int level; +} Callback; + +static struct { + void* udata; + log_LockFn lock; + int level; + bool quiet; + Callback callbacks[MAX_CALLBACKS]; +} L; + + +static const char* level_strings[] = { + "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" +}; + +#ifdef LOG_USE_COLOR +static const char* level_colors[] = { + "\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m" +}; +#endif + +#define __ORBIS__ 1 + +#ifdef __ORBIS__ +#define DGB_CHANNEL_TTYL 0 +int sceKernelDebugOutText(int DBG_CHANNEL, const char *text); +#endif + +static void stdout_callback(log_Event* ev) { + char buf[16]; + char format_buf[400]; + char print_buf[400]; + buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0'; + + vsnprintf(&format_buf[0], 399, ev->fmt, ev->ap); + + snprintf(&print_buf[0], 399, "%s %-5s %s:%d: [ItemzDaemon] %s\n", buf, level_strings[ev->level], ev->file, ev->line, format_buf); + +#ifdef __ORBIS__ + sceKernelDebugOutText(DGB_CHANNEL_TTYL, &print_buf[0]); +#else + printf("%s\n" &print_buf[0]); +#endif +} + + +static void file_callback(log_Event* ev) { + char buf[64]; + buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0'; + fprintf( + ev->udata, "%s %-5s %s:%d: [ItemzDaemon]", + buf, level_strings[ev->level], ev->file, ev->line); + vfprintf(ev->udata, ev->fmt, ev->ap); + fprintf(ev->udata, "\n"); + fflush(ev->udata); +} + + +static void lock(void) { + if (L.lock) { L.lock(true, L.udata); } +} + + +static void unlock(void) { + if (L.lock) { L.lock(false, L.udata); } +} + + +const char* log_level_string(int level) { + return level_strings[level]; +} + + +void log_set_lock(log_LockFn fn, void* udata) { + L.lock = fn; + L.udata = udata; +} + + +void log_set_level(int level) { + L.level = level; +} + + +void log_set_quiet(bool enable) { + L.quiet = enable; +} + + +int log_add_callback(log_LogFn fn, void* udata, int level) { + for (int i = 0; i < MAX_CALLBACKS; i++) { + if (!L.callbacks[i].fn) { + L.callbacks[i] = (Callback){ fn, udata, level }; + return 0; + } + } + return -1; +} + + +int log_add_fp(FILE* fp, int level) { + return log_add_callback(file_callback, fp, level); +} + + +static void init_event(log_Event* ev, void* udata) { + if (!ev->time) { + time_t t = time(NULL); + ev->time = localtime(&t); + } + ev->udata = udata; +} + + +void log_log(int level, const char* file, int line, const char* fmt, ...) { + log_Event ev = { + .fmt = fmt, + .file = file, + .line = line, + .level = level, + }; + + lock(); + + if (!L.quiet && level >= L.level) { + init_event(&ev, stderr); + va_start(ev.ap, fmt); + stdout_callback(&ev); + va_end(ev.ap); + } + + for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { + Callback* cb = &L.callbacks[i]; + if (level >= cb->level) { + init_event(&ev, cb->udata); + va_start(ev.ap, fmt); + cb->fn(&ev); + va_end(ev.ap); + } + } + + unlock(); +} \ No newline at end of file diff --git a/itemz-daemon/source/main.c b/itemz-daemon/source/main.c new file mode 100644 index 0000000..8cba55d --- /dev/null +++ b/itemz-daemon/source/main.c @@ -0,0 +1,263 @@ +#include "defines.h" +#include +#include +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool IS_ERROR(uint32_t a1) +{ + return a1 & 0x80000000; +} + +bool is_home_redirect_enabled = false; +bool critical_suspend = false; +// bool critical_suspend2 = false; +// int pid = 0; + +bool mount_procFS(){ + char profpath[150]; + + snprintf(profpath, 149, "/mnt/proc/%i/", getpid()); + + if (getuid() == 0 && !if_exists(profpath)) + { + int result = mkdir("/mnt/proc", 0777); + if (result < 0 && errno != 17) + { + log_debug("Failed to create /mnt/proc"); + return true; + } + + result = mount("procfs", "/mnt/proc", 0, NULL); + if (result < 0) + { + log_debug("Failed to mount procfs: %s", strerror(errno)); + return true; + } + } + return false; +} + +void PS_Button_loop() +{ + OrbisUserServiceInitializeParams params; + memset(¶ms, 0, sizeof(params)); + params.priority = 256; + int userId = -1; + log_info(" sceUserServiceInitialize %x", sceUserServiceInitialize((int*)¶ms)); + log_info(" sceUserServiceGetForegroundUser %x", sceUserServiceGetForegroundUser(&userId)); + + int ret = scePadInit(); + if (ret < 0) + log_info(" %s scePadInit return error 0x%8x", __FUNCTION__, ret); + + + log_info(" scePadSetProcessPrivilege %x", scePadSetProcessPrivilege(1)); + + + int pad = scePadOpen(userId, 0, 0, NULL); + if (pad < 0) + log_info(" %s scePadOpen return error 0x%8x", __FUNCTION__, pad); + else + log_info(" Opened Pad"); + + + ScePadData data; + + log_info(" l1 %x", sceLncUtilInitialize()); + + LncAppParam param; + param.sz = sizeof(LncAppParam); + param.user_id = userId; + param.app_opt = 0; + param.crash_report = 0; + param.check_flag = SkipSystemUpdateCheck; + log_info(" Home menu Boot Option SkipSystemUpdateCheck Applied"); + + log_info(" Main Loop Started"); + + while(pad > 0) + { + if ((!isRestMode() && is_home_redirect_enabled) + || critical_suspend) + { + //get sample size + scePadReadState(pad, &data); + + if (data.buttons & PS_BUTTON) {//PS_BUTTON from RE + + log_info(" PS BUTTON Was Pressed & intercepted"); + log_info(" Redirecting Home Menu to ItemzCore"); + + uint32_t sys_res = sceLncUtilLaunchApp(HOME_TITLE_ID, 0, ¶m); + if (IS_ERROR(sys_res)) { + if (sys_res == SCE_LNC_UTIL_ERROR_ALREADY_RUNNING || sys_res == SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED || sys_res == SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED) { + log_info(" ITEMzFlow Already running, resuming App...."); + log_info(" Redirect Successful"); + } + else + log_info(" launch ret 0x%x", sys_res); + } + else + log_info(" Redirect Successful"); + + } + + if(critical_suspend){ + int BigAppid = sceSystemServiceGetAppIdOfBigApp(); + if ((BigAppid & ~0xFFFFFF) == 0x60000000) { + log_info(" FOUND Open Game: %x", BigAppid); + log_info(" Suspending Open Game"); + sceLncUtilLaunchApp(HOME_TITLE_ID, 0, ¶m); + critical_suspend = false; + } + } + } + usleep(15000); + } +} + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 01 + +void *Game_Stats_thread(void* args){ + + char tid[16]; + int retries = 0; + + log_info(" Game_Stats Thread Started"); + log_info(" sceLncUtilInitialize %x", sceLncUtilInitialize()); + +failed_timeout: + if(!if_exists(STAT_DB)){ + log_info(" Creating Stat DB"); + if(create_stat_db(STAT_DB)) + log_info(" Stat DB Created"); + else{ + log_info("[FATAL] Stat DB Creation Failed"); + goto err; + } + } + else + log_info(" Stat DB Exists"); + + if(open_stat_db(STAT_DB)) + log_info(" Stat DB Opened"); + else{ + log_info("[FATAL] Stat DB Open Failed"); + goto err; + } + + while (1){ + + if(retries > 4){ + retries = 0; + goto failed_timeout; + } + + //make sure app still exists + //if(!if_exists("/user/app/ITEM00001/")){ + // notify("ItemzFlow Not Installed!, Daemon Exiting..."); + // raise(SIGQUIT); + //} + + check_ftp_addr_change(); + + int BigAppid = sceSystemServiceGetAppIdOfBigApp(); + // IS Big App Running? + if ((BigAppid & ~0xFFFFFF) == 0x60000000){ + memset(tid, 0, 16); + // Get TID of Big App + if(sceLncUtilGetAppTitleId(BigAppid, &tid[0]) != 0) + log_info(" failed to get tid"); + else { + if(!update_game_time_played(&tid[0])) + log_info(" failed to update game time playe retry: %i", retries++); + else { + log_info(" Game Time Played Updated for 0x%08x", BigAppid); + sleep(59); //sleep for 59 Secs if everything successful + } + } + } + + sleep(1); + } + +err: + notify("Failed, Game Stats will be Unavailable"); + pthread_exit(NULL); + return NULL; + +} +void *resource_monitor_thread(void *args){ + + log_info(" Resource Monitor Thread Started"); + + while (1){ + print_memory(); + sleep(5 * 60); //sleep for 5 mins + } + + pthread_exit(NULL); + return NULL; +} +int main(int argc, char* argv[]) +{ + ScePthread thread, up_thread, stats_thr, fuse_thread; + // internals: net, user_service, system_service + loadModulesVanilla(); + + if (!jailbreak("/app0/Media/jb.prx")) goto exit; + + if (!full_init()) goto exit; + + log_info(" Registering Daemon..."); + + sceSystemServiceRegisterDaemon(); + + log_info("Starting SQL Services..."); + log_info("SQL library Version: %s", sqlite3_libversion()); + log_info("Started SQL Services "); + + log_info(" Starting IPC loop Thread..."); + scePthreadCreate(&thread, NULL, IPC_loop, NULL, "IPC_loop_thread"); + + log_info(" Starting Game Stats Thread..."); + scePthreadCreate(&stats_thr, NULL, Game_Stats_thread, NULL, "Game_Stats_Thread"); + + log_info(" Starting Resource Monitor Thread..."); + scePthreadCreate(&up_thread, NULL, resource_monitor_thread, NULL, "Resource_Monitor_Thread"); + + //log_info(" Starting FUSE Thread..."); + //scePthreadCreate(&fuse_thread, NULL, initialize_userland_fuse, NULL, "FUSE_Thread"); + log_info(" Starting FTP & Infinix..."); + if(!StartFTP()) + log_error(" Failed to Start FTP & Infinix"); + else + log_info(" FTP Started Successfully"); + + log_info(" Starting main PS Button loop..."); + PS_Button_loop(); + + log_info(" WTF the Loop eneded???"); + + +exit: + log_info(" Exiting"); + if (!rejail()) + log_info(" rejail failed"); + + sceKernelIccSetBuzzer(2); + return sceSystemServiceLoadExec("exit", 0); +} \ No newline at end of file diff --git a/itemz-daemon/source/md5.c b/itemz-daemon/source/md5.c new file mode 100644 index 0000000..a374ca3 --- /dev/null +++ b/itemz-daemon/source/md5.c @@ -0,0 +1,294 @@ +/* + * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. + * MD5 Message-Digest Algorithm (RFC 1321). + * + * Homepage: + * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 + * + * Author: + * Alexander Peslyak, better known as Solar Designer + * + * This software was written by Alexander Peslyak in 2001. No copyright is + * claimed, and the software is hereby placed in the public domain. + * In case this attempt to disclaim copyright and place the software in the + * public domain is deemed null and void, then the software is + * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the + * general public under the following terms: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * There's ABSOLUTELY NO WARRANTY, express or implied. + * + * (This is a heavily cut-down "BSD license".) + * + * This differs from Colin Plumb's older public domain implementation in that + * no exactly 32-bit integer data type is required (any 32-bit or wider + * unsigned integer data type will do), there's no compile-time endianness + * configuration, and the function prototypes match OpenSSL's. No code from + * Colin Plumb's implementation has been reused; this comment merely compares + * the properties of the two independent implementations. + * + * The primary goals of this implementation are portability and ease of use. + * It is meant to be fast, but not as fast as possible. Some known + * optimizations are not included to reduce source code size and avoid + * compile-time configuration. + */ + +#ifndef HAVE_OPENSSL + +#include + +#include "md5.h" + +/* + * The basic MD5 functions. + * + * F and G are optimized compared to their RFC 1321 definitions for + * architectures that lack an AND-NOT instruction, just like in Colin Plumb's + * implementation. + */ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y)))) +#define H(x, y, z) (((x) ^ (y)) ^ (z)) +#define H2(x, y, z) ((x) ^ ((y) ^ (z))) +#define I(x, y, z) ((y) ^ ((x) | ~(z))) + +/* + * The MD5 transformation for all four rounds. + */ +#define STEP(f, a, b, c, d, x, t, s) \ + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); + +/* + * SET reads 4 input bytes in little-endian byte order and stores them in a + * properly aligned word in host byte order. + * + * The check for little-endian architectures that tolerate unaligned memory + * accesses is just an optimization. Nothing will break if it fails to detect + * a suitable architecture. + * + * Unfortunately, this optimization may be a C strict aliasing rules violation + * if the caller's data buffer has effective type that cannot be aliased by + * MD5_u32plus. In practice, this problem may occur if these MD5 routines are + * inlined into a calling function, or with future and dangerously advanced + * link-time optimizations. For the time being, keeping these MD5 routines in + * their own translation unit avoids the problem. + */ +#if defined(__i386__) || defined(__x86_64__) || defined(__vax__) +#define SET(n) \ + (*(MD5_u32plus *)&ptr[(n) * 4]) +#define GET(n) \ + SET(n) +#else +#define SET(n) \ + (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define GET(n) \ + (ctx->block[(n)]) +#endif + + + void* unused; + +/* + * This processes one or more 64-byte data blocks, but does NOT update the bit + * counters. There are no alignment requirements. + */ +static const void *body(MD5_CTX *ctx, const void *data, unsigned long size) +{ + const unsigned char *ptr; + MD5_u32plus a, b, c, d; + MD5_u32plus saved_a, saved_b, saved_c, saved_d; + + ptr = (const unsigned char *)data; + + a = ctx->a; + b = ctx->b; + c = ctx->c; + d = ctx->d; + + do { + saved_a = a; + saved_b = b; + saved_c = c; + saved_d = d; + +/* Round 1 */ + STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7) + STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12) + STEP(F, c, d, a, b, SET(2), 0x242070db, 17) + STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22) + STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7) + STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12) + STEP(F, c, d, a, b, SET(6), 0xa8304613, 17) + STEP(F, b, c, d, a, SET(7), 0xfd469501, 22) + STEP(F, a, b, c, d, SET(8), 0x698098d8, 7) + STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12) + STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17) + STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22) + STEP(F, a, b, c, d, SET(12), 0x6b901122, 7) + STEP(F, d, a, b, c, SET(13), 0xfd987193, 12) + STEP(F, c, d, a, b, SET(14), 0xa679438e, 17) + STEP(F, b, c, d, a, SET(15), 0x49b40821, 22) + +/* Round 2 */ + STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5) + STEP(G, d, a, b, c, GET(6), 0xc040b340, 9) + STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14) + STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20) + STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5) + STEP(G, d, a, b, c, GET(10), 0x02441453, 9) + STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14) + STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20) + STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5) + STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9) + STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14) + STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20) + STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5) + STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9) + STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14) + STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20) + +/* Round 3 */ + STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4) + STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11) + STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16) + STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23) + STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4) + STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11) + STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16) + STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23) + STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4) + STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11) + STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16) + STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23) + STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4) + STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11) + STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16) + STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23) + +/* Round 4 */ + STEP(I, a, b, c, d, GET(0), 0xf4292244, 6) + STEP(I, d, a, b, c, GET(7), 0x432aff97, 10) + STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15) + STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21) + STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6) + STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10) + STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15) + STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21) + STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6) + STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10) + STEP(I, c, d, a, b, GET(6), 0xa3014314, 15) + STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21) + STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6) + STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10) + STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15) + STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21) + + a += saved_a; + b += saved_b; + c += saved_c; + d += saved_d; + + ptr += 64; + } while (size -= 64); + + ctx->a = a; + ctx->b = b; + ctx->c = c; + ctx->d = d; + + return ptr; +} + +void MD5_Init(MD5_CTX *ctx) +{ + ctx->a = 0x67452301; + ctx->b = 0xefcdab89; + ctx->c = 0x98badcfe; + ctx->d = 0x10325476; + + ctx->lo = 0; + ctx->hi = 0; +} + +void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size) +{ + MD5_u32plus saved_lo; + unsigned long used, available; + + saved_lo = ctx->lo; + if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) + ctx->hi++; + ctx->hi += size >> 29; + + used = saved_lo & 0x3f; + + if (used) { + available = 64 - used; + + if (size < available) { + memcpy(&ctx->buffer[used], data, size); + return; + } + + unused = memcpy(&ctx->buffer[used], data, available); + data = (const unsigned char *)data + available; + size -= available; + body(ctx, ctx->buffer, 64); + } + + if (size >= 64) { + data = body(ctx, data, size & ~(unsigned long)0x3f); + size &= 0x3f; + } + + memcpy(ctx->buffer, data, size); +} + +#define OUT(dst, src) \ + (dst)[0] = (unsigned char)(src); \ + (dst)[1] = (unsigned char)((src) >> 8); \ + (dst)[2] = (unsigned char)((src) >> 16); \ + (dst)[3] = (unsigned char)((src) >> 24); + +void MD5_Final(unsigned char *result, MD5_CTX *ctx) +{ + unsigned long used, available; + + used = ctx->lo & 0x3f; + + ctx->buffer[used++] = 0x80; + + available = 64 - used; + + if (available < 8) { + unused = memset(&ctx->buffer[used], 0, available); + body(ctx, ctx->buffer, 64); + used = 0; + available = 64; + } + + unused = memset(&ctx->buffer[used], 0, available - 8); + + ctx->lo <<= 3; + OUT(&ctx->buffer[56], ctx->lo) + OUT(&ctx->buffer[60], ctx->hi) + + body(ctx, ctx->buffer, 64); + + OUT(&result[0], ctx->a) + OUT(&result[4], ctx->b) + OUT(&result[8], ctx->c) + OUT(&result[12], ctx->d) + + unused =memset(ctx, 0, sizeof(*ctx)); +} + +#endif \ No newline at end of file diff --git a/itemz-daemon/source/net.c b/itemz-daemon/source/net.c new file mode 100644 index 0000000..0a08410 --- /dev/null +++ b/itemz-daemon/source/net.c @@ -0,0 +1,153 @@ +#include "defines.h" +#include +#include +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INVAIL -1 +#define IPC_SOC "/system_tmp/IPC_Socket" +int DaemonSocket = 0; + +struct sockaddr_in networkAdress(uint16_t port) +{ + struct sockaddr_in address; + address.sin_len = sizeof(address); + address.sin_family = AF_INET; + address.sin_port = sceNetHtons(port); + memset(address.sin_zero, 0, sizeof(address.sin_zero)); + return address; +} + +int networkListen(const char* soc_path) +{ + struct sockaddr_un server; + unlink(soc_path); + log_info("[Daemon] Deleted Socket..."); + int s = socket(AF_UNIX, SOCK_STREAM, 0); + if (s < 0) + { + log_info("[Daemon] Socket failed! %s", strerror(errno)); + return INVAIL; + } + + memset(&server, 0, sizeof(server)); + server.sun_family = AF_UNIX; + strcpy(server.sun_path, soc_path); + + int r = bind(s, (struct sockaddr*)&server, SUN_LEN(&server)); + if (r < 0) + { + log_info("[Daemon] Bind failed! %s", strerror(errno)); + return INVAIL; + } + + log_info("Socket has name %s", server.sun_path); + + r = listen(s, 100); + if (r < 0) + { + log_info("[Daemon] listen failed! %s", strerror(errno)); + return INVAIL; + } + + return s; +} + +int networkAccept(int socket) +{ + touch_file("/system_tmp/IPC_init"); + return accept(socket, 0, 0); +} + + +int networkReceiveData(int socket, uint8_t* buffer, int32_t size) +{ + return recv(socket, buffer, size, 0); +} + +int networkSendData(int socket, uint8_t* buffer, int32_t size) +{ + return send(socket, buffer, size, MSG_NOSIGNAL); +} + +int networkSendDebugData(uint8_t* buffer, int32_t size) +{ + return networkSendData(DaemonSocket, buffer, size); +} + +int networkCloseConnection(int socket) +{ + return close(socket); +} + +int networkCloseDebugConnection() +{ + return networkCloseConnection(DaemonSocket); +} + +bool touch_file(char* destfile) +{ + int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (fd > 0) { + close(fd); + return true; + } + else + return false; +} + +void *IPC_loop(void* args) +{ + // Listen on port + int serverSocket = networkListen(IPC_SOC); + if (serverSocket < 0) + { + log_debug("[Daemon IPC] networkListen error %s", strerror(errno)); + return NULL; + } + + + // Keep accepting client connections + int cli_new = 0; + while (true) + { + // Accept a client connection + int clientSocket = networkAccept(serverSocket); + if (clientSocket < 0) + { + log_debug("[Daemon IPC] networkAccept error %s", strerror(errno)); + goto clean; + } + + log_debug("[Daemon IPC] Connection Accepted"); + + + log_info("[Daemon IPC] cl_nmb %i", cli_new); + // Build data to send to thread + struct clientArgs* clientParams = (struct clientArgs*)malloc(sizeof(struct clientArgs)); + clientParams->ip = "localhost"; + clientParams->socket = clientSocket; + clientParams->cl_nmb = cli_new; + + log_info("[Daemon IPC] clientParams->cl_nmb %i", clientParams->cl_nmb); + + // Handle client on a thread + ScePthread thread; + scePthreadCreate(&thread, NULL, ipc_client, (void*)clientParams, "IPC_SERVER_THREAD"); + cli_new++; + } + + clean: + // Close Server Socket + networkCloseConnection(serverSocket); + scePthreadExit(NULL); + return NULL; +} diff --git a/itemz-daemon/source/rpc.c b/itemz-daemon/source/rpc.c new file mode 100644 index 0000000..c9522f5 --- /dev/null +++ b/itemz-daemon/source/rpc.c @@ -0,0 +1,261 @@ +#include "defines.h" +#include +#include +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint8_t CONNECT_TEST(struct clientArgs* client, uint8_t** mode, uint32_t* length) +{ + // Re-allocate memory + *mode = realloc(*mode, 99); + + sprintf((char*)(*mode), "Connected"); + *length = strlen((char*)(*mode)); + + return NO_ERROR; +} + +extern bool is_home_redirect_enabled; +extern bool critical_suspend; +// extern bool critical_suspend2; + +int sys_kill(pid_t pid, int sig) +{ + return syscall(37, pid, sig); +} + +uint8_t get_game_mins(struct clientArgs* client, uint8_t* in, uint32_t* length) +{ + char* input = (char*)(in + 1); // TITLE ID, SKIP THE COMMAND BIT + + //DumpHex((const void*)input, strlen(input)); //HEX Dump IPC Title ID + + int mins = get_game_time_played(input); // get_game_time_played(TITLE_ID) + if(mins == -1){ + log_error("[ItemzDaemon] Failed to get game time played, tid: %s", input); + return OPERATION_FAILED; + } + else + log_info("[ItemzDaemon] Game time played for %s: %d", input, mins); + + //Build IPC Response without the ERROR Bit + *length = strlen(input); + memset(in, 0, *length); + + *length = 70; + sprintf((char*)in, "%d", mins); + + return NO_ERROR; +} + +uint8_t get_game_start(struct clientArgs* client, uint8_t* in, uint32_t* length) +{ + char* input = (char*)(in + 1); + + //DumpHex((const void*)input, strlen(input)); + + time_t date = get_game_start_date(input); + if(date == 0){ + log_error("[ItemzDaemon] Failed to get game time played, tid: %s", input); + return OPERATION_FAILED; + } + else + log_info("[ItemzDaemon] Game Start date for %s: ld", input, date); + + //rewind pointer + *length = strlen(input); + memset(in, 0, *length); + + *length = 70; + sprintf((char*)in, "%ld", (long)date); + //log_info("[ItemzDaemon] Game Start date for %s: %ld", input, (long)date); + + return NO_ERROR; +} + +int isNumber(char *n) { + + int i = strlen(n); + int isnum = (i>0); + while (i-- && isnum) { + if (!(n[i] >= '0' && n[i] <= '9')) { + isnum = 0; + } + } + return isnum; +} + +void handleIPC(struct clientArgs* client, uint8_t* buffer, uint32_t length) +{ + uint8_t error = NO_ERROR; + uint8_t *outputBuffer = (uint8_t*)malloc(sizeof(uint8_t)); + uint32_t outputLength = 0; + + + uint8_t method = buffer[0]; + switch (method) + { + case GAME_GET_START_TIME: + error = get_game_start(client, buffer, &outputLength); + outputBuffer = realloc(outputBuffer, outputLength); + memcpy(outputBuffer, buffer, outputLength); + break; + case RESTART_FTP_SERVICE: + ShutdownFTP(); + notify("FTP Restarting..."); + StartFTP(); + error = NO_ERROR; + break; + case SHUTDOWN_DAEMON: + log_info("[Daemon IPC][client %i] command SHUTDOWN_DAEMON() called", client->cl_nmb); + notify("Daemon Shutting Down..."); + raise(SIGQUIT); + break; + case GAME_GET_MINS: + error = get_game_mins(client, buffer, &outputLength); + outputBuffer = realloc(outputBuffer, outputLength); + memcpy(outputBuffer, buffer, outputLength); + break; + case CONNECTION_TEST: { + log_info("[Daemon IPC][client %i] command CONNECTION_TEST() called", client->cl_nmb); + error = CONNECT_TEST(client, &outputBuffer, &outputLength); + break; + } + case DISABLE_HOME_REDIRECT: { + log_info("[Daemon IPC][client %i] command DISABLE_HOME_REDIRECT() called", client->cl_nmb); + is_home_redirect_enabled = false; + error = NO_ERROR; + break; + } + case ENABLE_HOME_REDIRECT: { + log_info("[Daemon IPC][client %i] command ENABLE_HOME_REDIRECT() called", client->cl_nmb); + is_home_redirect_enabled = true; + error = NO_ERROR; + break; + } + case DEAMON_UPDATE: { + log_info("[Daemon IPC][client %i] command DEAMON_UPDATE() called", client->cl_nmb); + unlink("/system_tmp/IPC_init"); + unlink("/system_tmp/IPC_Socket"); + log_info("[Daemon IPC][client %i] Reloading Daemon ...", client->cl_nmb); + rejail(); + log_info("Daemon Rejailed, Rebooting Daemon ..."); + sceSystemServiceLoadExec("/app0/eboot.bin", 0); + error = NO_ERROR; + break; + } + case CRITICAL_SUSPEND: { + log_info("[Daemon IPC][client %i] command CRITICAL_SUSPEND() called", client->cl_nmb); + critical_suspend = true; + log_info("[Daemon] Critical Suspend activated"); + error = NO_ERROR; + break; + } + case INSTALL_IF_UPDATE:{ + //Kill IF with SIGQUIT so it rejails + DumpHex((const void*)buffer, 10); + if(isNumber((char*)&buffer[1])) + sys_kill(atoi((char*)&buffer[1]), SIGQUIT); + else{ + log_error("[Daemon IPC][client %i] command INSTALL_IF_UPDATE() failed, invalid PID (tried %i)", client->cl_nmb, atoi((char*)&buffer[1])); + error = OPERATION_FAILED; + break; + } + + log_info("[Daemon IPC][client %i] command INSTALL_IF_UPDATE() called", client->cl_nmb); + mkdir("/user/update_tmp", 0777); + mkdir("/user/update_tmp/covers", 0777); + mkdir("/user/update_tmp/custom_app_names", 0777); + copyRegFile("/user/app/ITEM00001/settings.ini", "/user/update_tmp/settings.ini"); + copy_dir("/user/app/ITEM00001/covers", "/user/update_tmp/covers"); + copy_dir("/user/app/ITEM00001/custom_app_names", "/user/update_tmp/custom_app_names"); + + + + //copy_dir("/user/update", "/user/update_tmp"); + long pkg_size = 0; + if(if_exists("/user/app/if_update.pkg") && (pkg_size = CalcAppsize("/user/app/if_update.pkg")) > 0){ + log_info("[Daemon] Update Return 0x%X | sz %i", pkginstall("/user/app/if_update.pkg", true), pkg_size); + log_debug("[Daemon] Copying files back ..."); + + copy_dir("/user/update_tmp/covers", "/user/app/ITEM00001/covers"); + copy_dir("/user/update_tmp/custom_app_names", "/user/app/ITEM00001/custom_app_names"); + copyRegFile("/user/update_tmp/settings.ini", "/user/app/ITEM00001/settings.ini"); + unlink("/user/app/if_update.pkg"); + unlink("/mnt/usb0/if_update.pkg"); + unlink("/mnt/usb1/if_update.pkg"); + unlink("/mnt/usb2/if_update.pkg"); + unlink("/user/app/if_update.pkg.sig"); + rmdir("/user/update_tmp"); + error = NO_ERROR; + } + else{ + log_info("[Daemon] No Update Found or 0 bytes Update"); + error = INVALID; + } + + break; + } + default:{// + log_info("[Daemon IPC][client %i] command %i called", client->cl_nmb, buffer[0]); + error = INVALID; + break; + } + } + + uint8_t* outputBufferFull = malloc(outputLength + 1); + + outputBufferFull[0] = error; // First byte is always error byte + + memcpy(&outputBufferFull[1], outputBuffer, outputLength); + + // Send response + networkSendData(client->socket, outputBufferFull, outputLength + 1); + + // Free allocated memory + free(outputBuffer); + outputBuffer = NULL; + free(outputBufferFull); + outputBufferFull = NULL; +} + +void* ipc_client(void* args) +{ + struct clientArgs* cArgs = (struct clientArgs*)args; + + + log_debug("[Daemon IPC] Thread created, Socket %i", cArgs->socket); + + + uint32_t readSize = 0; + uint8_t buffer[100]; + while ((readSize = networkReceiveData(cArgs->socket, buffer, sizeof buffer)) > 0) + { + // Handle buffer + handleIPC(cArgs, buffer, readSize); + memset(buffer, 0, sizeof buffer); + //make sure app still exists + //if(!if_exists("/user/app/ITEM00001/")){ + // notify("ItemzFlow Not Installed!, Daemon Exiting..."); + // raise(SIGQUIT); + //} + } + + + log_debug("[Daemon IPC][client %i] IPC Connection disconnected, Shutting down ...", cArgs->cl_nmb); + + + networkCloseConnection(cArgs->socket); + scePthreadExit(NULL); + free(args); + return NULL; +} diff --git a/itemz-daemon/source/utils.c b/itemz-daemon/source/utils.c new file mode 100644 index 0000000..697fde1 --- /dev/null +++ b/itemz-daemon/source/utils.c @@ -0,0 +1,1037 @@ +#include "defines.h" +#include +#include +#include "log.h" +#include +#include +#include +#include +#include +#include +#include "jsmn.h" +#include +#include "md5.h" +#include +#include +#include + +sqlite3 *db; +#define SSL_HEAP_SIZE (304 * 1024) +#define HTTP_HEAP_SIZE (1024 * 1024) +#define NET_HEAP_SIZE (1 * 1024 * 1024) +#define TEST_USER_AGENT "Daemon/PS4" + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 01 + +const unsigned char completeVersion[] = { + VERSION_MAJOR_INIT, + '.', + VERSION_MINOR_INIT, + '-', + 'V', + '-', + BUILD_YEAR_CH0, + BUILD_YEAR_CH1, + BUILD_YEAR_CH2, + BUILD_YEAR_CH3, + '-', + BUILD_MONTH_CH0, + BUILD_MONTH_CH1, + '-', + BUILD_DAY_CH0, + BUILD_DAY_CH1, + 'T', + BUILD_HOUR_CH0, + BUILD_HOUR_CH1, + ':', + BUILD_MIN_CH0, + BUILD_MIN_CH1, + ':', + BUILD_SEC_CH0, + BUILD_SEC_CH1, + '\0' +}; + +#define DIFFERENT_HASH true +#define SAME_HASH false +#define UPDATE_NEEDED true +#define UPDATE_NOT_NEEDED false + + +static int (*jailbreak_me)(void) = NULL; +static int (*rejail_multi)(void) = NULL; + +int64_t sys_dynlib_load_prx(char* prxPath, int* moduleID) +{ + return (int64_t)syscall4(594, prxPath, 0, moduleID, 0); +} + +int64_t sys_dynlib_unload_prx(int64_t prxID) +{ + return (int64_t)syscall1(595, (void*)prxID); +} + + +int64_t sys_dynlib_dlsym(int64_t moduleHandle, const char* functionName, void* destFuncOffset) +{ + return (int64_t)syscall3(591, (void*)moduleHandle, (void*)functionName, destFuncOffset); +} + + +int libjbc_module = 0; + +int PKG_ERROR(const char* name, int ret) +{ + log_error( "%s error: %i", name, ret); + return ret; +} + +/* we use bgft heap menagement as init/fini as flatz already shown at + * https://github.com/flatz/ps4_remote_pkg_installer/blob/master/installer.c + */ + +#define BGFT_HEAP_SIZE (1 * 1024 * 1024) + +static bool s_app_inst_util_initialized = false; +static bool s_bgft_initialized = false; +static struct bgft_init_params s_bgft_init_params; + +bool app_inst_util_init(void) { + int ret; + + if (s_app_inst_util_initialized) { + goto done; + } + + ret = sceAppInstUtilInitialize(); + if (ret) { + log_debug( "sceAppInstUtilInitialize failed: 0x%08X", ret); + goto err; + } + + s_app_inst_util_initialized = true; + +done: + return true; + +err: + s_app_inst_util_initialized = false; + + return false; +} + +void app_inst_util_fini(void) { + int ret; + + if (!s_app_inst_util_initialized) { + return; + } + + ret = sceAppInstUtilTerminate(); + if (ret) { + log_debug( "sceAppInstUtilTerminate failed: 0x%08X", ret); + } + + s_app_inst_util_initialized = false; +} + +bool bgft_init(void) { + int ret; + + if (s_bgft_initialized) { + goto done; + } + + memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params)); + { + s_bgft_init_params.heapSize = BGFT_HEAP_SIZE; + s_bgft_init_params.heap = (uint8_t*)malloc(s_bgft_init_params.heapSize); + if (!s_bgft_init_params.heap) { + log_debug( "No memory for BGFT heap."); + goto err; + } + memset(s_bgft_init_params.heap, 0, s_bgft_init_params.heapSize); + } + + ret = sceBgftServiceInit(&s_bgft_init_params); + if (ret) { + log_debug( "sceBgftInitialize failed: 0x%08X", ret); + goto err_bgft_heap_free; + } + + s_bgft_initialized = true; + +done: + return true; + +err_bgft_heap_free: + if (s_bgft_init_params.heap) { + free(s_bgft_init_params.heap); + s_bgft_init_params.heap = NULL; + } + + memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params)); + +err: + s_bgft_initialized = false; + + return false; +} + +void bgft_fini(void) { + int ret; + + if (!s_bgft_initialized) { + return; + } + + ret = sceBgftServiceTerm(); + if (ret) { + log_debug( "sceBgftServiceTerm failed: 0x%08X", ret); + } + + if (s_bgft_init_params.heap) { + free(s_bgft_init_params.heap); + s_bgft_init_params.heap = NULL; + } + + memset(&s_bgft_init_params, 0, sizeof(s_bgft_init_params)); + + s_bgft_initialized = false; +} +/* sample ends */ + + +/* install package wrapper: + init, (install), then clean AppInstUtil and BGFT + for next install */ + +uint32_t pkginstall(const char *path, bool is_if_update) +{ + int ret = -1; + int task_id = -1; + bool is_app = false; + char title_id[30]; + SceBgftTaskProgress progress_info; + + if( if_exists(path) ) + { + log_info("Initializing AppInstUtil..."); + if (!app_inst_util_init()) { + log_debug( "AppInstUtil initialization failed."); + return -1; + } + log_info("Initializing BGFT..."); + if (!bgft_init()) { + log_debug( "BGFT initialization failed."); + return -1; + } + + struct bgft_download_param_ex download_params; + memset(&download_params, 0, sizeof(download_params)); + download_params.param.entitlement_type = 5; + download_params.param.id = ""; + download_params.param.content_url = path; + if(is_if_update) + download_params.param.content_name = "ItemzFlow Update"; + else + download_params.param.content_name = "PKG Installed remotely"; + + download_params.param.icon_path = "/update/fakepic.png"; + download_params.param.playgo_scenario_id = "0"; + download_params.param.option = BGFT_TASK_OPTION_DELETE_AFTER_UPLOAD; + download_params.slot = 0; + + ret = sceAppInstUtilGetTitleIdFromPkg(path, &title_id[0], &is_app); + if (ret) + return PKG_ERROR("sceAppInstUtilGetTitleIdFromPkg", ret); + +retry: + ret = sceBgftServiceIntDownloadRegisterTaskByStorageEx(&download_params, &task_id); + if(ret == 0x80990088 || ret == 0x80990015) + { + ret = sceAppInstUtilAppUnInstall(&title_id[0]); + if(ret != 0) + return PKG_ERROR("sceAppInstUtilAppUnInstall", ret); + + log_info("Uninstalled %s, retrying install...", &title_id[0]); + goto retry; + } + + log_info("Task ID(s): 0x%08X", task_id); + + ret = sceBgftServiceDownloadStartTask(task_id); + if(ret) + return PKG_ERROR("sceBgftDownloadStartTask", ret); + + int prog = 0; + while (prog < 99) { + memset(&progress_info, 0, sizeof(progress_info)); + + int ret = sceBgftServiceDownloadGetProgress(task_id, &progress_info); + if (ret) + return PKG_ERROR("sceBgftDownloadGetProgress", ret); + + prog = (uint32_t)(((float)progress_info.transferred / progress_info.length) * 100.f); + } + + } + else + return PKG_ERROR("no file at", ret); + + return 0; +} + + +void cleanup_net(int req, int connid, int tmpid) +{ + int ret; + if (req > 0) { + ret = sceHttpDeleteRequest(req); + if (ret < 0) { + log_error("[Download] sceHttpDeleteRequest(%i) error: 0x%08X\n", req, ret); + } + } + if (connid > 0) { + ret = sceHttpDeleteConnection(connid); + if (ret < 0) { + log_error("[Download] sceHttpDeleteConnection(%i) error: 0x%08X\n", connid, ret); + } + } + if (tmpid > 0) { + ret = sceHttpDeleteTemplate(tmpid); + if (ret < 0) { + log_error("[Download] sceHttpDeleteTemplate(%i) error: 0x%08X\n", tmpid, ret); + } + } +} + +bool rejail() +{ + int ret = sys_dynlib_dlsym(libjbc_module, "rejail_multi", &rejail_multi); + if (!ret) + { + log_info("[Daemon] rejail_multi resolved from PRX"); + + if ((ret = rejail_multi() != 0)) return false; + else + return true; + } + else + { + // fail con + log_debug("[Daemon] rejail_multi failed to resolve"); + return false; + } + + return false; +} + +bool jailbreak(const char* prx_path) +{ + sys_dynlib_load_prx((char*)prx_path, &libjbc_module); + int ret = sys_dynlib_dlsym(libjbc_module, "jailbreak_me", &jailbreak_me); + if (!ret) + { + log_info("[Daemon] jailbreak_me resolved from PRX"); + + if ((ret = jailbreak_me() != 0)) + { + log_debug("[Daemon] jailbreak_me returned %i", ret); + return false; + } + else + return true; + } + else + log_debug("[Daemon] jailbreak_me failed to resolve"); + + return false; +} + + +bool if_exists(const char* path) +{ + int dfd = open(path, O_RDONLY, 0); // try to open dir + if (dfd < 0) { + log_info("path %s, errno %s", path, strerror(errno)); + return false; + } + else + close(dfd); + + + return true; +} + +void SIG_Handler(int sig_numb) +{ + char profpath[150]; + void* array[100]; + + sceKernelIccSetBuzzer(2); + + snprintf(profpath, 149, "/mnt/proc/%i/", getpid()); + + if (getuid() == 0 && !if_exists(profpath)) + { + int result = mkdir("/mnt/proc", 0777); + if (result < 0 && errno != 17) + { + log_debug("Failed to create /mnt/proc"); + } + + result = mount("procfs", "/mnt/proc", 0, NULL); + if (result < 0) + { + log_debug("Failed to mount procfs: %s", strerror(errno)); + } + } + // + + log_debug("############# DAEMON HAS CRASHED ##########"); + log_debug("# Thread ID: %i", pthread_getthreadid_np()); + log_debug("# PID: %i", getpid()); + + if (getuid() == 0) + log_debug("# mounted ProcFS to %s", profpath); + + + log_debug("# UID: %i", getuid()); + + char buff[255]; + + if (getuid() == 0) + { + FILE* fp; + + fp = fopen("/mnt/proc/curproc/status", "r"); + fscanf(fp, "%s", buff); + + log_debug("# Reading curproc..."); + + log_debug("# Proc Name: %s", buff); + + fclose(fp); + } + log_debug("################### Backtrace ########################"); + backtrace(array, 100); + + if(sig_numb != SIGQUIT) + notify("ItemzDaemon has crashed, Restarting it..."); + + rejail(); + //if(sig_numb != SIGQUIT) + // sceSystemServiceLoadExec("/app0/eboot.bin", 0); + //else + sceSystemServiceLoadExec("exit", 0); + +} + + + +bool MD5_hash_compare(const char* file1, const char* hash) +{ + unsigned char c[MD5_HASH_LENGTH]; + FILE* f1 = fopen(file1, "rb"); + if (f1 == NULL) + return true; + MD5_CTX mdContext; + + int bytes = 0; + unsigned char data[1024]; + + MD5_Init(&mdContext); + while ((bytes = fread(data, 1, 1024, f1)) != 0) + MD5_Update(&mdContext, data, bytes); + MD5_Final(c, &mdContext); + + char md5_string[33] = { 0 }; + + for (int i = 0; i < 16; ++i) { + snprintf(&md5_string[i * 2], 32, "%02x", (unsigned int)c[i]); + } + log_info("FILE HASH: %s", md5_string); + md5_string[32] = 0; + + if (strcmp(md5_string, hash) != 0) { + return DIFFERENT_HASH; + } + + log_info("Input HASH: %s", hash); + fclose(f1); + + return SAME_HASH; +} + + +#define ORBIS_TRUE 1 + +struct dl_args { + const char* src, + * dst; + int req, + idx, // thread index! + connid, + tmpid, + status, // thread status + g_idx; // global item index in icon panel + double progress; + uint64_t contentLength; +} dl_args; + + +int libnetMemId = 0xFF, +libsslCtxId = 0xFF, +libhttpCtxId = 0xFF, +statusCode = 0xFF; + +int contentLengthType; +uint64_t contentLength; + + + +void DL_ERROR(const char* name, int statusCode, struct dl_args* i) +{ + log_warn("Download Failed with code HEX: %x Int: %i from Function %s src: %s", statusCode, statusCode, name, i->src); +} + + +int ini_dl_req(struct dl_args* i) +{ + log_info("i->src %s", i->src); + + statusCode = sceHttpCreateTemplate(libhttpCtxId, TEST_USER_AGENT, 2, 1); + if (statusCode < 0) { + DL_ERROR("sceHttpCreateTemplate()", i->tmpid, i); + goto error; + } + i->tmpid = statusCode; + + statusCode = sceHttpCreateConnectionWithURL(i->tmpid, i->src, ORBIS_TRUE); + if (statusCode < 0) + { + DL_ERROR("sceHttpCreateConnectionWithURL()", statusCode, i); + goto error; + } + i->connid = statusCode; + // ret = sceHttpSendRequest(req, NULL, 0); + statusCode = sceHttpCreateRequestWithURL(i->connid, 0, i->src, 0); + if (statusCode < 0) + { + DL_ERROR("sceHttpCreateRequestWithURL()", statusCode, i); + goto error; + } + i->req = statusCode; + + statusCode = sceHttpSendRequest(i->req, NULL, 0); + if (statusCode < 0) { + DL_ERROR("sceHttpSendRequest()", statusCode, i); + goto error; + } + + int ret = sceHttpGetStatusCode(i->req, &statusCode); + if (ret < 0 || statusCode != 200) { + DL_ERROR("sceHttpGetStatusCode()", statusCode, i); + goto error; //fail silently (its for JSON Func) + + } + + log_info("[%s:%i] ----- statusCode: %i ---", __FUNCTION__, __LINE__, statusCode); + + + ret = sceHttpGetResponseContentLength(i->req, &contentLengthType, &contentLength); + if (ret < 0) + { + log_error("[%s:%i] ----- sceHttpGetContentLength() error: %i ---", __FUNCTION__, __LINE__, ret); + goto error; + } + else + { + if (contentLengthType == 0) + { + i->contentLength = contentLength; + log_info("[%s:%i] ----- Content-Length = %lu ---", __FUNCTION__, __LINE__, contentLength); + } + else { // for some reason COUNT and MD5 have no LENs but the app still loads the content fine??? + i->contentLength = 255; + log_warn("Code 200 Success.. however no content len was reported by the server by default this app only downloads 8kbs "); + } + + return statusCode; + } + +error: + log_error("%s error: %d, 0x%x", __FUNCTION__, statusCode, statusCode); + if (i->req > 0) { + ret = sceHttpDeleteRequest(i->req); + if (ret < 0) { + log_info("sceHttpDeleteRequest() error: 0x%08X\n", ret); + } + } + if (i->connid > 0) { + ret = sceHttpDeleteConnection(i->connid); + if (ret < 0) { + log_info("sceHttpDeleteConnection() error: 0x%08X\n", ret); + } + } + if (i->tmpid > 0) { + ret = sceHttpDeleteTemplate(i->tmpid); + if (ret < 0) { + log_info("sceHttpDeleteTemplate() error: 0x%08X\n", ret); + } + } + + // failsafe + if (statusCode < 1) statusCode = 0x1337; + + return statusCode; +} + + +int netInit(void) +{ + + int libnetMemId; + int ret; + /* libnet */ + ret = sceNetInit(); + ret = sceNetPoolCreate("simple", NET_HEAP_SIZE, 0); + libnetMemId = ret; + + return libnetMemId; +} + + +#include + + +void Network_Init() +{ + int ret = netInit(); + if (ret < 0) { log_info("netInit() error: 0x%08X", ret); } + libnetMemId = ret; + + ret = sceHttpInit(libnetMemId, libsslCtxId, HTTP_HEAP_SIZE); + if (ret < 0) { log_info("sceHttpInit() error: 0x%08X", ret); } + libhttpCtxId = ret; +} + +int jsoneq(const char* json, jsmntok_t* tok, const char* s) { + if (tok->type == JSMN_STRING && (int)strlen(s) == tok->end - tok->start && + strncmp(json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +static char *checkedsize = NULL; + +long CalcAppsize(char *path) +{ + FILE *fp = NULL; + long off; + + fp = fopen(path, "r"); + if (fp == NULL) return 0; + + if (fseek(fp, 0, SEEK_END) == -1) goto cleanup; + + off = ftell(fp); + if (off == (long)-1) goto cleanup; + + if (fclose(fp) != 0) goto cleanup; + + if(off) { return off; } + else { checkedsize = NULL; return 0; } + +cleanup: + if (fp != NULL) + fclose(fp); + + return 0; + +} +bool full_init() +{ + + // pad + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_PAD)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SYSUTIL)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_NETCTL)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_NET)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_HTTP)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SSL)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SYS_CORE)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_BGFT)) return false; + if (sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_APPINSTUTIL)) return false; + + mkdir("/data/itemzflow_daemon", 0777); + mkdir("/mnt/usb0/itemzflow", 0777); + unlink(DAEMON_LOG_PS4); + + /*-- INIT LOGGING FUNCS --*/ + log_set_quiet(false); + log_set_level(LOG_DEBUG); + FILE* fp = fopen(DAEMON_LOG_PS4, "w"); + log_add_fp(fp, LOG_DEBUG); + + if (touch_file(DAEMON_LOG_USB)) + { + fp = fopen(DAEMON_LOG_USB, "w"); + log_add_fp(fp, LOG_DEBUG); + } + /* -- END OF LOGINIT --*/ + + + log_info("------------------------ ItemzFlow[Daemon] Compiled Time: %s @ %s -------------------------", __DATE__, __TIME__); + log_info(" --------------------------- Daemon Version: %s ------------------------------------", completeVersion); + + //Dump code and sig hanlder + struct sigaction new_SIG_action; + + new_SIG_action.sa_handler = SIG_Handler; + sigemptyset(&new_SIG_action.sa_mask); + new_SIG_action.sa_flags = 0; + //for now just SEGSEV + for (int i = 0; i < 12; i++) + sigaction(i, &new_SIG_action, NULL); + + sceSystemServiceHideSplashScreen(); + + return true; +} + +bool isRestMode() +{ + //return (unsigned int)sceSystemStateMgrGetCurrentState() == MAIN_ON_STANDBY; + return false; +} + +bool IsOn() +{ + //return (unsigned int)sceSystemStateMgrGetCurrentState() == WORKING; + return true; +} + +int sceSysUtilSendSystemNotificationWithText(int messageType, char* message); + +void notify(char* message) +{ + log_info(message); + sceKernelLoadStartModule("/system/common/lib/libSceSysUtil.sprx", 0, NULL, 0, 0, 0); + sceSysUtilSendSystemNotificationWithText(222, message); +} + +bool create_stat_db(const char* path){ + char *err_msg = 0; + + // if(!if_exists("/user/app/ITEM00001/")){ + // notify("Daemon Stats are only available with ItemzFlow Installed!"); + // return false; + // } + + mkdir("/user/app/ITEM00001/game_stats/", 0777); + int rc = sqlite3_open(path, &db); + if (rc != SQLITE_OK) { + log_error("[STATS] Cannot open database: %s", sqlite3_errmsg(db)); + sqlite3_close(db); + return false; + } + + char *smt = "CREATE TABLE Game_Stats(tid TEXT, mins_played INT, first_started INT, PRIMARY KEY(tid));"; + + rc = sqlite3_exec(db, smt, 0, 0, &err_msg); + + if (rc != SQLITE_OK ) { + log_error("[STATS] SQL error: %s", err_msg); + sqlite3_free(err_msg); + sqlite3_close(db); + return false; + } + + sqlite3_close(db); + return true; +} + +void DumpHex(const void* data, size_t size) { + char ascii[17]; + size_t i, j; + ascii[16] = '\0'; + for (i = 0; i < size; ++i) { + printf("%02X ", ((unsigned char*)data)[i]); + if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { + ascii[i % 16] = ((unsigned char*)data)[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + printf(" "); + if ((i+1) % 16 == 0) { + printf("| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + printf(" "); + } + for (j = (i+1) % 16; j < 16; ++j) { + printf(" "); + } + printf("| %s \n", ascii); + } + } + } +} + +typedef struct LibcMallocManagedSize { + uint16_t size; + uint16_t version; + uint32_t reserved1; + size_t maxSystemSize; + size_t currentSystemSize; + size_t maxInuseSize; + size_t currentInuseSize; +} LibcMallocManagedSize; + +int malloc_stats_fast(LibcMallocManagedSize *ManagedSize); +#define ORBIS_LIBC_MALLOC_MANAGED_SIZE_VERSION (0x0001U) + +#ifndef SCE_LIBC_INIT_MALLOC_MANAGED_SIZE +#define SCE_LIBC_INIT_MALLOC_MANAGED_SIZE(mmsize) do { \ + mmsize.size = sizeof(mmsize); \ + mmsize.version = ORBIS_LIBC_MALLOC_MANAGED_SIZE_VERSION; \ + mmsize.reserved1 = 0; \ + mmsize.maxSystemSize = 0; \ + mmsize.currentSystemSize = 0; \ + mmsize.maxInuseSize = 0; \ + mmsize.currentInuseSize = 0; \ +} while (0) +#endif + +void print_memory() +{ + size_t sz = 0; + LibcMallocManagedSize ManagedSize; + SCE_LIBC_INIT_MALLOC_MANAGED_SIZE(ManagedSize); + malloc_stats_fast(&ManagedSize); + log_info("[MEM_MANAGER] ================================================]"); + log_info("[MEM] CurrentSystemSize: %i, CurrentInUseSize: %i", ManagedSize.currentSystemSize, ManagedSize.currentInuseSize); + log_info("[MEM] MaxSystemSize: %i, MaxInUseSize: %i", ManagedSize.maxSystemSize, ManagedSize.maxInuseSize); + log_info("[MEM_MANAGER] ================================================]"); + +} + +bool open_stat_db(const char* path){ + int ret; + struct stat sb; + + // check if our sqlite db is already present in our path + ret = sceKernelStat(path, &sb); + if (ret != 0) + { + log_error("[ERROR][SQLLDR][%s][%d] sceKernelStat(%s) failed: 0x%08X", __FUNCTION__, __LINE__, path, ret); + return false; + } + ret = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL); + if (ret != SQLITE_OK) + { + log_error("[ERROR][SQLLDR][%s][%d] ERROR 0x%08X: %s", __FUNCTION__, __LINE__, ret, sqlite3_errmsg(db)); + return false; + } + + return true; +} + +bool update_game_time_played(const char* tid){ + + char smt[200]; + char *err_msg = NULL; + + if(!tid && strlen(tid) != 9){ + log_error("[STATS] Invalid tid"); + return false; + } + + snprintf(&smt[0], 199, "INSERT OR IGNORE INTO Game_Stats(tid, mins_played, first_started) VALUES('%s', 0, '%ld')", tid, (long)time(NULL)); + + int rc = sqlite3_exec(db, &smt[0], 0, 0, &err_msg); + if (rc != SQLITE_OK ) { + log_error("[STATS] SQL error: %s", err_msg); + sqlite3_free(err_msg); + return false; + } + + snprintf(&smt[0], 199, "UPDATE Game_Stats SET mins_played = mins_played+1 WHERE tid = '%s'", tid); + + rc = sqlite3_exec(db, &smt[0], 0, 0, &err_msg); + if (rc != SQLITE_OK ) { + log_error("[STATS] SQL error: %s", err_msg); + sqlite3_free(err_msg); + return false; + } + + return true; +} + +int int_cb(void *in, int idc, char **argv, char **idc_2) +{ + int *out = (int *)in; + *out = atoi(argv[0]); + return 0; +} +/* +static int token_cb(void *in, int count, char **data, char **columns) +{ + char **result_str = (char **)in; + *result_str = sqlite3_mprintf("%w", data[0]); + + return 0; +} +*/ +int get_game_time_played(const char* tid){ + char smt[200]; + char *err_msg = NULL; + int mins_played = -1; + + snprintf(&smt[0], 199, "SELECT mins_played FROM Game_Stats WHERE tid = '%s'", tid); + + int rc = sqlite3_exec(db, &smt[0], int_cb, &mins_played, &err_msg); + if (rc != SQLITE_OK ) { + log_error("[STATS] SQL error: %s", err_msg); + sqlite3_free(err_msg); + return -1; + } + + return mins_played; +} + +time_t get_game_start_date(const char* tid){ + char smt[200]; + char* err_msg = NULL; + time_t epoch = 0; + + snprintf(&smt[0], 199, "SELECT first_started FROM Game_Stats WHERE tid = '%s'", tid); + + int rc = sqlite3_exec(db, &smt[0], int_cb, &epoch, &err_msg); + if (rc != SQLITE_OK ) { + log_error("[STATS] SQL error: %s", err_msg); + sqlite3_free(err_msg); + return 0; + } + + return epoch; +} +bool copyRegFile(const char* source, const char* dest) +{ + + int src = sceKernelOpen(source, 0x0000, 0); + if (src > 0) + { + + int out = sceKernelOpen(dest, 0x0001 | 0x0200 | 0x0400, 0777); + if (out > 0) + { + size_t bytes = 0; + char buf[4096]; + while (0 < (bytes = sceKernelRead(src, &buf[0], 4096))){ + sceKernelWrite(out, &buf[0], bytes); + memset(&buf[0], 0, 4096); + } + } + else + { + sceKernelClose(src); + return false; + } + + sceKernelClose(src); + sceKernelClose(out); + return true; + } + else + return false; + +} + +bool rmtree(const char path[]) { + + struct dirent* de; + char fname[300]; + DIR* dr = opendir(path); + if (dr == NULL) + { + log_debug("No file or directory found: %s", path); + return false; + } + while ((de = readdir(dr)) != NULL) + { + int ret = -1; + struct stat statbuf; + snprintf(fname, 299, "%s/%s", path, de->d_name); + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + if (!stat(fname, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + { + log_debug("removing dir: %s Err: %d", fname, ret = unlinkat(dirfd(dr), fname, AT_REMOVEDIR)); + if (ret != 0) + { + rmtree(fname); + log_debug("Err: %d", ret = unlinkat(dirfd(dr), fname, AT_REMOVEDIR)); + } + } + else + { + log_debug("Removing file: %s, Err: %d", fname, unlink(fname)); + } + } + } + closedir(dr); + + return true; +} + + +bool copy_dir(const char* sourcedir,const char* destdir) { + + log_info("s: %s d: %s", sourcedir, destdir); + DIR* dir = opendir(sourcedir); + + struct dirent* dp; + struct stat info; + char src_path[1024]; + char dst_path[1024]; + + if (!dir) { + return false; + } + mkdir(destdir, 0777); + while ((dp = readdir(dir)) != NULL) { + if(strstr(dp->d_name, "save.ini") != NULL) + log_info("Save.ini file skipped..."); + else if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..") + || strstr(dp->d_name, "nobackup") != NULL) { + continue; + } + else { + sprintf(src_path, "%s/%s", sourcedir, dp->d_name); + sprintf(dst_path, "%s/%s", destdir, dp->d_name); + + if (!stat(src_path, &info)) { + if (S_ISDIR(info.st_mode)) { + copy_dir(src_path, dst_path); + } + else if (S_ISREG(info.st_mode)) { + if (!copyRegFile(src_path, dst_path)) + return false; + } + } + } + } + closedir(dir); + + return true; +} + diff --git a/itemz-loader/Makefile b/itemz-loader/Makefile new file mode 100644 index 0000000..3288300 --- /dev/null +++ b/itemz-loader/Makefile @@ -0,0 +1,29 @@ +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target ?= ps4_elf_sce +TargetFile=homebrew.elf + +include $(ORBISDEV)/make/ps4sdk.mk + +LinkerFlags += -lSceLncUtil_stub -lc++ -lc++abi -lc++experimental -luser_mem_sys -lkernel_stub -lSceLibcInternal_stub -lSceSysmodule_stub -lSceSystemService_stub -lSceNet_stub -lSceUserService_stub -lScePigletv2VSH_stub -lSceVideoOut_stub -lSceImeDialog_stub -lSceGnmDriver_stub -lorbis -lorbisGl -lScePad_stub -lSceCommonDialog_stub -lSceMsgDialog_stub -lSceIme_stub -lSceSysUtil_stub -lSceHttp_stub -lSceSsl_stub -lSceNetCtl_stub -lkernel_sys_stub + +CompilerFlags += -D__PS4__ -D__ORBIS__ + +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -I$(ORBISDEV)/usr/include/orbis + + +install: + @cp $(OutPath)/homebrew.self /hostapp/homebrew.self + @echo "Installed!" +oelf: + orbis-elf-create bin/homebrew.elf bin/homebrew.oelf + + +AUTH_INFO = 000000000000000000000000001C004000FF000000000080000000000000000000000000000000000000008000400040000000000000008000000000000000080040FFFF000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +eboot: + python2 $(ORBISDEV)/bin/make_fself.py --auth-info $(AUTH_INFO) bin/homebrew.oelf bin/eboot.bin +pkg_build: + cp bin/homebrew.self pkg/eboot.bin && cd pkg && pkgTool pkg_build Project.gp4 . && cp *.pkg ../bin/ diff --git a/itemz-loader/README.md b/itemz-loader/README.md new file mode 100644 index 0000000..e64fe98 --- /dev/null +++ b/itemz-loader/README.md @@ -0,0 +1,67 @@ +# Sample: Jailbreak PRX + +[![Version](https://img.shields.io/badge/Version-1.01-brightgreen.svg)](https://github.com/Cryptogenic/OpenOrbis-PS4-Toolchain) + +This project contains example code for creating a library with a Jailbreak function. It will generate an output .prx (Playstation Relocatable Executable) for the PS4, as well as a stub .so shared object file for linking on the PC side. + +to Compile this PRX correctly you must replace your link.x with this one (from OO) here +`$OO_PS4_TOOLCHAIN/link.x` + +[Fix building libraries](https://github.com/sleirsgoevy/OpenOrbis-PS4-Toolchain/commit/f1cda6002d8e3af6f530cfaa5929c5d8b8167b0d) + +AND +Replace `$OO_PS4_TOOLCHAIN/bin/linux/create-lib` and `$OO_PS4_TOOLCHAIN/bin/linux/create-eboot` with these + +[Fix create-eboot generating non-contiguous relro and data segments #112 create-eboot/create-lib #45](https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain/actions/runs/503278524) + + + +## Directory structure +``` +Jailbreak PRX\Jailbreak +|-- Jailbreak + |-- x64 + |-- Debug // Object files / intermediate directory + |-- build.bat // Batch file for building on Windows + |-- main.cpp // Mira Jailbreak and main function + |-- mira_header.h + |-- multi-jb.c // all the Jailbreak code for HEN + |-- multi-jb.h // Jailbreak Offsets + |-- new.s // ASM for syscall etc +|-- jb.prx // final library file (not present until built) +|-- jb.so // final library stub (not present until built) +|-- Makefile // Make rules for building on Linux +``` +The ELF, Orbis ELF (OELF), and object files will all be stored in the intermediate directory `x64/Debug`. The final library prx and stub files will be found in the root directory. + + + +## Libraries used + +- libSceLibcInternal +- libkernel + + + +## Building + +On Linux, a makefile has been included. + +To build this project, the developer will need clang, which is provided in the toolchain. The `OO_PS4_TOOLCHAIN` environment variable will also need to be set to the root directory of the SDK installation. + + +__Linux__ +Run the makefile. +``` +make +``` + +## Reference(s) used + +Libjbc - https://github.com/sleirsgoevy/ps4-libjbc + + +## Author(s) +- LM +- Sleirsgoevy +- Specter diff --git a/itemz-loader/include/Header.h b/itemz-loader/include/Header.h new file mode 100644 index 0000000..6a47a6b --- /dev/null +++ b/itemz-loader/include/Header.h @@ -0,0 +1,222 @@ +#pragma once +#include +#include +#include +#include //O_CEAT +#include + +#include +#include +#include +#include +#include + +#define SCE_KERNEL_MAX_MODULES 256 +#define SCE_KERNEL_MAX_NAME_LENGTH 256 +#define SCE_KERNEL_MAX_SEGMENTS 4 +#define SCE_KERNEL_NUM_FINGERPRINT 20 + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(ar) (sizeof(ar) / sizeof((ar)[0])) +#endif + +#define DIFFERENT_HASH 1 +#define SAME_HASH 0 + +#define YES 1 +#define NO 2 + +#define DGB_CHANNEL_TTYL 0 + +#define TRUE 1 +#define FALSE 0 + +void logshit(char* format, ...); + +#define SCE_SYSMODULE_INTERNAL_SYS_CORE 0x80000004 +#define SCE_SYSMODULE_INTERNAL_NETCTL 0x80000009 +#define SCE_SYSMODULE_INTERNAL_HTTP 0x8000000A +#define SCE_SYSMODULE_INTERNAL_SSL 0x8000000B +#define SCE_SYSMODULE_INTERNAL_NP_COMMON 0x8000000C +#define SCE_SYSMODULE_INTERNAL_SYSTEM_SERVICE 0x80000010 +#define SCE_SYSMODULE_INTERNAL_USER_SERVICE 0x80000011 +#define SCE_SYSMODULE_INTERNAL_APPINSTUTIL 0x80000014 +#define SCE_SYSMODULE_INTERNAL_NET 0x8000001C +#define SCE_SYSMODULE_INTERNAL_IPMI 0x8000001D +#define SCE_SYSMODULE_INTERNAL_VIDEO_OUT 0x80000022 +#define SCE_SYSMODULE_INTERNAL_BGFT 0x8000002A +#define SCE_SYSMODULE_INTERNAL_PRECOMPILED_SHADERS 0x80000064 + + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 4 + +#define BUILD_YEAR_CH0 (__DATE__[ 7]) +#define BUILD_YEAR_CH1 (__DATE__[ 8]) +#define BUILD_YEAR_CH2 (__DATE__[ 9]) +#define BUILD_YEAR_CH3 (__DATE__[10]) + + +#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') + + +#define BUILD_MONTH_CH0 \ + ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0') + +#define BUILD_MONTH_CH1 \ + ( \ + (BUILD_MONTH_IS_JAN) ? '1' : \ + (BUILD_MONTH_IS_FEB) ? '2' : \ + (BUILD_MONTH_IS_MAR) ? '3' : \ + (BUILD_MONTH_IS_APR) ? '4' : \ + (BUILD_MONTH_IS_MAY) ? '5' : \ + (BUILD_MONTH_IS_JUN) ? '6' : \ + (BUILD_MONTH_IS_JUL) ? '7' : \ + (BUILD_MONTH_IS_AUG) ? '8' : \ + (BUILD_MONTH_IS_SEP) ? '9' : \ + (BUILD_MONTH_IS_OCT) ? '0' : \ + (BUILD_MONTH_IS_NOV) ? '1' : \ + (BUILD_MONTH_IS_DEC) ? '2' : \ + /* error default */ '?' \ + ) + +#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +#define BUILD_DAY_CH1 (__DATE__[ 5]) + + + +// Example of __TIME__ string: "21:06:19" +// 01234567 + +#define BUILD_HOUR_CH0 (__TIME__[0]) +#define BUILD_HOUR_CH1 (__TIME__[1]) + +#define BUILD_MIN_CH0 (__TIME__[3]) +#define BUILD_MIN_CH1 (__TIME__[4]) + +#define BUILD_SEC_CH0 (__TIME__[6]) +#define BUILD_SEC_CH1 (__TIME__[7]) + + +#if VERSION_MAJOR > 100 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 100) + '0'), \ + (((VERSION_MAJOR % 100) / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#elif VERSION_MAJOR > 10 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#else + +#define VERSION_MAJOR_INIT \ + (VERSION_MAJOR + '0') + +#endif + +#if VERSION_MINOR > 100 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 100) + '0'), \ + (((VERSION_MINOR % 100) / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#elif VERSION_MINOR > 10 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#else + +#define VERSION_MINOR_INIT \ + (VERSION_MINOR + '0') +#endif + + +#define SCE_SYSMODULE_INTERNAL_COMMON_DIALOG 0x80000018 +#define SCE_SYSMODULE_INTERNAL_SYSUTIL 0x80000018 + +enum IPC_Errors +{ + INVALID = -1, + NO_ERROR = 0, + OPERATION_FAILED = 1, + DEAMON_UPDATING = 100 +}; + + +enum IPC_Commands +{ + CONNECTION_TEST = 1, + ENABLE_HOME_REDIRECT = 2, + DISABLE_HOME_REDIRECT = 3, + GAME_GET_MINS = 4, + GAME_GET_START_TIME = 5, + CRITICAL_SUSPEND = 6, + INSTALL_IF_UPDATE = 7, + DEAMON_UPDATE = 100 +}; + +enum { CWD_KEEP, CWD_ROOT, CWD_RESET }; +extern void (*jbc_run_as_root)(void(*fn)(void* arg), void* arg, int cwd_mode); + +enum Flag +{ + Flag_None = 0, + SkipLaunchCheck = 1, + SkipResumeCheck = 1, + SkipSystemUpdateCheck = 2, + RebootPatchInstall = 4, + VRMode = 8, + NonVRMode = 16 +}; + +typedef struct _LncAppParam +{ + uint32_t sz; + uint32_t user_id; + uint32_t app_opt; + uint64_t crash_report; + enum Flag check_flag; +} +LncAppParam; + +extern uint8_t daemon_eboot[]; +extern int32_t daemon_eboot_size; + +int32_t sceSystemServiceHideSplashScreen(); +int32_t sceSystemServiceParamGetInt(int32_t paramId, int32_t *value); +uint32_t sceLncUtilLaunchApp(const char* tid, const char* argv[], LncAppParam* param); +bool boot_daemon_services(); +int sceLncUtilGetAppId(const char* tid); +int sceSystemServiceLoadExec(const char* eboot, const char* argv[]); +int copyFile(char* sourcefile, char* destfile); +void loader_rooted(void *arg); +void init_itemzGL_modules(); +int msgok(char* format, ...); +int loadmsg(char* format, ...); +int pingtest(int libnetMemId, int libhttpCtxId, const char* src); +int download_file(int libnetMemId, int libhttpCtxId, const char* src, const char* dst); +bool if_exists(const char* path); +int32_t netInit(void); +void logshit(char* format, ...); +void init_STOREGL_modules(); +int sceKernelDebugOutText(int DBG_CHANNEL, const char* text); +int Confirmation_Msg(const char* msg); +bool rmtree(const char path[]); diff --git a/itemz-loader/include/MsgDialog.h b/itemz-loader/include/MsgDialog.h new file mode 100644 index 0000000..f4b98f1 --- /dev/null +++ b/itemz-loader/include/MsgDialog.h @@ -0,0 +1,157 @@ +#ifndef _ORBIS_MSG_H_ +#define _ORBIS_MSG_H_ +#pragma once + + +#include +#include + +#define ORBIS_COMMON_DIALOG_MAGIC_NUMBER 0xC0D1A109 + + +typedef enum OrbisCommonDialogStatus { + ORBIS_COMMON_DIALOG_STATUS_NONE = 0, + ORBIS_COMMON_DIALOG_STATUS_INITIALIZED = 1, + ORBIS_COMMON_DIALOG_STATUS_RUNNING = 2, + ORBIS_COMMON_DIALOG_STATUS_FINISHED = 3 +} OrbisCommonDialogStatus; + +typedef enum OrbisCommonDialogResult { + ORBIS_COMMON_DIALOG_RESULT_OK = 0, + ORBIS_COMMON_DIALOG_RESULT_USER_CANCELED = 1, +} OrbisCommonDialogResult; + +typedef struct OrbisCommonDialogBaseParam { + size_t size; + uint8_t reserved[36]; + uint32_t magic; +} OrbisCommonDialogBaseParam __attribute__ ((__aligned__(8))); + + +static inline void _sceCommonDialogSetMagicNumber( uint32_t* magic, const OrbisCommonDialogBaseParam* param ) +{ + *magic = (uint32_t)( ORBIS_COMMON_DIALOG_MAGIC_NUMBER + (uint64_t)param ); +} + +static inline void _sceCommonDialogBaseParamInit(OrbisCommonDialogBaseParam *param) +{ + memset(param, 0x0, sizeof(OrbisCommonDialogBaseParam)); + param->size = (uint32_t)sizeof(OrbisCommonDialogBaseParam); + _sceCommonDialogSetMagicNumber( &(param->magic), param ); +} + + +// Empty Comment +void sceCommonDialogInitialize(); +// Empty Comment +void sceCommonDialogIsUsed(); + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ORBIS_SYSMODULE_MESSAGE_DIALOG 0x00a4 +#define ORBIS_MSG_DIALOG_MODE_USER_MSG (1) +#define ORBIS_MSG_DIALOG_BUTTON_TYPE_WAIT (5) +#define ORBIS_MSG_DIALOG_BUTTON_TYPE_OK (0) + +typedef struct OrbisMsgDialogButtonsParam { + const char *msg1; + const char *msg2; + char reserved[32]; +} OrbisMsgDialogButtonsParam; + +typedef struct OrbisMsgDialogUserMessageParam { + int32_t buttonType; + int :32; + const char *msg; + OrbisMsgDialogButtonsParam *buttonsParam; + char reserved[24]; + +} OrbisMsgDialogUserMessageParam; + +typedef struct OrbisMsgDialogSystemMessageParam { + int32_t sysMsgType; + char reserved[32]; +} OrbisMsgDialogSystemMessageParam; + +typedef struct OrbisMsgDialogProgressBarParam { + int32_t barType; + int :32; + const char *msg; + char reserved[64]; +} OrbisMsgDialogProgressBarParam; + + + +typedef struct OrbisMsgDialogParam { + OrbisCommonDialogBaseParam baseParam; + size_t size; + int32_t mode; + int :32; + OrbisMsgDialogUserMessageParam *userMsgParam; + OrbisMsgDialogProgressBarParam *progBarParam; + OrbisMsgDialogSystemMessageParam *sysMsgParam; + int32_t userId; + char reserved[40]; + int :32; +} OrbisMsgDialogParam; + + + +typedef struct OrbisMsgDialogResult { + int32_t mode; + + int32_t result; + + int32_t buttonId; + + char reserved[32]; + +} OrbisMsgDialogResult; + + +static inline +void OrbisMsgDialogParamInitialize(OrbisMsgDialogParam *param) +{ + memset( param, 0x0, sizeof(OrbisMsgDialogParam) ); + + _sceCommonDialogBaseParamInit( ¶m->baseParam ); + param->size = sizeof(OrbisMsgDialogParam); +} + +// Initialize the message dialog. Should be called before trying to use the +// message dialog. +int32_t sceMsgDialogInitialize(void); + +// Display the message dialog. +int32_t sceMsgDialogOpen(const OrbisMsgDialogParam *param); + +// Get the result of the message dialog after the user closes the dialog. +// This can be used to detect which option was pressed (yes, no, cancel, etc). +int32_t sceMsgDialogGetResult(OrbisMsgDialogResult *result); + +// Get the status of the message dialog. This can be used to check if a +// message dialog is initialized, is being displayed, or is finished. +OrbisCommonDialogStatus sceMsgDialogGetStatus(); + +// Update the current status of the message dialog. +OrbisCommonDialogStatus sceMsgDialogUpdateStatus(void); + +// Close the message dialog. +int32_t sceMsgDialogClose(void); + +// Terminate the message dialog. Should be called when all message dialog +// operations are finished. +int32_t sceMsgDialogTerminate(void); + +#endif + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/itemz-loader/include/ini.h b/itemz-loader/include/ini.h new file mode 100644 index 0000000..78015d1 --- /dev/null +++ b/itemz-loader/include/ini.h @@ -0,0 +1,157 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef INI_H +#define INI_H + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See https://github.com/benhoyt/inih/issues/21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +/* Nonzero to call the handler at the start of each new section (with + name and value NULL). Default is to only call the handler on + each name=value pair. */ +#ifndef INI_CALL_HANDLER_ON_NEW_SECTION +#define INI_CALL_HANDLER_ON_NEW_SECTION 0 +#endif + +/* Nonzero to allow a name without a value (no '=' or ':' on the line) and + call the handler with value NULL in this case. Default is to treat + no-value lines as an error. */ +#ifndef INI_ALLOW_NO_VALUE +#define INI_ALLOW_NO_VALUE 0 +#endif + +/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory + allocation functions (INI_USE_STACK must also be 0). These functions must + have the same signatures as malloc/free/realloc and behave in a similar + way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */ +#ifndef INI_CUSTOM_ALLOCATOR +#define INI_CUSTOM_ALLOCATOR 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* INI_H */ diff --git a/itemz-loader/include/lang.h b/itemz-loader/include/lang.h new file mode 100644 index 0000000..500e812 --- /dev/null +++ b/itemz-loader/include/lang.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include +#include +#include +#include +enum Lang_STR { + LOADER_FATAL, + FATAL_JB, + FATAL_REJAIL, + EXT_NOT_SUPPORTED, + PING_FAILED, + SWU_ERROR, + RSA_LOAD, + RSA_FAILED, + SECURE_FAIL, + REINSTALL_PKG, + LOADER_ERROR, + MORE_INFO, + DOWNLOADING_UPDATE, + INI_FAIL, + UPDATE_REQ, + UPDATE_APPLIED, + OPT_UPDATE, + STR_NOT_FOUND, + //DO NOT DELETE THIS, ALWAYS KEEP AT THE BOTTOM + LANG_NUM_OF_STRINGS +}; + +typedef struct +{ + char* strings[LANG_NUM_OF_STRINGS]; +} LangStrings; + + +#define LANG_DIR "/app0/langs/%i/lang.ini" + +bool LoadLangs(int LangCode); +char* getLangSTR(enum Lang_STR str); +int32_t PS4GetLang(); \ No newline at end of file diff --git a/itemz-loader/source/app.c b/itemz-loader/source/app.c new file mode 100644 index 0000000..e21d92e --- /dev/null +++ b/itemz-loader/source/app.c @@ -0,0 +1,275 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "Header.h" + +const unsigned char completeVersion[] = {VERSION_MAJOR_INIT, + '.', + VERSION_MINOR_INIT, + '-', + 'V', + '-', + BUILD_YEAR_CH0, + BUILD_YEAR_CH1, + BUILD_YEAR_CH2, + BUILD_YEAR_CH3, + '-', + BUILD_MONTH_CH0, + BUILD_MONTH_CH1, + '-', + BUILD_DAY_CH0, + BUILD_DAY_CH1, + 'T', + BUILD_HOUR_CH0, + BUILD_HOUR_CH1, + ':', + BUILD_MIN_CH0, + BUILD_MIN_CH1, + ':', + BUILD_SEC_CH0, + BUILD_SEC_CH1, + '\0'}; + + +void logshit(char* format, ...) +{ + char buff[1024]; + memset(buff, 0, 1024); + + va_list args; + va_start(args, format); + vsprintf(&buff[0], format, args); + va_end(args); + + sceKernelDebugOutText(DGB_CHANNEL_TTYL, &buff[0]); + + int fd = sceKernelOpen("/user/app/ITEM00001/logs/loader.log", O_WRONLY | O_CREAT | O_APPEND, 0777); + if (fd >= 0) + { + sceKernelWrite(fd, &buff[0], strlen(&buff[0])); + sceKernelClose(fd); + } +} + + +bool rmtree(const char path[]) { + + struct dirent* de; + char fname[300]; + DIR* dr = opendir(path); + if (dr == NULL) + { + logshit("No file or directory found: %s\n", path); + return false; + } + while ((de = readdir(dr)) != NULL) + { + int ret = -1; + struct stat statbuf; + snprintf(fname, 299, "%s/%s", path, de->d_name); + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + if (!stat(fname, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + { + logshit("removing dir: %s Err: %d\n", fname, ret = unlinkat(dirfd(dr), fname, AT_REMOVEDIR)); + if (ret != 0) + { + rmtree(fname); + //logshit("Err: %d", ret = unlinkat(dirfd(dr), fname, AT_REMOVEDIR)); + } + } + else + { + logshit("Removing file: %s, Err: %d\n", fname, unlink(fname)); + } + } + } + closedir(dr); + + return true; +} + +int copyFile(char* sourcefile, char* destfile) +{ + int src = sceKernelOpen(sourcefile, 0x0000, 0); + if (src > 0) + { + int out = sceKernelOpen(destfile, 0x0001 | 0x0200 | 0x0400, 0777); + if (out > 0) + { + size_t bytes; + char* buffer = (char*)malloc(65536); + if (buffer != NULL) + { + while (0 < (bytes = sceKernelRead(src, buffer, 65536))) + sceKernelWrite(out, buffer, bytes); + free(buffer); + } + sceKernelClose(out); + } + else + return -1; + + + sceKernelClose(src); + return 0; + } + else + { + logshit("[ELFLOADER] fuxking error\n"); + logshit("[Itemz-loader:%s:%i] ----- src fd = %i---\n", __FUNCTION__, __LINE__, src); + return -1; + } +} + +bool if_exists(const char* path) +{ + int dfd = open(path, O_RDONLY, 0); // try to open dir + if (dfd < 0) { + logshit("path %s, errno %s\n", path, strerror(errno)); + return false; + } + else + close(dfd); + + + return true; +} + +void init_itemzGL_modules() +{ + + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SYSTEM_SERVICE); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_SYSTEM_SERVICE\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_USER_SERVICE); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_USER_SERVICE\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_NETCTL); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_NETCTL\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_NET); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_NET\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_HTTP); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_HTTP\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SSL); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_SSL\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_SYS_CORE); + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_SYS_CORE\n"); + sceSysmoduleLoadModuleInternal(0x80000018); + logshit("[DEBUG] Started Internal Module 0x80000018\n"); + sceSysmoduleLoadModuleInternal(0x80000026); // 0x80000026 + logshit("[DEBUG] Started Internal Module libSceSysUtil_SYSMODULE_INTERNAL_NETCTL\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_BGFT); // 0x80000026 + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_BGFT\n"); + sceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_APPINSTUTIL); // 0x80000026 0x80000037 + logshit("[DEBUG] Started Internal Module SCE_SYSMODULE_INTERNAL_APPINSTUTIL\n"); + sceSysmoduleLoadModuleInternal(0x80000024); // 0x80000026 0x80000037 + logshit("[DEBUG] Started Internal Module PAD (0x80000024)\n"); + sceSysmoduleLoadModule(ORBIS_SYSMODULE_MESSAGE_DIALOG); + orbisPadInit(); +} + +void (*jbc_run_as_root)(void(*fn)(void* arg), void* arg, int cwd_mode); + +void loader_rooted(void *arg){ + + if(if_exists("/usb0/recovery.flag") || if_exists("/user/recovery.flag")){ + + if(Confirmation_Msg("ItemzLoader Recovery Menu\n\n\nDo you want to Factory reset ItemzFlow??\n\nWarning: ItemzFlow App Stats, Covers, Settings, Updates, Themes and More will be Deleted!") == YES){ + //rmtree app.xml app.pkg app.pbm.backup app.pbm app.json + logshit("Starting factory reset...\n"); + mkdir("/user/app/reset", 0777); + copyFile("/user/app/ITEM00001/app.xml", "/user/app/reset/app.xml"); + copyFile("/user/app/ITEM00001/app.pkg", "/user/app/reset/app.pkg"); + copyFile("/user/app/ITEM00001/app.pbm.backup", "/user/app/reset/app.pbm.backup"); + copyFile("/user/app/ITEM00001/app.pbm", "/user/app/reset/app.pbm"); + copyFile("/user/app/ITEM00001/app.json", "/user/app/reset/app.json"); + + rmtree("/user/app/ITEM00001"); + mkdir("/user/app/ITEM00001", 0777); + + copyFile("/user/app/reset/app.xml", "/user/app/ITEM00001/app.xml"); + copyFile("/user/app/reset/app.pkg", "/user/app/ITEM00001/app.pkg"); + copyFile("/user/app/reset/app.pbm.backup", "/user/app/ITEM00001/app.pbm.backup"); + copyFile("/user/app/reset/app.pbm", "/user/app/ITEM00001/app.pbm"); + copyFile("/user/app/reset/app.json", "/user/app/ITEM00001/app.json"); + rmtree("/user/app/reset"); + rmdir("/user/app/reset"); + + logshit("Factory reset done!\n"); + unlink("/usb0/recovery.flag"); + rmdir("/usb0/recovery.flag"); + unlink("/user/recovery.flag"); + rmdir("/user/recovery.flag"); + msgok("ItemzLoader Recovery Menu\n\n\nItemzFlow has been Factory Reset!\n\nPress OK to exit"); + logshit("Factory reset complete!\n"); + sceSystemServiceLoadExec("EXIT", NULL); + } + else + logshit("ItemzLoader Recovery Canned...\n"); + + unlink("/usb0/recovery.flag"); + rmdir("/usb0/recovery.flag"); + unlink("/user/recovery.flag"); + rmdir("/user/recovery.flag"); + } + + logshit("After jb\n"); + mkdir("/user/app/ITEM00001/storedata/", 0777); + mkdir("/user/app/ITEM00001/logs/", 0777); + unlink("/user/app/ITEM00001/logs/loader.log"); + + logshit("[Itemz-loader:%s:%i] ----- All Internal Modules Loaded -----\n", __FUNCTION__, __LINE__); + logshit("------------------------ Itemz Loader[GL] Compiled Time: %s @ %s EST -------------------------\n", __DATE__, __TIME__); + logshit("[Itemz-loader:%s:%i] ----- Itemz-Loader Version: %s -----\n", __FUNCTION__, __LINE__, completeVersion); + logshit("----------------------------------------------- -------------------------\n"); + + if (if_exists("/usb0/settings.ini")) + logshit("[Itemz-loader:%s:%i] ----- FOUND USB RECOVERY INI ---\n", __FUNCTION__, __LINE__); + else + { + if (!if_exists("/user/app/ITEM00001/settings.ini")) + { + logshit("[Itemz-loader:%s:%i] ----- APP INI Not Found, Making ini ---\n", __FUNCTION__, __LINE__); + + char buff[1024]; + memset(&buff[0], 0, 1024); + snprintf(&buff[0], 1024, "[Settings]\nSort_By=1\nSecure_Boot=1\nDumper_option=0\nFTP_Auto_Start=1\nShow_install_prog=1\nHomeMenu_Redirection=0\nDaemon_on_start=1\ncover_message=1\n"); + + int fd = open("/user/app/ITEM00001/settings.ini", O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (fd >= 0) + { + write(fd, &buff[0], strlen(&buff[0])); + close(fd); + } + else + logshit("Could not make create INI File"); + + mkdir("/user/app/ITEM00001/downloads", 0777); + + } + else + logshit("[Itemz-loader:%s:%i] ----- INI FOUND ---\n", __FUNCTION__, __LINE__); + + } + + logshit("[Itemz-loader:%s:%i] ----- Starting daemon services -----\n", __FUNCTION__, __LINE__); + if(boot_daemon_services()) + logshit("[Itemz-loader:%s:%i] ----- Daemon services started -----\n", __FUNCTION__, __LINE__); + else + logshit("[Itemz-loader:%s:%i] ----- Daemon services failed to start -----\n", __FUNCTION__, __LINE__); + // wrapper(); + +} + diff --git a/itemz-loader/source/daemon.c b/itemz-loader/source/daemon.c new file mode 100644 index 0000000..7270744 --- /dev/null +++ b/itemz-loader/source/daemon.c @@ -0,0 +1,313 @@ +#include +#include +#include "ini.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DAEMON_PATH "/system/vsh/app/ITEM00002" +#define LATEST_DAEMON_VERSION 0x1001 + +int daemon_ver = 0x1337; +static int daemon_ini(void* user, const char* section, const char* name, + const char* value, int idc) +{ + +#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + + if (MATCH("Daemon", "version")) { + logshit("DVERLL: %s\n", value); + daemon_ver = atoi(value); + } + + return 1; +} + + +/* *********************** IPC SHIT **********************/ +#define IPC_SOC "/system_tmp/IPC_Socket" + +int DaemonSocket = -1; +bool is_daemon_connected = false; + +int OpenConnection(const char* path) +{ + struct sockaddr_un server; + int soc = socket(AF_UNIX, SOCK_STREAM, 0); + server.sun_family = AF_UNIX; + strcpy(server.sun_path, path); + connect(soc, (struct sockaddr*)&server, SUN_LEN(&server)); + return soc; +} + +void GetIPCMessageWithoutError(uint8_t* buf, uint32_t sz) +{ + memmove(buf, buf + 1, sz); +} + +bool IPCOpenConnection() +{ + + DaemonSocket = OpenConnection(IPC_SOC); + if (DaemonSocket > 0 && DaemonSocket != -1) + return true; + else + return false; + +} + +int IPCReceiveData(uint8_t* buffer, int32_t size) +{ + return recv(DaemonSocket, buffer, size, MSG_NOSIGNAL); +} + +int IPCSendData(uint8_t* buffer, int32_t size) +{ + return send(DaemonSocket, buffer, size, MSG_NOSIGNAL); +} + +int IPCCloseConnection() +{ + return close(DaemonSocket); +} + +int IPCSendCommand(enum IPC_Commands cmd, uint8_t* IPC_BUFFER) { + + int error = INVALID; + + if (!is_daemon_connected) + is_daemon_connected = IPCOpenConnection(); + + + if (is_daemon_connected) + { + + logshit(" IPC Connected via Domain Socket\n"); + + IPC_BUFFER[0] = cmd; // First byte is always command + + logshit(" Sending IPC Command\n"); + IPCSendData(IPC_BUFFER, 100); + logshit(" Sent IPC Command %i\n", cmd); + + memset(IPC_BUFFER, 0, 100); + + if (cmd == DEAMON_UPDATE) + { + logshit(" Daemon Updating...\n"); + is_daemon_connected = false; + return DEAMON_UPDATING; + } + + //Get message back from daemon + uint32_t readSize = IPCReceiveData(IPC_BUFFER, 100); + if (readSize > 0 && readSize != -1) + { + logshit(" Got message with Size: %i from Daemon\n", readSize); + //Get IPC Error code + error = IPC_BUFFER[0]; + if (error != INVALID) + { + // Modifies the Buffer to exclude the error code + GetIPCMessageWithoutError(IPC_BUFFER, readSize); + logshit("[ItemzDaemon] Daemon IPC Response: %s, code: %s, readSize: %i\n", IPC_BUFFER, error == NO_ERROR ? "NO_ERROR" : "Other", readSize); + } + else + logshit("[ItemzDaemon] Daemon returned INVAL\n"); + } + else + logshit("IPCReceiveData failed with: %s\n", strerror(errno)); + } + + + return error; +} +/* *********************** IPC SHIT **********************/ +/* *********************** daemon shit **********************/ + + +bool is_daemon_outdated(void) +{ + + if (!if_exists(DAEMON_PATH"/daemon.ini")) + return false; + else + { + logshit(" Daemon INI Does exist\n"); + int error = ini_parse(DAEMON_PATH"/daemon.ini", (ini_handler)daemon_ini, NULL); + if (error) { logshit("Bad config file (first error on line %d)!\n", error); return false; } + logshit("Daemon Version: %x, Latest Version: %x, Is Outdated?: %s\n", daemon_ver, LATEST_DAEMON_VERSION, daemon_ver == LATEST_DAEMON_VERSION ? "No" : "Yes"); + } + + return (daemon_ver == LATEST_DAEMON_VERSION); +} + +void build_iovec(struct iovec** iov, int* iovlen, const char* name, const void* val, size_t len) { + int i; + + if (*iovlen < 0) + return; + + i = *iovlen; + *iov = (struct iovec*)realloc((void*)(*iov), sizeof(struct iovec) * (i + 2)); + if (*iov == NULL) { + *iovlen = -1; + return; + } + + (*iov)[i].iov_base = strdup(name); + (*iov)[i].iov_len = strlen(name) + 1; + ++i; + + (*iov)[i].iov_base = (void*)val; + if (len == (size_t)-1) { + if (val != NULL) + len = strlen((const char*)val) + 1; + else + len = 0; + } + (*iov)[i].iov_len = (int)len; + + *iovlen = ++i; +} + + +int mountfs(const char* device, const char* mountpoint, const char* fstype, const char* mode, uint64_t flags) +{ + struct iovec* iov = NULL; + int iovlen = 0; + int ret; + + build_iovec(&iov, &iovlen, "fstype", fstype, -1); + build_iovec(&iov, &iovlen, "fspath", mountpoint, -1); + build_iovec(&iov, &iovlen, "from", device, -1); + build_iovec(&iov, &iovlen, "large", "yes", -1); + build_iovec(&iov, &iovlen, "timezone", "static", -1); + build_iovec(&iov, &iovlen, "async", "", -1); + build_iovec(&iov, &iovlen, "ignoreacl", "", -1); + + if (mode) { + build_iovec(&iov, &iovlen, "dirmask", mode, -1); + build_iovec(&iov, &iovlen, "mask", mode, -1); + } + + logshit("##^ [I] Mounting %s \"%s\" to \"%s\"\n", fstype, device, mountpoint); + ret = nmount(iov, iovlen, flags); + if (ret < 0) { + logshit("##^ [E] Failed: %d (errno: %d).\n", ret, errno); + goto error; + } + else { + logshit("##^ [I] Success.\n"); + } + +error: + return ret; +} + +uint32_t Launch_Daemon(const char* TITLE_ID) { + uint32_t userId = -1; + + int libcmi = sceKernelLoadStartModule("/system/common/lib/libSceSystemService.sprx", 0, NULL, 0, 0, 0); + if (libcmi > 0) + { + + LncAppParam param; + param.sz = sizeof(LncAppParam); + param.user_id = userId; + param.app_opt = 0; + param.crash_report = 0; + param.check_flag = SkipSystemUpdateCheck; + + return sceLncUtilLaunchApp(TITLE_ID, NULL, ¶m); + + } + + return 0; +} + +bool boot_daemon_services() +{ + + char buff[100]; + char IPC_BUFFER[100]; + int fd = -1; + logshit("Booting Daemon Services\n"); + + if (!if_exists(DAEMON_PATH) || !is_daemon_outdated()) + { + if (!!mountfs("/dev/da0x4.crypt", "/system", "exfatfs", "511", MNT_UPDATE)) + { + logshit("mounting /system failed with %s.\n", strerror(errno)); + return false; + } + else + { + + logshit("Remount Successful\n"); + //Delete the folder and all its files + rmtree(DAEMON_PATH); + mkdir(DAEMON_PATH, 0777); + mkdir(DAEMON_PATH"/Media", 0777); + mkdir(DAEMON_PATH"/sce_sys", 0777); + + if (copyFile("/mnt/sandbox/pfsmnt/ITEM00001-app0/Media/jb.prx", DAEMON_PATH"/Media/jb.prx") != -1 && + copyFile("/system/vsh/app/NPXS21007/sce_sys/param.sfo", DAEMON_PATH"/sce_sys/param.sfo") != -1) + { + + if ((fd = open(DAEMON_PATH"/eboot.bin", O_WRONLY | O_CREAT | O_TRUNC, 0777)) > 0 && fd != -1) { + write(fd, daemon_eboot, daemon_eboot_size); + close(fd); + + snprintf(&buff[0], 99, "[Daemon]\nversion=%i\n", LATEST_DAEMON_VERSION); + fd = open(DAEMON_PATH"/daemon.ini", O_WRONLY | O_CREAT | O_TRUNC, 0777); + if (fd >= 0) + { + write(fd, &buff[0], strlen(&buff[0])); + close(fd); + } + else { + logshit("Creating the Daemon ini failed to create: %s\n", strerror(errno)); + return false; + } + + chmod(DAEMON_PATH"/daemon.ini", 0777); + IPCSendCommand(DEAMON_UPDATE, (uint8_t *)&IPC_BUFFER[0]); + + } + else + { + logshit("Creating the Daemon eboot failed to create: %s\n", strerror(errno)); + return false; + } + } + else + { + logshit("Copying Daemon files failed\n"); + return false; + } + } + } + + uint32_t appid = sceLncUtilGetAppId("ITEM00002"); + //Launch Daemon with silent + if ((appid & ~0xFFFFFF) != 0x60000000) { + appid = Launch_Daemon("ITEM00002"); + logshit("Launched Daemon AppId: %x\n", appid); + } + else + logshit("Found Daemon AppId: %x\n", appid); + + + + return true; + +} +/* *********************** daemon shit **********************/ \ No newline at end of file diff --git a/itemz-loader/source/embed_daemon.s b/itemz-loader/source/embed_daemon.s new file mode 100644 index 0000000..872494a --- /dev/null +++ b/itemz-loader/source/embed_daemon.s @@ -0,0 +1,15 @@ +.intel_syntax noprefix +.section .rodata + +# elf +.global daemon_eboot +.type daemon_eboot, @object +.align 4 +daemon_eboot: + .incbin "../itemz-daemon/bin/eboot.bin" +daemon_eboot_end: + .global daemon_eboot_size + .type daemon_eboot_size, @object + .align 4 +daemon_eboot_size: + .int daemon_eboot_end - daemon_eboot \ No newline at end of file diff --git a/itemz-loader/source/ini.c b/itemz-loader/source/ini.c new file mode 100644 index 0000000..f8a3ea3 --- /dev/null +++ b/itemz-loader/source/ini.c @@ -0,0 +1,298 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include + +#include "ini.h" + +#if !INI_USE_STACK +#if INI_CUSTOM_ALLOCATOR +#include +void* ini_malloc(size_t size); +void ini_free(void* ptr); +void* ini_realloc(void* ptr, size_t size); +#else +#include +#define ini_malloc malloc +#define ini_free free +#define ini_realloc realloc +#endif +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. Return s. */ +static char* rstrip(char* s) +{ + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) + *p = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to NUL at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Similar to strncpy, but ensures dest (size bytes) is + NUL-terminated, and doesn't pad with NULs. */ +static char* strncpy0(char* dest, const char* src, size_t size) +{ + /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */ + size_t i; + for (i = 0; i < size - 1 && src[i]; i++) + dest[i] = src[i]; + dest[i] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; +#else + char* line; + size_t max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC && !INI_USE_STACK + char* new_line; + size_t offset; +#endif + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; + + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + +#if !INI_USE_STACK + line = (char*)ini_malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, (int)max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC && !INI_USE_STACK + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = ini_realloc(line, max_line); + if (!new_line) { + ini_free(line); + return -2; + } + line = new_line; + if (reader(line + offset, (int)(max_line - offset), stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = lskip(rstrip(start)); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; +#if INI_CALL_HANDLER_ON_NEW_SECTION + if (!HANDLER(user, section, NULL, NULL) && !error) + error = lineno; +#endif + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) + *end = '\0'; +#endif + value = lskip(value); + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else if (!error) { + /* No '=' or ':' found on name[=:]value line */ +#if INI_ALLOW_NO_VALUE + *end = '\0'; + name = rstrip(start); + if (!HANDLER(user, section, name, NULL) && !error) + error = lineno; +#else + error = lineno; +#endif + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + ini_free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/itemz-loader/source/lang.c b/itemz-loader/source/lang.c new file mode 100644 index 0000000..f592d7e --- /dev/null +++ b/itemz-loader/source/lang.c @@ -0,0 +1,134 @@ + +#include "lang.h" +#include "ini.h" +#include "Header.h" + +LangStrings* stropts; +bool lang_is_initialized = false; +int32_t PS4GetLang() { + int32_t lang; + + if (sceSystemServiceParamGetInt(1, &lang) != 0) { + logshit("Unable to qet language code"); + return 0x1; + } + + return lang; +} + +char* getLangSTR(enum Lang_STR str) +{ + + if (lang_is_initialized) { + if (str > LANG_NUM_OF_STRINGS) { + return stropts->strings[STR_NOT_FOUND]; + } + else + { + if (stropts->strings[str] != NULL) + return stropts->strings[str]; + else + return stropts->strings[STR_NOT_FOUND]; + } + } + else + return "ERROR: Lang has not loaded"; +} + + +static int load_lang_ini(void* user, const char* section, const char* name, + const char* value) +{ + LangStrings* set = (LangStrings*)user; + +#define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0 + + if (MATCH("LOADER", "REINSTALL_PKG")) { + snprintf(set->strings[REINSTALL_PKG], 255, "%s", value); + } + else if (MATCH("LOADER", "LOADER_ERROR")) { + snprintf(set->strings[LOADER_ERROR], 255, "%s", value); + } + else if (MATCH("LOADER", "MORE_INFO")) { + snprintf(set->strings[MORE_INFO], 255, "%s", value); + } + else if (MATCH("LOADER", "DOWNLOADING_UPDATE")) { + snprintf(set->strings[DOWNLOADING_UPDATE], 255, "%s", value); + } + else if (MATCH("LOADER", "INI_FAIL")) { + snprintf(set->strings[INI_FAIL], 255, "%s", value); + } + else if (MATCH("LOADER", "UPDATE_REQ")) { + snprintf(set->strings[UPDATE_REQ], 255, "%s", value); + } + else if (MATCH("LOADER", "UPDATE_APPLIED")) { + snprintf(set->strings[UPDATE_APPLIED], 255, "%s", value); + } + else if (MATCH("LOADER", "OPT_UPDATE")) { + snprintf(set->strings[OPT_UPDATE], 255, "%s", value); + } + else if (MATCH("LOADER", "LOADER_FATAL")) { + snprintf(set->strings[LOADER_FATAL], 255, "%s", value); + } + else if (MATCH("LOADER", "FATAL_JB")) { + snprintf(set->strings[FATAL_JB], 255, "%s", value); + } + else if (MATCH("LOADER", "FATAL_REJAIL")) { + snprintf(set->strings[FATAL_REJAIL], 255, "%s", value); + } + else if (MATCH("LOADER", "EXT_NOT_SUPPORTED")) { + snprintf(set->strings[EXT_NOT_SUPPORTED], 255, "%s", value); + } + else if (MATCH("LOADER", "SWU_ERROR")) { + snprintf(set->strings[SWU_ERROR], 255, "%s", value); + } + else if (MATCH("LOADER", "RSA_LOAD")) { + snprintf(set->strings[RSA_LOAD], 255, "%s", value);// + } + else if (MATCH("LOADER", "RSA_FAILED")) { + snprintf(set->strings[RSA_FAILED], 255, "%s", value);// + } + else if (MATCH("LOADER", "SECURE_FAIL")) { + snprintf(set->strings[SECURE_FAIL], 255, "%s", value); + } + else if (MATCH("LOADER", "STR_NOT_FOUND")) { + snprintf(set->strings[STR_NOT_FOUND], 255, "%s", value); + } + else if (MATCH("LOADER", "PING_FAILED")) { + snprintf(set->strings[PING_FAILED], 255, "%s", value); + } + + return 1; + +} + +bool LoadLangs(int LangCode) +{ + + stropts = (LangStrings*)malloc(sizeof(LangStrings)); + if (stropts != NULL) { + for (int i = 0; i < LANG_NUM_OF_STRINGS; i++) { + stropts->strings[i] = calloc(256, sizeof(char)); + + if (stropts->strings[i] == NULL) { + msgok("Failed to load Language(s)... Failed to allocate stropts->strings[%i]", i); + return false; + } + } + + char tmp[100]; + snprintf(tmp, 99, LANG_DIR, LangCode); + + int error = ini_parse(tmp, load_lang_ini, stropts); + if (error) { + logshit("Bad config file (first error on line %d)!\n", error); + return false; + } + else + lang_is_initialized = true; + } + else + return false; + + return true; +} \ No newline at end of file diff --git a/itemz-loader/source/main.c b/itemz-loader/source/main.c new file mode 100644 index 0000000..b648312 --- /dev/null +++ b/itemz-loader/source/main.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Header.h" +#include +#include +#include "lang.h" +#include "ini.h" + +int ret; +int libnetMemId = 0; +int libsslCtxId = 0; +int libhttpCtxId = 0; +bool restart_nessary = false; + +void is_restart_needed_for_daemon(void* arg){ + + + logshit("is_restart_needed_for_daemon (%i)\n", atoi(arg)); + uint32_t appid = sceLncUtilGetAppId("ITEM00002"); + //Launch Daemon with silent + if ((appid & ~0xFFFFFF) != 0x60000000){ + restart_nessary = true; + logshit("Restart needed for Daemon!"); + } + else + logshit("Found Daemon AppId: %x, No restart needed\n", appid); +} + +int main(int argc, char* argv[]) +{ + init_itemzGL_modules(); + + int libjb = -1; + + sceSystemServiceHideSplashScreen(); + sceCommonDialogInitialize(); + sceMsgDialogInitialize(); + + + if (!LoadLangs(PS4GetLang())) { + if (!LoadLangs(0x01)) { + msgok("Failed to load Backup Lang...\nThe App is unable to continue"); + goto exit_no_lang; + } + else + logshit("Loaded the backup, lang %i failed to load", PS4GetLang()); + } + + libjb = sceKernelLoadStartModule("/app0/Media/jb.prx", 0, NULL, 0, 0, 0); + int ret = sceKernelDlsym(libjb, "jbc_run_as_root", (void**)&jbc_run_as_root); + if (ret >= 0){ + logshit("jbc_run_as_root resolved from PRX\n"); + if (!jbc_run_as_root){ + msgok("%s: %x\n", getLangSTR(FATAL_JB),ret); + goto err; + } + else{ + jbc_run_as_root(loader_rooted, NULL, CWD_ROOT); + logshit("jbc_run_as_root() succesful\n"); + } + } + else{ + msgok("%s: %x\n", getLangSTR(FATAL_JB),ret); goto err; + } + + if(atoi(argv[0]) < 3){ + jbc_run_as_root(is_restart_needed_for_daemon, argv[0], CWD_ROOT); + if(restart_nessary){ + char buffer[256]; + sprintf(buffer, "%i", atoi(argv[0])+1); + const char* argv[2] = { buffer, NULL }; + sceSystemServiceLoadExec("/app0/eboot.bin", argv); + } + } + + + logshit("[Itemz-loader:%s:%i] ----- Launching() ---\n", __FUNCTION__, __LINE__); + orbisPadFinish(); + if (sceSystemServiceLoadExec("/app0/ItemzCore.self", 0) == 0) + logshit("[Itemz-loader:%s:%i] ----- Launched (shouldnt see) ---\n", __FUNCTION__, __LINE__); + +err: + msgok("%s\n\n%s\n", getLangSTR(LOADER_ERROR), getLangSTR(MORE_INFO)); +exit_no_lang: + copyFile("/user/app/ITEM00001/logs/loader.log", "/usb0/itemzflow/loader.log"); + mkdir("/user/recovery.flag", 0777); + + return sceSystemServiceLoadExec("exit", 0); +} + +void catchReturnFromMain(int exit_code) +{ +} diff --git a/itemz-loader/source/msgs.c b/itemz-loader/source/msgs.c new file mode 100644 index 0000000..b35f7e3 --- /dev/null +++ b/itemz-loader/source/msgs.c @@ -0,0 +1,135 @@ +#include "Header.h" +#include +#include +#include "lang.h" +#define ORBIS_TRUE 1 + +int Confirmation_Msg(const char* msg) +{ + + sceMsgDialogTerminate(); + //ds + + sceMsgDialogInitialize(); + OrbisMsgDialogParam param; + OrbisMsgDialogParamInitialize(¶m); + param.mode = ORBIS_MSG_DIALOG_MODE_USER_MSG; + + OrbisMsgDialogUserMessageParam userMsgParam; + memset(&userMsgParam, 0, sizeof(userMsgParam)); + userMsgParam.msg = msg; + userMsgParam.buttonType = 1; + param.userMsgParam = &userMsgParam; + // cv + if (0 < sceMsgDialogOpen(¶m)) + return NO; + + OrbisCommonDialogStatus stat; + // + while (1) { + stat = sceMsgDialogUpdateStatus(); + if (stat == ORBIS_COMMON_DIALOG_STATUS_FINISHED) { + + OrbisMsgDialogResult result; + memset(&result, 0, sizeof(result)); + + sceMsgDialogGetResult(&result); + + return result.buttonId; + } + } + //c + return NO; +} + +int msgok(char* format, ...) +{ + int ret = 0; + sceSysmoduleLoadModule(ORBIS_SYSMODULE_MESSAGE_DIALOG); + + sceMsgDialogTerminate(); + + char buff[1024]; + char buffer[1000]; + memset(buff, 0, 1024); + + va_list args; + va_start(args, format); + vsprintf(&buff[0], format, args); + va_end(args); + + strcpy(&buffer[0], &buff[0]); + + logshit(&buff[0]); + + sceMsgDialogInitialize(); + OrbisMsgDialogParam param; + OrbisMsgDialogParamInitialize(¶m); + param.mode = ORBIS_MSG_DIALOG_MODE_USER_MSG; + + OrbisMsgDialogUserMessageParam userMsgParam; + memset(&userMsgParam, 0, sizeof(userMsgParam)); + userMsgParam.msg = buffer; + userMsgParam.buttonType = ORBIS_MSG_DIALOG_BUTTON_TYPE_OK; + param.userMsgParam = &userMsgParam; + + if (sceMsgDialogOpen(¶m) < 0) + ret = -1; + + + OrbisCommonDialogStatus stat; + + while (1) + { + stat = sceMsgDialogUpdateStatus(); + if (stat == ORBIS_COMMON_DIALOG_STATUS_FINISHED) + { + OrbisMsgDialogResult result; + memset(&result, 0, sizeof(result)); + + if (0 > sceMsgDialogGetResult(&result)) + ret = -2; + + sceMsgDialogTerminate(); + break; + } + } + + return ret; +} + +int loadmsg(char* format, ...) +{ + sceSysmoduleLoadModule(ORBIS_SYSMODULE_MESSAGE_DIALOG); + + sceMsgDialogInitialize(); + + char buff[1024]; + memset(&buff[0], 0, 1024); + + va_list args; + va_start(args, format); + vsprintf(&buff[0], format, args); + va_end(args); + + OrbisMsgDialogButtonsParam buttonsParam; + OrbisMsgDialogUserMessageParam messageParam; + OrbisMsgDialogParam dialogParam; + + OrbisMsgDialogParamInitialize(&dialogParam); + + memset(&buttonsParam, 0x00, sizeof(buttonsParam)); + memset(&messageParam, 0x00, sizeof(messageParam)); + + dialogParam.userMsgParam = &messageParam; + dialogParam.mode = ORBIS_MSG_DIALOG_MODE_USER_MSG; + + messageParam.buttonType = ORBIS_MSG_DIALOG_BUTTON_TYPE_WAIT; + + messageParam.msg = buff; + + sceMsgDialogOpen(&dialogParam); + + return 0; +} + diff --git a/itemzflow/Makefile b/itemzflow/Makefile new file mode 100644 index 0000000..33af518 --- /dev/null +++ b/itemzflow/Makefile @@ -0,0 +1,30 @@ + + +ifndef ORBISDEV +$(error ORBISDEV, is not set) +endif + +target ?= ps4_elf_sce +TargetFile=homebrew.elf +AUTH_INFO = 000000000000000000000000001C004000FF000000000080000000000000000000000000000000000000008000400040000000000000008000000000000000080040FFFF000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + +include $(ORBISDEV)/make/ps4sdk.mk + +LinkerFlags += -ltag -lSceShellCoreUtil_stub -ldumper -lc++ -lc++abi -lc++experimental -luser_mem_sys -lkernel_stub -lSceLibcInternal_stub -lSceSysmodule_stub -lSceSystemService_stub -lSceNet_stub -lSceUserService_stub -lScePigletv2VSH_stub -lSceVideoOut_stub -lSceImeDialog_stub -lSceGnmDriver_stub -lorbis -lorbisGl -lScePad_stub -lSceCommonDialog_stub -lSceMsgDialog_stub -lSceAudioOut_stub -lSceIme_stub -lSceAppInstUtil_stub -lSceBgft_stub -lSceSysUtil_stub -lSceHttp_stub -lSceSsl_stub -lSceNetCtl_stub -lfreetype-gl -lSceFreeTypeOl_stub -lkernel_sys_stub -lSceLncUtil_stub -lSQLite -lSceSaveData_stub -lSceShellUIUtil_stub -lSceSysCore_stub +CompilerFlagsCpp += -fstack-protector-all -Wall -Werror -Wno-excess-initializers -DFMT_HEADER_ONLY # -DHAVE_SHADER_COMPILER +CompilerFlagsCpp += -std=c++17 -D_FILE_OFFSET_BITS=64 -Wno-c++11-narrowing -DHAVE_CONFIG_H -D_U_="__attribute__((unused))" -D__ORBIS__=1 -D_ORBIS_ -DNDEBUG -D_BSD_SOURCE -fno-exceptions -frtti +CompilerFlags += -D_FILE_OFFSET_BITS=64 +IncludePath += -I$(ORBISDEV)/usr/include -I$(ORBISDEV)/usr/include/c++/v1 -I$(ORBISDEV)/usr/include/orbis +IncludePath += -I$(ORBISDEV)/usr/include/orbis/freetype-gl + + +install: + @cp $(OutPath)/homebrew.self /hostapp/homebrew.self + @echo "Installed!" +oelf: + orbis-elf-create bin/homebrew.elf bin/homebrew.oelf >/dev/null 2>&1 + +eboot: + python2 $(ORBISDEV)/bin/make_fself.py --auth-info $(AUTH_INFO) bin/homebrew.oelf bin/ItemzCore.self +pkg_build: + pkgTool pkg_build ../App-Media-Assets/itemzflow.gp4 . diff --git a/itemzflow/build.sh b/itemzflow/build.sh new file mode 100644 index 0000000..2194298 --- /dev/null +++ b/itemzflow/build.sh @@ -0,0 +1 @@ +cd ../libyaml-cpp && make -j24 && make install && cd ../libdumper/ && make -j24 && make install && cd ../itemz-daemon/ && make clean && make -j24 && make oelf && make eboot && cd ../itemzflow/ && make clean && make -j24 && make oelf && make eboot \ No newline at end of file diff --git a/itemzflow/cp.sh b/itemzflow/cp.sh new file mode 100644 index 0000000..c6954cb --- /dev/null +++ b/itemzflow/cp.sh @@ -0,0 +1,11 @@ +#!/bin/bash +cp -rf ./source/[GLES2_]* /mnt/d/GLES_App/source +cp -rf ./source/lang.cpp /mnt/d/GLES_App/source +cp -rf ./include/shaders/ /mnt/d/GLES_App/inc/ +cp -rf ./include/defines.h /mnt/d/GLES_App/inc/defines.h +cp -rf ./include/GLES2_common.h /mnt/d/GLES_App/inc/GLES2_common.h +cp -rf ./include/utils.h /mnt/d/GLES_App/inc/utils.h +cp -rf ./include/lang.h /mnt/d/GLES_App/inc/lang.h +cp -rf ./source/ls_dir.cpp /mnt/d/GLES_App/source +cp -rf ./source/demo-font.cpp /mnt/d/GLES_App/source +cp -rf ./lang.ini /mnt/d/GLES_App/lang/lang.ini diff --git a/itemzflow/include/GLES2_common.h b/itemzflow/include/GLES2_common.h new file mode 100644 index 0000000..52129c0 --- /dev/null +++ b/itemzflow/include/GLES2_common.h @@ -0,0 +1,558 @@ +#pragma once +#include +/// from demo-font.c +#include +#include +#include +#include +#include +#include +#ifdef __ORBIS__ +#include +#endif +#include +#include + + +typedef enum vbo_status +{ + EMPTY, + APPEND, + CLOSED, + ASK_REFRESH, + IN_ATLAS, + IN_ATLAS_APPEND, + IN_ATLAS_CLOSED +} vbo_status; + +struct multi_t +{ + ivec4 pos = (ivec4){0, 0, 0, 0}; + bool is_active = false; +}; + +struct item_t +{ + std::string id, name, image, package, + version, picpath, sfopath; //App Data + + int token_c, HDD_count = 0; // count + GLuint texture; // the item icon + // if the item icon is cached in atlas, use UV + vec4 uv; // normalized p1, p2 + multi_t multi_sel; + + std::unordered_map extra_sfo_data; + bool is_ext_hdd = false, is_fpkg = true, is_dumpable = false, app_vis = true, is_ph = false; + // need to add index for texture atlas +}; + +struct layout_t +{ + vec4 bound_box; // total field size, in px + ivec2 fieldsize, // total field size, in items number + item_sel, // current selected item into field + page_sel; // page_selection: current, max page + int retries; // check for what's used for and remove + // an array of items + std::vector item_d; // item_data array + int item_c, // item_count + curr_item, // current selected item: + f_size, // field size + f_sele; // selected in field + vec4* f_rect = NULL; // field rectangle array + // each layout will hold its ft-gl vertex buffer object + vertex_buffer_t* vbo = NULL; + enum vbo_status vbo_s; // vbo_status + // layout status + bool is_shown = false, is_active = false, fs_is_active = false; // to control selected_item (deprecated by active_p) +}; + + +struct _ent { + std::string fname, fname2; + uint32_t sz; + int lvl; +}; + + + + +// freetype-gl pass last composed Text_Length in pixel, we use to align text! + +/* + GLES2 layout rework, v2 +*/ + +/* + todo: we need to differentiate and made use of vbo_status + to avoid useless pushes to gpu +*/ + +/* + auxiliary array of item_index_t: + - shared for Search/Groups + - the query to save search results; +*/ +enum SH_type +{ + USE_COLOR, + USE_UTIME, + CUSTOM_BADGE, + NUM_OF_PROGRAMS +}; + +typedef enum token_name +{ + ID, + NAME, + IMAGE, + PACKAGE, + VERSION, + PICPATH, + SFO_PATH, + SIZE, + AUTHOR, + APPTYPE, + PV, + TOTAL_NUM_OF_TOKENS, + // should match NUM_OF_USER_TOKENS +} token_name; + +typedef enum { + ITEMZCORE_GENERAL_ERROR = 0xDEADBEEF, + ITEMZCORE_PRX_RESOLVE_ERROR = 0xCCCCCCC, + ITEMZCORE_EINVAL = 0xEEEEEEE, + ITEMZCORE_QUEUE_FULL = 0xAAAAAAA, + ITEMZCORE_NULL_BUFFER = 0x123123, + ITEMZCORE_SUCCESS = 0 +} ITEMZCORE_ERRORS; + +typedef struct +{ + char* name; +} entry_t; + +typedef enum pt_status +{ + CANCELED = -1, + READY, + PAUSED, + RUNNING, + COMPLETED +} pt_status; + +typedef enum badge_t +{ + AVAILABLE = 1, + SOON, + SELECTED, + NUM_OF_BADGES +} badge_t; + +typedef enum +{ + NO_CATEGORY_FILTER, + FILTER_RETAIL_GAMES, + FILTER_FPKG, + FILTER_GAMES, + FILTER_HOMEBREW = 4, + NUMB_OF_CATEGORIES = 4 +} Sort_Category; + +#define ORBIS_LIBC_MALLOC_MANAGED_SIZE_VERSION (0x0001U) + +#ifndef SCE_LIBC_INIT_MALLOC_MANAGED_SIZE +#define SCE_LIBC_INIT_MALLOC_MANAGED_SIZE(mmsize) do { \ + mmsize.size = sizeof(mmsize); \ + mmsize.version = ORBIS_LIBC_MALLOC_MANAGED_SIZE_VERSION; \ + mmsize.reserved1 = 0; \ + mmsize.maxSystemSize = 0; \ + mmsize.currentSystemSize = 0; \ + mmsize.maxInuseSize = 0; \ + mmsize.currentInuseSize = 0; \ +} while (0) +#endif + +typedef struct LibcMallocManagedSize { + uint16_t size; + uint16_t version; + uint32_t reserved1; + size_t maxSystemSize; + size_t currentSystemSize; + size_t maxInuseSize; + size_t currentInuseSize; +} LibcMallocManagedSize; + +typedef enum { + NA_SORT = 0, + TID_ALPHA_SORT, + TITLE_ALPHA_SORT, +} Sort_Multi_Sel; + +typedef enum { + POWER_OFF_OPT = 0, + RESTART_OPT, + SUSPEND_OPT, +} Power_control_sel; + +typedef enum { + MOVE_APP = 0, + MOVE_DLC, + MOVE_PATCH +} MOVE_OPTIONS; + +typedef enum +{ + RESTORE_APP = 0, + RESTORE_DLC, + RESTORE_PATCH +} RESTORE_OPTIONS; + +typedef enum { + UNINSTALL_GAME = 0, + UNINSTALL_PATCH, + UNINSTALL_DLC, +} Uninstall_Multi_Sel; + +typedef enum { + SHELLUI_SETTINGS_MENU = 0, + SHELLUI_POWER_SAVE +} ShellUI_Multi_Sel; + +typedef enum { + REBUILD_ALL = 0, + REBUILD_DLC, + REBUILD_REACT, +} Rebuild_db_Multi_Sel; + +typedef enum { + GM_INVAL = -1, + BACKUP_GAME_SAVE = 0, + RESTORE_GAME_SAVE, + DELETE_GAME_SAVE +} SAVE_Multi_Sel; + +typedef enum { + SEL_DUMP_ALL = 0, + SEL_BASE_GAME, + SEL_GAME_PATCH, + SEL_REMASTER, + SEL_DLC, + SEL_FPKG, + SEL_RESET = 999, + SEL_RUNNING_NOW = 696969 +} Dump_Multi_Sels; + + +#define FIRST_MULTI_LINE 1 +#define RESET_MULTI_SEL 0 + + +typedef enum { + NOTIFI_INFO, + NOTIFI_WARNING, + NOTIFI_SUCCESS, + NOTIFI_ERROR, + NOTIFI_GAME, + NOTIFI_KOFI, + NOTIFI_PROFILE, + NUM_OF_NOTIS +} NOTI_LEVELS; + +#define FIRST_MULTI_LINE 1 +#define RESET_MULTI_SEL 0 + +typedef enum { + DUMPER_PATH_OPTION, + CHECK_FOR_UPDATE_OPTION, + SORT_BY_OPTION, + HOME_MENU_OPTION, + REBUILD_DB_OPTION, + THEME_OPTION, + BACKGROUND_MP3_OPTION, + SHOW_BUTTON_OPTION, + OPEN_SHELLUI_MENU, + IF_PKG_INSTALLER_OPTION, + POWER_CONTROL_OPTION, + SAVE_ITEMZFLOW_SETTINGS +} Settings; + +typedef enum +{ + DOWNLOAD_COVERS_OPTION = 12, + RESET_THEME_OPTION = 13, + REFLECTION_OPTION = 14, + CHANGE_BACKGROUND_OPTION = 15, + COVER_MESSAGE_OPTION = 16, + FONT_OPTION = 11, + NUMB_OF_EXTRAS = 17, + +} Advanced_Settings; + +#define ARRAYSIZE(a) ((sizeof(a) / sizeof(*(a))) / ((size_t)(!(sizeof(a) % sizeof(*(a)))))) + +typedef enum view_t +{ + RANDOM = -1, + ITEMzFLOW = 0, + ITEM_PAGE = 1, + ITEM_SETTINGS = 2, + FILE_BROWSER = 3 +} view_t; +void GLES2_render_list(enum view_t v); + +struct CVec +{ + uint32_t sz, cur; // In BYTES + void* ptr; +}; + +enum views +{ + ON_ITEMzFLOW = 8, // 8 + +}; + +typedef struct { float s, t; } st; +typedef struct { float x, y, z; } xyz; +typedef struct { float r, g, b, a; } rgba; + +typedef struct retry_t +{ + GLuint tex; // the real texture + bool exists; +} retry_t; + +typedef enum +{ + Launch_Game_opt, + Dump_Game_opt, + Uninstall_opt, + Game_Save_opt, + Trainers_opt, + Hide_App_opt, + Change_icon_opt, + Change_name_opt, + Move_apps_opt, + Restore_apps_opt, + +} Ops_for_cf; + +// menu entry strings +#define LPANEL_Y (5) + +#if defined(__ORBIS__) + +#define UP (111) +#define DOW (116) +#define LEF (113) +#define RIG (114) +#define CRO ( 53) +#define CIR ( 54) +#define TRI ( 28) +#define SQU ( 39) +#define OPT ( 32) +#define L1 ( 10) +#define R1 ( 11) +#define L2 (222) +#else + +#define UP (98) +#define DOW (104) +#define LEF (100) +#define RIG (102) +#define CRO ( 53) +#define CIR ( 54) +#define TRI ( 28) +#define SQU ( 39) +#define OPT ( 32) +#define L1 ( 10) +#define R1 ( 27) +#define L2 ( 12) +#endif + + +extern GLuint fallback_t; + +// for Settings (options_panel) +extern bool use_reflection, +use_pixelshader; + +int count_availables_json(void); +void refresh_atlas(void); + +// from GLES2_rects.c +void on_GLES2_Update1(double time); + +// from GLES2_textures.c +void on_GLES2_Init_icons(int view_w, int view_h); +void on_GLES2_Update(double time); +//void on_GLES2_Render_icons(int num); +//void on_GLES2_Render_icon(enum SH_type SL_program, GLuint texture, int num, vec4* frect, vec4* uv); + +void on_GLES2_Render_box(vec4* frect); +void on_GLES2_Final(void); + +// from pixelshader.c +void pixelshader_render(GLuint SL_program, vertex_buffer_t* vbo, vec2* resolution); +void pixelshader_init(int width, int height); +void pixelshader_fini(void); + +void ORBIS_RenderSubMenu(int num); + +// GLES2_font.c +bool GLES2_fonts_from_ttf(const char* path); +void GLES2_init_submenu(void); +void ftgl_render_vbo(vertex_buffer_t* vbo, vec3* offset); + +void escalate_priv(void); +int Start_IF_internal_Services(int reboot_num); +int pingtest(int libnetMemId, int libhttpCtxId, const char* src); + +int df(std::string mountPoint, std::string &out); + +int get_item_index(layout_t* l); +// from GLES2_scene_v2.c +void GLES2_layout_init(int req_item_count, layout_t *l); + +vertex_buffer_t* vbo_from_rect(vec4* rect); + +void GLES2_UpdateVboForLayout(layout_t* l); + +int layout_fill_item_from_list(layout_t *l, std::vector &i_list); + +void fw_action_to_cf(int button); + +void GLES2_render_menu(int unused); + +// from GLES2_scene.c +void init_ItemzCore(int w, int h); +void Render_ItemzCore(void); +void fw_action_to_cf(int button); +//void X_action_dispatch(int action, layout_t *l); + +/// pthreads used in GLES2_q.c + +/* normalized rgba colors */ +extern vec4 sele, // default for selection (blue) +grey, // rect fg +white, +col; // text fg + +extern ivec4 menu_pos; +extern double u_t; + +extern std::string completeVersion; + +void GLES2_Draw_sysinfo(void); +void GLES2_refresh_sysinfo(void); + +// disk free percentages +extern double dfp_hdd, dfp_ext, dfp_now; +extern layout_t *active_p, ls_p, setting_p; + +// GLES2_layout +void layout_update_fsize(layout_t* l); +void layout_update_sele(layout_t* l, int movement); +void GLES2_Refresh_for_settings(); +void layout_set_active(layout_t* l); +void swap_panels(void); +void GLES2_render_layout_v2(layout_t* l, int unused); + + +// scene_v2.c +void set_cmp_token(const int index); +int struct_cmp_by_token(const void* a, const void* b); + +/// from shader-common.c +GLuint BuildProgram(const char* vShader, const char* fShader, int vs_size, int fs_size); +/* a double side (L/R) panel filemanager */ +extern layout_t fm_lp, fm_rp; + +int es2init_text(int width, int height); +void render_text(void); +void es2sample_end(void); + +/// from png.c +typedef struct { + /* for image data */ + const int width; + const int height; + const int size; + const GLenum gl_color_format; + const void* data; +} RawImageData; + +#if __cplusplus +extern "C" { +#endif +extern float tl; + +/* GLES2_panel.h */ +extern texture_font_t *main_font, // small + *sub_font, // left panel + *titl_font; // bigger + +// from GLES2_ani.c +RawImageData get_raw_image_data_from_png(const void *png_data, const int png_data_size, const char *fp); +void release_raw_image_data(const RawImageData *data); +GLuint load_texture(const GLsizei width, const GLsizei height, + const GLenum type, const GLvoid* pixels); +// higher level helper +GLuint load_png_asset_into_texture(const char* relative_path); +GLuint load_png_data_into_texture(const char* data, int size); +bool is_png_vaild(const char *relative_path, int *out_width, int *out_height); +extern vec2 tex_size; // last loaded png size as (w, h) +int writeImage(char* filename, int width, int height, int* buffer, char* title); +/// from timing.c +unsigned int get_time_ms(void); +bool if_exists(const char* path); +#if __cplusplus +} +#endif + +void add_text(vertex_buffer_t* buffer, texture_font_t* font, std::string text, vec4* color, vec2* pen); +void GLES2_ani_update(double time); +void GLES2_ani_fini(void); +void GLES2_ani_draw(void); +void on_GLES2_Render_icon(enum SH_type SL_program, GLuint texture, int num, vec4 *frect, vec4 *uv); +void GLES2_ani_init(int width, int height); +int ani_notify(NOTI_LEVELS lvl, std::string message, std::string detail); +int index_token_from_sfo(std::string *title, std::string *apptype, std::string *version, std::string path, int lang);; + /// from ls_dir() +int check_stat(const char *filepath); + +entry_t* get_item_entries(const char* dirpath, int* count); +void free_item_entries(entry_t* e, int num); + +// from my_rects.c +vec2 px_pos_to_normalized(vec2* pos); + + +// from lines_and_rects +void es2rndr_lines_and_rect(void); +void es2init_lines_and_rect(int width, int height); +void es2fini_lines_and_rect(void); + + +/// GLES2_rects.c +void ORBIS_RenderFillRects_init(int width, int height); +void ORBIS_RenderFillRects_rndr(void); +void ORBIS_RenderFillRects_fini(void); +void ORBIS_RenderDrawLines(const vec2* points, int count); +void ORBIS_RenderFillRects(enum SH_type SL_program, const vec4 *rgba, const vec4 *rects, int count); +void ORBIS_RenderDrawBox(enum SH_type SL_program, const vec4 *rgba, const vec4 *rect); +void GLES2_DrawFillingRect(vec4* frect, vec4* color, double* percentage); + +void check_tex_for_reload(int idx); +void check_n_load_textures(int idx); +void InitScene_4(int width, int height); +void InitScene_5(int width, int height); +void O_action_dispatch(void); +void realloc_app_retries(); +void index_items_from_dir(std::vector &out_vec, std::string dirpath, std::string dirpath2, Sort_Category category); +void get_stat_from_file(std::string &out_str, std::string &filepath_str); +std::string category_get_str(Sort_Category num); +std::string power_menu_get_str(Power_control_sel num); +std::string uninstall_get_str(Uninstall_Multi_Sel num); diff --git a/itemzflow/include/defines.h b/itemzflow/include/defines.h new file mode 100644 index 0000000..b5eb275 --- /dev/null +++ b/itemzflow/include/defines.h @@ -0,0 +1,380 @@ +#pragma once + +/* + ES2_goodness, a GLES2 playground on EGL + 2019-2021 masterzorag & LM + here follows the parts: +*/ + +// nfs or local stdio +//#define USE_NFS (1) +#if defined (USE_NFS) +#include +#endif + +#include "GLES2_common.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" + +#define ITEMZFLOW_TID "ITEM00001" +#define GL_NULL 0 +#define FM_ENTRIES (10) // max num we split bound_box Height, in px + + +#if defined (__ORBIS__) + +#include +#include +#include +#include //sceKernelIccSetBuzzer +#include +#include +#include +#include +#include +#include +#include "dialog.h" +#include +#include //O_CEAT +#include "md5.h" +#include "lang.h" +#include "dialog.h" + +#define ITEMZ_CUSTOM_SFO "/user/app/ITEM00001/sfos" + +#define SSL_HEAP_SIZE (304 * 1024) +#define HTTP_HEAP_SIZE MB(5) +#define NET_HEAP_SIZE MB(5) + +#define SCE_SYSMODULE_INTERNAL_SYS_CORE 0x80000004 +#define SCE_SYSMODULE_INTERNAL_NETCTL 0x80000009 +#define SCE_SYSMODULE_INTERNAL_HTTP 0x8000000A +#define SCE_SYSMODULE_INTERNAL_SSL 0x8000000B +#define SCE_SYSMODULE_INTERNAL_AUDIOOUT 0x80000001 +#define SCE_SYSMODULE_INTERNAL_AUDIOIN 0x80000002 +#define SCE_SYSMODULE_INTERNAL_NP_COMMON 0x8000000C +#define SCE_SYSMODULE_INTERNAL_SYSTEM_SERVICE 0x80000010 +#define SCE_SYSMODULE_INTERNAL_USER_SERVICE 0x80000011 +#define SCE_SYSMODULE_INTERNAL_APPINSTUTIL 0x80000014 +#define SCE_SYSMODULE_INTERNAL_NET 0x8000001C +#define SCE_SYSMODULE_INTERNAL_IPMI 0x8000001D +#define SCE_SYSMODULE_INTERNAL_VIDEO_OUT 0x80000022 +#define SCE_SYSMODULE_INTERNAL_BGFT 0x8000002A +#define SCE_SYSMODULE_INTERNAL_PRECOMPILED_SHADERS 0x80000064 + +#define SCE_LNC_ERROR_APP_NOT_FOUND 0x80940031 // Usually happens if you to launch an app not in app.db +#define SCE_LNC_UTIL_ERROR_ALREADY_INITIALIZED 0x80940018 +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING 0x8094000c +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED 0x80940010 +#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED 0x80940011 +#define SCE_LNC_UTIL_ERROR_APP_ALREADY_RESUMED 0x8094001e +#define SCE_LNC_UTIL_ERROR_APP_ALREADY_SUSPENDED 0x8094001d +#define SCE_LNC_UTIL_ERROR_APP_NOT_IN_BACKGROUND 0x80940015 +#define SCE_LNC_UTIL_ERROR_APPHOME_EBOOTBIN_NOT_FOUND 0x80940008 +#define SCE_LNC_UTIL_ERROR_APPHOME_PARAMSFO_NOT_FOUND 0x80940009 +#define SCE_LNC_UTIL_ERROR_CANNOT_RESUME_INITIAL_USER_NEEDED 0x80940012 +#define SCE_LNC_UTIL_ERROR_DEVKIT_EXPIRED 0x8094000b +#define SCE_LNC_UTIL_ERROR_IN_LOGOUT_PROCESSING 0x8094001a +#define SCE_LNC_UTIL_ERROR_IN_SPECIAL_RESUME 0x8094001b +#define SCE_LNC_UTIL_ERROR_INVALID_PARAM 0x80940005 +#define SCE_LNC_UTIL_ERROR_INVALID_STATE 0x80940019 +#define SCE_LNC_UTIL_ERROR_INVALID_TITLE_ID 0x8094001c +#define SCE_LNC_UTIL_ERROR_LAUNCH_DISABLED_BY_MEMORY_MODE 0x8094000d +#define SCE_LNC_UTIL_ERROR_NO_APP_INFO 0x80940004 +#define SCE_LNC_UTIL_ERROR_NO_LOGIN_USER 0x8094000a +#define SCE_LNC_UTIL_ERROR_NO_SESSION_MEMORY 0x80940002 +#define SCE_LNC_UTIL_ERROR_NO_SFOKEY_IN_APP_INFO 0x80940014 +#define SCE_LNC_UTIL_ERROR_NO_SHELL_UI 0x8094000e +#define SCE_LNC_UTIL_ERROR_NOT_ALLOWED 0x8094000f +#define SCE_LNC_UTIL_ERROR_NOT_INITIALIZED 0x80940001 +#define SCE_LNC_UTIL_ERROR_OPTICAL_DISC_DRIVE 0x80940013 +#define SCE_LNC_UTIL_ERROR_SETUP_FS_SANDBOX 0x80940006 +#define SCE_LNC_UTIL_ERROR_SUSPEND_BLOCK_TIMEOUT 0x80940017 +#define SCE_LNC_UTIL_ERROR_VIDEOOUT_NOT_SUPPORTED 0x80940016 +#define SCE_LNC_UTIL_ERROR_WAITING_READY_FOR_SUSPEND_TIMEOUT 0x80940021 +#define SCE_APP_INSTALLER_ERROR_DISC_NOT_INSERTED 0x80A30005 +#define SCE_SYSCORE_ERROR_LNC_INVALID_STATE 0x80aa000a +#define SCE_LNC_UTIL_ERROR_NOT_INITIALIZED 0x80940001 +#define ORBIS_KERNEL_EAGAIN 0x80020023 +#define SFO_PATCH_FLAG_REMOVE_COPY_PROTECTION (1 << 0) +#define SFO_ACCOUNT_ID_SIZE 8 +#define SFO_PSID_SIZE 16 +#define SFO_DIRECTORY_SIZE 32 + +#define asset_path(x) "/mnt/sandbox/pfsmnt/" ITEMZFLOW_TID "-app0/assets/" x +#define APP_PATH(x) "/user/app/ITEM00001/" x + +#else // on linux +#include + +#define APP_PATH(x) "./app_path/" x +#define asset_path(x) "./assets/" x + +#endif // defined (__ORBIS__) + +#define APP_HOME_DATA_FOLDER "/user/app/NPXS29998" +#define APP_HOME_DATA_TID "NPXS29998" +#define GL_CHECK(stmt) if(glGetError() != GL_NO_ERROR) msgok(FATAL, "GL_STATEMENT %s: %x", getLangSTR(FAILED_W_CODE),glGetError()); +#define PS4_OK 0 +#define INIT_FAILED -1 +#define DEBUG_SETTINGS_TID "NPXS20993" + +#define SCE_KERNEL_MAX_MODULES 256 +#define SCE_KERNEL_MAX_NAME_LENGTH 256 +#define SCE_KERNEL_MAX_SEGMENTS 4 +#define SCE_KERNEL_NUM_FINGERPRINT 20 + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(ar) (sizeof(ar) / sizeof((ar)[0])) +#endif + + +#define IS_INTERNAL 0 +#define DIFFERENT_HASH true +#define SAME_HASH false + +#define DKS_TIMEOUT 0x804101E2 + +#define UPDATE_NEEDED true +#define UPDATE_NOT_NEEDED false +#define TRUE 1 +#define FALSE 0 + + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 02 + +#define BUILD_YEAR_CH0 (__DATE__[ 7]) +#define BUILD_YEAR_CH1 (__DATE__[ 8]) +#define BUILD_YEAR_CH2 (__DATE__[ 9]) +#define BUILD_YEAR_CH3 (__DATE__[10]) + + +#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F') +#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r') +#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p') +#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y') +#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n') +#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l') +#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u') +#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S') +#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O') +#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N') +#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D') + + +#define BUILD_MONTH_CH0 \ + ((BUILD_MONTH_IS_OCT || BUILD_MONTH_IS_NOV || BUILD_MONTH_IS_DEC) ? '1' : '0') + +#define BUILD_MONTH_CH1 \ + ( \ + (BUILD_MONTH_IS_JAN) ? '1' : \ + (BUILD_MONTH_IS_FEB) ? '2' : \ + (BUILD_MONTH_IS_MAR) ? '3' : \ + (BUILD_MONTH_IS_APR) ? '4' : \ + (BUILD_MONTH_IS_MAY) ? '5' : \ + (BUILD_MONTH_IS_JUN) ? '6' : \ + (BUILD_MONTH_IS_JUL) ? '7' : \ + (BUILD_MONTH_IS_AUG) ? '8' : \ + (BUILD_MONTH_IS_SEP) ? '9' : \ + (BUILD_MONTH_IS_OCT) ? '0' : \ + (BUILD_MONTH_IS_NOV) ? '1' : \ + (BUILD_MONTH_IS_DEC) ? '2' : \ + /* error default */ '?' \ + ) + +#define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') +#define BUILD_DAY_CH1 (__DATE__[ 5]) + + + +// Example of __TIME__ string: "21:06:19" +// 01234567 + +#define BUILD_HOUR_CH0 (__TIME__[0]) +#define BUILD_HOUR_CH1 (__TIME__[1]) + +#define BUILD_MIN_CH0 (__TIME__[3]) +#define BUILD_MIN_CH1 (__TIME__[4]) + +#define BUILD_SEC_CH0 (__TIME__[6]) +#define BUILD_SEC_CH1 (__TIME__[7]) + + +#if VERSION_MAJOR > 100 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 100) + '0'), \ + (((VERSION_MAJOR % 100) / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#elif VERSION_MAJOR > 10 + +#define VERSION_MAJOR_INIT \ + ((VERSION_MAJOR / 10) + '0'), \ + ((VERSION_MAJOR % 10) + '0') + +#else + +#define VERSION_MAJOR_INIT \ + (VERSION_MAJOR + '0') + +#endif + +#if VERSION_MINOR > 100 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 100) + '0'), \ + (((VERSION_MINOR % 100) / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#elif VERSION_MINOR > 10 + +#define VERSION_MINOR_INIT \ + ((VERSION_MINOR / 10) + '0'), \ + ((VERSION_MINOR % 10) + '0') + +#else + +#define VERSION_MINOR_INIT \ + (VERSION_MINOR + '0') +#endif +// reuse this type to index texts around! +/// for icons.c, sprite.c +#define NUM_OF_TEXTURES (8) +#define NUM_OF_SPRITES (6) +#define ITEMZ_LOG "/user/app/ITEM00001/logs/itemzflow_app.log" +/// from GLES2_rects.c + +typedef struct sfo_context_s sfo_context_t; + +typedef struct sfo_key_pair_s { + const char* name; + int flag; +} sfo_key_pair_t; + +typedef struct { + uint32_t flags; + uint32_t user_id; + uint64_t account_id; + uint8_t* psid; + char* directory; + char* title_id; + char* title_name; +} sfo_patch_t; + +typedef struct { + uint32_t unk1; + uint32_t user_id; +} sfo_params_ids_t; +//#define SFO_MAGIC 0x46535000u +#define SFO_VERSION 0x0101u /* 1.1 */ + +typedef struct sfo_header_s { + uint32_t magic; + uint32_t version; + uint32_t key_table_offset; + uint32_t data_table_offset; + uint32_t num_entries; +} sfo_header_t; + +typedef struct list_node_s +{ + void* value; + struct list_node_s* next; +} list_node_t; + +typedef struct list_s +{ + list_node_t* head; + size_t count; +} list_t; + +typedef struct sfo_index_table_s { + uint16_t key_offset; + uint16_t param_format; + uint32_t param_length; + uint32_t param_max_length; + uint32_t data_offset; +} sfo_index_table_t; + +typedef struct sfo_param_params_s { + uint32_t unk1; + uint32_t user_id; + uint8_t unk2[32]; + uint32_t unk3; + char title_id_1[0x10]; + char title_id_2[0x10]; + uint32_t unk4; + uint8_t chunk[0x3B0]; +} sfo_param_params_t; + +typedef struct sfo_context_param_s { + char* key; + uint16_t format; + uint32_t length; + uint32_t max_length; + size_t actual_length; + uint8_t* value; +} sfo_context_param_t; + +struct sfo_context_s { + list_t* params; +}; + +typedef enum { + SFO_SAVE_RESIGN = 0, + SFO_CHANGE_GAME_NAME +} SFO_PATH_OPT; + +enum Settings_options +{ + CDN_SETTING, + TMP__SETTING, + HOME_MENU_SETTING, + INI_SETTING, + FNT__SETTING, + STORE_USB_SETTING, + CLEAR_CACHE_SETTING, + SHOW_INSTALL_PROG, + USE_PIXELSHADER_SETTING, + SAVE_SETTINGS, + NUM_OF_SETTINGS +}; + +int pingtest(int libnetMemId, int libhttpCtxId, const char* src); +int32_t netInit(void); + +/// from fileIO.c +void queue_panel_init(void); +int thread_find_by_item(int req_idx); +int thread_find_by_status(int req_idx, int req_status); +int thread_count_by_status(int req_status); +int thread_dispatch_index(void); + +/// from GLES2_badges +int scan_for_badges(layout_t* l, item_t* apps); +void GLES2_Init_badge(void); +void GLES2_Render_badge(int idx, vec4* rect); + +/// GLES2_filemamager +void fw_action_to_fm(int button); +void GLES2_render_filemanager(int unused); +void GLES2_render_queue(layout_t* l, int used); + +// UI panels new way, v3 +vec4 get_rect_from_index(const int idx, const layout_t* l, vec4* io); +bool filter_entry_on_IDs(const char* entry); +bool patch_sfo(const char* in_file_path, sfo_patch_t* patches); \ No newline at end of file diff --git a/itemzflow/include/dialog.h b/itemzflow/include/dialog.h new file mode 100644 index 0000000..27a93bb --- /dev/null +++ b/itemzflow/include/dialog.h @@ -0,0 +1,413 @@ +#ifndef _ORBIS_IME_H_ +#define _ORBIS_IME_H_ +#pragma once + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ORBIS_COMMON_DIALOG_MAGIC_NUMBER 0xC0D1A109 + + + +typedef enum OrbisCommonDialogStatus { + ORBIS_COMMON_DIALOG_STATUS_NONE = 0, + ORBIS_COMMON_DIALOG_STATUS_INITIALIZED = 1, + ORBIS_COMMON_DIALOG_STATUS_RUNNING = 2, + ORBIS_COMMON_DIALOG_STATUS_FINISHED = 3 +} OrbisCommonDialogStatus; + +typedef enum OrbisCommonDialogResult { + ORBIS_COMMON_DIALOG_RESULT_OK = 0, + ORBIS_COMMON_DIALOG_RESULT_USER_CANCELED = 1, +} OrbisCommonDialogResult; + +typedef struct OrbisCommonDialogBaseParam { + size_t size; + uint8_t reserved[36]; + uint32_t magic; +} OrbisCommonDialogBaseParam __attribute__ ((__aligned__(8))); + + +static inline void _sceCommonDialogSetMagicNumber( uint32_t* magic, const OrbisCommonDialogBaseParam* param ) +{ + *magic = (uint32_t)( ORBIS_COMMON_DIALOG_MAGIC_NUMBER + (uint64_t)param ); +} + +static inline void _sceCommonDialogBaseParamInit(OrbisCommonDialogBaseParam *param) +{ + memset(param, 0x0, sizeof(OrbisCommonDialogBaseParam)); + param->size = (uint32_t)sizeof(OrbisCommonDialogBaseParam); + _sceCommonDialogSetMagicNumber( &(param->magic), param ); +} + + +// Empty Comment +void sceCommonDialogInitialize(); +// Empty Comment +void sceCommonDialogIsUsed(); + + +#define ORBIS_SYSMODULE_IME_DIALOG 0x0096 + +#include + +typedef struct OrbisRtcTick { + uint64_t tick; +} OrbisRtcTick; + +typedef enum +{ + ORBIS_IME_DIALOG_STATUS_NONE = 0, + + ORBIS_IME_DIALOG_STATUS_RUNNING, + + ORBIS_IME_DIALOG_STATUS_FINISHED, + +} OrbisImeDialogStatus; + + +typedef enum +{ + ORBIS_IME_DIALOG_END_STATUS_OK = 0, + + ORBIS_IME_DIALOG_END_STATUS_USER_CANCELED, + + ORBIS_IME_DIALOG_END_STATUS_ABORTED, + +} OrbisImeDialogEndStatus; + + +typedef enum OrbisImeEnterLabel +{ + ORBIS_IME_ENTER_LABEL_DEFAULT= 0, + ORBIS_IME_ENTER_LABEL_SEND = 1, + ORBIS_IME_ENTER_LABEL_SEARCH = 2, + ORBIS_IME_ENTER_LABEL_GO = 3, +} OrbisImeEnterLabel; + + +typedef enum OrbisImeType +{ + ORBIS_IME_TYPE_DEFAULT = 0, + ORBIS_IME_TYPE_BASIC_LATIN = 1, + ORBIS_IME_TYPE_URL = 2, + ORBIS_IME_TYPE_MAIL = 3, + ORBIS_IME_TYPE_NUMBER = 4, +} OrbisImeType; + +typedef struct OrbisImeDialogResult { + OrbisImeDialogEndStatus endstatus; + + int8_t reserved[12]; + +} OrbisImeDialogResult; + + +typedef enum OrbisImeInputMethod +{ + ORBIS_IME_INPUT_METHOD_DEFAULT = 0, +} OrbisImeInputMethod; + +typedef int32_t (*OrbisImeTextFilter)( + wchar_t *outText, + uint32_t *outTextLength, + const wchar_t *srcText, + uint32_t srcTextLength +); + +typedef enum OrbisImeHorizontalAlignment +{ + ORBIS_IME_HALIGN_LEFT = 0, + ORBIS_IME_HALIGN_CENTER = 1, + ORBIS_IME_HALIGN_RIGHT = 2, +} OrbisImeHorizontalAlignment; + + +typedef enum OrbisImeVerticalAlignment +{ + ORBIS_IME_VALIGN_TOP = 0, + ORBIS_IME_VALIGN_CENTER = 1, + ORBIS_IME_VALIGN_BOTTOM = 2, +} OrbisImeVerticalAlignment; + +typedef struct OrbisImeDialogParam { + int32_t userId; + + OrbisImeType type; + + uint64_t supportedLanguages; + + OrbisImeEnterLabel enterLabel; + + OrbisImeInputMethod inputMethod; + + OrbisImeTextFilter filter; + + uint32_t option; + + uint32_t maxTextLength; + + wchar_t *inputTextBuffer; + + float posx; + + float posy; + + OrbisImeHorizontalAlignment horizontalAlignment; + + OrbisImeVerticalAlignment verticalAlignment; + + const wchar_t *placeholder; + + const wchar_t *title; + + int8_t reserved[16]; + +} OrbisImeDialogParam; + +typedef struct OrbisImeColor +{ + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +} OrbisImeColor; + +typedef enum OrbisImePanelPriority +{ + ORBIS_IME_PANEL_PRIORITY_DEFAULT = 0, + ORBIS_IME_PANEL_PRIORITY_ALPHABET = 1, + ORBIS_IME_PANEL_PRIORITY_SYMBOL = 2, + ORBIS_IME_PANEL_PRIORITY_ACCENT = 3, + +} OrbisImePanelPriority; + +typedef enum OrbisImeKeyboardType +{ + ORBIS_IME_KEYBOARD_TYPE_NONE = 0, //baseParam ); + param->size = sizeof(OrbisMsgDialogParam); +} + +#endif + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/itemzflow/include/fmt/args.h b/itemzflow/include/fmt/args.h new file mode 100644 index 0000000..a3966d1 --- /dev/null +++ b/itemzflow/include/fmt/args.h @@ -0,0 +1,234 @@ +// Formatting library for C++ - dynamic format arguments +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_ARGS_H_ +#define FMT_ARGS_H_ + +#include // std::reference_wrapper +#include // std::unique_ptr +#include + +#include "core.h" + +FMT_BEGIN_NAMESPACE + +namespace detail { + +template struct is_reference_wrapper : std::false_type {}; +template +struct is_reference_wrapper> : std::true_type {}; + +template const T& unwrap(const T& v) { return v; } +template const T& unwrap(const std::reference_wrapper& v) { + return static_cast(v); +} + +class dynamic_arg_list { + // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for + // templates it doesn't complain about inability to deduce single translation + // unit for placing vtable. So storage_node_base is made a fake template. + template struct node { + virtual ~node() = default; + std::unique_ptr> next; + }; + + template struct typed_node : node<> { + T value; + + template + FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} + + template + FMT_CONSTEXPR typed_node(const basic_string_view& arg) + : value(arg.data(), arg.size()) {} + }; + + std::unique_ptr> head_; + + public: + template const T& push(const Arg& arg) { + auto new_node = std::unique_ptr>(new typed_node(arg)); + auto& value = new_node->value; + new_node->next = std::move(head_); + head_ = std::move(new_node); + return value; + } +}; +} // namespace detail + +/** + \rst + A dynamic version of `fmt::format_arg_store`. + It's equipped with a storage to potentially temporary objects which lifetimes + could be shorter than the format arguments object. + + It can be implicitly converted into `~fmt::basic_format_args` for passing + into type-erased formatting functions such as `~fmt::vformat`. + \endrst + */ +template +class dynamic_format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args +#endif +{ + private: + using char_type = typename Context::char_type; + + template struct need_copy { + static constexpr detail::type mapped_type = + detail::mapped_type_constant::value; + + enum { + value = !(detail::is_reference_wrapper::value || + std::is_same>::value || + std::is_same>::value || + (mapped_type != detail::type::cstring_type && + mapped_type != detail::type::string_type && + mapped_type != detail::type::custom_type)) + }; + }; + + template + using stored_type = conditional_t< + std::is_convertible>::value && + !detail::is_reference_wrapper::value, + std::basic_string, T>; + + // Storage of basic_format_arg must be contiguous. + std::vector> data_; + std::vector> named_info_; + + // Storage of arguments not fitting into basic_format_arg must grow + // without relocation because items in data_ refer to it. + detail::dynamic_arg_list dynamic_args_; + + friend class basic_format_args; + + unsigned long long get_types() const { + return detail::is_unpacked_bit | data_.size() | + (named_info_.empty() + ? 0ULL + : static_cast(detail::has_named_args_bit)); + } + + const basic_format_arg* data() const { + return named_info_.empty() ? data_.data() : data_.data() + 1; + } + + template void emplace_arg(const T& arg) { + data_.emplace_back(detail::make_arg(arg)); + } + + template + void emplace_arg(const detail::named_arg& arg) { + if (named_info_.empty()) { + constexpr const detail::named_arg_info* zero_ptr{nullptr}; + data_.insert(data_.begin(), {zero_ptr, 0}); + } + data_.emplace_back(detail::make_arg(detail::unwrap(arg.value))); + auto pop_one = [](std::vector>* data) { + data->pop_back(); + }; + std::unique_ptr>, decltype(pop_one)> + guard{&data_, pop_one}; + named_info_.push_back({arg.name, static_cast(data_.size() - 2u)}); + data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; + guard.release(); + } + + public: + constexpr dynamic_format_arg_store() = default; + + /** + \rst + Adds an argument into the dynamic store for later passing to a formatting + function. + + Note that custom types and string types (but not string views) are copied + into the store dynamically allocating memory if necessary. + + **Example**:: + + fmt::dynamic_format_arg_store store; + store.push_back(42); + store.push_back("abc"); + store.push_back(1.5f); + std::string result = fmt::vformat("{} and {} and {}", store); + \endrst + */ + template void push_back(const T& arg) { + if (detail::const_check(need_copy::value)) + emplace_arg(dynamic_args_.push>(arg)); + else + emplace_arg(detail::unwrap(arg)); + } + + /** + \rst + Adds a reference to the argument into the dynamic store for later passing to + a formatting function. + + **Example**:: + + fmt::dynamic_format_arg_store store; + char band[] = "Rolling Stones"; + store.push_back(std::cref(band)); + band[9] = 'c'; // Changing str affects the output. + std::string result = fmt::vformat("{}", store); + // result == "Rolling Scones" + \endrst + */ + template void push_back(std::reference_wrapper arg) { + static_assert( + need_copy::value, + "objects of built-in types and string views are always copied"); + emplace_arg(arg.get()); + } + + /** + Adds named argument into the dynamic store for later passing to a formatting + function. ``std::reference_wrapper`` is supported to avoid copying of the + argument. The name is always copied into the store. + */ + template + void push_back(const detail::named_arg& arg) { + const char_type* arg_name = + dynamic_args_.push>(arg.name).c_str(); + if (detail::const_check(need_copy::value)) { + emplace_arg( + fmt::arg(arg_name, dynamic_args_.push>(arg.value))); + } else { + emplace_arg(fmt::arg(arg_name, arg.value)); + } + } + + /** Erase all elements from the store */ + void clear() { + data_.clear(); + named_info_.clear(); + dynamic_args_ = detail::dynamic_arg_list(); + } + + /** + \rst + Reserves space to store at least *new_cap* arguments including + *new_cap_named* named arguments. + \endrst + */ + void reserve(size_t new_cap, size_t new_cap_named) { + FMT_ASSERT(new_cap >= new_cap_named, + "Set of arguments includes set of named arguments"); + data_.reserve(new_cap); + named_info_.reserve(new_cap_named); + } +}; + +FMT_END_NAMESPACE + +#endif // FMT_ARGS_H_ diff --git a/itemzflow/include/fmt/chrono.h b/itemzflow/include/fmt/chrono.h new file mode 100644 index 0000000..83bf4ab --- /dev/null +++ b/itemzflow/include/fmt/chrono.h @@ -0,0 +1,2081 @@ +// Formatting library for C++ - chrono support +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CHRONO_H_ +#define FMT_CHRONO_H_ + +#include +#include +#include // std::isfinite +#include // std::memcpy +#include +#include +#include +#include +#include +#include + +#include "format.h" + +FMT_BEGIN_NAMESPACE + +// Enable tzset. +#ifndef FMT_USE_TZSET +// UWP doesn't provide _tzset. +# if FMT_HAS_INCLUDE("winapifamily.h") +# include +# endif +# if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \ + (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) +# define FMT_USE_TZSET 1 +# else +# define FMT_USE_TZSET 0 +# endif +#endif + +// Enable safe chrono durations, unless explicitly disabled. +#ifndef FMT_SAFE_DURATION_CAST +# define FMT_SAFE_DURATION_CAST 1 +#endif +#if FMT_SAFE_DURATION_CAST + +// For conversion between std::chrono::durations without undefined +// behaviour or erroneous results. +// This is a stripped down version of duration_cast, for inclusion in fmt. +// See https://github.com/pauldreik/safe_duration_cast +// +// Copyright Paul Dreik 2019 +namespace safe_duration_cast { + +template ::value && + std::numeric_limits::is_signed == + std::numeric_limits::is_signed)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + // A and B are both signed, or both unsigned. + if (detail::const_check(F::digits <= T::digits)) { + // From fits in To without any problem. + } else { + // From does not always fit in To, resort to a dynamic check. + if (from < (T::min)() || from > (T::max)()) { + // outside range. + ec = 1; + return {}; + } + } + return static_cast(from); +} + +/** + * converts From to To, without loss. If the dynamic value of from + * can't be converted to To without loss, ec is set. + */ +template ::value && + std::numeric_limits::is_signed != + std::numeric_limits::is_signed)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + ec = 0; + using F = std::numeric_limits; + using T = std::numeric_limits; + static_assert(F::is_integer, "From must be integral"); + static_assert(T::is_integer, "To must be integral"); + + if (detail::const_check(F::is_signed && !T::is_signed)) { + // From may be negative, not allowed! + if (fmt::detail::is_negative(from)) { + ec = 1; + return {}; + } + // From is positive. Can it always fit in To? + if (detail::const_check(F::digits > T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + } + + if (detail::const_check(!F::is_signed && T::is_signed && + F::digits >= T::digits) && + from > static_cast(detail::max_value())) { + ec = 1; + return {}; + } + return static_cast(from); // Lossless conversion. +} + +template ::value)> +FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { + ec = 0; + return from; +} // function + +// clang-format off +/** + * converts From to To if possible, otherwise ec is set. + * + * input | output + * ---------------------------------|--------------- + * NaN | NaN + * Inf | Inf + * normal, fits in output | converted (possibly lossy) + * normal, does not fit in output | ec is set + * subnormal | best effort + * -Inf | -Inf + */ +// clang-format on +template ::value)> +FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { + ec = 0; + using T = std::numeric_limits; + static_assert(std::is_floating_point::value, "From must be floating"); + static_assert(std::is_floating_point::value, "To must be floating"); + + // catch the only happy case + if (std::isfinite(from)) { + if (from >= T::lowest() && from <= (T::max)()) { + return static_cast(from); + } + // not within range. + ec = 1; + return {}; + } + + // nan and inf will be preserved + return static_cast(from); +} // function + +template ::value)> +FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { + ec = 0; + static_assert(std::is_floating_point::value, "From must be floating"); + return from; +} + +/** + * safe duration cast between integral durations + */ +template ::value), + FMT_ENABLE_IF(std::is_integral::value)> +To safe_duration_cast(std::chrono::duration from, + int& ec) { + using From = std::chrono::duration; + ec = 0; + // the basic idea is that we need to convert from count() in the from type + // to count() in the To type, by multiplying it with this: + struct Factor + : std::ratio_divide {}; + + static_assert(Factor::num > 0, "num must be positive"); + static_assert(Factor::den > 0, "den must be positive"); + + // the conversion is like this: multiply from.count() with Factor::num + // /Factor::den and convert it to To::rep, all this without + // overflow/underflow. let's start by finding a suitable type that can hold + // both To, From and Factor::num + using IntermediateRep = + typename std::common_type::type; + + // safe conversion to IntermediateRep + IntermediateRep count = + lossless_integral_conversion(from.count(), ec); + if (ec) return {}; + // multiply with Factor::num without overflow or underflow + if (detail::const_check(Factor::num != 1)) { + const auto max1 = detail::max_value() / Factor::num; + if (count > max1) { + ec = 1; + return {}; + } + const auto min1 = + (std::numeric_limits::min)() / Factor::num; + if (count < min1) { + ec = 1; + return {}; + } + count *= Factor::num; + } + + if (detail::const_check(Factor::den != 1)) count /= Factor::den; + auto tocount = lossless_integral_conversion(count, ec); + return ec ? To() : To(tocount); +} + +/** + * safe duration_cast between floating point durations + */ +template ::value), + FMT_ENABLE_IF(std::is_floating_point::value)> +To safe_duration_cast(std::chrono::duration from, + int& ec) { + using From = std::chrono::duration; + ec = 0; + if (std::isnan(from.count())) { + // nan in, gives nan out. easy. + return To{std::numeric_limits::quiet_NaN()}; + } + // maybe we should also check if from is denormal, and decide what to do about + // it. + + // +-inf should be preserved. + if (std::isinf(from.count())) { + return To{from.count()}; + } + + // the basic idea is that we need to convert from count() in the from type + // to count() in the To type, by multiplying it with this: + struct Factor + : std::ratio_divide {}; + + static_assert(Factor::num > 0, "num must be positive"); + static_assert(Factor::den > 0, "den must be positive"); + + // the conversion is like this: multiply from.count() with Factor::num + // /Factor::den and convert it to To::rep, all this without + // overflow/underflow. let's start by finding a suitable type that can hold + // both To, From and Factor::num + using IntermediateRep = + typename std::common_type::type; + + // force conversion of From::rep -> IntermediateRep to be safe, + // even if it will never happen be narrowing in this context. + IntermediateRep count = + safe_float_conversion(from.count(), ec); + if (ec) { + return {}; + } + + // multiply with Factor::num without overflow or underflow + if (detail::const_check(Factor::num != 1)) { + constexpr auto max1 = detail::max_value() / + static_cast(Factor::num); + if (count > max1) { + ec = 1; + return {}; + } + constexpr auto min1 = std::numeric_limits::lowest() / + static_cast(Factor::num); + if (count < min1) { + ec = 1; + return {}; + } + count *= static_cast(Factor::num); + } + + // this can't go wrong, right? den>0 is checked earlier. + if (detail::const_check(Factor::den != 1)) { + using common_t = typename std::common_type::type; + count /= static_cast(Factor::den); + } + + // convert to the to type, safely + using ToRep = typename To::rep; + + const ToRep tocount = safe_float_conversion(count, ec); + if (ec) { + return {}; + } + return To{tocount}; +} +} // namespace safe_duration_cast +#endif + +// Prevents expansion of a preceding token as a function-style macro. +// Usage: f FMT_NOMACRO() +#define FMT_NOMACRO + +namespace detail { +template struct null {}; +inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); } +inline null<> localtime_s(...) { return null<>(); } +inline null<> gmtime_r(...) { return null<>(); } +inline null<> gmtime_s(...) { return null<>(); } + +inline const std::locale& get_classic_locale() { + static const auto& locale = std::locale::classic(); + return locale; +} + +template struct codecvt_result { + static constexpr const size_t max_size = 32; + CodeUnit buf[max_size]; + CodeUnit* end; +}; +template +constexpr const size_t codecvt_result::max_size; + +template +void write_codecvt(codecvt_result& out, string_view in_buf, + const std::locale& loc) { +#if FMT_CLANG_VERSION +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" + auto& f = std::use_facet>(loc); +# pragma clang diagnostic pop +#else + auto& f = std::use_facet>(loc); +#endif + auto mb = std::mbstate_t(); + const char* from_next = nullptr; + auto result = f.in(mb, in_buf.begin(), in_buf.end(), from_next, + std::begin(out.buf), std::end(out.buf), out.end); + if (result != std::codecvt_base::ok) + log_error("failed to format time"); +} + +template +auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) + -> OutputIt { + if (detail::is_utf8() && loc != get_classic_locale()) { + // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and + // gcc-4. +#if FMT_MSC_VERSION != 0 || \ + (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)) + // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5 + // and newer. + using code_unit = wchar_t; +#else + using code_unit = char32_t; +#endif + + using unit_t = codecvt_result; + unit_t unit; + write_codecvt(unit, in, loc); + // In UTF-8 is used one to four one-byte code units. + auto&& buf = basic_memory_buffer(); + for (code_unit* p = unit.buf; p != unit.end; ++p) { + uint32_t c = static_cast(*p); + if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) { + // surrogate pair + ++p; + if (p == unit.end || (c & 0xfc00) != 0xd800 || + (*p & 0xfc00) != 0xdc00) { + log_error("failed to format time"); + } + c = (c << 10) + static_cast(*p) - 0x35fdc00; + } + if (c < 0x80) { + buf.push_back(static_cast(c)); + } else if (c < 0x800) { + buf.push_back(static_cast(0xc0 | (c >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { + buf.push_back(static_cast(0xe0 | (c >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else if (c >= 0x10000 && c <= 0x10ffff) { + buf.push_back(static_cast(0xf0 | (c >> 18))); + buf.push_back(static_cast(0x80 | ((c & 0x3ffff) >> 12))); + buf.push_back(static_cast(0x80 | ((c & 0xfff) >> 6))); + buf.push_back(static_cast(0x80 | (c & 0x3f))); + } else { + log_error("failed to format time"); + } + } + return copy_str(buf.data(), buf.data() + buf.size(), out); + } + return copy_str(in.data(), in.data() + in.size(), out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + codecvt_result unit; + write_codecvt(unit, sv, loc); + return copy_str(unit.buf, unit.end, out); +} + +template ::value)> +auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc) + -> OutputIt { + return write_encoded_tm_str(out, sv, loc); +} + +template +inline void do_write(buffer& buf, const std::tm& time, + const std::locale& loc, char format, char modifier) { + auto&& format_buf = formatbuf>(buf); + auto&& os = std::basic_ostream(&format_buf); + os.imbue(loc); + using iterator = std::ostreambuf_iterator; + const auto& facet = std::use_facet>(loc); + auto end = facet.put(os, os, Char(' '), &time, format, modifier); + if (end.failed()) log_error("failed to format time"); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = get_buffer(out); + do_write(buf, time, loc, format, modifier); + return buf.out(); +} + +template ::value)> +auto write(OutputIt out, const std::tm& time, const std::locale& loc, + char format, char modifier = 0) -> OutputIt { + auto&& buf = basic_memory_buffer(); + do_write(buf, time, loc, format, modifier); + return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc); +} + +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +/** + Converts given time since epoch as ``std::time_t`` value into calendar time, + expressed in local time. Unlike ``std::localtime``, this function is + thread-safe on most platforms. + */ +inline std::tm localtime(std::time_t time) { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + bool run() { + using namespace fmt::detail; + return handle(localtime_r(&time_, &tm_)); + } + + bool handle(std::tm* tm) { return tm != nullptr; } + + bool handle(detail::null<>) { + using namespace fmt::detail; + return fallback(localtime_s(&tm_, &time_)); + } + + bool fallback(int res) { return res == 0; } + +#if !FMT_MSC_VERSION + bool fallback(detail::null<>) { + using namespace fmt::detail; + std::tm* tm = std::localtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + dispatcher lt(time); + // Too big time values may be unsupported. + if (!lt.run()) log_error("time_t value out of range"); + return lt.tm_; +} + +inline std::tm localtime( + std::chrono::time_point time_point) { + return localtime(std::chrono::system_clock::to_time_t(time_point)); +} + +/** + Converts given time since epoch as ``std::time_t`` value into calendar time, + expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this + function is thread-safe on most platforms. + */ +inline std::tm gmtime(std::time_t time) { + struct dispatcher { + std::time_t time_; + std::tm tm_; + + dispatcher(std::time_t t) : time_(t) {} + + bool run() { + using namespace fmt::detail; + return handle(gmtime_r(&time_, &tm_)); + } + + bool handle(std::tm* tm) { return tm != nullptr; } + + bool handle(detail::null<>) { + using namespace fmt::detail; + return fallback(gmtime_s(&tm_, &time_)); + } + + bool fallback(int res) { return res == 0; } + +#if !FMT_MSC_VERSION + bool fallback(detail::null<>) { + std::tm* tm = std::gmtime(&time_); + if (tm) tm_ = *tm; + return tm != nullptr; + } +#endif + }; + dispatcher gt(time); + // Too big time values may be unsupported. + if (!gt.run()) log_error("time_t value out of range"); + return gt.tm_; +} + +inline std::tm gmtime( + std::chrono::time_point time_point) { + return gmtime(std::chrono::system_clock::to_time_t(time_point)); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +// Writes two-digit numbers a, b and c separated by sep to buf. +// The method by Pavel Novikov based on +// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/. +inline void write_digit2_separated(char* buf, unsigned a, unsigned b, + unsigned c, char sep) { + unsigned long long digits = + a | (b << 24) | (static_cast(c) << 48); + // Convert each value to BCD. + // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b. + // The difference is + // y - x = a * 6 + // a can be found from x: + // a = floor(x / 10) + // then + // y = x + a * 6 = x + floor(x / 10) * 6 + // floor(x / 10) is (x * 205) >> 11 (needs 16 bits). + digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6; + // Put low nibbles to high bytes and high nibbles to low bytes. + digits = ((digits & 0x00f00000f00000f0) >> 4) | + ((digits & 0x000f00000f00000f) << 8); + auto usep = static_cast(sep); + // Add ASCII '0' to each digit byte and insert separators. + digits |= 0x3030003030003030 | (usep << 16) | (usep << 40); + + constexpr const size_t len = 8; + if (const_check(is_big_endian())) { + char tmp[len]; + std::memcpy(tmp, &digits, len); + std::reverse_copy(tmp, tmp + len, buf); + } else { + std::memcpy(buf, &digits, len); + } +} + +template FMT_CONSTEXPR inline const char* get_units() { + if (std::is_same::value) return "as"; + if (std::is_same::value) return "fs"; + if (std::is_same::value) return "ps"; + if (std::is_same::value) return "ns"; + if (std::is_same::value) return "µs"; + if (std::is_same::value) return "ms"; + if (std::is_same::value) return "cs"; + if (std::is_same::value) return "ds"; + if (std::is_same>::value) return "s"; + if (std::is_same::value) return "das"; + if (std::is_same::value) return "hs"; + if (std::is_same::value) return "ks"; + if (std::is_same::value) return "Ms"; + if (std::is_same::value) return "Gs"; + if (std::is_same::value) return "Ts"; + if (std::is_same::value) return "Ps"; + if (std::is_same::value) return "Es"; + if (std::is_same>::value) return "m"; + if (std::is_same>::value) return "h"; + return nullptr; +} + +enum class numeric_system { + standard, + // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale. + alternative +}; + +// Parses a put_time-like format string and invokes handler actions. +template +FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin, + const Char* end, + Handler&& handler) { + auto ptr = begin; + while (ptr != end) { + auto c = *ptr; + if (c == '}') break; + if (c != '%') { + ++ptr; + continue; + } + if (begin != ptr) handler.on_text(begin, ptr); + ++ptr; // consume '%' + if (ptr == end) log_error("invaild format"); + c = *ptr++; + switch (c) { + case '%': + handler.on_text(ptr - 1, ptr); + break; + case 'n': { + const Char newline[] = {'\n'}; + handler.on_text(newline, newline + 1); + break; + } + case 't': { + const Char tab[] = {'\t'}; + handler.on_text(tab, tab + 1); + break; + } + // Year: + case 'Y': + handler.on_year(numeric_system::standard); + break; + case 'y': + handler.on_short_year(numeric_system::standard); + break; + case 'C': + handler.on_century(numeric_system::standard); + break; + case 'G': + handler.on_iso_week_based_year(); + break; + case 'g': + handler.on_iso_week_based_short_year(); + break; + // Day of the week: + case 'a': + handler.on_abbr_weekday(); + break; + case 'A': + handler.on_full_weekday(); + break; + case 'w': + handler.on_dec0_weekday(numeric_system::standard); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::standard); + break; + // Month: + case 'b': + case 'h': + handler.on_abbr_month(); + break; + case 'B': + handler.on_full_month(); + break; + case 'm': + handler.on_dec_month(numeric_system::standard); + break; + // Day of the year/month: + case 'U': + handler.on_dec0_week_of_year(numeric_system::standard); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::standard); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::standard); + break; + case 'j': + handler.on_day_of_year(); + break; + case 'd': + handler.on_day_of_month(numeric_system::standard); + break; + case 'e': + handler.on_day_of_month_space(numeric_system::standard); + break; + // Hour, minute, second: + case 'H': + handler.on_24_hour(numeric_system::standard); + break; + case 'I': + handler.on_12_hour(numeric_system::standard); + break; + case 'M': + handler.on_minute(numeric_system::standard); + break; + case 'S': + handler.on_second(numeric_system::standard); + break; + // Other: + case 'c': + handler.on_datetime(numeric_system::standard); + break; + case 'x': + handler.on_loc_date(numeric_system::standard); + break; + case 'X': + handler.on_loc_time(numeric_system::standard); + break; + case 'D': + handler.on_us_date(); + break; + case 'F': + handler.on_iso_date(); + break; + case 'r': + handler.on_12_hour_time(); + break; + case 'R': + handler.on_24_hour_time(); + break; + case 'T': + handler.on_iso_time(); + break; + case 'p': + handler.on_am_pm(); + break; + case 'Q': + handler.on_duration_value(); + break; + case 'q': + handler.on_duration_unit(); + break; + case 'z': + handler.on_utc_offset(); + break; + case 'Z': + handler.on_tz_name(); + break; + // Alternative representation: + case 'E': { + if (ptr == end) log_error("invalid format"); + c = *ptr++; + switch (c) { + case 'Y': + handler.on_year(numeric_system::alternative); + break; + case 'y': + handler.on_offset_year(); + break; + case 'C': + handler.on_century(numeric_system::alternative); + break; + case 'c': + handler.on_datetime(numeric_system::alternative); + break; + case 'x': + handler.on_loc_date(numeric_system::alternative); + break; + case 'X': + handler.on_loc_time(numeric_system::alternative); + break; + default: + log_error("invalid format"); + } + break; + } + case 'O': + if (ptr == end) log_error("invalid format"); + c = *ptr++; + switch (c) { + case 'y': + handler.on_short_year(numeric_system::alternative); + break; + case 'm': + handler.on_dec_month(numeric_system::alternative); + break; + case 'U': + handler.on_dec0_week_of_year(numeric_system::alternative); + break; + case 'W': + handler.on_dec1_week_of_year(numeric_system::alternative); + break; + case 'V': + handler.on_iso_week_of_year(numeric_system::alternative); + break; + case 'd': + handler.on_day_of_month(numeric_system::alternative); + break; + case 'e': + handler.on_day_of_month_space(numeric_system::alternative); + break; + case 'w': + handler.on_dec0_weekday(numeric_system::alternative); + break; + case 'u': + handler.on_dec1_weekday(numeric_system::alternative); + break; + case 'H': + handler.on_24_hour(numeric_system::alternative); + break; + case 'I': + handler.on_12_hour(numeric_system::alternative); + break; + case 'M': + handler.on_minute(numeric_system::alternative); + break; + case 'S': + handler.on_second(numeric_system::alternative); + break; + default: + log_error("invalid format"); + } + break; + default: + log_error("invalid format"); + } + begin = ptr; + } + if (begin != ptr) handler.on_text(begin, ptr); + return ptr; +} + +template struct null_chrono_spec_handler { + FMT_CONSTEXPR void unsupported() { + static_cast(this)->unsupported(); + } + FMT_CONSTEXPR void on_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_short_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_offset_year() { unsupported(); } + FMT_CONSTEXPR void on_century(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); } + FMT_CONSTEXPR void on_iso_week_based_short_year() { unsupported(); } + FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); } + FMT_CONSTEXPR void on_full_weekday() { unsupported(); } + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_abbr_month() { unsupported(); } + FMT_CONSTEXPR void on_full_month() { unsupported(); } + FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_day_of_year() { unsupported(); } + FMT_CONSTEXPR void on_day_of_month(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_us_date() { unsupported(); } + FMT_CONSTEXPR void on_iso_date() { unsupported(); } + FMT_CONSTEXPR void on_12_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_24_hour_time() { unsupported(); } + FMT_CONSTEXPR void on_iso_time() { unsupported(); } + FMT_CONSTEXPR void on_am_pm() { unsupported(); } + FMT_CONSTEXPR void on_duration_value() { unsupported(); } + FMT_CONSTEXPR void on_duration_unit() { unsupported(); } + FMT_CONSTEXPR void on_utc_offset() { unsupported(); } + FMT_CONSTEXPR void on_tz_name() { unsupported(); } +}; + +struct tm_format_checker : null_chrono_spec_handler { + void unsupported() { log_error("no format"); } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_year(numeric_system) {} + FMT_CONSTEXPR void on_short_year(numeric_system) {} + FMT_CONSTEXPR void on_offset_year() {} + FMT_CONSTEXPR void on_century(numeric_system) {} + FMT_CONSTEXPR void on_iso_week_based_year() {} + FMT_CONSTEXPR void on_iso_week_based_short_year() {} + FMT_CONSTEXPR void on_abbr_weekday() {} + FMT_CONSTEXPR void on_full_weekday() {} + FMT_CONSTEXPR void on_dec0_weekday(numeric_system) {} + FMT_CONSTEXPR void on_dec1_weekday(numeric_system) {} + FMT_CONSTEXPR void on_abbr_month() {} + FMT_CONSTEXPR void on_full_month() {} + FMT_CONSTEXPR void on_dec_month(numeric_system) {} + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_day_of_year() {} + FMT_CONSTEXPR void on_day_of_month(numeric_system) {} + FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {} + FMT_CONSTEXPR void on_24_hour(numeric_system) {} + FMT_CONSTEXPR void on_12_hour(numeric_system) {} + FMT_CONSTEXPR void on_minute(numeric_system) {} + FMT_CONSTEXPR void on_second(numeric_system) {} + FMT_CONSTEXPR void on_datetime(numeric_system) {} + FMT_CONSTEXPR void on_loc_date(numeric_system) {} + FMT_CONSTEXPR void on_loc_time(numeric_system) {} + FMT_CONSTEXPR void on_us_date() {} + FMT_CONSTEXPR void on_iso_date() {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_utc_offset() {} + FMT_CONSTEXPR void on_tz_name() {} +}; + +inline const char* tm_wday_full_name(int wday) { + static constexpr const char* full_name_list[] = { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday"}; + return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?"; +} +inline const char* tm_wday_short_name(int wday) { + static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat"}; + return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???"; +} + +inline const char* tm_mon_full_name(int mon) { + static constexpr const char* full_name_list[] = { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?"; +} +inline const char* tm_mon_short_name(int mon) { + static constexpr const char* short_name_list[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + }; + return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???"; +} + +template +struct has_member_data_tm_gmtoff : std::false_type {}; +template +struct has_member_data_tm_gmtoff> + : std::true_type {}; + +template +struct has_member_data_tm_zone : std::false_type {}; +template +struct has_member_data_tm_zone> + : std::true_type {}; + +#if FMT_USE_TZSET +inline void tzset_once() { + static bool init = []() -> bool { + _tzset(); + return true; + }(); + ignore_unused(init); +} +#endif + +template class tm_writer { + private: + static constexpr int days_per_week = 7; + + const std::locale& loc_; + const bool is_classic_; + OutputIt out_; + const std::tm& tm_; + + auto tm_sec() const noexcept -> int { + FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, ""); + return tm_.tm_sec; + } + auto tm_min() const noexcept -> int { + FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, ""); + return tm_.tm_min; + } + auto tm_hour() const noexcept -> int { + FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, ""); + return tm_.tm_hour; + } + auto tm_mday() const noexcept -> int { + FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, ""); + return tm_.tm_mday; + } + auto tm_mon() const noexcept -> int { + FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, ""); + return tm_.tm_mon; + } + auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; } + auto tm_wday() const noexcept -> int { + FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, ""); + return tm_.tm_wday; + } + auto tm_yday() const noexcept -> int { + FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, ""); + return tm_.tm_yday; + } + + auto tm_hour12() const noexcept -> int { + const auto h = tm_hour(); + const auto z = h < 12 ? h : h - 12; + return z == 0 ? 12 : z; + } + + // POSIX and the C Standard are unclear or inconsistent about what %C and %y + // do if the year is negative or exceeds 9999. Use the convention that %C + // concatenated with %y yields the same output as %Y, and that %Y contains at + // least 4 characters, with more only if necessary. + auto split_year_lower(long long year) const noexcept -> int { + auto l = year % 100; + if (l < 0) l = -l; // l in [0, 99] + return static_cast(l); + } + + // Algorithm: + // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_from_a_month_and_day_of_the_month_or_ordinal_date + auto iso_year_weeks(long long curr_year) const noexcept -> int { + const auto prev_year = curr_year - 1; + const auto curr_p = + (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) % + days_per_week; + const auto prev_p = + (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) % + days_per_week; + return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0); + } + auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int { + return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) / + days_per_week; + } + auto tm_iso_week_year() const noexcept -> long long { + const auto year = tm_year(); + const auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return year - 1; + if (w > iso_year_weeks(year)) return year + 1; + return year; + } + auto tm_iso_week_of_year() const noexcept -> int { + const auto year = tm_year(); + const auto w = iso_week_num(tm_yday(), tm_wday()); + if (w < 1) return iso_year_weeks(year - 1); + if (w > iso_year_weeks(year)) return 1; + return w; + } + + void write1(int value) { + *out_++ = static_cast('0' + to_unsigned(value) % 10); + } + void write2(int value) { + const char* d = digits2(to_unsigned(value) % 100); + *out_++ = *d++; + *out_++ = *d; + } + + void write_year_extended(long long year) { + // At least 4 characters. + int width = 4; + if (year < 0) { + *out_++ = '-'; + year = 0 - year; + --width; + } + uint32_or_64_or_128_t n = to_unsigned(year); + const int num_digits = count_digits(n); + if (width > num_digits) out_ = std::fill_n(out_, width - num_digits, '0'); + out_ = format_decimal(out_, n, num_digits).end; + } + void write_year(long long year) { + if (year >= 0 && year < 10000) { + write2(static_cast(year / 100)); + write2(static_cast(year % 100)); + } else { + write_year_extended(year); + } + } + + void write_utc_offset(long offset) { + if (offset < 0) { + *out_++ = '-'; + offset = -offset; + } else { + *out_++ = '+'; + } + offset /= 60; + write2(static_cast(offset / 60)); + write2(static_cast(offset % 60)); + } + template ::value)> + void format_utc_offset_impl(const T& tm) { + write_utc_offset(tm.tm_gmtoff); + } + template ::value)> + void format_utc_offset_impl(const T& tm) { +#if defined(_WIN32) && defined(_UCRT) +# if FMT_USE_TZSET + tzset_once(); +# endif + long offset = 0; + _get_timezone(&offset); + if (tm.tm_isdst) { + long dstbias = 0; + _get_dstbias(&dstbias); + offset += dstbias; + } + write_utc_offset(-offset); +#else + ignore_unused(tm); + format_localized('z'); +#endif + } + + template ::value)> + void format_tz_name_impl(const T& tm) { + if (is_classic_) + out_ = write_tm_str(out_, tm.tm_zone, loc_); + else + format_localized('Z'); + } + template ::value)> + void format_tz_name_impl(const T&) { + format_localized('Z'); + } + + void format_localized(char format, char modifier = 0) { + out_ = write(out_, tm_, loc_, format, modifier); + } + + public: + tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm) + : loc_(loc), + is_classic_(loc_ == get_classic_locale()), + out_(out), + tm_(tm) {} + + OutputIt out() const { return out_; } + + FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { + out_ = copy_str(begin, end, out_); + } + + void on_abbr_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_short_name(tm_wday())); + else + format_localized('a'); + } + void on_full_weekday() { + if (is_classic_) + out_ = write(out_, tm_wday_full_name(tm_wday())); + else + format_localized('A'); + } + void on_dec0_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday()); + format_localized('w', 'O'); + } + void on_dec1_weekday(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write1(wday == 0 ? days_per_week : wday); + } else { + format_localized('u', 'O'); + } + } + + void on_abbr_month() { + if (is_classic_) + out_ = write(out_, tm_mon_short_name(tm_mon())); + else + format_localized('b'); + } + void on_full_month() { + if (is_classic_) + out_ = write(out_, tm_mon_full_name(tm_mon())); + else + format_localized('B'); + } + + void on_datetime(numeric_system ns) { + if (is_classic_) { + on_abbr_weekday(); + *out_++ = ' '; + on_abbr_month(); + *out_++ = ' '; + on_day_of_month_space(numeric_system::standard); + *out_++ = ' '; + on_iso_time(); + *out_++ = ' '; + on_year(numeric_system::standard); + } else { + format_localized('c', ns == numeric_system::standard ? '\0' : 'E'); + } + } + void on_loc_date(numeric_system ns) { + if (is_classic_) + on_us_date(); + else + format_localized('x', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_loc_time(numeric_system ns) { + if (is_classic_) + on_iso_time(); + else + format_localized('X', ns == numeric_system::standard ? '\0' : 'E'); + } + void on_us_date() { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_mon() + 1), + to_unsigned(tm_mday()), + to_unsigned(split_year_lower(tm_year())), '/'); + out_ = copy_str(std::begin(buf), std::end(buf), out_); + } + void on_iso_date() { + auto year = tm_year(); + char buf[10]; + size_t offset = 0; + if (year >= 0 && year < 10000) { + copy2(buf, digits2(static_cast(year / 100))); + } else { + offset = 4; + write_year_extended(year); + year = 0; + } + write_digit2_separated(buf + 2, static_cast(year % 100), + to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()), + '-'); + out_ = copy_str(std::begin(buf) + offset, std::end(buf), out_); + } + + void on_utc_offset() { format_utc_offset_impl(tm_); } + void on_tz_name() { format_tz_name_impl(tm_); } + + void on_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write_year(tm_year()); + format_localized('Y', 'E'); + } + void on_short_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(split_year_lower(tm_year())); + format_localized('y', 'O'); + } + void on_offset_year() { + if (is_classic_) return write2(split_year_lower(tm_year())); + format_localized('y', 'E'); + } + + void on_century(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto year = tm_year(); + auto upper = year / 100; + if (year >= -99 && year < 0) { + // Zero upper on negative year. + *out_++ = '-'; + *out_++ = '0'; + } else if (upper >= 0 && upper < 100) { + write2(static_cast(upper)); + } else { + out_ = write(out_, upper); + } + } else { + format_localized('C', 'E'); + } + } + + void on_dec_month(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mon() + 1); + format_localized('m', 'O'); + } + + void on_dec0_week_of_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week); + format_localized('U', 'O'); + } + void on_dec1_week_of_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto wday = tm_wday(); + write2((tm_yday() + days_per_week - + (wday == 0 ? (days_per_week - 1) : (wday - 1))) / + days_per_week); + } else { + format_localized('W', 'O'); + } + } + void on_iso_week_of_year(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_iso_week_of_year()); + format_localized('V', 'O'); + } + + void on_iso_week_based_year() { write_year(tm_iso_week_year()); } + void on_iso_week_based_short_year() { + write2(split_year_lower(tm_iso_week_year())); + } + + void on_day_of_year() { + auto yday = tm_yday() + 1; + write1(yday / 100); + write2(yday % 100); + } + void on_day_of_month(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday()); + format_localized('d', 'O'); + } + void on_day_of_month_space(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) { + auto mday = to_unsigned(tm_mday()) % 100; + const char* d2 = digits2(mday); + *out_++ = mday < 10 ? ' ' : d2[0]; + *out_++ = d2[1]; + } else { + format_localized('e', 'O'); + } + } + + void on_24_hour(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_hour()); + format_localized('H', 'O'); + } + void on_12_hour(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_hour12()); + format_localized('I', 'O'); + } + void on_minute(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_min()); + format_localized('M', 'O'); + } + void on_second(numeric_system ns) { + if (is_classic_ || ns == numeric_system::standard) return write2(tm_sec()); + format_localized('S', 'O'); + } + + void on_12_hour_time() { + if (is_classic_) { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour12()), + to_unsigned(tm_min()), to_unsigned(tm_sec()), ':'); + out_ = copy_str(std::begin(buf), std::end(buf), out_); + *out_++ = ' '; + on_am_pm(); + } else { + format_localized('r'); + } + } + void on_24_hour_time() { + write2(tm_hour()); + *out_++ = ':'; + write2(tm_min()); + } + void on_iso_time() { + char buf[8]; + write_digit2_separated(buf, to_unsigned(tm_hour()), to_unsigned(tm_min()), + to_unsigned(tm_sec()), ':'); + out_ = copy_str(std::begin(buf), std::end(buf), out_); + } + + void on_am_pm() { + if (is_classic_) { + *out_++ = tm_hour() < 12 ? 'A' : 'P'; + *out_++ = 'M'; + } else { + format_localized('p'); + } + } + + // These apply to chrono durations but not tm. + void on_duration_value() {} + void on_duration_unit() {} +}; + +struct chrono_format_checker : null_chrono_spec_handler { + FMT_NORETURN void unsupported() { log_error("no date"); raise(SIGUSR2); } + + template + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + FMT_CONSTEXPR void on_24_hour(numeric_system) {} + FMT_CONSTEXPR void on_12_hour(numeric_system) {} + FMT_CONSTEXPR void on_minute(numeric_system) {} + FMT_CONSTEXPR void on_second(numeric_system) {} + FMT_CONSTEXPR void on_12_hour_time() {} + FMT_CONSTEXPR void on_24_hour_time() {} + FMT_CONSTEXPR void on_iso_time() {} + FMT_CONSTEXPR void on_am_pm() {} + FMT_CONSTEXPR void on_duration_value() {} + FMT_CONSTEXPR void on_duration_unit() {} +}; + +template ::value)> +inline bool isfinite(T) { + return true; +} + +// Converts value to Int and checks that it's in the range [0, upper). +template ::value)> +inline Int to_nonnegative_int(T value, Int upper) { + FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper), + "invalid value"); + (void)upper; + return static_cast(value); +} +template ::value)> +inline Int to_nonnegative_int(T value, Int upper) { + if (value < 0 || value > static_cast(upper)) + log_error("invalid value"); + return static_cast(value); +} + +template ::value)> +inline T mod(T x, int y) { + return x % static_cast(y); +} +template ::value)> +inline T mod(T x, int y) { + return std::fmod(x, static_cast(y)); +} + +// If T is an integral type, maps T to its unsigned counterpart, otherwise +// leaves it unchanged (unlike std::make_unsigned). +template ::value> +struct make_unsigned_or_unchanged { + using type = T; +}; + +template struct make_unsigned_or_unchanged { + using type = typename std::make_unsigned::type; +}; + +#if FMT_SAFE_DURATION_CAST +// throwing version of safe_duration_cast +template +To fmt_safe_duration_cast(std::chrono::duration from) { + int ec; + To to = safe_duration_cast::safe_duration_cast(from, ec); + if (ec) log_error("cannot format duration"); + return to; +} +#endif + +template ::value)> +inline std::chrono::duration get_milliseconds( + std::chrono::duration d) { + // this may overflow and/or the result may not fit in the + // target type. +#if FMT_SAFE_DURATION_CAST + using CommonSecondsType = + typename std::common_type::type; + const auto d_as_common = fmt_safe_duration_cast(d); + const auto d_as_whole_seconds = + fmt_safe_duration_cast(d_as_common); + // this conversion should be nonproblematic + const auto diff = d_as_common - d_as_whole_seconds; + const auto ms = + fmt_safe_duration_cast>(diff); + return ms; +#else + auto s = std::chrono::duration_cast(d); + return std::chrono::duration_cast(d - s); +#endif +} + +// Counts the number of fractional digits in the range [0, 18] according to the +// C++20 spec. If more than 18 fractional digits are required then returns 6 for +// microseconds precision. +template () / 10)> +struct count_fractional_digits { + static constexpr int value = + Num % Den == 0 ? N : count_fractional_digits::value; +}; + +// Base case that doesn't instantiate any more templates +// in order to avoid overflow. +template +struct count_fractional_digits { + static constexpr int value = (Num % Den == 0) ? N : 6; +}; + +constexpr long long pow10(std::uint32_t n) { + return n == 0 ? 1 : 10 * pow10(n - 1); +} + +template ::is_signed)> +constexpr std::chrono::duration abs( + std::chrono::duration d) { + // We need to compare the duration using the count() method directly + // due to a compiler bug in clang-11 regarding the spaceship operator, + // when -Wzero-as-null-pointer-constant is enabled. + // In clang-12 the bug has been fixed. See + // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example: + // https://www.godbolt.org/z/Knbb5joYx. + return d.count() >= d.zero().count() ? d : -d; +} + +template ::is_signed)> +constexpr std::chrono::duration abs( + std::chrono::duration d) { + return d; +} + +template ::value)> +OutputIt format_duration_value(OutputIt out, Rep val, int) { + return write(out, val); +} + +template ::value)> +OutputIt format_duration_value(OutputIt out, Rep val, int precision) { + auto specs = basic_format_specs(); + specs.precision = precision; + specs.type = precision >= 0 ? presentation_type::fixed_lower + : presentation_type::general_lower; + return write(out, val, specs); +} + +template +OutputIt copy_unit(string_view unit, OutputIt out, Char) { + return std::copy(unit.begin(), unit.end(), out); +} + +template +OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) { + // This works when wchar_t is UTF-32 because units only contain characters + // that have the same representation in UTF-16 and UTF-32. + utf8_to_utf16 u(unit); + return std::copy(u.c_str(), u.c_str() + u.size(), out); +} + +template +OutputIt format_duration_unit(OutputIt out) { + if (const char* unit = get_units()) + return copy_unit(string_view(unit), out, Char()); + *out++ = '['; + out = write(out, Period::num); + if (const_check(Period::den != 1)) { + *out++ = '/'; + out = write(out, Period::den); + } + *out++ = ']'; + *out++ = 's'; + return out; +} + +class get_locale { + private: + union { + std::locale locale_; + }; + bool has_locale_ = false; + + public: + get_locale(bool localized, locale_ref loc) : has_locale_(localized) { + if (localized) + ::new (&locale_) std::locale(loc.template get()); + } + ~get_locale() { + if (has_locale_) locale_.~locale(); + } + operator const std::locale&() const { + return has_locale_ ? locale_ : get_classic_locale(); + } +}; + +template +struct chrono_formatter { + FormatContext& context; + OutputIt out; + int precision; + bool localized = false; + // rep is unsigned to avoid overflow. + using rep = + conditional_t::value && sizeof(Rep) < sizeof(int), + unsigned, typename make_unsigned_or_unchanged::type>; + rep val; + using seconds = std::chrono::duration; + seconds s; + using milliseconds = std::chrono::duration; + bool negative; + + using char_type = typename FormatContext::char_type; + using tm_writer_type = tm_writer; + + chrono_formatter(FormatContext& ctx, OutputIt o, + std::chrono::duration d) + : context(ctx), + out(o), + val(static_cast(d.count())), + negative(false) { + if (d.count() < 0) { + val = 0 - val; + negative = true; + } + + // this may overflow and/or the result may not fit in the + // target type. +#if FMT_SAFE_DURATION_CAST + // might need checked conversion (rep!=Rep) + auto tmpval = std::chrono::duration(val); + s = fmt_safe_duration_cast(tmpval); +#else + s = std::chrono::duration_cast( + std::chrono::duration(val)); +#endif + } + + // returns true if nan or inf, writes to out. + bool handle_nan_inf() { + if (isfinite(val)) { + return false; + } + if (isnan(val)) { + write_nan(); + return true; + } + // must be +-inf + if (val > 0) { + write_pinf(); + } else { + write_ninf(); + } + return true; + } + + Rep hour() const { return static_cast(mod((s.count() / 3600), 24)); } + + Rep hour12() const { + Rep hour = static_cast(mod((s.count() / 3600), 12)); + return hour <= 0 ? 12 : hour; + } + + Rep minute() const { return static_cast(mod((s.count() / 60), 60)); } + Rep second() const { return static_cast(mod(s.count(), 60)); } + + std::tm time() const { + auto time = std::tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + time.tm_min = to_nonnegative_int(minute(), 60); + time.tm_sec = to_nonnegative_int(second(), 60); + return time; + } + + void write_sign() { + if (negative) { + *out++ = '-'; + negative = false; + } + } + + void write(Rep value, int width) { + write_sign(); + if (isnan(value)) return write_nan(); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(value, max_value())); + int num_digits = detail::count_digits(n); + if (width > num_digits) out = std::fill_n(out, width - num_digits, '0'); + out = format_decimal(out, n, num_digits).end; + } + + template void write_fractional_seconds(Duration d) { + FMT_ASSERT(!std::is_floating_point::value, ""); + constexpr auto num_fractional_digits = + count_fractional_digits::value; + + using subsecond_precision = std::chrono::duration< + typename std::common_type::type, + std::ratio<1, detail::pow10(num_fractional_digits)>>; + if (std::ratio_less::value) { + *out++ = '.'; + auto fractional = + detail::abs(d) - std::chrono::duration_cast(d); + auto subseconds = + std::chrono::treat_as_floating_point< + typename subsecond_precision::rep>::value + ? fractional.count() + : std::chrono::duration_cast(fractional) + .count(); + uint32_or_64_or_128_t n = + to_unsigned(to_nonnegative_int(subseconds, max_value())); + int num_digits = detail::count_digits(n); + if (num_fractional_digits > num_digits) + out = std::fill_n(out, num_fractional_digits - num_digits, '0'); + out = format_decimal(out, n, num_digits).end; + } + } + + void write_nan() { std::copy_n("nan", 3, out); } + void write_pinf() { std::copy_n("inf", 3, out); } + void write_ninf() { std::copy_n("-inf", 4, out); } + + template + void format_tm(const tm& time, Callback cb, Args... args) { + if (isnan(val)) return write_nan(); + get_locale loc(localized, context.locale()); + auto w = tm_writer_type(loc, out, time); + (w.*cb)(args...); + out = w.out(); + } + + void on_text(const char_type* begin, const char_type* end) { + std::copy(begin, end, out); + } + + // These are not implemented because durations don't have date information. + void on_abbr_weekday() {} + void on_full_weekday() {} + void on_dec0_weekday(numeric_system) {} + void on_dec1_weekday(numeric_system) {} + void on_abbr_month() {} + void on_full_month() {} + void on_datetime(numeric_system) {} + void on_loc_date(numeric_system) {} + void on_loc_time(numeric_system) {} + void on_us_date() {} + void on_iso_date() {} + void on_utc_offset() {} + void on_tz_name() {} + void on_year(numeric_system) {} + void on_short_year(numeric_system) {} + void on_offset_year() {} + void on_century(numeric_system) {} + void on_iso_week_based_year() {} + void on_iso_week_based_short_year() {} + void on_dec_month(numeric_system) {} + void on_dec0_week_of_year(numeric_system) {} + void on_dec1_week_of_year(numeric_system) {} + void on_iso_week_of_year(numeric_system) {} + void on_day_of_year() {} + void on_day_of_month(numeric_system) {} + void on_day_of_month_space(numeric_system) {} + + void on_24_hour(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour(), 2); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour(), 24); + format_tm(time, &tm_writer_type::on_24_hour, ns); + } + + void on_12_hour(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(hour12(), 2); + auto time = tm(); + time.tm_hour = to_nonnegative_int(hour12(), 12); + format_tm(time, &tm_writer_type::on_12_hour, ns); + } + + void on_minute(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) return write(minute(), 2); + auto time = tm(); + time.tm_min = to_nonnegative_int(minute(), 60); + format_tm(time, &tm_writer_type::on_minute, ns); + } + + void on_second(numeric_system ns) { + if (handle_nan_inf()) return; + + if (ns == numeric_system::standard) { + if (std::is_floating_point::value) { + constexpr auto num_fractional_digits = + count_fractional_digits::value; + auto buf = memory_buffer(); + format_to(std::back_inserter(buf), runtime("{:.{}f}"), + std::fmod(val * static_cast(Period::num) / + static_cast(Period::den), + 60), + num_fractional_digits); + if (negative) *out++ = '-'; + if (buf.size() < 2 || buf[1] == '.') *out++ = '0'; + out = std::copy(buf.begin(), buf.end(), out); + } else { + write(second(), 2); + write_fractional_seconds(std::chrono::duration(val)); + } + return; + } + auto time = tm(); + time.tm_sec = to_nonnegative_int(second(), 60); + format_tm(time, &tm_writer_type::on_second, ns); + } + + void on_12_hour_time() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_12_hour_time); + } + + void on_24_hour_time() { + if (handle_nan_inf()) { + *out++ = ':'; + handle_nan_inf(); + return; + } + + write(hour(), 2); + *out++ = ':'; + write(minute(), 2); + } + + void on_iso_time() { + on_24_hour_time(); + *out++ = ':'; + if (handle_nan_inf()) return; + on_second(numeric_system::standard); + } + + void on_am_pm() { + if (handle_nan_inf()) return; + format_tm(time(), &tm_writer_type::on_am_pm); + } + + void on_duration_value() { + if (handle_nan_inf()) return; + write_sign(); + out = format_duration_value(out, val, precision); + } + + void on_duration_unit() { + out = format_duration_unit(out); + } +}; + +FMT_END_DETAIL_NAMESPACE + +#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 +using weekday = std::chrono::weekday; +#else +// A fallback version of weekday. +class weekday { + private: + unsigned char value; + + public: + weekday() = default; + explicit constexpr weekday(unsigned wd) noexcept + : value(static_cast(wd != 7 ? wd : 0)) {} + constexpr unsigned c_encoding() const noexcept { return value; } +}; + +class year_month_day {}; +#endif + +// A rudimentary weekday formatter. +template struct formatter { + private: + bool localized = false; + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin != end && *begin == 'L') { + ++begin; + localized = true; + } + return begin; + } + + template + auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) { + auto time = std::tm(); + time.tm_wday = static_cast(wd.c_encoding()); + detail::get_locale loc(localized, ctx.locale()); + auto w = detail::tm_writer(loc, ctx.out(), time); + w.on_abbr_weekday(); + return w.out(); + } +}; + +template +struct formatter, Char> { + private: + basic_format_specs specs; + int precision = -1; + using arg_ref_type = detail::arg_ref; + arg_ref_type width_ref; + arg_ref_type precision_ref; + bool localized = false; + basic_string_view format_str; + using duration = std::chrono::duration; + + struct spec_handler { + formatter& f; + basic_format_parse_context& context; + basic_string_view format_str; + + template FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) { + context.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view arg_id) { + context.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id) { + return arg_ref_type(context.next_arg_id()); + } + + void on_error(const char* msg) { log_error(msg); } + FMT_CONSTEXPR void on_fill(basic_string_view fill) { + f.specs.fill = fill; + } + FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; } + FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; } + FMT_CONSTEXPR void on_precision(int _precision) { + f.precision = _precision; + } + FMT_CONSTEXPR void end_precision() {} + + template FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + f.width_ref = make_arg_ref(arg_id); + } + + template FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + f.precision_ref = make_arg_ref(arg_id); + } + }; + + using iterator = typename basic_format_parse_context::iterator; + struct parse_range { + iterator begin; + iterator end; + }; + + FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context& ctx) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end || *begin == '}') return {begin, begin}; + spec_handler handler{*this, ctx, format_str}; + begin = detail::parse_align(begin, end, handler); + if (begin == end) return {begin, begin}; + begin = detail::parse_width(begin, end, handler); + if (begin == end) return {begin, begin}; + if (*begin == '.') { + if (std::is_floating_point::value) + begin = detail::parse_precision(begin, end, handler); + else + handler.on_error("precision not allowed for this argument type"); + } + if (begin != end && *begin == 'L') { + ++begin; + localized = true; + } + end = detail::parse_chrono_format(begin, end, + detail::chrono_format_checker()); + return {begin, end}; + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto range = do_parse(ctx); + format_str = basic_string_view( + &*range.begin, detail::to_unsigned(range.end - range.begin)); + return range.end; + } + + template + auto format(const duration& d, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs_copy = specs; + auto precision_copy = precision; + auto begin = format_str.begin(), end = format_str.end(); + // As a possible future optimization, we could avoid extra copying if width + // is not specified. + basic_memory_buffer buf; + auto out = std::back_inserter(buf); + detail::handle_dynamic_spec(specs_copy.width, + width_ref, ctx); + detail::handle_dynamic_spec(precision_copy, + precision_ref, ctx); + if (begin == end || *begin == '}') { + out = detail::format_duration_value(out, d.count(), precision_copy); + detail::format_duration_unit(out); + } else { + detail::chrono_formatter f( + ctx, out, d); + f.precision = precision_copy; + f.localized = localized; + detail::parse_chrono_format(begin, end, f); + } + return detail::write( + ctx.out(), basic_string_view(buf.data(), buf.size()), specs_copy); + } +}; + +template +struct formatter, + Char> : formatter { + FMT_CONSTEXPR formatter() { + this->do_parse(default_specs, + default_specs + sizeof(default_specs) / sizeof(Char)); + } + + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return this->do_parse(ctx.begin(), ctx.end(), true); + } + + template + auto format(std::chrono::time_point val, + FormatContext& ctx) const -> decltype(ctx.out()) { + return formatter::format(localtime(val), ctx); + } + + static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'}; +}; + +template +constexpr const Char + formatter, + Char>::default_specs[]; + +template struct formatter { + private: + enum class spec { + unknown, + year_month_day, + hh_mm_ss, + }; + spec spec_ = spec::unknown; + basic_string_view specs; + + protected: + template + FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false) + -> It { + if (begin != end && *begin == ':') ++begin; + end = detail::parse_chrono_format(begin, end, detail::tm_format_checker()); + if (!with_default || end != begin) + specs = {begin, detail::to_unsigned(end - begin)}; + // basic_string_view<>::compare isn't constexpr before C++17. + if (specs.size() == 2 && specs[0] == Char('%')) { + if (specs[1] == Char('F')) + spec_ = spec::year_month_day; + else if (specs[1] == Char('T')) + spec_ = spec::hh_mm_ss; + } + return end; + } + + public: + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return this->do_parse(ctx.begin(), ctx.end()); + } + + template + auto format(const std::tm& tm, FormatContext& ctx) const + -> decltype(ctx.out()) { + const auto loc_ref = ctx.locale(); + detail::get_locale loc(static_cast(loc_ref), loc_ref); + auto w = detail::tm_writer(loc, ctx.out(), tm); + if (spec_ == spec::year_month_day) + w.on_iso_date(); + else if (spec_ == spec::hh_mm_ss) + w.on_iso_time(); + else + detail::parse_chrono_format(specs.begin(), specs.end(), w); + return w.out(); + } +}; + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_CHRONO_H_ diff --git a/itemzflow/include/fmt/color.h b/itemzflow/include/fmt/color.h new file mode 100644 index 0000000..bb9d7d6 --- /dev/null +++ b/itemzflow/include/fmt/color.h @@ -0,0 +1,650 @@ +// Formatting library for C++ - color support +// +// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COLOR_H_ +#define FMT_COLOR_H_ + +#include "format.h" +#include "../log.h" + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +enum class color : uint32_t { + alice_blue = 0xF0F8FF, // rgb(240,248,255) + antique_white = 0xFAEBD7, // rgb(250,235,215) + aqua = 0x00FFFF, // rgb(0,255,255) + aquamarine = 0x7FFFD4, // rgb(127,255,212) + azure = 0xF0FFFF, // rgb(240,255,255) + beige = 0xF5F5DC, // rgb(245,245,220) + bisque = 0xFFE4C4, // rgb(255,228,196) + black = 0x000000, // rgb(0,0,0) + blanched_almond = 0xFFEBCD, // rgb(255,235,205) + blue = 0x0000FF, // rgb(0,0,255) + blue_violet = 0x8A2BE2, // rgb(138,43,226) + brown = 0xA52A2A, // rgb(165,42,42) + burly_wood = 0xDEB887, // rgb(222,184,135) + cadet_blue = 0x5F9EA0, // rgb(95,158,160) + chartreuse = 0x7FFF00, // rgb(127,255,0) + chocolate = 0xD2691E, // rgb(210,105,30) + coral = 0xFF7F50, // rgb(255,127,80) + cornflower_blue = 0x6495ED, // rgb(100,149,237) + cornsilk = 0xFFF8DC, // rgb(255,248,220) + crimson = 0xDC143C, // rgb(220,20,60) + cyan = 0x00FFFF, // rgb(0,255,255) + dark_blue = 0x00008B, // rgb(0,0,139) + dark_cyan = 0x008B8B, // rgb(0,139,139) + dark_golden_rod = 0xB8860B, // rgb(184,134,11) + dark_gray = 0xA9A9A9, // rgb(169,169,169) + dark_green = 0x006400, // rgb(0,100,0) + dark_khaki = 0xBDB76B, // rgb(189,183,107) + dark_magenta = 0x8B008B, // rgb(139,0,139) + dark_olive_green = 0x556B2F, // rgb(85,107,47) + dark_orange = 0xFF8C00, // rgb(255,140,0) + dark_orchid = 0x9932CC, // rgb(153,50,204) + dark_red = 0x8B0000, // rgb(139,0,0) + dark_salmon = 0xE9967A, // rgb(233,150,122) + dark_sea_green = 0x8FBC8F, // rgb(143,188,143) + dark_slate_blue = 0x483D8B, // rgb(72,61,139) + dark_slate_gray = 0x2F4F4F, // rgb(47,79,79) + dark_turquoise = 0x00CED1, // rgb(0,206,209) + dark_violet = 0x9400D3, // rgb(148,0,211) + deep_pink = 0xFF1493, // rgb(255,20,147) + deep_sky_blue = 0x00BFFF, // rgb(0,191,255) + dim_gray = 0x696969, // rgb(105,105,105) + dodger_blue = 0x1E90FF, // rgb(30,144,255) + fire_brick = 0xB22222, // rgb(178,34,34) + floral_white = 0xFFFAF0, // rgb(255,250,240) + forest_green = 0x228B22, // rgb(34,139,34) + fuchsia = 0xFF00FF, // rgb(255,0,255) + gainsboro = 0xDCDCDC, // rgb(220,220,220) + ghost_white = 0xF8F8FF, // rgb(248,248,255) + gold = 0xFFD700, // rgb(255,215,0) + golden_rod = 0xDAA520, // rgb(218,165,32) + gray = 0x808080, // rgb(128,128,128) + green = 0x008000, // rgb(0,128,0) + green_yellow = 0xADFF2F, // rgb(173,255,47) + honey_dew = 0xF0FFF0, // rgb(240,255,240) + hot_pink = 0xFF69B4, // rgb(255,105,180) + indian_red = 0xCD5C5C, // rgb(205,92,92) + indigo = 0x4B0082, // rgb(75,0,130) + ivory = 0xFFFFF0, // rgb(255,255,240) + khaki = 0xF0E68C, // rgb(240,230,140) + lavender = 0xE6E6FA, // rgb(230,230,250) + lavender_blush = 0xFFF0F5, // rgb(255,240,245) + lawn_green = 0x7CFC00, // rgb(124,252,0) + lemon_chiffon = 0xFFFACD, // rgb(255,250,205) + light_blue = 0xADD8E6, // rgb(173,216,230) + light_coral = 0xF08080, // rgb(240,128,128) + light_cyan = 0xE0FFFF, // rgb(224,255,255) + light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210) + light_gray = 0xD3D3D3, // rgb(211,211,211) + light_green = 0x90EE90, // rgb(144,238,144) + light_pink = 0xFFB6C1, // rgb(255,182,193) + light_salmon = 0xFFA07A, // rgb(255,160,122) + light_sea_green = 0x20B2AA, // rgb(32,178,170) + light_sky_blue = 0x87CEFA, // rgb(135,206,250) + light_slate_gray = 0x778899, // rgb(119,136,153) + light_steel_blue = 0xB0C4DE, // rgb(176,196,222) + light_yellow = 0xFFFFE0, // rgb(255,255,224) + lime = 0x00FF00, // rgb(0,255,0) + lime_green = 0x32CD32, // rgb(50,205,50) + linen = 0xFAF0E6, // rgb(250,240,230) + magenta = 0xFF00FF, // rgb(255,0,255) + maroon = 0x800000, // rgb(128,0,0) + medium_aquamarine = 0x66CDAA, // rgb(102,205,170) + medium_blue = 0x0000CD, // rgb(0,0,205) + medium_orchid = 0xBA55D3, // rgb(186,85,211) + medium_purple = 0x9370DB, // rgb(147,112,219) + medium_sea_green = 0x3CB371, // rgb(60,179,113) + medium_slate_blue = 0x7B68EE, // rgb(123,104,238) + medium_spring_green = 0x00FA9A, // rgb(0,250,154) + medium_turquoise = 0x48D1CC, // rgb(72,209,204) + medium_violet_red = 0xC71585, // rgb(199,21,133) + midnight_blue = 0x191970, // rgb(25,25,112) + mint_cream = 0xF5FFFA, // rgb(245,255,250) + misty_rose = 0xFFE4E1, // rgb(255,228,225) + moccasin = 0xFFE4B5, // rgb(255,228,181) + navajo_white = 0xFFDEAD, // rgb(255,222,173) + navy = 0x000080, // rgb(0,0,128) + old_lace = 0xFDF5E6, // rgb(253,245,230) + olive = 0x808000, // rgb(128,128,0) + olive_drab = 0x6B8E23, // rgb(107,142,35) + orange = 0xFFA500, // rgb(255,165,0) + orange_red = 0xFF4500, // rgb(255,69,0) + orchid = 0xDA70D6, // rgb(218,112,214) + pale_golden_rod = 0xEEE8AA, // rgb(238,232,170) + pale_green = 0x98FB98, // rgb(152,251,152) + pale_turquoise = 0xAFEEEE, // rgb(175,238,238) + pale_violet_red = 0xDB7093, // rgb(219,112,147) + papaya_whip = 0xFFEFD5, // rgb(255,239,213) + peach_puff = 0xFFDAB9, // rgb(255,218,185) + peru = 0xCD853F, // rgb(205,133,63) + pink = 0xFFC0CB, // rgb(255,192,203) + plum = 0xDDA0DD, // rgb(221,160,221) + powder_blue = 0xB0E0E6, // rgb(176,224,230) + purple = 0x800080, // rgb(128,0,128) + rebecca_purple = 0x663399, // rgb(102,51,153) + red = 0xFF0000, // rgb(255,0,0) + rosy_brown = 0xBC8F8F, // rgb(188,143,143) + royal_blue = 0x4169E1, // rgb(65,105,225) + saddle_brown = 0x8B4513, // rgb(139,69,19) + salmon = 0xFA8072, // rgb(250,128,114) + sandy_brown = 0xF4A460, // rgb(244,164,96) + sea_green = 0x2E8B57, // rgb(46,139,87) + sea_shell = 0xFFF5EE, // rgb(255,245,238) + sienna = 0xA0522D, // rgb(160,82,45) + silver = 0xC0C0C0, // rgb(192,192,192) + sky_blue = 0x87CEEB, // rgb(135,206,235) + slate_blue = 0x6A5ACD, // rgb(106,90,205) + slate_gray = 0x708090, // rgb(112,128,144) + snow = 0xFFFAFA, // rgb(255,250,250) + spring_green = 0x00FF7F, // rgb(0,255,127) + steel_blue = 0x4682B4, // rgb(70,130,180) + tan = 0xD2B48C, // rgb(210,180,140) + teal = 0x008080, // rgb(0,128,128) + thistle = 0xD8BFD8, // rgb(216,191,216) + tomato = 0xFF6347, // rgb(255,99,71) + turquoise = 0x40E0D0, // rgb(64,224,208) + violet = 0xEE82EE, // rgb(238,130,238) + wheat = 0xF5DEB3, // rgb(245,222,179) + white = 0xFFFFFF, // rgb(255,255,255) + white_smoke = 0xF5F5F5, // rgb(245,245,245) + yellow = 0xFFFF00, // rgb(255,255,0) + yellow_green = 0x9ACD32 // rgb(154,205,50) +}; // enum class color + +enum class terminal_color : uint8_t { + black = 30, + red, + green, + yellow, + blue, + magenta, + cyan, + white, + bright_black = 90, + bright_red, + bright_green, + bright_yellow, + bright_blue, + bright_magenta, + bright_cyan, + bright_white +}; + +enum class emphasis : uint8_t { + bold = 1, + faint = 1 << 1, + italic = 1 << 2, + underline = 1 << 3, + blink = 1 << 4, + reverse = 1 << 5, + conceal = 1 << 6, + strikethrough = 1 << 7, +}; + +// rgb is a struct for red, green and blue colors. +// Using the name "rgb" makes some editors show the color in a tooltip. +struct rgb { + FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {} + FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {} + FMT_CONSTEXPR rgb(uint32_t hex) + : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {} + FMT_CONSTEXPR rgb(color hex) + : r((uint32_t(hex) >> 16) & 0xFF), + g((uint32_t(hex) >> 8) & 0xFF), + b(uint32_t(hex) & 0xFF) {} + uint8_t r; + uint8_t g; + uint8_t b; +}; + +FMT_BEGIN_DETAIL_NAMESPACE + +// color is a struct of either a rgb color or a terminal color. +struct color_type { + FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {} + FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} { + value.rgb_color = static_cast(rgb_color); + } + FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} { + value.rgb_color = (static_cast(rgb_color.r) << 16) | + (static_cast(rgb_color.g) << 8) | rgb_color.b; + } + FMT_CONSTEXPR color_type(terminal_color term_color) noexcept + : is_rgb(), value{} { + value.term_color = static_cast(term_color); + } + bool is_rgb; + union color_union { + uint8_t term_color; + uint32_t rgb_color; + } value; +}; + +FMT_END_DETAIL_NAMESPACE + +/** A text style consisting of foreground and background colors and emphasis. */ +class text_style { + public: + FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept + : set_foreground_color(), set_background_color(), ems(em) {} + + FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) { + if (!set_foreground_color) { + set_foreground_color = rhs.set_foreground_color; + foreground_color = rhs.foreground_color; + } else if (rhs.set_foreground_color) { + if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) + log_error("can't OR a terminal color"); + foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color; + } + + if (!set_background_color) { + set_background_color = rhs.set_background_color; + background_color = rhs.background_color; + } else if (rhs.set_background_color) { + if (!background_color.is_rgb || !rhs.background_color.is_rgb) + log_error("can't OR a terminal color"); + background_color.value.rgb_color |= rhs.background_color.value.rgb_color; + } + + ems = static_cast(static_cast(ems) | + static_cast(rhs.ems)); + return *this; + } + + friend FMT_CONSTEXPR text_style operator|(text_style lhs, + const text_style& rhs) { + return lhs |= rhs; + } + + FMT_CONSTEXPR bool has_foreground() const noexcept { + return set_foreground_color; + } + FMT_CONSTEXPR bool has_background() const noexcept { + return set_background_color; + } + FMT_CONSTEXPR bool has_emphasis() const noexcept { + return static_cast(ems) != 0; + } + FMT_CONSTEXPR detail::color_type get_foreground() const noexcept { + FMT_ASSERT(has_foreground(), "no foreground specified for this style"); + return foreground_color; + } + FMT_CONSTEXPR detail::color_type get_background() const noexcept { + FMT_ASSERT(has_background(), "no background specified for this style"); + return background_color; + } + FMT_CONSTEXPR emphasis get_emphasis() const noexcept { + FMT_ASSERT(has_emphasis(), "no emphasis specified for this style"); + return ems; + } + + private: + FMT_CONSTEXPR text_style(bool is_foreground, + detail::color_type text_color) noexcept + : set_foreground_color(), set_background_color(), ems() { + if (is_foreground) { + foreground_color = text_color; + set_foreground_color = true; + } else { + background_color = text_color; + set_background_color = true; + } + } + + friend FMT_CONSTEXPR text_style fg(detail::color_type foreground) noexcept; + + friend FMT_CONSTEXPR text_style bg(detail::color_type background) noexcept; + + detail::color_type foreground_color; + detail::color_type background_color; + bool set_foreground_color; + bool set_background_color; + emphasis ems; +}; + +/** Creates a text style from the foreground (text) color. */ +FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) noexcept { + return text_style(true, foreground); +} + +/** Creates a text style from the background color. */ +FMT_CONSTEXPR inline text_style bg(detail::color_type background) noexcept { + return text_style(false, background); +} + +FMT_CONSTEXPR inline text_style operator|(emphasis lhs, emphasis rhs) noexcept { + return text_style(lhs) | rhs; +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template struct ansi_color_escape { + FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color, + const char* esc) noexcept { + // If we have a terminal color, we need to output another escape code + // sequence. + if (!text_color.is_rgb) { + bool is_background = esc == string_view("\x1b[48;2;"); + uint32_t value = text_color.value.term_color; + // Background ASCII codes are the same as the foreground ones but with + // 10 more. + if (is_background) value += 10u; + + size_t index = 0; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + + if (value >= 100u) { + buffer[index++] = static_cast('1'); + value %= 100u; + } + buffer[index++] = static_cast('0' + value / 10u); + buffer[index++] = static_cast('0' + value % 10u); + + buffer[index++] = static_cast('m'); + buffer[index++] = static_cast('\0'); + return; + } + + for (int i = 0; i < 7; i++) { + buffer[i] = static_cast(esc[i]); + } + rgb color(text_color.value.rgb_color); + to_esc(color.r, buffer + 7, ';'); + to_esc(color.g, buffer + 11, ';'); + to_esc(color.b, buffer + 15, 'm'); + buffer[19] = static_cast(0); + } + FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept { + uint8_t em_codes[num_emphases] = {}; + if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1; + if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2; + if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3; + if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4; + if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5; + if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7; + if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8; + if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9; + + size_t index = 0; + for (size_t i = 0; i < num_emphases; ++i) { + if (!em_codes[i]) continue; + buffer[index++] = static_cast('\x1b'); + buffer[index++] = static_cast('['); + buffer[index++] = static_cast('0' + em_codes[i]); + buffer[index++] = static_cast('m'); + } + buffer[index++] = static_cast(0); + } + FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; } + + FMT_CONSTEXPR const Char* begin() const noexcept { return buffer; } + FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const noexcept { + return buffer + std::char_traits::length(buffer); + } + + private: + static constexpr size_t num_emphases = 8; + Char buffer[7u + 3u * num_emphases + 1u]; + + static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out, + char delimiter) noexcept { + out[0] = static_cast('0' + c / 100); + out[1] = static_cast('0' + c / 10 % 10); + out[2] = static_cast('0' + c % 10); + out[3] = static_cast(delimiter); + } + static FMT_CONSTEXPR bool has_emphasis(emphasis em, emphasis mask) noexcept { + return static_cast(em) & static_cast(mask); + } +}; + +template +FMT_CONSTEXPR ansi_color_escape make_foreground_color( + detail::color_type foreground) noexcept { + return ansi_color_escape(foreground, "\x1b[38;2;"); +} + +template +FMT_CONSTEXPR ansi_color_escape make_background_color( + detail::color_type background) noexcept { + return ansi_color_escape(background, "\x1b[48;2;"); +} + +template +FMT_CONSTEXPR ansi_color_escape make_emphasis(emphasis em) noexcept { + return ansi_color_escape(em); +} + +template inline void fputs(const Char* chars, FILE* stream) { + __unused(stream); + log_info("%s", chars); +} + +template <> inline void fputs(const wchar_t* chars, FILE* stream) { + __unused(stream); + log_info("%s", chars); +} + +template inline void reset_color(FILE* stream) { + fputs("\x1b[0m", stream); +} + +template <> inline void reset_color(FILE* stream) { + fputs(L"\x1b[0m", stream); +} + +template inline void reset_color(buffer& buffer) { + auto reset_color = string_view("\x1b[0m"); + buffer.append(reset_color.begin(), reset_color.end()); +} + +template struct styled_arg { + const T& value; + text_style style; +}; + +template +void vformat_to(buffer& buf, const text_style& ts, + basic_string_view format_str, + basic_format_args>> args) { + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis(ts.get_emphasis()); + buf.append(emphasis.begin(), emphasis.end()); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = detail::make_foreground_color(ts.get_foreground()); + buf.append(foreground.begin(), foreground.end()); + } + if (ts.has_background()) { + has_style = true; + auto background = detail::make_background_color(ts.get_background()); + buf.append(background.begin(), background.end()); + } + detail::vformat_to(buf, format_str, args, {}); + if (has_style) detail::reset_color(buf); +} + +FMT_END_DETAIL_NAMESPACE + +template > +void vprint(std::FILE* f, const text_style& ts, const S& format, + basic_format_args>> args) { + basic_memory_buffer buf; + detail::vformat_to(buf, ts, detail::to_string_view(format), args); + if (detail::is_utf8()) { + detail::print(f, basic_string_view(buf.begin(), buf.size())); + } else { + buf.push_back(Char(0)); + detail::fputs(buf.data(), f); + } +} + +/** + \rst + Formats a string and prints it to the specified file stream using ANSI + escape sequences to specify text formatting. + + **Example**:: + + fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + "Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template ::value)> +void print(std::FILE* f, const text_style& ts, const S& format_str, + const Args&... args) { + vprint(f, ts, format_str, + fmt::make_format_args>>(args...)); +} + +/** + \rst + Formats a string and prints it to stdout using ANSI escape sequences to + specify text formatting. + + **Example**:: + + fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + "Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template ::value)> +void print(const text_style& ts, const S& format_str, const Args&... args) { + return print(stdout, ts, format_str, args...); +} + +template > +inline std::basic_string vformat( + const text_style& ts, const S& format_str, + basic_format_args>> args) { + basic_memory_buffer buf; + detail::vformat_to(buf, ts, detail::to_string_view(format_str), args); + return fmt::to_string(buf); +} + +/** + \rst + Formats arguments and returns the result as a string using ANSI + escape sequences to specify text formatting. + + **Example**:: + + #include + std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), + "The answer is {}", 42); + \endrst +*/ +template > +inline std::basic_string format(const text_style& ts, const S& format_str, + const Args&... args) { + return fmt::vformat(ts, detail::to_string_view(format_str), + fmt::make_format_args>(args...)); +} + +/** + Formats a string with the given text_style and writes the output to ``out``. + */ +template ::value)> +OutputIt vformat_to( + OutputIt out, const text_style& ts, basic_string_view format_str, + basic_format_args>> args) { + auto&& buf = detail::get_buffer(out); + detail::vformat_to(buf, ts, format_str, args); + return detail::get_iterator(buf); +} + +/** + \rst + Formats arguments with the given text_style, writes the result to the output + iterator ``out`` and returns the iterator past the end of the output range. + + **Example**:: + + std::vector out; + fmt::format_to(std::back_inserter(out), + fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); + \endrst +*/ +template >::value&& + detail::is_string::value> +inline auto format_to(OutputIt out, const text_style& ts, const S& format_str, + Args&&... args) -> + typename std::enable_if::type { + return vformat_to(out, ts, detail::to_string_view(format_str), + fmt::make_format_args>>(args...)); +} + +template +struct formatter, Char> : formatter { + template + auto format(const detail::styled_arg& arg, FormatContext& ctx) const + -> decltype(ctx.out()) { + const auto& ts = arg.style; + const auto& value = arg.value; + auto out = ctx.out(); + + bool has_style = false; + if (ts.has_emphasis()) { + has_style = true; + auto emphasis = detail::make_emphasis(ts.get_emphasis()); + out = std::copy(emphasis.begin(), emphasis.end(), out); + } + if (ts.has_foreground()) { + has_style = true; + auto foreground = + detail::make_foreground_color(ts.get_foreground()); + out = std::copy(foreground.begin(), foreground.end(), out); + } + if (ts.has_background()) { + has_style = true; + auto background = + detail::make_background_color(ts.get_background()); + out = std::copy(background.begin(), background.end(), out); + } + out = formatter::format(value, ctx); + if (has_style) { + auto reset_color = string_view("\x1b[0m"); + out = std::copy(reset_color.begin(), reset_color.end(), out); + } + return out; + } +}; + +/** + \rst + Returns an argument that will be formatted using ANSI escape sequences, + to be used in a formatting function. + + **Example**:: + + fmt::print("Elapsed time: {s:.2f} seconds", + fmt::styled(1.23, fmt::fg(fmt::color::green) | + fmt::bg(fmt::color::blue))); + \endrst + */ +template +FMT_CONSTEXPR auto styled(const T& value, text_style ts) + -> detail::styled_arg> { + return detail::styled_arg>{value, ts}; +} + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_COLOR_H_ diff --git a/itemzflow/include/fmt/compile.h b/itemzflow/include/fmt/compile.h new file mode 100644 index 0000000..7aa85ab --- /dev/null +++ b/itemzflow/include/fmt/compile.h @@ -0,0 +1,603 @@ +// Formatting library for C++ - experimental format string compilation +// +// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_COMPILE_H_ +#define FMT_COMPILE_H_ + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { + +template +inline counting_iterator copy_str(InputIt begin, InputIt end, + counting_iterator it) { + return it + (end - begin); +} + +template class truncating_iterator_base { + protected: + OutputIt out_; + size_t limit_; + size_t count_ = 0; + + truncating_iterator_base() : out_(), limit_(0) {} + + truncating_iterator_base(OutputIt out, size_t limit) + : out_(out), limit_(limit) {} + + public: + using iterator_category = std::output_iterator_tag; + using value_type = typename std::iterator_traits::value_type; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; + FMT_UNCHECKED_ITERATOR(truncating_iterator_base); + + OutputIt base() const { return out_; } + size_t count() const { return count_; } +}; + +// An output iterator that truncates the output and counts the number of objects +// written to it. +template ::value_type>::type> +class truncating_iterator; + +template +class truncating_iterator + : public truncating_iterator_base { + mutable typename truncating_iterator_base::value_type blackhole_; + + public: + using value_type = typename truncating_iterator_base::value_type; + + truncating_iterator() = default; + + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base(out, limit) {} + + truncating_iterator& operator++() { + if (this->count_++ < this->limit_) ++this->out_; + return *this; + } + + truncating_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + value_type& operator*() const { + return this->count_ < this->limit_ ? *this->out_ : blackhole_; + } +}; + +template +class truncating_iterator + : public truncating_iterator_base { + public: + truncating_iterator() = default; + + truncating_iterator(OutputIt out, size_t limit) + : truncating_iterator_base(out, limit) {} + + template truncating_iterator& operator=(T val) { + if (this->count_++ < this->limit_) *this->out_++ = val; + return *this; + } + + truncating_iterator& operator++() { return *this; } + truncating_iterator& operator++(int) { return *this; } + truncating_iterator& operator*() { return *this; } +}; + +// A compile-time string which is compiled into fast formatting code. +class compiled_string {}; + +template +struct is_compiled_string : std::is_base_of {}; + +/** + \rst + Converts a string literal *s* into a format string that will be parsed at + compile time and converted into efficient formatting code. Requires C++17 + ``constexpr if`` compiler support. + + **Example**:: + + // Converts 42 into std::string using the most efficient method and no + // runtime format string processing. + std::string s = fmt::format(FMT_COMPILE("{}"), 42); + \endrst + */ +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +# define FMT_COMPILE(s) \ + FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit) +#else +# define FMT_COMPILE(s) FMT_STRING(s) +#endif + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template Str> +struct udl_compiled_string : compiled_string { + using char_type = Char; + explicit constexpr operator basic_string_view() const { + return {Str.data, N - 1}; + } +}; +#endif + +template +const T& first(const T& value, const Tail&...) { + return value; +} + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +template struct type_list {}; + +// Returns a reference to the argument at index N from [first, rest...]. +template +constexpr const auto& get([[maybe_unused]] const T& first, + [[maybe_unused]] const Args&... rest) { + static_assert(N < 1 + sizeof...(Args), "index is out of bounds"); + if constexpr (N == 0) + return first; + else + return detail::get(rest...); +} + +template +constexpr int get_arg_index_by_name(basic_string_view name, + type_list) { + return get_arg_index_by_name(name); +} + +template struct get_type_impl; + +template struct get_type_impl> { + using type = + remove_cvref_t(std::declval()...))>; +}; + +template +using get_type = typename get_type_impl::type; + +template struct is_compiled_format : std::false_type {}; + +template struct text { + basic_string_view data; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write(out, data); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr text make_text(basic_string_view s, size_t pos, + size_t size) { + return {{&s[pos], size}}; +} + +template struct code_unit { + Char value; + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&...) const { + return write(out, value); + } +}; + +// This ensures that the argument type is convertible to `const T&`. +template +constexpr const T& get_arg_checked(const Args&... args) { + const auto& arg = detail::get(args...); + if constexpr (detail::is_named_arg>()) { + return arg.value; + } else { + return arg; + } +} + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N. +template struct field { + using char_type = Char; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + return write(out, get_arg_checked(args...)); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument with name. +template struct runtime_named_field { + using char_type = Char; + basic_string_view name; + + template + constexpr static bool try_format_argument( + OutputIt& out, + // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9 + [[maybe_unused]] basic_string_view arg_name, const T& arg) { + if constexpr (is_named_arg::type>::value) { + if (arg_name == arg.name) { + out = write(out, arg.value); + return true; + } + } + return false; + } + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + bool found = (try_format_argument(out, name, args) || ...); + if (!found) { + log_error("argument with specified name is not found"); + } + return out; + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +// A replacement field that refers to argument N and has format specifiers. +template struct spec_field { + using char_type = Char; + formatter fmt; + + template + constexpr FMT_INLINE OutputIt format(OutputIt out, + const Args&... args) const { + const auto& vargs = + fmt::make_format_args>(args...); + basic_format_context ctx(out, vargs); + return fmt.format(get_arg_checked(args...), ctx); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template struct concat { + L lhs; + R rhs; + using char_type = typename L::char_type; + + template + constexpr OutputIt format(OutputIt out, const Args&... args) const { + out = lhs.format(out, args...); + return rhs.format(out, args...); + } +}; + +template +struct is_compiled_format> : std::true_type {}; + +template +constexpr concat make_concat(L lhs, R rhs) { + return {lhs, rhs}; +} + +struct unknown_format {}; + +template +constexpr size_t parse_text(basic_string_view str, size_t pos) { + for (size_t size = str.size(); pos != size; ++pos) { + if (str[pos] == '{' || str[pos] == '}') break; + } + return pos; +} + +template +constexpr auto compile_format_string(S format_str); + +template +constexpr auto parse_tail(T head, S format_str) { + if constexpr (POS != + basic_string_view(format_str).size()) { + constexpr auto tail = compile_format_string(format_str); + if constexpr (std::is_same, + unknown_format>()) + return tail; + else + return make_concat(head, tail); + } else { + return head; + } +} + +template struct parse_specs_result { + formatter fmt; + size_t end; + int next_arg_id; +}; + +constexpr int manual_indexing_id = -1; + +template +constexpr parse_specs_result parse_specs(basic_string_view str, + size_t pos, int next_arg_id) { + str.remove_prefix(pos); + auto ctx = compile_parse_context(str, max_value(), nullptr, {}, + next_arg_id); + auto f = formatter(); + auto end = f.parse(ctx); + return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, + next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; +} + +template struct arg_id_handler { + arg_ref arg_id; + + constexpr int operator()() { + FMT_ASSERT(false, "handler cannot be used with automatic indexing"); + return 0; + } + constexpr int operator()(int id) { + arg_id = arg_ref(id); + return 0; + } + constexpr int operator()(basic_string_view id) { + arg_id = arg_ref(id); + return 0; + } + + constexpr void on_error(const char* message) { + log_error(message); + } +}; + +template struct parse_arg_id_result { + arg_ref arg_id; + const Char* arg_id_end; +}; + +template +constexpr auto parse_arg_id(const Char* begin, const Char* end) { + auto handler = arg_id_handler{arg_ref{}}; + auto arg_id_end = parse_arg_id(begin, end, handler); + return parse_arg_id_result{handler.arg_id, arg_id_end}; +} + +template struct field_type { + using type = remove_cvref_t; +}; + +template +struct field_type::value>> { + using type = remove_cvref_t; +}; + +template +constexpr auto parse_replacement_field_then_tail(S format_str) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(format_str); + constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); + if constexpr (c == '}') { + return parse_tail( + field::type, ARG_INDEX>(), + format_str); + } else if constexpr (c == ':') { + constexpr auto result = parse_specs::type>( + str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); + return parse_tail( + spec_field::type, ARG_INDEX>{ + result.fmt}, + format_str); + } +} + +// Compiles a non-empty format string and returns the compiled representation +// or unknown_format() on unrecognized input. +template +constexpr auto compile_format_string(S format_str) { + using char_type = typename S::char_type; + constexpr auto str = basic_string_view(format_str); + if constexpr (str[POS] == '{') { + if constexpr (POS + 1 == str.size()) + log_error("unmatched '{' in format string"); + if constexpr (str[POS + 1] == '{') { + return parse_tail(make_text(str, POS, 1), format_str); + } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { + static_assert(ID != manual_indexing_id, + "cannot switch from manual to automatic argument indexing"); + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail, Args, + POS + 1, ID, next_id>( + format_str); + } else { + constexpr auto arg_id_result = + parse_arg_id(str.data() + POS + 1, str.data() + str.size()); + constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data(); + constexpr char_type c = + arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type(); + static_assert(c == '}' || c == ':', "missing '}' in format string"); + if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) { + static_assert( + ID == manual_indexing_id || ID == 0, + "cannot switch from automatic to manual argument indexing"); + constexpr auto arg_index = arg_id_result.arg_id.val.index; + return parse_replacement_field_then_tail, + Args, arg_id_end_pos, + arg_index, manual_indexing_id>( + format_str); + } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { + constexpr auto arg_index = + get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{}); + if constexpr (arg_index != invalid_arg_index) { + constexpr auto next_id = + ID != manual_indexing_id ? ID + 1 : manual_indexing_id; + return parse_replacement_field_then_tail< + decltype(get_type::value), Args, arg_id_end_pos, + arg_index, next_id>(format_str); + } else { + if constexpr (c == '}') { + return parse_tail( + runtime_named_field{arg_id_result.arg_id.val.name}, + format_str); + } else if constexpr (c == ':') { + return unknown_format(); // no type info for specs parsing + } + } + } + } + } else if constexpr (str[POS] == '}') { + if constexpr (POS + 1 == str.size()) + log_error("unmatched '}' in format string"); + return parse_tail(make_text(str, POS, 1), format_str); + } else { + constexpr auto end = parse_text(str, POS + 1); + if constexpr (end - POS > 1) { + return parse_tail(make_text(str, POS, end - POS), + format_str); + } else { + return parse_tail(code_unit{str[POS]}, + format_str); + } + } +} + +template ::value)> +constexpr auto compile(S format_str) { + constexpr auto str = basic_string_view(format_str); + if constexpr (str.size() == 0) { + return detail::make_text(str, 0, 0); + } else { + constexpr auto result = + detail::compile_format_string, 0, 0>( + format_str); + return result; + } +} +#endif // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) + +template ::value)> +FMT_INLINE std::basic_string format(const CompiledFormat& cf, + const Args&... args) { + auto s = std::basic_string(); + cf.format(std::back_inserter(s), args...); + return s; +} + +template ::value)> +constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, + const Args&... args) { + return cf.format(out, args...); +} + +template ::value)> +FMT_INLINE std::basic_string format(const S&, + Args&&... args) { + if constexpr (std::is_same::value) { + constexpr auto str = basic_string_view(S()); + if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { + const auto& first = detail::first(args...); + if constexpr (detail::is_named_arg< + remove_cvref_t>::value) { + return fmt::to_string(first.value); + } else { + return fmt::to_string(first); + } + } + } + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format( + static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format(compiled, std::forward(args)...); + } +} + +template ::value)> +FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { + constexpr auto compiled = detail::compile(S()); + if constexpr (std::is_same, + detail::unknown_format>()) { + return fmt::format_to( + out, static_cast>(S()), + std::forward(args)...); + } else { + return fmt::format_to(out, compiled, std::forward(args)...); + } +} +#endif + +template ::value)> +format_to_n_result format_to_n(OutputIt out, size_t n, + const S& format_str, Args&&... args) { + auto it = fmt::format_to(detail::truncating_iterator(out, n), + format_str, std::forward(args)...); + return {it.base(), it.count()}; +} + +template ::value)> +size_t formatted_size(const S& format_str, const Args&... args) { + return fmt::format_to(detail::counting_iterator(), format_str, args...) + .count(); +} + +template ::value)> +void print(std::FILE* f, const S& format_str, const Args&... args) { + memory_buffer buffer; + fmt::format_to(std::back_inserter(buffer), format_str, args...); + detail::print(f, {buffer.data(), buffer.size()}); +} + +template ::value)> +void print(const S& format_str, const Args&... args) { + print(stdout, format_str, args...); +} + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +inline namespace literals { +template constexpr auto operator""_cf() { + using char_t = remove_cvref_t; + return detail::udl_compiled_string(); +} +} // namespace literals +#endif + +FMT_MODULE_EXPORT_END +FMT_END_NAMESPACE + +#endif // FMT_COMPILE_H_ diff --git a/itemzflow/include/fmt/core.h b/itemzflow/include/fmt/core.h new file mode 100644 index 0000000..82cfdbb --- /dev/null +++ b/itemzflow/include/fmt/core.h @@ -0,0 +1,3272 @@ +// Formatting library for C++ - the core API for char/UTF-8 +// +// Copyright (c) 2012 - present, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_CORE_H_ +#define FMT_CORE_H_ + +#include // std::byte +#include // std::FILE +#include // std::strlen +#include +#include +#include +#include + +// The fmt library version in the form major * 10000 + minor * 100 + patch. +#define FMT_VERSION 90000 + +#if defined(__clang__) && !defined(__ibmxl__) +# define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#else +# define FMT_CLANG_VERSION 0 +#endif + +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \ + !defined(__NVCOMPILER) +# define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define FMT_GCC_VERSION 0 +#endif + +#ifndef FMT_GCC_PRAGMA +// Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884. +# if FMT_GCC_VERSION >= 504 +# define FMT_GCC_PRAGMA(arg) _Pragma(arg) +# else +# define FMT_GCC_PRAGMA(arg) +# endif +#endif + +#ifdef __ICL +# define FMT_ICC_VERSION __ICL +#elif defined(__INTEL_COMPILER) +# define FMT_ICC_VERSION __INTEL_COMPILER +#else +# define FMT_ICC_VERSION 0 +#endif + +#ifdef _MSC_VER +# define FMT_MSC_VERSION _MSC_VER +# define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) +#else +# define FMT_MSC_VERSION 0 +# define FMT_MSC_WARNING(...) +#endif + +#ifdef _MSVC_LANG +# define FMT_CPLUSPLUS _MSVC_LANG +#else +# define FMT_CPLUSPLUS __cplusplus +#endif + +#ifdef __has_feature +# define FMT_HAS_FEATURE(x) __has_feature(x) +#else +# define FMT_HAS_FEATURE(x) 0 +#endif + +#if (defined(__has_include) || FMT_ICC_VERSION >= 1600 || \ + FMT_MSC_VERSION > 1900) && \ + !defined(__INTELLISENSE__) +# define FMT_HAS_INCLUDE(x) __has_include(x) +#else +# define FMT_HAS_INCLUDE(x) 0 +#endif + +#ifdef __has_cpp_attribute +# define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +# define FMT_HAS_CPP_ATTRIBUTE(x) 0 +#endif + +#define FMT_HAS_CPP14_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +#define FMT_HAS_CPP17_ATTRIBUTE(attribute) \ + (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute)) + +// Check if relaxed C++14 constexpr is supported. +// GCC doesn't allow throw in constexpr until version 6 (bug 67371). +#ifndef FMT_USE_CONSTEXPR +# if (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 || \ + (FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L)) && \ + !FMT_ICC_VERSION && !defined(__NVCC__) +# define FMT_USE_CONSTEXPR 1 +# else +# define FMT_USE_CONSTEXPR 0 +# endif +#endif +#if FMT_USE_CONSTEXPR +# define FMT_CONSTEXPR constexpr +#else +# define FMT_CONSTEXPR +#endif + +#if ((FMT_CPLUSPLUS >= 202002L) && \ + (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 9)) || \ + (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002) +# define FMT_CONSTEXPR20 constexpr +#else +# define FMT_CONSTEXPR20 +#endif + +// Check if constexpr std::char_traits<>::{compare,length} are supported. +#if defined(__GLIBCXX__) +# if FMT_CPLUSPLUS >= 201703L && defined(_GLIBCXX_RELEASE) && \ + _GLIBCXX_RELEASE >= 7 // GCC 7+ libstdc++ has _GLIBCXX_RELEASE. +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +# endif +#elif defined(_LIBCPP_VERSION) && FMT_CPLUSPLUS >= 201703L && \ + _LIBCPP_VERSION >= 4000 +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#elif FMT_MSC_VERSION >= 1914 && FMT_CPLUSPLUS >= 201703L +# define FMT_CONSTEXPR_CHAR_TRAITS constexpr +#endif +#ifndef FMT_CONSTEXPR_CHAR_TRAITS +# define FMT_CONSTEXPR_CHAR_TRAITS +#endif + +// Check if exceptions are disabled. +#ifndef FMT_EXCEPTIONS +# if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \ + (FMT_MSC_VERSION && !_HAS_EXCEPTIONS) +# define FMT_EXCEPTIONS 0 +# else +# define FMT_EXCEPTIONS 1 +# endif +#endif + +#ifndef FMT_DEPRECATED +# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900 +# define FMT_DEPRECATED [[deprecated]] +# else +# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__) +# define FMT_DEPRECATED __attribute__((deprecated)) +# elif FMT_MSC_VERSION +# define FMT_DEPRECATED __declspec(deprecated) +# else +# define FMT_DEPRECATED /* deprecated */ +# endif +# endif +#endif + +// [[noreturn]] is disabled on MSVC and NVCC because of bogus unreachable code +// warnings. +#if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && \ + !defined(__NVCC__) +# define FMT_NORETURN [[noreturn]] +#else +# define FMT_NORETURN +#endif + +#if FMT_HAS_CPP17_ATTRIBUTE(fallthrough) +# define FMT_FALLTHROUGH [[fallthrough]] +#elif defined(__clang__) +# define FMT_FALLTHROUGH [[clang::fallthrough]] +#elif FMT_GCC_VERSION >= 700 && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520) +# define FMT_FALLTHROUGH [[gnu::fallthrough]] +#else +# define FMT_FALLTHROUGH +#endif + +#ifndef FMT_NODISCARD +# if FMT_HAS_CPP17_ATTRIBUTE(nodiscard) +# define FMT_NODISCARD [[nodiscard]] +# else +# define FMT_NODISCARD +# endif +#endif + +#ifndef FMT_USE_FLOAT +# define FMT_USE_FLOAT 1 +#endif +#ifndef FMT_USE_DOUBLE +# define FMT_USE_DOUBLE 1 +#endif +#ifndef FMT_USE_LONG_DOUBLE +# define FMT_USE_LONG_DOUBLE 1 +#endif + +#ifndef FMT_INLINE +# if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_INLINE inline __attribute__((always_inline)) +# else +# define FMT_INLINE inline +# endif +#endif + +#ifdef _MSC_VER +# define FMT_UNCHECKED_ITERATOR(It) \ + using _Unchecked_type = It // Mark iterator as checked. +#else +# define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It +#endif + +#ifndef FMT_BEGIN_NAMESPACE +# define FMT_BEGIN_NAMESPACE \ + namespace fmt { \ + inline namespace v9 { +# define FMT_END_NAMESPACE \ + } \ + } +#endif + +#ifndef FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT +# define FMT_MODULE_EXPORT_BEGIN +# define FMT_MODULE_EXPORT_END +# define FMT_BEGIN_DETAIL_NAMESPACE namespace detail { +# define FMT_END_DETAIL_NAMESPACE } +#endif + +#if !defined(FMT_HEADER_ONLY) && defined(_WIN32) +# define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275) +# ifdef FMT_EXPORT +# define FMT_API __declspec(dllexport) +# elif defined(FMT_SHARED) +# define FMT_API __declspec(dllimport) +# endif +#else +# define FMT_CLASS_API +# if defined(FMT_EXPORT) || defined(FMT_SHARED) +# if defined(__GNUC__) || defined(__clang__) +# define FMT_API __attribute__((visibility("default"))) +# endif +# endif +#endif +#ifndef FMT_API +# define FMT_API +#endif + +// libc++ supports string_view in pre-c++17. +#if FMT_HAS_INCLUDE() && \ + (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) +# include +# define FMT_USE_STRING_VIEW +#elif FMT_HAS_INCLUDE("experimental/string_view") && FMT_CPLUSPLUS >= 201402L +# include +# define FMT_USE_EXPERIMENTAL_STRING_VIEW +#endif + +#ifndef FMT_UNICODE +# define FMT_UNICODE !FMT_MSC_VERSION +#endif + +#ifndef FMT_CONSTEVAL +# if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \ + FMT_CPLUSPLUS >= 202002L && !defined(__apple_build_version__)) || \ + (defined(__cpp_consteval) && \ + (!FMT_MSC_VERSION || _MSC_FULL_VER >= 193030704)) +// consteval is broken in MSVC before VS2022 and Apple clang 13. +# define FMT_CONSTEVAL consteval +# define FMT_HAS_CONSTEVAL +# else +# define FMT_CONSTEVAL +# endif +#endif + +#ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS +# if defined(__cpp_nontype_template_args) && \ + ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \ + __cpp_nontype_template_args >= 201911L) +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +# else +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 +# endif +#endif + +// Enable minimal optimizations for more compact code in debug mode. +FMT_GCC_PRAGMA("GCC push_options") +#if !defined(__OPTIMIZE__) && !defined(__NVCOMPILER) +FMT_GCC_PRAGMA("GCC optimize(\"Og\")") +#endif + +FMT_BEGIN_NAMESPACE +FMT_MODULE_EXPORT_BEGIN + +// Implementations of enable_if_t and other metafunctions for older systems. +template +using enable_if_t = typename std::enable_if::type; +template +using conditional_t = typename std::conditional::type; +template using bool_constant = std::integral_constant; +template +using remove_reference_t = typename std::remove_reference::type; +template +using remove_const_t = typename std::remove_const::type; +template +using remove_cvref_t = typename std::remove_cv>::type; +template struct type_identity { using type = T; }; +template using type_identity_t = typename type_identity::type; +template +using underlying_t = typename std::underlying_type::type; + +template struct disjunction : std::false_type {}; +template struct disjunction

: P {}; +template +struct disjunction + : conditional_t> {}; + +template struct conjunction : std::true_type {}; +template struct conjunction

: P {}; +template +struct conjunction + : conditional_t, P1> {}; + +struct monostate { + constexpr monostate() {} +}; + +// An enable_if helper to be used in template parameters which results in much +// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed +// to workaround a bug in MSVC 2019 (see #1140 and #1186). +#ifdef FMT_DOC +# define FMT_ENABLE_IF(...) +#else +# define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 +#endif + +FMT_BEGIN_DETAIL_NAMESPACE + +// Suppresses "unused variable" warnings with the method described in +// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/. +// (void)var does not work on many Intel compilers. +template FMT_CONSTEXPR void ignore_unused(const T&...) {} + +constexpr FMT_INLINE auto is_constant_evaluated( + bool default_value = false) noexcept -> bool { +#ifdef __cpp_lib_is_constant_evaluated + ignore_unused(default_value); + return std::is_constant_evaluated(); +#else + return default_value; +#endif +} + +// Suppresses "conditional expression is constant" warnings. +template constexpr FMT_INLINE auto const_check(T value) -> T { + return value; +} + + + +FMT_NORETURN FMT_API void assert_fail(const char* file, int line, + const char* message); + +#define FMT_ASSERT(condition, message) \ +::fmt::detail::ignore_unused((condition), (message)) + +#if defined(FMT_USE_STRING_VIEW) +template using std_string_view = std::basic_string_view; +#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW) +template +using std_string_view = std::experimental::basic_string_view; +#else +template struct std_string_view {}; +#endif + +#ifdef FMT_USE_INT128 +// Do nothing. +#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \ + !(FMT_CLANG_VERSION && FMT_MSC_VERSION) +# define FMT_USE_INT128 1 +using int128_opt = __int128_t; // An optional native 128-bit integer. +using uint128_opt = __uint128_t; +template inline auto convert_for_visit(T value) -> T { + return value; +} +#else +# define FMT_USE_INT128 0 +#endif +#if !FMT_USE_INT128 +enum class int128_opt {}; +enum class uint128_opt {}; +// Reduce template instantiations. +template auto convert_for_visit(T) -> monostate { return {}; } +#endif + +// Casts a nonnegative integer to unsigned. +template +FMT_CONSTEXPR auto to_unsigned(Int value) -> + typename std::make_unsigned::type { + FMT_ASSERT(value >= 0, "negative value"); + return static_cast::type>(value); +} + +FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5"; + +constexpr auto is_utf8() -> bool { + // Avoid buggy sign extensions in MSVC's constant evaluation mode (#2297). + using uchar = unsigned char; + return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 && + uchar(micro[1]) == 0xB5); +} +FMT_END_DETAIL_NAMESPACE + +/** + An implementation of ``std::basic_string_view`` for pre-C++17. It provides a + subset of the API. ``fmt::basic_string_view`` is used for format strings even + if ``std::string_view`` is available to prevent issues when a library is + compiled with a different ``-std`` option than the client code (which is not + recommended). + */ +template class basic_string_view { + private: + const Char* data_; + size_t size_; + + public: + using value_type = Char; + using iterator = const Char*; + + constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} + + /** Constructs a string reference object from a C string and a size. */ + constexpr basic_string_view(const Char* s, size_t count) noexcept + : data_(s), size_(count) {} + + /** + \rst + Constructs a string reference object from a C string computing + the size with ``std::char_traits::length``. + \endrst + */ + FMT_CONSTEXPR_CHAR_TRAITS + FMT_INLINE + basic_string_view(const Char* s) + : data_(s), + size_(detail::const_check(std::is_same::value && + !detail::is_constant_evaluated(true)) + ? std::strlen(reinterpret_cast(s)) + : std::char_traits::length(s)) {} + + /** Constructs a string reference from a ``std::basic_string`` object. */ + template + FMT_CONSTEXPR basic_string_view( + const std::basic_string& s) noexcept + : data_(s.data()), size_(s.size()) {} + + template >::value)> + FMT_CONSTEXPR basic_string_view(S s) noexcept + : data_(s.data()), size_(s.size()) {} + + /** Returns a pointer to the string data. */ + constexpr auto data() const noexcept -> const Char* { return data_; } + + /** Returns the string size. */ + constexpr auto size() const noexcept -> size_t { return size_; } + + constexpr auto begin() const noexcept -> iterator { return data_; } + constexpr auto end() const noexcept -> iterator { return data_ + size_; } + + constexpr auto operator[](size_t pos) const noexcept -> const Char& { + return data_[pos]; + } + + FMT_CONSTEXPR void remove_prefix(size_t n) noexcept { + data_ += n; + size_ -= n; + } + + // Lexicographically compare this string reference to other. + FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int { + size_t str_size = size_ < other.size_ ? size_ : other.size_; + int result = std::char_traits::compare(data_, other.data_, str_size); + if (result == 0) + result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1); + return result; + } + + FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs, + basic_string_view rhs) + -> bool { + return lhs.compare(rhs) == 0; + } + friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) != 0; + } + friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) < 0; + } + friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) <= 0; + } + friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) > 0; + } + friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool { + return lhs.compare(rhs) >= 0; + } +}; + +using string_view = basic_string_view; + +/** Specifies if ``T`` is a character type. Can be specialized by users. */ +template struct is_char : std::false_type {}; +template <> struct is_char : std::true_type {}; + +FMT_BEGIN_DETAIL_NAMESPACE + +// A base class for compile-time strings. +struct compile_string {}; + +template +struct is_compile_string : std::is_base_of {}; + +// Returns a string view of `s`. +template ::value)> +FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view { + return s; +} +template +inline auto to_string_view(const std::basic_string& s) + -> basic_string_view { + return s; +} +template +constexpr auto to_string_view(basic_string_view s) + -> basic_string_view { + return s; +} +template >::value)> +inline auto to_string_view(std_string_view s) -> basic_string_view { + return s; +} +template ::value)> +constexpr auto to_string_view(const S& s) + -> basic_string_view { + return basic_string_view(s); +} +void to_string_view(...); + +// Specifies whether S is a string type convertible to fmt::basic_string_view. +// It should be a constexpr function but MSVC 2017 fails to compile it in +// enable_if and MSVC 2015 fails to compile it as an alias template. +// ADL invocation of to_string_view is DEPRECATED! +template +struct is_string : std::is_class()))> { +}; + +template struct char_t_impl {}; +template struct char_t_impl::value>> { + using result = decltype(to_string_view(std::declval())); + using type = typename result::value_type; +}; + +enum class type { + none_type, + // Integer types should go first, + int_type, + uint_type, + long_long_type, + ulong_long_type, + int128_type, + uint128_type, + bool_type, + char_type, + last_integer_type = char_type, + // followed by floating-point types. + float_type, + double_type, + long_double_type, + last_numeric_type = long_double_type, + cstring_type, + string_type, + pointer_type, + custom_type +}; + +// Maps core type T to the corresponding type enum constant. +template +struct type_constant : std::integral_constant {}; + +#define FMT_TYPE_CONSTANT(Type, constant) \ + template \ + struct type_constant \ + : std::integral_constant {} + +FMT_TYPE_CONSTANT(int, int_type); +FMT_TYPE_CONSTANT(unsigned, uint_type); +FMT_TYPE_CONSTANT(long long, long_long_type); +FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type); +FMT_TYPE_CONSTANT(int128_opt, int128_type); +FMT_TYPE_CONSTANT(uint128_opt, uint128_type); +FMT_TYPE_CONSTANT(bool, bool_type); +FMT_TYPE_CONSTANT(Char, char_type); +FMT_TYPE_CONSTANT(float, float_type); +FMT_TYPE_CONSTANT(double, double_type); +FMT_TYPE_CONSTANT(long double, long_double_type); +FMT_TYPE_CONSTANT(const Char*, cstring_type); +FMT_TYPE_CONSTANT(basic_string_view, string_type); +FMT_TYPE_CONSTANT(const void*, pointer_type); + +constexpr bool is_integral_type(type t) { + return t > type::none_type && t <= type::last_integer_type; +} + +constexpr bool is_arithmetic_type(type t) { + return t > type::none_type && t <= type::last_numeric_type; +} + +FMT_API void throw_format_error(const char* message); + +struct error_handler { + constexpr error_handler() = default; + constexpr error_handler(const error_handler&) = default; + + // This function is intentionally not constexpr to give a compile-time error. + void on_error(const char* message) { + throw_format_error(message); + } +}; +FMT_END_DETAIL_NAMESPACE + +/** String's character type. */ +template using char_t = typename detail::char_t_impl::type; + +/** + \rst + Parsing context consisting of a format string range being parsed and an + argument counter for automatic indexing. + You can use the ``format_parse_context`` type alias for ``char`` instead. + \endrst + */ +template +class basic_format_parse_context : private ErrorHandler { + private: + basic_string_view format_str_; + int next_arg_id_; + + FMT_CONSTEXPR void do_check_arg_id(int id); + + public: + using char_type = Char; + using iterator = typename basic_string_view::iterator; + + explicit constexpr basic_format_parse_context( + basic_string_view format_str, ErrorHandler eh = {}, + int next_arg_id = 0) + : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id) {} + + /** + Returns an iterator to the beginning of the format string range being + parsed. + */ + constexpr auto begin() const noexcept -> iterator { + return format_str_.begin(); + } + + /** + Returns an iterator past the end of the format string range being parsed. + */ + constexpr auto end() const noexcept -> iterator { return format_str_.end(); } + + /** Advances the begin iterator to ``it``. */ + FMT_CONSTEXPR void advance_to(iterator it) { + format_str_.remove_prefix(detail::to_unsigned(it - begin())); + } + + /** + Reports an error if using the manual argument indexing; otherwise returns + the next argument index and switches to the automatic indexing. + */ + FMT_CONSTEXPR auto next_arg_id() -> int { + if (next_arg_id_ < 0) { + on_error("cannot switch from manual to automatic argument indexing"); + return 0; + } + int id = next_arg_id_++; + do_check_arg_id(id); + return id; + } + + /** + Reports an error if using the automatic argument indexing; otherwise + switches to the manual indexing. + */ + FMT_CONSTEXPR void check_arg_id(int id) { + if (next_arg_id_ > 0) { + on_error("cannot switch from automatic to manual argument indexing"); + return; + } + next_arg_id_ = -1; + do_check_arg_id(id); + } + + FMT_CONSTEXPR void check_arg_id(basic_string_view) {} + + FMT_CONSTEXPR void on_error(const char* message) { + ErrorHandler::on_error(message); + } + + constexpr auto error_handler() const -> ErrorHandler { return *this; } +}; + +using format_parse_context = basic_format_parse_context; + +FMT_BEGIN_DETAIL_NAMESPACE +// A parse context with extra data used only in compile-time checks. +template +class compile_parse_context + : public basic_format_parse_context { + private: + int num_args_; + const type* types_; + using base = basic_format_parse_context; + + public: + explicit FMT_CONSTEXPR compile_parse_context( + basic_string_view format_str, int num_args, const type* types, + ErrorHandler eh = {}, int next_arg_id = 0) + : base(format_str, eh, next_arg_id), num_args_(num_args), types_(types) {} + + constexpr int num_args() const { return num_args_; } + + FMT_CONSTEXPR auto next_arg_id() -> int { + int id = base::next_arg_id(); + if (id >= num_args_) this->on_error("argument not found"); + return id; + } + + FMT_CONSTEXPR void check_arg_id(int id) { + base::check_arg_id(id); + if (id >= num_args_) this->on_error("argument not found"); + } + using base::check_arg_id; +}; +FMT_END_DETAIL_NAMESPACE + +template +FMT_CONSTEXPR void +basic_format_parse_context::do_check_arg_id(int id) { + // Argument id is only checked at compile-time during parsing because + // formatting has its own validation. + if (detail::is_constant_evaluated() && FMT_GCC_VERSION >= 1200) { + using context = detail::compile_parse_context; + if (id >= static_cast(this)->num_args()) + on_error("argument not found"); + } +} + +template class basic_format_arg; +template class basic_format_args; +template class dynamic_format_arg_store; + +// A formatter for objects of type T. +template +struct formatter { + // A deleted default constructor indicates a disabled formatter. + formatter() = delete; +}; + +// Specifies if T has an enabled formatter specialization. A type can be +// formattable even if it doesn't have a formatter e.g. via a conversion. +template +using has_formatter = + std::is_constructible>; + +// Checks whether T is a container with contiguous storage. +template struct is_contiguous : std::false_type {}; +template +struct is_contiguous> : std::true_type {}; + +class appender; + +FMT_BEGIN_DETAIL_NAMESPACE + +template +constexpr auto has_const_formatter_impl(T*) + -> decltype(typename Context::template formatter_type().format( + std::declval(), std::declval()), + true) { + return true; +} +template +constexpr auto has_const_formatter_impl(...) -> bool { + return false; +} +template +constexpr auto has_const_formatter() -> bool { + return has_const_formatter_impl(static_cast(nullptr)); +} + +// Extracts a reference to the container from back_insert_iterator. +template +inline auto get_container(std::back_insert_iterator it) + -> Container& { + using base = std::back_insert_iterator; + struct accessor : base { + accessor(base b) : base(b) {} + using base::container; + }; + return *accessor(it).container; +} + +template +FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + while (begin != end) *out++ = static_cast(*begin++); + return out; +} + +template , U>::value&& is_char::value)> +FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* { + if (is_constant_evaluated()) return copy_str(begin, end, out); + auto size = to_unsigned(end - begin); + memcpy(out, begin, size * sizeof(U)); + return out + size; +} + +/** + \rst + A contiguous memory buffer with an optional growing ability. It is an internal + class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. + \endrst + */ +template class buffer { + private: + T* ptr_; + size_t size_; + size_t capacity_; + + protected: + // Don't initialize ptr_ since it is not accessed to save a few cycles. + FMT_MSC_WARNING(suppress : 26495) + buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {} + + FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept + : ptr_(p), size_(sz), capacity_(cap) {} + + FMT_CONSTEXPR20 ~buffer() = default; + buffer(buffer&&) = default; + + /** Sets the buffer data and capacity. */ + FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept { + ptr_ = buf_data; + capacity_ = buf_capacity; + } + + /** Increases the buffer capacity to hold at least *capacity* elements. */ + virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0; + + public: + using value_type = T; + using const_reference = const T&; + + buffer(const buffer&) = delete; + void operator=(const buffer&) = delete; + + auto begin() noexcept -> T* { return ptr_; } + auto end() noexcept -> T* { return ptr_ + size_; } + + auto begin() const noexcept -> const T* { return ptr_; } + auto end() const noexcept -> const T* { return ptr_ + size_; } + + /** Returns the size of this buffer. */ + constexpr auto size() const noexcept -> size_t { return size_; } + + /** Returns the capacity of this buffer. */ + constexpr auto capacity() const noexcept -> size_t { return capacity_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; } + + /** Returns a pointer to the buffer data. */ + FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; } + + /** Clears this buffer. */ + void clear() { size_ = 0; } + + // Tries resizing the buffer to contain *count* elements. If T is a POD type + // the new elements may not be initialized. + FMT_CONSTEXPR20 void try_resize(size_t count) { + try_reserve(count); + size_ = count <= capacity_ ? count : capacity_; + } + + // Tries increasing the buffer capacity to *new_capacity*. It can increase the + // capacity by a smaller amount than requested but guarantees there is space + // for at least one additional element either by increasing the capacity or by + // flushing the buffer if it is full. + FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) { + if (new_capacity > capacity_) grow(new_capacity); + } + + FMT_CONSTEXPR20 void push_back(const T& value) { + try_reserve(size_ + 1); + ptr_[size_++] = value; + } + + /** Appends data to the end of the buffer. */ + template void append(const U* begin, const U* end); + + template FMT_CONSTEXPR auto operator[](I index) -> T& { + return ptr_[index]; + } + template + FMT_CONSTEXPR auto operator[](I index) const -> const T& { + return ptr_[index]; + } +}; + +struct buffer_traits { + explicit buffer_traits(size_t) {} + auto count() const -> size_t { return 0; } + auto limit(size_t size) -> size_t { return size; } +}; + +class fixed_buffer_traits { + private: + size_t count_ = 0; + size_t limit_; + + public: + explicit fixed_buffer_traits(size_t limit) : limit_(limit) {} + auto count() const -> size_t { return count_; } + auto limit(size_t size) -> size_t { + size_t n = limit_ > count_ ? limit_ - count_ : 0; + count_ += size; + return size < n ? size : n; + } +}; + +// A buffer that writes to an output iterator when flushed. +template +class iterator_buffer final : public Traits, public buffer { + private: + OutputIt out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == buffer_size) flush(); + } + + void flush() { + auto size = this->size(); + this->clear(); + out_ = copy_str(data_, data_ + this->limit(size), out_); + } + + public: + explicit iterator_buffer(OutputIt out, size_t n = buffer_size) + : Traits(n), buffer(data_, 0, buffer_size), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : Traits(other), buffer(data_, 0, buffer_size), out_(other.out_) {} + ~iterator_buffer() { flush(); } + + auto out() -> OutputIt { + flush(); + return out_; + } + auto count() const -> size_t { return Traits::count() + this->size(); } +}; + +template +class iterator_buffer final + : public fixed_buffer_traits, + public buffer { + private: + T* out_; + enum { buffer_size = 256 }; + T data_[buffer_size]; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() == this->capacity()) flush(); + } + + void flush() { + size_t n = this->limit(this->size()); + if (this->data() == out_) { + out_ += n; + this->set(data_, buffer_size); + } + this->clear(); + } + + public: + explicit iterator_buffer(T* out, size_t n = buffer_size) + : fixed_buffer_traits(n), buffer(out, 0, n), out_(out) {} + iterator_buffer(iterator_buffer&& other) + : fixed_buffer_traits(other), + buffer(std::move(other)), + out_(other.out_) { + if (this->data() != out_) { + this->set(data_, buffer_size); + this->clear(); + } + } + ~iterator_buffer() { flush(); } + + auto out() -> T* { + flush(); + return out_; + } + auto count() const -> size_t { + return fixed_buffer_traits::count() + this->size(); + } +}; + +template class iterator_buffer final : public buffer { + protected: + FMT_CONSTEXPR20 void grow(size_t) override {} + + public: + explicit iterator_buffer(T* out, size_t = 0) : buffer(out, 0, ~size_t()) {} + + auto out() -> T* { return &*this->end(); } +}; + +// A buffer that writes to a container with the contiguous storage. +template +class iterator_buffer, + enable_if_t::value, + typename Container::value_type>> + final : public buffer { + private: + Container& container_; + + protected: + FMT_CONSTEXPR20 void grow(size_t capacity) override { + container_.resize(capacity); + this->set(&container_[0], capacity); + } + + public: + explicit iterator_buffer(Container& c) + : buffer(c.size()), container_(c) {} + explicit iterator_buffer(std::back_insert_iterator out, size_t = 0) + : iterator_buffer(get_container(out)) {} + + auto out() -> std::back_insert_iterator { + return std::back_inserter(container_); + } +}; + +// A buffer that counts the number of code units written discarding the output. +template class counting_buffer final : public buffer { + private: + enum { buffer_size = 256 }; + T data_[buffer_size]; + size_t count_ = 0; + + protected: + FMT_CONSTEXPR20 void grow(size_t) override { + if (this->size() != buffer_size) return; + count_ += this->size(); + this->clear(); + } + + public: + counting_buffer() : buffer(data_, 0, buffer_size) {} + + auto count() -> size_t { return count_ + this->size(); } +}; + +template +using buffer_appender = conditional_t::value, appender, + std::back_insert_iterator>>; + +// Maps an output iterator to a buffer. +template +auto get_buffer(OutputIt out) -> iterator_buffer { + return iterator_buffer(out); +} + +template +auto get_iterator(Buffer& buf) -> decltype(buf.out()) { + return buf.out(); +} +template auto get_iterator(buffer& buf) -> buffer_appender { + return buffer_appender(buf); +} + +template +struct fallback_formatter { + fallback_formatter() = delete; +}; + +// Specifies if T has an enabled fallback_formatter specialization. +template +using has_fallback_formatter = +#ifdef FMT_DEPRECATED_OSTREAM + std::is_constructible>; +#else + std::false_type; +#endif + +struct view {}; + +template struct named_arg : view { + const Char* name; + const T& value; + named_arg(const Char* n, const T& v) : name(n), value(v) {} +}; + +template struct named_arg_info { + const Char* name; + int id; +}; + +template +struct arg_data { + // args_[0].named_args points to named_args_ to avoid bloating format_args. + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)]; + named_arg_info named_args_[NUM_NAMED_ARGS]; + + template + arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {} + arg_data(const arg_data& other) = delete; + auto args() const -> const T* { return args_ + 1; } + auto named_args() -> named_arg_info* { return named_args_; } +}; + +template +struct arg_data { + // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning. + T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; + + template + FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {} + FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; } + FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t { + return nullptr; + } +}; + +template +inline void init_named_args(named_arg_info*, int, int) {} + +template struct is_named_arg : std::false_type {}; +template struct is_statically_named_arg : std::false_type {}; + +template +struct is_named_arg> : std::true_type {}; + +template ::value)> +void init_named_args(named_arg_info* named_args, int arg_count, + int named_arg_count, const T&, const Tail&... args) { + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template ::value)> +void init_named_args(named_arg_info* named_args, int arg_count, + int named_arg_count, const T& arg, const Tail&... args) { + named_args[named_arg_count++] = {arg.name, arg_count}; + init_named_args(named_args, arg_count + 1, named_arg_count, args...); +} + +template +FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, + const Args&...) {} + +template constexpr auto count() -> size_t { return B ? 1 : 0; } +template constexpr auto count() -> size_t { + return (B1 ? 1 : 0) + count(); +} + +template constexpr auto count_named_args() -> size_t { + return count::value...>(); +} + +template +constexpr auto count_statically_named_args() -> size_t { + return count::value...>(); +} + +struct unformattable {}; +struct unformattable_char : unformattable {}; +struct unformattable_const : unformattable {}; +struct unformattable_pointer : unformattable {}; + +template struct string_value { + const Char* data; + size_t size; +}; + +template struct named_arg_value { + const named_arg_info* data; + size_t size; +}; + +template struct custom_value { + using parse_context = typename Context::parse_context_type; + void* value; + void (*format)(void* arg, parse_context& parse_ctx, Context& ctx); +}; + +// A formatting argument value. +template class value { + public: + using char_type = typename Context::char_type; + + union { + monostate no_value; + int int_value; + unsigned uint_value; + long long long_long_value; + unsigned long long ulong_long_value; + int128_opt int128_value; + uint128_opt uint128_value; + bool bool_value; + char_type char_value; + float float_value; + double double_value; + long double long_double_value; + const void* pointer; + string_value string; + custom_value custom; + named_arg_value named_args; + }; + + constexpr FMT_INLINE value() : no_value() {} + constexpr FMT_INLINE value(int val) : int_value(val) {} + constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} + constexpr FMT_INLINE value(long long val) : long_long_value(val) {} + constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} + FMT_INLINE value(int128_opt val) : int128_value(val) {} + FMT_INLINE value(uint128_opt val) : uint128_value(val) {} + constexpr FMT_INLINE value(float val) : float_value(val) {} + constexpr FMT_INLINE value(double val) : double_value(val) {} + FMT_INLINE value(long double val) : long_double_value(val) {} + constexpr FMT_INLINE value(bool val) : bool_value(val) {} + constexpr FMT_INLINE value(char_type val) : char_value(val) {} + FMT_CONSTEXPR FMT_INLINE value(const char_type* val) { + string.data = val; + if (is_constant_evaluated()) string.size = {}; + } + FMT_CONSTEXPR FMT_INLINE value(basic_string_view val) { + string.data = val.data(); + string.size = val.size(); + } + FMT_INLINE value(const void* val) : pointer(val) {} + FMT_INLINE value(const named_arg_info* args, size_t size) + : named_args{args, size} {} + + template FMT_CONSTEXPR FMT_INLINE value(T& val) { + using value_type = remove_cvref_t; + custom.value = const_cast(&val); + // Get the formatter type through the context to allow different contexts + // have different extension points, e.g. `formatter` for `format` and + // `printf_formatter` for `printf`. + custom.format = format_custom_arg< + value_type, + conditional_t::value, + typename Context::template formatter_type, + fallback_formatter>>; + } + value(unformattable); + value(unformattable_char); + value(unformattable_const); + value(unformattable_pointer); + + private: + // Formats an argument of a custom type, such as a user-defined class. + template + static void format_custom_arg(void* arg, + typename Context::parse_context_type& parse_ctx, + Context& ctx) { + auto f = Formatter(); + parse_ctx.advance_to(f.parse(parse_ctx)); + using qualified_type = + conditional_t(), const T, T>; + ctx.advance_to(f.format(*static_cast(arg), ctx)); + } +}; + +template +FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg; + +// To minimize the number of types we need to deal with, long is translated +// either to int or to long long depending on its size. +enum { long_short = sizeof(long) == sizeof(int) }; +using long_type = conditional_t; +using ulong_type = conditional_t; + +#ifdef __cpp_lib_byte +inline auto format_as(std::byte b) -> unsigned char { + return static_cast(b); +} +#endif + +template struct has_format_as { + template ::value&& std::is_integral::value)> + static auto check(U*) -> std::true_type; + static auto check(...) -> std::false_type; + + enum { value = decltype(check(static_cast(nullptr)))::value }; +}; + +// Maps formatting arguments to core types. +// arg_mapper reports errors by returning unformattable instead of using +// static_assert because it's used in the is_formattable trait. +template struct arg_mapper { + using char_type = typename Context::char_type; + + FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val) + -> unsigned long long { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type { + return val; + } + template ::value || +#ifdef __cpp_char8_t + std::is_same::value || +#endif + std::is_same::value || + std::is_same::value) && + !std::is_same::value, + int> = 0> + FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char { + return {}; + } + + FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double { + return val; + } + + FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* { + return val; + } + template ::value && !std::is_pointer::value && + std::is_same>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view { + return to_string_view(val); + } + template ::value && !std::is_pointer::value && + !std::is_same>::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char { + return {}; + } + template >::value && + !is_string::value && !has_formatter::value && + !has_fallback_formatter::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view { + return basic_string_view(val); + } + template >::value && + !std::is_convertible>::value && + !is_string::value && !has_formatter::value && + !has_fallback_formatter::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> basic_string_view { + return std_string_view(val); + } + + FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; } + FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* { + return val; + } + FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* { + return val; + } + + // We use SFINAE instead of a const T* parameter to avoid conflicting with + // the C array overload. + template < + typename T, + FMT_ENABLE_IF( + std::is_pointer::value || std::is_member_pointer::value || + std::is_function::type>::value || + (std::is_convertible::value && + !std::is_convertible::value && + !has_formatter::value))> + FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer { + return {}; + } + + template ::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] { + return values; + } + + template ::value&& std::is_convertible::value && + !has_format_as::value && !has_formatter::value && + !has_fallback_formatter::value)> + FMT_DEPRECATED FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> decltype(std::declval().map( + static_cast>(val))) { + return map(static_cast>(val)); + } + + template ::value && + !has_formatter::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& val) + -> decltype(std::declval().map(format_as(T()))) { + return map(format_as(val)); + } + + template > + struct formattable + : bool_constant() || + !std::is_const>::value || + has_fallback_formatter::value> {}; + +#if (FMT_MSC_VERSION != 0 && FMT_MSC_VERSION < 1910) || \ + FMT_ICC_VERSION != 0 || defined(__NVCC__) + // Workaround a bug in MSVC and Intel (Issue 2746). + template FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } +#else + template ::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T& { + return val; + } + template ::value)> + FMT_CONSTEXPR FMT_INLINE auto do_map(T&&) -> unformattable_const { + return {}; + } +#endif + + template , + FMT_ENABLE_IF(!is_string::value && !is_char::value && + !std::is_array::value && + !std::is_pointer::value && + !has_format_as::value && + (has_formatter::value || + has_fallback_formatter::value))> + FMT_CONSTEXPR FMT_INLINE auto map(T&& val) + -> decltype(this->do_map(std::forward(val))) { + return do_map(std::forward(val)); + } + + template ::value)> + FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg) + -> decltype(std::declval().map(named_arg.value)) { + return map(named_arg.value); + } + + auto map(...) -> unformattable { return {}; } +}; + +// A type constant after applying arg_mapper. +template +using mapped_type_constant = + type_constant().map(std::declval())), + typename Context::char_type>; + +enum { packed_arg_bits = 4 }; +// Maximum number of arguments with packed types. +enum { max_packed_args = 62 / packed_arg_bits }; +enum : unsigned long long { is_unpacked_bit = 1ULL << 63 }; +enum : unsigned long long { has_named_args_bit = 1ULL << 62 }; + +FMT_END_DETAIL_NAMESPACE + +// An output iterator that appends to a buffer. +// It is used to reduce symbol sizes for the common case. +class appender : public std::back_insert_iterator> { + using base = std::back_insert_iterator>; + + template + friend auto get_buffer(appender out) -> detail::buffer& { + return detail::get_container(out); + } + + public: + using std::back_insert_iterator>::back_insert_iterator; + appender(base it) noexcept : base(it) {} + FMT_UNCHECKED_ITERATOR(appender); + + auto operator++() noexcept -> appender& { return *this; } + auto operator++(int) noexcept -> appender { return *this; } +}; + +// A formatting argument. It is a trivially copyable/constructible type to +// allow storage in basic_memory_buffer. +template class basic_format_arg { + private: + detail::value value_; + detail::type type_; + + template + friend FMT_CONSTEXPR auto detail::make_arg(T&& value) + -> basic_format_arg; + + template + friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis, + const basic_format_arg& arg) + -> decltype(vis(0)); + + friend class basic_format_args; + friend class dynamic_format_arg_store; + + using char_type = typename Context::char_type; + + template + friend struct detail::arg_data; + + basic_format_arg(const detail::named_arg_info* args, size_t size) + : value_(args, size) {} + + public: + class handle { + public: + explicit handle(detail::custom_value custom) : custom_(custom) {} + + void format(typename Context::parse_context_type& parse_ctx, + Context& ctx) const { + custom_.format(custom_.value, parse_ctx, ctx); + } + + private: + detail::custom_value custom_; + }; + + constexpr basic_format_arg() : type_(detail::type::none_type) {} + + constexpr explicit operator bool() const noexcept { + return type_ != detail::type::none_type; + } + + auto type() const -> detail::type { return type_; } + + auto is_integral() const -> bool { return detail::is_integral_type(type_); } + auto is_arithmetic() const -> bool { + return detail::is_arithmetic_type(type_); + } +}; + +/** + \rst + Visits an argument dispatching to the appropriate visit method based on + the argument type. For example, if the argument type is ``double`` then + ``vis(value)`` will be called with the value of type ``double``. + \endrst + */ +template +FMT_CONSTEXPR FMT_INLINE auto visit_format_arg( + Visitor&& vis, const basic_format_arg& arg) -> decltype(vis(0)) { + switch (arg.type_) { + case detail::type::none_type: + break; + case detail::type::int_type: + return vis(arg.value_.int_value); + case detail::type::uint_type: + return vis(arg.value_.uint_value); + case detail::type::long_long_type: + return vis(arg.value_.long_long_value); + case detail::type::ulong_long_type: + return vis(arg.value_.ulong_long_value); + case detail::type::int128_type: + return vis(detail::convert_for_visit(arg.value_.int128_value)); + case detail::type::uint128_type: + return vis(detail::convert_for_visit(arg.value_.uint128_value)); + case detail::type::bool_type: + return vis(arg.value_.bool_value); + case detail::type::char_type: + return vis(arg.value_.char_value); + case detail::type::float_type: + return vis(arg.value_.float_value); + case detail::type::double_type: + return vis(arg.value_.double_value); + case detail::type::long_double_type: + return vis(arg.value_.long_double_value); + case detail::type::cstring_type: + return vis(arg.value_.string.data); + case detail::type::string_type: + using sv = basic_string_view; + return vis(sv(arg.value_.string.data, arg.value_.string.size)); + case detail::type::pointer_type: + return vis(arg.value_.pointer); + case detail::type::custom_type: + return vis(typename basic_format_arg::handle(arg.value_.custom)); + } + return vis(monostate()); +} + +FMT_BEGIN_DETAIL_NAMESPACE + +template +auto copy_str(InputIt begin, InputIt end, appender out) -> appender { + get_container(out).append(begin, end); + return out; +} + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 +// A workaround for gcc 4.8 to make void_t work in a SFINAE context. +template struct void_t_impl { using type = void; }; +template +using void_t = typename detail::void_t_impl::type; +#else +template using void_t = void; +#endif + +template +struct is_output_iterator : std::false_type {}; + +template +struct is_output_iterator< + It, T, + void_t::iterator_category, + decltype(*std::declval() = std::declval())>> + : std::true_type {}; + +template +struct is_back_insert_iterator : std::false_type {}; +template +struct is_back_insert_iterator> + : std::true_type {}; + +template +struct is_contiguous_back_insert_iterator : std::false_type {}; +template +struct is_contiguous_back_insert_iterator> + : is_contiguous {}; +template <> +struct is_contiguous_back_insert_iterator : std::true_type {}; + +// A type-erased reference to an std::locale to avoid a heavy include. +class locale_ref { + private: + const void* locale_; // A type-erased pointer to std::locale. + + public: + constexpr locale_ref() : locale_(nullptr) {} + template explicit locale_ref(const Locale& loc); + + explicit operator bool() const noexcept { return locale_ != nullptr; } + + template auto get() const -> Locale; +}; + +template constexpr auto encode_types() -> unsigned long long { + return 0; +} + +template +constexpr auto encode_types() -> unsigned long long { + return static_cast(mapped_type_constant::value) | + (encode_types() << packed_arg_bits); +} + +template +FMT_CONSTEXPR FMT_INLINE auto make_value(T&& val) -> value { + const auto& arg = arg_mapper().map(std::forward(val)); + + constexpr bool formattable_char = + !std::is_same::value; + static_assert(formattable_char, "Mixing character types is disallowed."); + + constexpr bool formattable_const = + !std::is_same::value; + static_assert(formattable_const, "Cannot format a const argument."); + + // Formatting of arbitrary pointers is disallowed. If you want to output + // a pointer cast it to "void *" or "const void *". In particular, this + // forbids formatting of "[const] volatile char *" which is printed as bool + // by iostreams. + constexpr bool formattable_pointer = + !std::is_same::value; + static_assert(formattable_pointer, + "Formatting of non-void pointers is disallowed."); + + constexpr bool formattable = + !std::is_same::value; + static_assert( + formattable, + "Cannot format an argument. To make type T formattable provide a " + "formatter specialization: https://fmt.dev/latest/api.html#udt"); + return {arg}; +} + +template +FMT_CONSTEXPR auto make_arg(T&& value) -> basic_format_arg { + basic_format_arg arg; + arg.type_ = mapped_type_constant::value; + arg.value_ = make_value(value); + return arg; +} + +// The type template parameter is there to avoid an ODR violation when using +// a fallback formatter in one translation unit and an implicit conversion in +// another (not recommended). +template +FMT_CONSTEXPR FMT_INLINE auto make_arg(T&& val) -> value { + return make_value(val); +} + +template +FMT_CONSTEXPR inline auto make_arg(T&& value) -> basic_format_arg { + return make_arg(value); +} +FMT_END_DETAIL_NAMESPACE + +// Formatting context. +template class basic_format_context { + public: + /** The character type for the output. */ + using char_type = Char; + + private: + OutputIt out_; + basic_format_args args_; + detail::locale_ref loc_; + + public: + using iterator = OutputIt; + using format_arg = basic_format_arg; + using parse_context_type = basic_format_parse_context; + template using formatter_type = formatter; + + basic_format_context(basic_format_context&&) = default; + basic_format_context(const basic_format_context&) = delete; + void operator=(const basic_format_context&) = delete; + /** + Constructs a ``basic_format_context`` object. References to the arguments are + stored in the object so make sure they have appropriate lifetimes. + */ + constexpr basic_format_context( + OutputIt out, basic_format_args ctx_args, + detail::locale_ref loc = detail::locale_ref()) + : out_(out), args_(ctx_args), loc_(loc) {} + + constexpr auto arg(int id) const -> format_arg { return args_.get(id); } + FMT_CONSTEXPR auto arg(basic_string_view name) -> format_arg { + return args_.get(name); + } + FMT_CONSTEXPR auto arg_id(basic_string_view name) -> int { + return args_.get_id(name); + } + auto args() const -> const basic_format_args& { + return args_; + } + + FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; } + void on_error(const char* message) { error_handler().on_error(message); } + + // Returns an iterator to the beginning of the output range. + FMT_CONSTEXPR auto out() -> iterator { return out_; } + + // Advances the begin iterator to ``it``. + void advance_to(iterator it) { + if (!detail::is_back_insert_iterator()) out_ = it; + } + + FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } +}; + +template +using buffer_context = + basic_format_context, Char>; +using format_context = buffer_context; + +// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164. +#define FMT_BUFFER_CONTEXT(Char) \ + basic_format_context, Char> + +template +using is_formattable = bool_constant< + !std::is_base_of>().map( + std::declval()))>::value && + !detail::has_fallback_formatter::value>; + +/** + \rst + An array of references to arguments. It can be implicitly converted into + `~fmt::basic_format_args` for passing into type-erased formatting functions + such as `~fmt::vformat`. + \endrst + */ +template +class format_arg_store +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + // Workaround a GCC template argument substitution bug. + : public basic_format_args +#endif +{ + private: + static const size_t num_args = sizeof...(Args); + static const size_t num_named_args = detail::count_named_args(); + static const bool is_packed = num_args <= detail::max_packed_args; + + using value_type = conditional_t, + basic_format_arg>; + + detail::arg_data + data_; + + friend class basic_format_args; + + static constexpr unsigned long long desc = + (is_packed ? detail::encode_types() + : detail::is_unpacked_bit | num_args) | + (num_named_args != 0 + ? static_cast(detail::has_named_args_bit) + : 0); + + public: + template + FMT_CONSTEXPR FMT_INLINE format_arg_store(T&&... args) + : +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 + basic_format_args(*this), +#endif + data_{detail::make_arg< + is_packed, Context, + detail::mapped_type_constant, Context>::value>( + std::forward(args))...} { + detail::init_named_args(data_.named_args(), 0, 0, args...); + } +}; + +/** + \rst + Constructs a `~fmt::format_arg_store` object that contains references to + arguments and can be implicitly converted to `~fmt::format_args`. `Context` + can be omitted in which case it defaults to `~fmt::context`. + See `~fmt::arg` for lifetime considerations. + \endrst + */ +template +constexpr auto make_format_args(Args&&... args) + -> format_arg_store...> { + return {std::forward(args)...}; +} + +/** + \rst + Returns a named argument to be used in a formatting function. + It should only be used in a call to a formatting function or + `dynamic_format_arg_store::push_back`. + + **Example**:: + + fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); + \endrst + */ +template +inline auto arg(const Char* name, const T& arg) -> detail::named_arg { + static_assert(!detail::is_named_arg(), "nested named arguments"); + return {name, arg}; +} + +/** + \rst + A view of a collection of formatting arguments. To avoid lifetime issues it + should only be used as a parameter type in type-erased functions such as + ``vformat``:: + + void vlog(string_view format_str, format_args args); // OK + format_args args = make_format_args(42); // Error: dangling reference + \endrst + */ +template class basic_format_args { + public: + using size_type = int; + using format_arg = basic_format_arg; + + private: + // A descriptor that contains information about formatting arguments. + // If the number of arguments is less or equal to max_packed_args then + // argument types are passed in the descriptor. This reduces binary code size + // per formatting function call. + unsigned long long desc_; + union { + // If is_packed() returns true then argument values are stored in values_; + // otherwise they are stored in args_. This is done to improve cache + // locality and reduce compiled code size since storing larger objects + // may require more code (at least on x86-64) even if the same amount of + // data is actually copied to stack. It saves ~10% on the bloat test. + const detail::value* values_; + const format_arg* args_; + }; + + constexpr auto is_packed() const -> bool { + return (desc_ & detail::is_unpacked_bit) == 0; + } + auto has_named_args() const -> bool { + return (desc_ & detail::has_named_args_bit) != 0; + } + + FMT_CONSTEXPR auto type(int index) const -> detail::type { + int shift = index * detail::packed_arg_bits; + unsigned int mask = (1 << detail::packed_arg_bits) - 1; + return static_cast((desc_ >> shift) & mask); + } + + constexpr FMT_INLINE basic_format_args(unsigned long long desc, + const detail::value* values) + : desc_(desc), values_(values) {} + constexpr basic_format_args(unsigned long long desc, const format_arg* args) + : desc_(desc), args_(args) {} + + public: + constexpr basic_format_args() : desc_(0), args_(nullptr) {} + + /** + \rst + Constructs a `basic_format_args` object from `~fmt::format_arg_store`. + \endrst + */ + template + constexpr FMT_INLINE basic_format_args( + const format_arg_store& store) + : basic_format_args(format_arg_store::desc, + store.data_.args()) {} + + /** + \rst + Constructs a `basic_format_args` object from + `~fmt::dynamic_format_arg_store`. + \endrst + */ + constexpr FMT_INLINE basic_format_args( + const dynamic_format_arg_store& store) + : basic_format_args(store.get_types(), store.data()) {} + + /** + \rst + Constructs a `basic_format_args` object from a dynamic set of arguments. + \endrst + */ + constexpr basic_format_args(const format_arg* args, int count) + : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), + args) {} + + /** Returns the argument with the specified id. */ + FMT_CONSTEXPR auto get(int id) const -> format_arg { + format_arg arg; + if (!is_packed()) { + if (id < max_size()) arg = args_[id]; + return arg; + } + if (id >= detail::max_packed_args) return arg; + arg.type_ = type(id); + if (arg.type_ == detail::type::none_type) return arg; + arg.value_ = values_[id]; + return arg; + } + + template + auto get(basic_string_view name) const -> format_arg { + int id = get_id(name); + return id >= 0 ? get(id) : format_arg(); + } + + template + auto get_id(basic_string_view name) const -> int { + if (!has_named_args()) return -1; + const auto& named_args = + (is_packed() ? values_[-1] : args_[-1].value_).named_args; + for (size_t i = 0; i < named_args.size; ++i) { + if (named_args.data[i].name == name) return named_args.data[i].id; + } + return -1; + } + + auto max_size() const -> int { + unsigned long long max_packed = detail::max_packed_args; + return static_cast(is_packed() ? max_packed + : desc_ & ~detail::is_unpacked_bit); + } +}; + +/** An alias to ``basic_format_args``. */ +// A separate type would result in shorter symbols but break ABI compatibility +// between clang and gcc on ARM (#1919). +using format_args = basic_format_args; + +// We cannot use enum classes as bit fields because of a gcc bug, so we put them +// in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414). +// Additionally, if an underlying type is specified, older gcc incorrectly warns +// that the type is too small. Both bugs are fixed in gcc 9.3. +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903 +# define FMT_ENUM_UNDERLYING_TYPE(type) +#else +# define FMT_ENUM_UNDERLYING_TYPE(type) : type +#endif +namespace align { +enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center, + numeric}; +} +using align_t = align::type; +namespace sign { +enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space}; +} +using sign_t = sign::type; + +FMT_BEGIN_DETAIL_NAMESPACE + +// Workaround an array initialization issue in gcc 4.8. +template struct fill_t { + private: + enum { max_size = 4 }; + Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)}; + unsigned char size_ = 1; + + public: + FMT_CONSTEXPR void operator=(basic_string_view s) { + auto size = s.size(); + if (size > max_size) return throw_format_error("invalid fill"); + for (size_t i = 0; i < size; ++i) data_[i] = s[i]; + size_ = static_cast(size); + } + + constexpr auto size() const -> size_t { return size_; } + constexpr auto data() const -> const Char* { return data_; } + + FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; } + FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& { + return data_[index]; + } +}; +FMT_END_DETAIL_NAMESPACE + +enum class presentation_type : unsigned char { + none, + // Integer types should go first, + dec, // 'd' + oct, // 'o' + hex_lower, // 'x' + hex_upper, // 'X' + bin_lower, // 'b' + bin_upper, // 'B' + hexfloat_lower, // 'a' + hexfloat_upper, // 'A' + exp_lower, // 'e' + exp_upper, // 'E' + fixed_lower, // 'f' + fixed_upper, // 'F' + general_lower, // 'g' + general_upper, // 'G' + chr, // 'c' + string, // 's' + pointer, // 'p' + debug // '?' +}; + +// Format specifiers for built-in and string types. +template struct basic_format_specs { + int width; + int precision; + presentation_type type; + align_t align : 4; + sign_t sign : 3; + bool alt : 1; // Alternate form ('#'). + bool localized : 1; + detail::fill_t fill; + + constexpr basic_format_specs() + : width(0), + precision(-1), + type(presentation_type::none), + align(align::none), + sign(sign::none), + alt(false), + localized(false) {} +}; + +using format_specs = basic_format_specs; + +FMT_BEGIN_DETAIL_NAMESPACE + +enum class arg_id_kind { none, index, name }; + +// An argument reference. +template struct arg_ref { + FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {} + + FMT_CONSTEXPR explicit arg_ref(int index) + : kind(arg_id_kind::index), val(index) {} + FMT_CONSTEXPR explicit arg_ref(basic_string_view name) + : kind(arg_id_kind::name), val(name) {} + + FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& { + kind = arg_id_kind::index; + val.index = idx; + return *this; + } + + arg_id_kind kind; + union value { + FMT_CONSTEXPR value(int id = 0) : index{id} {} + FMT_CONSTEXPR value(basic_string_view n) : name(n) {} + + int index; + basic_string_view name; + } val; +}; + +// Format specifiers with width and precision resolved at formatting rather +// than parsing time to allow re-using the same parsed specifiers with +// different sets of arguments (precompilation of format strings). +template +struct dynamic_format_specs : basic_format_specs { + arg_ref width_ref; + arg_ref precision_ref; +}; + +struct auto_id {}; + +// A format specifier handler that sets fields in basic_format_specs. +template class specs_setter { + protected: + basic_format_specs& specs_; + + public: + explicit FMT_CONSTEXPR specs_setter(basic_format_specs& specs) + : specs_(specs) {} + + FMT_CONSTEXPR specs_setter(const specs_setter& other) + : specs_(other.specs_) {} + + FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; } + FMT_CONSTEXPR void on_fill(basic_string_view fill) { + specs_.fill = fill; + } + FMT_CONSTEXPR void on_sign(sign_t s) { specs_.sign = s; } + FMT_CONSTEXPR void on_hash() { specs_.alt = true; } + FMT_CONSTEXPR void on_localized() { specs_.localized = true; } + + FMT_CONSTEXPR void on_zero() { + if (specs_.align == align::none) specs_.align = align::numeric; + specs_.fill[0] = Char('0'); + } + + FMT_CONSTEXPR void on_width(int width) { specs_.width = width; } + FMT_CONSTEXPR void on_precision(int precision) { + specs_.precision = precision; + } + FMT_CONSTEXPR void end_precision() {} + + FMT_CONSTEXPR void on_type(presentation_type type) { specs_.type = type; } +}; + +// Format spec handler that saves references to arguments representing dynamic +// width and precision to be resolved at formatting time. +template +class dynamic_specs_handler + : public specs_setter { + public: + using char_type = typename ParseContext::char_type; + + FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs& specs, + ParseContext& ctx) + : specs_setter(specs), specs_(specs), context_(ctx) {} + + FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other) + : specs_setter(other), + specs_(other.specs_), + context_(other.context_) {} + + template FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { + specs_.width_ref = make_arg_ref(arg_id); + } + + template FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { + specs_.precision_ref = make_arg_ref(arg_id); + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } + + private: + dynamic_format_specs& specs_; + ParseContext& context_; + + using arg_ref_type = arg_ref; + + FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type { + context_.check_arg_id(arg_id); + return arg_ref_type(arg_id); + } + + FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type { + return arg_ref_type(context_.next_arg_id()); + } + + FMT_CONSTEXPR auto make_arg_ref(basic_string_view arg_id) + -> arg_ref_type { + context_.check_arg_id(arg_id); + basic_string_view format_str( + context_.begin(), to_unsigned(context_.end() - context_.begin())); + return arg_ref_type(arg_id); + } +}; + +template constexpr bool is_ascii_letter(Char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +// Converts a character to ASCII. Returns a number > 127 on conversion failure. +template ::value)> +constexpr auto to_ascii(Char c) -> Char { + return c; +} +template ::value)> +constexpr auto to_ascii(Char c) -> underlying_t { + return c; +} + +template +FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { + if (const_check(sizeof(Char) != 1)) return 1; + auto lengths = + "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"; + int len = lengths[static_cast(*begin) >> 3]; + + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + return len + !len; +} + +// Return the result via the out param to workaround gcc bug 77539. +template +FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool { + for (out = first; out != last; ++out) { + if (*out == value) return true; + } + return false; +} + +template <> +inline auto find(const char* first, const char* last, char value, + const char*& out) -> bool { + out = static_cast( + std::memchr(first, value, to_unsigned(last - first))); + return out != nullptr; +} + +// Parses the range [begin, end) as an unsigned integer. This function assumes +// that the range is non-empty and the first character is a digit. +template +FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, + int error_value) noexcept -> int { + FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', ""); + unsigned value = 0, prev = 0; + auto p = begin; + do { + prev = value; + value = value * 10 + unsigned(*p - '0'); + ++p; + } while (p != end && '0' <= *p && *p <= '9'); + auto num_digits = p - begin; + begin = p; + if (num_digits <= std::numeric_limits::digits10) + return static_cast(value); + // Check for overflow. + const unsigned max = to_unsigned((std::numeric_limits::max)()); + return num_digits == std::numeric_limits::digits10 + 1 && + prev * 10ull + unsigned(p[-1] - '0') <= max + ? static_cast(value) + : error_value; +} + +// Parses fill and alignment. +template +FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + auto align = align::none; + auto p = begin + code_point_length(begin); + if (end - p <= 0) p = begin; + for (;;) { + switch (to_ascii(*p)) { + case '<': + align = align::left; + break; + case '>': + align = align::right; + break; + case '^': + align = align::center; + break; + default: + break; + } + if (align != align::none) { + if (p != begin) { + auto c = *begin; + if (c == '{') + return handler.on_error("invalid fill character '{'"), begin; + handler.on_fill(basic_string_view(begin, to_unsigned(p - begin))); + begin = p + 1; + } else + ++begin; + handler.on_align(align); + break; + } else if (p == begin) { + break; + } + p = begin; + } + return begin; +} + +template FMT_CONSTEXPR bool is_name_start(Char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c; +} + +template +FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + FMT_ASSERT(begin != end, ""); + Char c = *begin; + if (c >= '0' && c <= '9') { + int index = 0; + if (c != '0') + index = + parse_nonnegative_int(begin, end, (std::numeric_limits::max)()); + else + ++begin; + if (begin == end || (*begin != '}' && *begin != ':')) + handler.on_error("invalid format string"); + else + handler(index); + return begin; + } + if (!is_name_start(c)) { + handler.on_error("invalid format string"); + return begin; + } + auto it = begin; + do { + ++it; + } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9'))); + handler(basic_string_view(begin, to_unsigned(it - begin))); + return it; +} + +template +FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end, + IDHandler&& handler) -> const Char* { + Char c = *begin; + if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler); + handler(); + return begin; +} + +template +FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct width_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); } + FMT_CONSTEXPR void operator()(basic_string_view id) { + handler.on_dynamic_width(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + FMT_ASSERT(begin != end, ""); + if ('0' <= *begin && *begin <= '9') { + int width = parse_nonnegative_int(begin, end, -1); + if (width != -1) + handler.on_width(width); + else + handler.on_error("number is too big"); + } else if (*begin == '{') { + ++begin; + if (begin != end) begin = parse_arg_id(begin, end, width_adapter{handler}); + if (begin == end || *begin != '}') + return handler.on_error("invalid format string"), begin; + ++begin; + } + return begin; +} + +template +FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + using detail::auto_id; + struct precision_adapter { + Handler& handler; + + FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); } + FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); } + FMT_CONSTEXPR void operator()(basic_string_view id) { + handler.on_dynamic_precision(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++begin; + auto c = begin != end ? *begin : Char(); + if ('0' <= c && c <= '9') { + auto precision = parse_nonnegative_int(begin, end, -1); + if (precision != -1) + handler.on_precision(precision); + else + handler.on_error("number is too big"); + } else if (c == '{') { + ++begin; + if (begin != end) + begin = parse_arg_id(begin, end, precision_adapter{handler}); + if (begin == end || *begin++ != '}') + return handler.on_error("invalid format string"), begin; + } else { + return handler.on_error("missing precision specifier"), begin; + } + handler.end_precision(); + return begin; +} + +template +FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type { + switch (to_ascii(type)) { + case 'd': + return presentation_type::dec; + case 'o': + return presentation_type::oct; + case 'x': + return presentation_type::hex_lower; + case 'X': + return presentation_type::hex_upper; + case 'b': + return presentation_type::bin_lower; + case 'B': + return presentation_type::bin_upper; + case 'a': + return presentation_type::hexfloat_lower; + case 'A': + return presentation_type::hexfloat_upper; + case 'e': + return presentation_type::exp_lower; + case 'E': + return presentation_type::exp_upper; + case 'f': + return presentation_type::fixed_lower; + case 'F': + return presentation_type::fixed_upper; + case 'g': + return presentation_type::general_lower; + case 'G': + return presentation_type::general_upper; + case 'c': + return presentation_type::chr; + case 's': + return presentation_type::string; + case 'p': + return presentation_type::pointer; + case '?': + return presentation_type::debug; + default: + return presentation_type::none; + } +} + +// Parses standard format specifiers and sends notifications about parsed +// components to handler. +template +FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char* begin, + const Char* end, + SpecHandler&& handler) + -> const Char* { + if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) && + *begin != 'L') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + return begin; + } + + if (begin == end) return begin; + + begin = parse_align(begin, end, handler); + if (begin == end) return begin; + + // Parse sign. + switch (to_ascii(*begin)) { + case '+': + handler.on_sign(sign::plus); + ++begin; + break; + case '-': + handler.on_sign(sign::minus); + ++begin; + break; + case ' ': + handler.on_sign(sign::space); + ++begin; + break; + default: + break; + } + if (begin == end) return begin; + + if (*begin == '#') { + handler.on_hash(); + if (++begin == end) return begin; + } + + // Parse zero flag. + if (*begin == '0') { + handler.on_zero(); + if (++begin == end) return begin; + } + + begin = parse_width(begin, end, handler); + if (begin == end) return begin; + + // Parse precision. + if (*begin == '.') { + begin = parse_precision(begin, end, handler); + if (begin == end) return begin; + } + + if (*begin == 'L') { + handler.on_localized(); + ++begin; + } + + // Parse type. + if (begin != end && *begin != '}') { + presentation_type type = parse_presentation_type(*begin++); + if (type == presentation_type::none) + handler.on_error("invalid type specifier"); + handler.on_type(type); + } + return begin; +} + +template +FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end, + Handler&& handler) -> const Char* { + struct id_adapter { + Handler& handler; + int arg_id; + + FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); } + FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); } + FMT_CONSTEXPR void operator()(basic_string_view id) { + arg_id = handler.on_arg_id(id); + } + FMT_CONSTEXPR void on_error(const char* message) { + if (message) handler.on_error(message); + } + }; + + ++begin; + if (begin == end) return handler.on_error("invalid format string"), end; + if (*begin == '}') { + handler.on_replacement_field(handler.on_arg_id(), begin); + } else if (*begin == '{') { + handler.on_text(begin, begin + 1); + } else { + auto adapter = id_adapter{handler, 0}; + begin = parse_arg_id(begin, end, adapter); + Char c = begin != end ? *begin : Char(); + if (c == '}') { + handler.on_replacement_field(adapter.arg_id, begin); + } else if (c == ':') { + begin = handler.on_format_specs(adapter.arg_id, begin + 1, end); + if (begin == end || *begin != '}') + return handler.on_error("unknown format specifier"), end; + } else { + return handler.on_error("missing '}' in format string"), end; + } + } + return begin + 1; +} + +template +FMT_CONSTEXPR FMT_INLINE void parse_format_string( + basic_string_view format_str, Handler&& handler) { + // Workaround a name-lookup bug in MSVC's modules implementation. + using detail::find; + + auto begin = format_str.data(); + auto end = begin + format_str.size(); + if (end - begin < 32) { + // Use a simple loop instead of memchr for small strings. + const Char* p = begin; + while (p != end) { + auto c = *p++; + if (c == '{') { + handler.on_text(begin, p - 1); + begin = p = parse_replacement_field(p - 1, end, handler); + } else if (c == '}') { + if (p == end || *p != '}') + return handler.on_error("unmatched '}' in format string"); + handler.on_text(begin, p); + begin = ++p; + } + } + handler.on_text(begin, end); + return; + } + struct writer { + FMT_CONSTEXPR void operator()(const Char* from, const Char* to) { + if (from == to) return; + for (;;) { + const Char* p = nullptr; + if (!find(from, to, Char('}'), p)) + return handler_.on_text(from, to); + ++p; + if (p == to || *p != '}') + return handler_.on_error("unmatched '}' in format string"); + handler_.on_text(from, p); + from = p + 1; + } + } + Handler& handler_; + } write = {handler}; + while (begin != end) { + // Doing two passes with memchr (one for '{' and another for '}') is up to + // 2.5x faster than the naive one-pass implementation on big format strings. + const Char* p = begin; + if (*begin != '{' && !find(begin + 1, end, Char('{'), p)) + return write(begin, end); + write(begin, p); + begin = parse_replacement_field(p, end, handler); + } +} + +template ::value> struct strip_named_arg { + using type = T; +}; +template struct strip_named_arg { + using type = remove_cvref_t; +}; + +template +FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx) + -> decltype(ctx.begin()) { + using char_type = typename ParseContext::char_type; + using context = buffer_context; + using stripped_type = typename strip_named_arg::type; + using mapped_type = conditional_t< + mapped_type_constant::value != type::custom_type, + decltype(arg_mapper().map(std::declval())), + stripped_type>; + auto f = conditional_t::value, + formatter, + fallback_formatter>(); + return f.parse(ctx); +} + +template +FMT_CONSTEXPR void check_int_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type > presentation_type::bin_upper && type != presentation_type::chr) + eh.on_error("invalid type specifier"); +} + +// Checks char specs and returns true if the type spec is char (and not int). +template +FMT_CONSTEXPR auto check_char_specs(const basic_format_specs& specs, + ErrorHandler&& eh = {}) -> bool { + if (specs.type != presentation_type::none && + specs.type != presentation_type::chr && + specs.type != presentation_type::debug) { + check_int_type_spec(specs.type, eh); + return false; + } + if (specs.align == align::numeric || specs.sign != sign::none || specs.alt) + eh.on_error("invalid format specifier for char"); + return true; +} + +// A floating-point presentation format. +enum class float_format : unsigned char { + general, // General: exponent notation or fixed point based on magnitude. + exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. + fixed, // Fixed point with the default precision of 6, e.g. 0.0012. + hex +}; + +struct float_specs { + int precision; + float_format format : 8; + sign_t sign : 8; + bool upper : 1; + bool locale : 1; + bool binary32 : 1; + bool showpoint : 1; +}; + +template +FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs& specs, + ErrorHandler&& eh = {}) + -> float_specs { + auto result = float_specs(); + result.showpoint = specs.alt; + result.locale = specs.localized; + switch (specs.type) { + case presentation_type::none: + result.format = float_format::general; + break; + case presentation_type::general_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::general_lower: + result.format = float_format::general; + break; + case presentation_type::exp_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::exp_lower: + result.format = float_format::exp; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::fixed_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::fixed_lower: + result.format = float_format::fixed; + result.showpoint |= specs.precision != 0; + break; + case presentation_type::hexfloat_upper: + result.upper = true; + FMT_FALLTHROUGH; + case presentation_type::hexfloat_lower: + result.format = float_format::hex; + break; + default: + eh.on_error("invalid type specifier"); + break; + } + return result; +} + +template +FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type, + ErrorHandler&& eh = {}) -> bool { + if (type == presentation_type::none || type == presentation_type::string) + return true; + if (type != presentation_type::pointer) eh.on_error("invalid type specifier"); + return false; +} + +template +FMT_CONSTEXPR void check_string_type_spec(presentation_type type, + ErrorHandler&& eh = {}) { + if (type != presentation_type::none && type != presentation_type::string && + type != presentation_type::debug) + eh.on_error("invalid type specifier"); +} + +template +FMT_CONSTEXPR void check_pointer_type_spec(presentation_type type, + ErrorHandler&& eh) { + if (type != presentation_type::none && type != presentation_type::pointer) + eh.on_error("invalid type specifier"); +} + +// A parse_format_specs handler that checks if specifiers are consistent with +// the argument type. +template class specs_checker : public Handler { + private: + detail::type arg_type_; + + FMT_CONSTEXPR void require_numeric_argument() { + if (!is_arithmetic_type(arg_type_)) + this->on_error("format specifier requires numeric argument"); + } + + public: + FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type) + : Handler(handler), arg_type_(arg_type) {} + + FMT_CONSTEXPR void on_align(align_t align) { + if (align == align::numeric) require_numeric_argument(); + Handler::on_align(align); + } + + FMT_CONSTEXPR void on_sign(sign_t s) { + require_numeric_argument(); + if (is_integral_type(arg_type_) && arg_type_ != type::int_type && + arg_type_ != type::long_long_type && arg_type_ != type::int128_type && + arg_type_ != type::char_type) { + this->on_error("format specifier requires signed argument"); + } + Handler::on_sign(s); + } + + FMT_CONSTEXPR void on_hash() { + require_numeric_argument(); + Handler::on_hash(); + } + + FMT_CONSTEXPR void on_localized() { + require_numeric_argument(); + Handler::on_localized(); + } + + FMT_CONSTEXPR void on_zero() { + require_numeric_argument(); + Handler::on_zero(); + } + + FMT_CONSTEXPR void end_precision() { + if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type) + this->on_error("precision not allowed for this argument type"); + } +}; + +constexpr int invalid_arg_index = -1; + +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template +constexpr auto get_arg_index_by_name(basic_string_view name) -> int { + if constexpr (detail::is_statically_named_arg()) { + if (name == T::name) return N; + } + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name(name); + (void)name; // Workaround an MSVC bug about "unused" parameter. + return invalid_arg_index; +} +#endif + +template +FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view name) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS + if constexpr (sizeof...(Args) > 0) + return get_arg_index_by_name<0, Args...>(name); +#endif + (void)name; + return invalid_arg_index; +} + +template +class format_string_checker { + private: + // In the future basic_format_parse_context will replace compile_parse_context + // here and will use is_constant_evaluated and downcasting to access the data + // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1. + using parse_context_type = compile_parse_context; + static constexpr int num_args = sizeof...(Args); + + // Format specifier parsing function. + using parse_func = const Char* (*)(parse_context_type&); + + parse_context_type context_; + parse_func parse_funcs_[num_args > 0 ? static_cast(num_args) : 1]; + type types_[num_args > 0 ? static_cast(num_args) : 1]; + + public: + explicit FMT_CONSTEXPR format_string_checker( + basic_string_view format_str, ErrorHandler eh) + : context_(format_str, num_args, types_, eh), + parse_funcs_{&parse_format_specs...}, + types_{type_constant::value...} {} + + FMT_CONSTEXPR void on_text(const Char*, const Char*) {} + + FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); } + FMT_CONSTEXPR auto on_arg_id(int id) -> int { + return context_.check_arg_id(id), id; + } + FMT_CONSTEXPR auto on_arg_id(basic_string_view id) -> int { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS + auto index = get_arg_index_by_name(id); + if (index == invalid_arg_index) on_error("named argument is not found"); + return context_.check_arg_id(index), index; +#else + (void)id; + on_error("compile-time checks for named arguments require C++20 support"); + return 0; +#endif + } + + FMT_CONSTEXPR void on_replacement_field(int, const Char*) {} + + FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*) + -> const Char* { + context_.advance_to(context_.begin() + (begin - &*context_.begin())); + // id >= 0 check is a workaround for gcc 10 bug (#2065). + return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin; + } + + FMT_CONSTEXPR void on_error(const char* message) { + context_.on_error(message); + } +}; + +// Reports a compile-time error if S is not a valid format string. +template ::value)> +FMT_INLINE void check_format_string(const S&) { +#ifdef FMT_ENFORCE_COMPILE_STRING + static_assert(is_compile_string::value, + "FMT_ENFORCE_COMPILE_STRING requires all format strings to use " + "FMT_STRING."); +#endif +} +template ::value)> +void check_format_string(S format_str) { + FMT_CONSTEXPR auto s = basic_string_view(format_str); + using checker = format_string_checker...>; + FMT_CONSTEXPR bool invalid_format = + (parse_format_string(s, checker(s, {})), true); + ignore_unused(invalid_format); +} + +template +void vformat_to( + buffer& buf, basic_string_view fmt, + basic_format_args)> args, + locale_ref loc = {}); + +FMT_API void vprint_mojibake(std::FILE*, string_view, format_args); +#ifndef _WIN32 +inline void vprint_mojibake(std::FILE*, string_view, format_args) {} +#endif +FMT_END_DETAIL_NAMESPACE + +// A formatter specialization for the core types corresponding to detail::type +// constants. +template +struct formatter::value != + detail::type::custom_type>> { + private: + detail::dynamic_format_specs specs_; + + public: + // Parses format specifiers stopping either at the end of the range or at the + // terminating '}'. + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + auto begin = ctx.begin(), end = ctx.end(); + if (begin == end) return begin; + using handler_type = detail::dynamic_specs_handler; + auto type = detail::type_constant::value; + auto checker = + detail::specs_checker(handler_type(specs_, ctx), type); + auto it = detail::parse_format_specs(begin, end, checker); + auto eh = ctx.error_handler(); + switch (type) { + case detail::type::none_type: + FMT_ASSERT(false, "invalid argument type"); + break; + case detail::type::bool_type: + if (specs_.type == presentation_type::none || + specs_.type == presentation_type::string) { + break; + } + FMT_FALLTHROUGH; + case detail::type::int_type: + case detail::type::uint_type: + case detail::type::long_long_type: + case detail::type::ulong_long_type: + case detail::type::int128_type: + case detail::type::uint128_type: + detail::check_int_type_spec(specs_.type, eh); + break; + case detail::type::char_type: + detail::check_char_specs(specs_, eh); + break; + case detail::type::float_type: + if (detail::const_check(FMT_USE_FLOAT)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "float support disabled"); + break; + case detail::type::double_type: + if (detail::const_check(FMT_USE_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "double support disabled"); + break; + case detail::type::long_double_type: + if (detail::const_check(FMT_USE_LONG_DOUBLE)) + detail::parse_float_type_spec(specs_, eh); + else + FMT_ASSERT(false, "long double support disabled"); + break; + case detail::type::cstring_type: + detail::check_cstring_type_spec(specs_.type, eh); + break; + case detail::type::string_type: + detail::check_string_type_spec(specs_.type, eh); + break; + case detail::type::pointer_type: + detail::check_pointer_type_spec(specs_.type, eh); + break; + case detail::type::custom_type: + // Custom format specifiers are checked in parse functions of + // formatter specializations. + break; + } + return it; + } + + template + FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const + -> decltype(ctx.out()); +}; + +#define FMT_FORMAT_AS(Type, Base) \ + template \ + struct formatter : formatter { \ + template \ + auto format(Type const& val, FormatContext& ctx) const \ + -> decltype(ctx.out()) { \ + return formatter::format(static_cast(val), ctx); \ + } \ + } + +FMT_FORMAT_AS(signed char, int); +FMT_FORMAT_AS(unsigned char, unsigned); +FMT_FORMAT_AS(short, int); +FMT_FORMAT_AS(unsigned short, unsigned); +FMT_FORMAT_AS(long, long long); +FMT_FORMAT_AS(unsigned long, unsigned long long); +FMT_FORMAT_AS(Char*, const Char*); +FMT_FORMAT_AS(std::basic_string, basic_string_view); +FMT_FORMAT_AS(std::nullptr_t, const void*); +FMT_FORMAT_AS(detail::std_string_view, basic_string_view); + +template struct basic_runtime { basic_string_view str; }; + +/** A compile-time format string. */ +template class basic_format_string { + private: + basic_string_view str_; + + public: + template >::value)> + FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) { + static_assert( + detail::count< + (std::is_base_of>::value && + std::is_reference::value)...>() == 0, + "passing views as lvalues is disallowed"); +#ifdef FMT_HAS_CONSTEVAL + if constexpr (detail::count_named_args() == + detail::count_statically_named_args()) { + using checker = detail::format_string_checker...>; + detail::parse_format_string(str_, checker(s, {})); + } +#else + detail::check_format_string(s); +#endif + } + basic_format_string(basic_runtime r) : str_(r.str) {} + + FMT_INLINE operator basic_string_view() const { return str_; } +}; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +// Workaround broken conversion on older gcc. +template using format_string = string_view; +inline auto runtime(string_view s) -> basic_string_view { return s; } +#else +template +using format_string = basic_format_string...>; +/** + \rst + Creates a runtime format string. + + **Example**:: + + // Check format string at runtime instead of compile-time. + fmt::print(fmt::runtime("{:d}"), "I am not a number"); + \endrst + */ +inline auto runtime(string_view s) -> basic_runtime { return {{}}; } +#endif + +FMT_API auto vformat(string_view fmt, format_args args) -> std::string; + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and returns the result + as a string. + + **Example**:: + + #include + std::string message = fmt::format("The answer is {}.", 42); + \endrst +*/ +template +FMT_NODISCARD FMT_INLINE auto format(format_string fmt, T&&... args) + -> std::string { + return vformat(fmt, fmt::make_format_args(args...)); +} + +/** Formats a string and writes the output to ``out``. */ +template ::value)> +auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt { + using detail::get_buffer; + auto&& buf = get_buffer(out); + detail::vformat_to(buf, fmt, args, {}); + return detail::get_iterator(buf); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt``, writes the result to + the output iterator ``out`` and returns the iterator past the end of the output + range. `format_to` does not append a terminating null character. + + **Example**:: + + auto out = std::vector(); + fmt::format_to(std::back_inserter(out), "{}", 42); + \endrst + */ +template ::value)> +FMT_INLINE auto format_to(OutputIt out, format_string fmt, T&&... args) + -> OutputIt { + return vformat_to(out, fmt, fmt::make_format_args(args...)); +} + +template struct format_to_n_result { + /** Iterator past the end of the output range. */ + OutputIt out; + /** Total (not truncated) output size. */ + size_t size; +}; + +template ::value)> +auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) + -> format_to_n_result { + using traits = detail::fixed_buffer_traits; + auto buf = detail::iterator_buffer(out, n); + detail::vformat_to(buf, fmt, args, {}); + return {buf.out(), buf.count()}; +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt``, writes up to ``n`` + characters of the result to the output iterator ``out`` and returns the total + (not truncated) output size and the iterator past the end of the output range. + `format_to_n` does not append a terminating null character. + \endrst + */ +template ::value)> +FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string fmt, + T&&... args) -> format_to_n_result { + return vformat_to_n(out, n, fmt, fmt::make_format_args(args...)); +} + +/** Returns the number of chars in the output of ``format(fmt, args...)``. */ +template +FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, + T&&... args) -> size_t { + auto buf = detail::counting_buffer<>(); + detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {}); + return buf.count(); +} + +FMT_API void vprint(string_view fmt, format_args args); +FMT_API void vprint(std::FILE* f, string_view fmt, format_args args); + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the output + to ``stdout``. + + **Example**:: + + fmt::print("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template +FMT_INLINE void print(format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(fmt, vargs) + : detail::vprint_mojibake(stdout, fmt, vargs); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the + output to the file ``f``. + + **Example**:: + + fmt::print(stderr, "Don't {}!", "panic"); + \endrst + */ +template +FMT_INLINE void print(std::FILE* f, format_string fmt, T&&... args) { + const auto& vargs = fmt::make_format_args(args...); + return detail::is_utf8() ? vprint(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs); +} + +FMT_MODULE_EXPORT_END +FMT_GCC_PRAGMA("GCC pop_options") +FMT_END_NAMESPACE + +#ifdef FMT_HEADER_ONLY +# include "format.h" +#endif +#endif // FMT_CORE_H_ diff --git a/itemzflow/include/fmt/format-inl.h b/itemzflow/include/fmt/format-inl.h new file mode 100644 index 0000000..80b30b1 --- /dev/null +++ b/itemzflow/include/fmt/format-inl.h @@ -0,0 +1,1731 @@ +// Formatting library for C++ - implementation +// +// Copyright (c) 2012 - 2016, Victor Zverovich +// All rights reserved. +// +// For the license information refer to format.h. + +#ifndef FMT_FORMAT_INL_H_ +#define FMT_FORMAT_INL_H_ + +#include +#include +#include +#include // errno +#include +#include +#include +#include // std::memmove +#include +#include +#include "../log.h" +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +# include +#endif + +#ifdef _WIN32 +# include // _isatty +#endif + +#include "format.h" + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_FUNC void assert_fail(const char* file, int line, const char* message) { + // Use unchecked std::fprintf to avoid triggering another assertion when + // writing to stderr fails + log_error("[ERR] %s:%d: assertion failed: %s", file, line, message); + raise(SIGUSR2); +} + +FMT_FUNC void throw_format_error(const char* message) { + log_error("[ERR] %s", message); +} + +FMT_FUNC void format_error_code(detail::buffer& out, int error_code, + string_view message) noexcept { + // Report error code making sure that the output fits into + // inline_buffer_size to avoid dynamic memory allocation and potential + // bad_alloc. + out.try_resize(0); + static const char SEP[] = ": "; + static const char ERROR_STR[] = "error "; + // Subtract 2 to account for terminating null characters in SEP and ERROR_STR. + size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2; + auto abs_value = static_cast>(error_code); + if (detail::is_negative(error_code)) { + abs_value = 0 - abs_value; + ++error_code_size; + } + error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); + auto it = buffer_appender(out); + if (message.size() <= inline_buffer_size - error_code_size) + format_to(it, FMT_STRING("{}{}"), message, SEP); + format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); + FMT_ASSERT(out.size() <= inline_buffer_size, ""); +} + +FMT_FUNC void report_error(format_func func, int error_code, + const char* message) noexcept { + memory_buffer full_message; + func(full_message, error_code, message); + // Don't use fwrite_fully because the latter may throw. + log_error("%s, Error: %i", message, error_code); +} + +// A wrapper around fwrite that throws on error. +inline void fwrite_fully(const void* ptr, size_t size, size_t count, + FILE* stream) { + std::fwrite(ptr, size, count, stream); +} + +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR +template +locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { + static_assert(std::is_same::value, ""); +} + +template Locale locale_ref::get() const { + static_assert(std::is_same::value, ""); + return locale_ ? *static_cast(locale_) : std::locale(); +} + +template +FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result { + auto& facet = std::use_facet>(loc.get()); + auto grouping = facet.grouping(); + auto thousands_sep = grouping.empty() ? Char() : facet.thousands_sep(); + return {std::move(grouping), thousands_sep}; +} +template FMT_FUNC Char decimal_point_impl(locale_ref loc) { + return std::use_facet>(loc.get()) + .decimal_point(); +} +#else +template +FMT_FUNC auto thousands_sep_impl(locale_ref) -> thousands_sep_result { + return {"\03", FMT_STATIC_THOUSANDS_SEPARATOR}; +} +template FMT_FUNC Char decimal_point_impl(locale_ref) { + return '.'; +} +#endif +} // namespace detail + +#if !FMT_MSC_VERSION +FMT_API FMT_FUNC format_error::~format_error() noexcept = default; +#endif + +FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, + format_args args) { + auto ec = std::error_code(error_code, std::generic_category()); + return std::system_error(ec, vformat(format_str, args)); +} + +namespace detail { + +template inline bool operator==(basic_fp x, basic_fp y) { + return x.f == y.f && x.e == y.e; +} + +// Compilers should be able to optimize this into the ror instruction. +FMT_CONSTEXPR inline uint32_t rotr(uint32_t n, uint32_t r) noexcept { + r &= 31; + return (n >> r) | (n << (32 - r)); +} +FMT_CONSTEXPR inline uint64_t rotr(uint64_t n, uint32_t r) noexcept { + r &= 63; + return (n >> r) | (n << (64 - r)); +} + +// Computes 128-bit result of multiplication of two 64-bit unsigned integers. +inline uint128_fallback umul128(uint64_t x, uint64_t y) noexcept { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return {static_cast(p >> 64), static_cast(p)}; +#elif defined(_MSC_VER) && defined(_M_X64) + auto result = uint128_fallback(); + result.lo_ = _umul128(x, y, &result.hi_); + return result; +#else + const uint64_t mask = static_cast(max_value()); + + uint64_t a = x >> 32; + uint64_t b = x & mask; + uint64_t c = y >> 32; + uint64_t d = y & mask; + + uint64_t ac = a * c; + uint64_t bc = b * c; + uint64_t ad = a * d; + uint64_t bd = b * d; + + uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); + + return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), + (intermediate << 32) + (bd & mask)}; +#endif +} + +// Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. +namespace dragonbox { +// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. +inline uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept { +#if FMT_USE_INT128 + auto p = static_cast(x) * static_cast(y); + return static_cast(p >> 64); +#elif defined(_MSC_VER) && defined(_M_X64) + return __umulh(x, y); +#else + return umul128(x, y).high(); +#endif +} + +// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint128_fallback umul192_upper128(uint64_t x, + uint128_fallback y) noexcept { + uint128_fallback r = umul128(x, y.high()); + r += umul128_upper64(x, y.low()); + return r; +} + +// Computes upper 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint64_t umul96_upper64(uint32_t x, uint64_t y) noexcept { + return umul128_upper64(static_cast(x) << 32, y); +} + +// Computes lower 128 bits of multiplication of a 64-bit unsigned integer and a +// 128-bit unsigned integer. +inline uint128_fallback umul192_lower128(uint64_t x, + uint128_fallback y) noexcept { + uint64_t high = x * y.high(); + uint128_fallback high_low = umul128(x, y.low()); + return {high + high_low.high(), high_low.low()}; +} + +// Computes lower 64 bits of multiplication of a 32-bit unsigned integer and a +// 64-bit unsigned integer. +inline uint64_t umul96_lower64(uint32_t x, uint64_t y) noexcept { + return x * y; +} + +// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from +// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1. +inline int floor_log10_pow2(int e) noexcept { + FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent"); + static_assert((-1 >> 1) == -1, "right shift is not arithmetic"); + return (e * 315653) >> 20; +} + +// Various fast log computations. +inline int floor_log2_pow10(int e) noexcept { + FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); + return (e * 1741647) >> 19; +} +inline int floor_log10_pow2_minus_log10_4_over_3(int e) noexcept { + FMT_ASSERT(e <= 2936 && e >= -2985, "too large exponent"); + return (e * 631305 - 261663) >> 21; +} + +static constexpr struct { + uint32_t divisor; + int shift_amount; +} div_small_pow10_infos[] = {{10, 16}, {100, 16}}; + +// Replaces n by floor(n / pow(10, N)) returning true if and only if n is +// divisible by pow(10, N). +// Precondition: n <= pow(10, N + 1). +template +bool check_divisibility_and_divide_by_pow10(uint32_t& n) noexcept { + // The numbers below are chosen such that: + // 1. floor(n/d) = floor(nm / 2^k) where d=10 or d=100, + // 2. nm mod 2^k < m if and only if n is divisible by d, + // where m is magic_number, k is shift_amount + // and d is divisor. + // + // Item 1 is a common technique of replacing division by a constant with + // multiplication, see e.g. "Division by Invariant Integers Using + // Multiplication" by Granlund and Montgomery (1994). magic_number (m) is set + // to ceil(2^k/d) for large enough k. + // The idea for item 2 originates from Schubfach. + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + n *= magic_number; + const uint32_t comparison_mask = (1u << info.shift_amount) - 1; + bool result = (n & comparison_mask) < magic_number; + n >>= info.shift_amount; + return result; +} + +// Computes floor(n / pow(10, N)) for small n and N. +// Precondition: n <= pow(10, N + 1). +template uint32_t small_division_by_pow10(uint32_t n) noexcept { + constexpr auto info = div_small_pow10_infos[N - 1]; + FMT_ASSERT(n <= info.divisor * 10, "n is too large"); + constexpr uint32_t magic_number = + (1u << info.shift_amount) / info.divisor + 1; + return (n * magic_number) >> info.shift_amount; +} + +// Computes floor(n / 10^(kappa + 1)) (float) +inline uint32_t divide_by_10_to_kappa_plus_1(uint32_t n) noexcept { + // 1374389535 = ceil(2^37/100) + return static_cast((static_cast(n) * 1374389535) >> 37); +} +// Computes floor(n / 10^(kappa + 1)) (double) +inline uint64_t divide_by_10_to_kappa_plus_1(uint64_t n) noexcept { + // 2361183241434822607 = ceil(2^(64+7)/1000) + return umul128_upper64(n, 2361183241434822607ull) >> 7; +} + +// Various subroutines using pow10 cache +template struct cache_accessor; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint64_t; + + static uint64_t get_cached_power(int k) noexcept { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + static constexpr const uint64_t pow10_significands[] = { + 0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, + 0xfd87b5f28300ca0e, 0x9e74d1b791e07e49, 0xc612062576589ddb, + 0xf79687aed3eec552, 0x9abe14cd44753b53, 0xc16d9a0095928a28, + 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, + 0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, + 0xe69594bec44de15c, 0x901d7cf73ab0acda, 0xb424dc35095cd810, + 0xe12e13424bb40e14, 0x8cbccc096f5088cc, 0xafebff0bcb24aaff, + 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, + 0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, + 0xd1b71758e219652c, 0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, + 0xcccccccccccccccd, 0x8000000000000000, 0xa000000000000000, + 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, + 0xc350000000000000, 0xf424000000000000, 0x9896800000000000, + 0xbebc200000000000, 0xee6b280000000000, 0x9502f90000000000, + 0xba43b74000000000, 0xe8d4a51000000000, 0x9184e72a00000000, + 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, + 0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, + 0xad78ebc5ac620000, 0xd8d726b7177a8000, 0x878678326eac9000, + 0xa968163f0a57b400, 0xd3c21bcecceda100, 0x84595161401484a0, + 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940985, + 0xa18f07d736b90be6, 0xc9f2c9cd04674edf, 0xfc6f7c4045812297, + 0x9dc5ada82b70b59e, 0xc5371912364ce306, 0xf684df56c3e01bc7, + 0x9a130b963a6c115d, 0xc097ce7bc90715b4, 0xf0bdc21abb48db21, + 0x96769950b50d88f5, 0xbc143fa4e250eb32, 0xeb194f8e1ae525fe, + 0x92efd1b8d0cf37bf, 0xb7abc627050305ae, 0xe596b7b0c643c71a, + 0x8f7e32ce7bea5c70, 0xb35dbf821ae4f38c, 0xe0352f62a19e306f}; + return pow10_significands[k - float_info::min_k]; + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static compute_mul_result compute_mul( + carrier_uint u, const cache_entry_type& cache) noexcept { + auto r = umul96_upper64(u, cache); + return {static_cast(r >> 32), + static_cast(r) == 0}; + } + + static uint32_t compute_delta(const cache_entry_type& cache, + int beta) noexcept { + return static_cast(cache >> (64 - 1 - beta)); + } + + static compute_mul_parity_result compute_mul_parity( + carrier_uint two_f, const cache_entry_type& cache, int beta) noexcept { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul96_lower64(two_f, cache); + return {((r >> (64 - beta)) & 1) != 0, + static_cast(r >> (32 - beta)) == 0}; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return static_cast( + (cache - (cache >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return static_cast( + (cache + (cache >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta)); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return (static_cast( + cache >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +template <> struct cache_accessor { + using carrier_uint = float_info::carrier_uint; + using cache_entry_type = uint128_fallback; + + static uint128_fallback get_cached_power(int k) noexcept { + FMT_ASSERT(k >= float_info::min_k && k <= float_info::max_k, + "k is out of range"); + + static constexpr const uint128_fallback pow10_significands[] = { +#if FMT_USE_FULL_CACHE_DRAGONBOX + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0x9faacf3df73609b1, 0x77b191618c54e9ad}, + {0xc795830d75038c1d, 0xd59df5b9ef6a2418}, + {0xf97ae3d0d2446f25, 0x4b0573286b44ad1e}, + {0x9becce62836ac577, 0x4ee367f9430aec33}, + {0xc2e801fb244576d5, 0x229c41f793cda740}, + {0xf3a20279ed56d48a, 0x6b43527578c11110}, + {0x9845418c345644d6, 0x830a13896b78aaaa}, + {0xbe5691ef416bd60c, 0x23cc986bc656d554}, + {0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa9}, + {0x94b3a202eb1c3f39, 0x7bf7d71432f3d6aa}, + {0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc54}, + {0xe858ad248f5c22c9, 0xd1b3400f8f9cff69}, + {0x91376c36d99995be, 0x23100809b9c21fa2}, + {0xb58547448ffffb2d, 0xabd40a0c2832a78b}, + {0xe2e69915b3fff9f9, 0x16c90c8f323f516d}, + {0x8dd01fad907ffc3b, 0xae3da7d97f6792e4}, + {0xb1442798f49ffb4a, 0x99cd11cfdf41779d}, + {0xdd95317f31c7fa1d, 0x40405643d711d584}, + {0x8a7d3eef7f1cfc52, 0x482835ea666b2573}, + {0xad1c8eab5ee43b66, 0xda3243650005eed0}, + {0xd863b256369d4a40, 0x90bed43e40076a83}, + {0x873e4f75e2224e68, 0x5a7744a6e804a292}, + {0xa90de3535aaae202, 0x711515d0a205cb37}, + {0xd3515c2831559a83, 0x0d5a5b44ca873e04}, + {0x8412d9991ed58091, 0xe858790afe9486c3}, + {0xa5178fff668ae0b6, 0x626e974dbe39a873}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0x80fa687f881c7f8e, 0x7ce66634bc9d0b9a}, + {0xa139029f6a239f72, 0x1c1fffc1ebc44e81}, + {0xc987434744ac874e, 0xa327ffb266b56221}, + {0xfbe9141915d7a922, 0x4bf1ff9f0062baa9}, + {0x9d71ac8fada6c9b5, 0x6f773fc3603db4aa}, + {0xc4ce17b399107c22, 0xcb550fb4384d21d4}, + {0xf6019da07f549b2b, 0x7e2a53a146606a49}, + {0x99c102844f94e0fb, 0x2eda7444cbfc426e}, + {0xc0314325637a1939, 0xfa911155fefb5309}, + {0xf03d93eebc589f88, 0x793555ab7eba27cb}, + {0x96267c7535b763b5, 0x4bc1558b2f3458df}, + {0xbbb01b9283253ca2, 0x9eb1aaedfb016f17}, + {0xea9c227723ee8bcb, 0x465e15a979c1cadd}, + {0x92a1958a7675175f, 0x0bfacd89ec191eca}, + {0xb749faed14125d36, 0xcef980ec671f667c}, + {0xe51c79a85916f484, 0x82b7e12780e7401b}, + {0x8f31cc0937ae58d2, 0xd1b2ecb8b0908811}, + {0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa16}, + {0xdfbdcece67006ac9, 0x67a791e093e1d49b}, + {0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e1}, + {0xaecc49914078536d, 0x58fae9f773886e19}, + {0xda7f5bf590966848, 0xaf39a475506a899f}, + {0x888f99797a5e012d, 0x6d8406c952429604}, + {0xaab37fd7d8f58178, 0xc8e5087ba6d33b84}, + {0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a65}, + {0x855c3be0a17fcd26, 0x5cf2eea09a550680}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0xd0601d8efc57b08b, 0xf13b94daf124da27}, + {0x823c12795db6ce57, 0x76c53d08d6b70859}, + {0xa2cb1717b52481ed, 0x54768c4b0c64ca6f}, + {0xcb7ddcdda26da268, 0xa9942f5dcf7dfd0a}, + {0xfe5d54150b090b02, 0xd3f93b35435d7c4d}, + {0x9efa548d26e5a6e1, 0xc47bc5014a1a6db0}, + {0xc6b8e9b0709f109a, 0x359ab6419ca1091c}, + {0xf867241c8cc6d4c0, 0xc30163d203c94b63}, + {0x9b407691d7fc44f8, 0x79e0de63425dcf1e}, + {0xc21094364dfb5636, 0x985915fc12f542e5}, + {0xf294b943e17a2bc4, 0x3e6f5b7b17b2939e}, + {0x979cf3ca6cec5b5a, 0xa705992ceecf9c43}, + {0xbd8430bd08277231, 0x50c6ff782a838354}, + {0xece53cec4a314ebd, 0xa4f8bf5635246429}, + {0x940f4613ae5ed136, 0x871b7795e136be9a}, + {0xb913179899f68584, 0x28e2557b59846e40}, + {0xe757dd7ec07426e5, 0x331aeada2fe589d0}, + {0x9096ea6f3848984f, 0x3ff0d2c85def7622}, + {0xb4bca50b065abe63, 0x0fed077a756b53aa}, + {0xe1ebce4dc7f16dfb, 0xd3e8495912c62895}, + {0x8d3360f09cf6e4bd, 0x64712dd7abbbd95d}, + {0xb080392cc4349dec, 0xbd8d794d96aacfb4}, + {0xdca04777f541c567, 0xecf0d7a0fc5583a1}, + {0x89e42caaf9491b60, 0xf41686c49db57245}, + {0xac5d37d5b79b6239, 0x311c2875c522ced6}, + {0xd77485cb25823ac7, 0x7d633293366b828c}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xa8530886b54dbdeb, 0xd9f57f830283fdfd}, + {0xd267caa862a12d66, 0xd072df63c324fd7c}, + {0x8380dea93da4bc60, 0x4247cb9e59f71e6e}, + {0xa46116538d0deb78, 0x52d9be85f074e609}, + {0xcd795be870516656, 0x67902e276c921f8c}, + {0x806bd9714632dff6, 0x00ba1cd8a3db53b7}, + {0xa086cfcd97bf97f3, 0x80e8a40eccd228a5}, + {0xc8a883c0fdaf7df0, 0x6122cd128006b2ce}, + {0xfad2a4b13d1b5d6c, 0x796b805720085f82}, + {0x9cc3a6eec6311a63, 0xcbe3303674053bb1}, + {0xc3f490aa77bd60fc, 0xbedbfc4411068a9d}, + {0xf4f1b4d515acb93b, 0xee92fb5515482d45}, + {0x991711052d8bf3c5, 0x751bdd152d4d1c4b}, + {0xbf5cd54678eef0b6, 0xd262d45a78a0635e}, + {0xef340a98172aace4, 0x86fb897116c87c35}, + {0x9580869f0e7aac0e, 0xd45d35e6ae3d4da1}, + {0xbae0a846d2195712, 0x8974836059cca10a}, + {0xe998d258869facd7, 0x2bd1a438703fc94c}, + {0x91ff83775423cc06, 0x7b6306a34627ddd0}, + {0xb67f6455292cbf08, 0x1a3bc84c17b1d543}, + {0xe41f3d6a7377eeca, 0x20caba5f1d9e4a94}, + {0x8e938662882af53e, 0x547eb47b7282ee9d}, + {0xb23867fb2a35b28d, 0xe99e619a4f23aa44}, + {0xdec681f9f4c31f31, 0x6405fa00e2ec94d5}, + {0x8b3c113c38f9f37e, 0xde83bc408dd3dd05}, + {0xae0b158b4738705e, 0x9624ab50b148d446}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d7}, + {0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4d}, + {0xd47487cc8470652b, 0x7647c32000696720}, + {0x84c8d4dfd2c63f3b, 0x29ecd9f40041e074}, + {0xa5fb0a17c777cf09, 0xf468107100525891}, + {0xcf79cc9db955c2cc, 0x7182148d4066eeb5}, + {0x81ac1fe293d599bf, 0xc6f14cd848405531}, + {0xa21727db38cb002f, 0xb8ada00e5a506a7d}, + {0xca9cf1d206fdc03b, 0xa6d90811f0e4851d}, + {0xfd442e4688bd304a, 0x908f4a166d1da664}, + {0x9e4a9cec15763e2e, 0x9a598e4e043287ff}, + {0xc5dd44271ad3cdba, 0x40eff1e1853f29fe}, + {0xf7549530e188c128, 0xd12bee59e68ef47d}, + {0x9a94dd3e8cf578b9, 0x82bb74f8301958cf}, + {0xc13a148e3032d6e7, 0xe36a52363c1faf02}, + {0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac2}, + {0x96f5600f15a7b7e5, 0x29ab103a5ef8c0ba}, + {0xbcb2b812db11a5de, 0x7415d448f6b6f0e8}, + {0xebdf661791d60f56, 0x111b495b3464ad22}, + {0x936b9fcebb25c995, 0xcab10dd900beec35}, + {0xb84687c269ef3bfb, 0x3d5d514f40eea743}, + {0xe65829b3046b0afa, 0x0cb4a5a3112a5113}, + {0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ac}, + {0xb3f4e093db73a093, 0x59ed216765690f57}, + {0xe0f218b8d25088b8, 0x306869c13ec3532d}, + {0x8c974f7383725573, 0x1e414218c73a13fc}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0xdbac6c247d62a583, 0xdf45f746b74abf3a}, + {0x894bc396ce5da772, 0x6b8bba8c328eb784}, + {0xab9eb47c81f5114f, 0x066ea92f3f326565}, + {0xd686619ba27255a2, 0xc80a537b0efefebe}, + {0x8613fd0145877585, 0xbd06742ce95f5f37}, + {0xa798fc4196e952e7, 0x2c48113823b73705}, + {0xd17f3b51fca3a7a0, 0xf75a15862ca504c6}, + {0x82ef85133de648c4, 0x9a984d73dbe722fc}, + {0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebbb}, + {0xcc963fee10b7d1b3, 0x318df905079926a9}, + {0xffbbcfe994e5c61f, 0xfdf17746497f7053}, + {0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa634}, + {0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc1}, + {0xf9bd690a1b68637b, 0x3dfdce7aa3c673b1}, + {0x9c1661a651213e2d, 0x06bea10ca65c084f}, + {0xc31bfa0fe5698db8, 0x486e494fcff30a63}, + {0xf3e2f893dec3f126, 0x5a89dba3c3efccfb}, + {0x986ddb5c6b3a76b7, 0xf89629465a75e01d}, + {0xbe89523386091465, 0xf6bbb397f1135824}, + {0xee2ba6c0678b597f, 0x746aa07ded582e2d}, + {0x94db483840b717ef, 0xa8c2a44eb4571cdd}, + {0xba121a4650e4ddeb, 0x92f34d62616ce414}, + {0xe896a0d7e51e1566, 0x77b020baf9c81d18}, + {0x915e2486ef32cd60, 0x0ace1474dc1d122f}, + {0xb5b5ada8aaff80b8, 0x0d819992132456bb}, + {0xe3231912d5bf60e6, 0x10e1fff697ed6c6a}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb3}, + {0xddd0467c64bce4a0, 0xac7cb3f6d05ddbdf}, + {0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96c}, + {0xad4ab7112eb3929d, 0x86c16c98d2c953c7}, + {0xd89d64d57a607744, 0xe871c7bf077ba8b8}, + {0x87625f056c7c4a8b, 0x11471cd764ad4973}, + {0xa93af6c6c79b5d2d, 0xd598e40d3dd89bd0}, + {0xd389b47879823479, 0x4aff1d108d4ec2c4}, + {0x843610cb4bf160cb, 0xcedf722a585139bb}, + {0xa54394fe1eedb8fe, 0xc2974eb4ee658829}, + {0xce947a3da6a9273e, 0x733d226229feea33}, + {0x811ccc668829b887, 0x0806357d5a3f5260}, + {0xa163ff802a3426a8, 0xca07c2dcb0cf26f8}, + {0xc9bcff6034c13052, 0xfc89b393dd02f0b6}, + {0xfc2c3f3841f17c67, 0xbbac2078d443ace3}, + {0x9d9ba7832936edc0, 0xd54b944b84aa4c0e}, + {0xc5029163f384a931, 0x0a9e795e65d4df12}, + {0xf64335bcf065d37d, 0x4d4617b5ff4a16d6}, + {0x99ea0196163fa42e, 0x504bced1bf8e4e46}, + {0xc06481fb9bcf8d39, 0xe45ec2862f71e1d7}, + {0xf07da27a82c37088, 0x5d767327bb4e5a4d}, + {0x964e858c91ba2655, 0x3a6a07f8d510f870}, + {0xbbe226efb628afea, 0x890489f70a55368c}, + {0xeadab0aba3b2dbe5, 0x2b45ac74ccea842f}, + {0x92c8ae6b464fc96f, 0x3b0b8bc90012929e}, + {0xb77ada0617e3bbcb, 0x09ce6ebb40173745}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0x8f57fa54c2a9eab6, 0x9fa946824a12232e}, + {0xb32df8e9f3546564, 0x47939822dc96abfa}, + {0xdff9772470297ebd, 0x59787e2b93bc56f8}, + {0x8bfbea76c619ef36, 0x57eb4edb3c55b65b}, + {0xaefae51477a06b03, 0xede622920b6b23f2}, + {0xdab99e59958885c4, 0xe95fab368e45ecee}, + {0x88b402f7fd75539b, 0x11dbcb0218ebb415}, + {0xaae103b5fcd2a881, 0xd652bdc29f26a11a}, + {0xd59944a37c0752a2, 0x4be76d3346f04960}, + {0x857fcae62d8493a5, 0x6f70a4400c562ddc}, + {0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb953}, + {0xd097ad07a71f26b2, 0x7e2000a41346a7a8}, + {0x825ecc24c873782f, 0x8ed400668c0c28c9}, + {0xa2f67f2dfa90563b, 0x728900802f0f32fb}, + {0xcbb41ef979346bca, 0x4f2b40a03ad2ffba}, + {0xfea126b7d78186bc, 0xe2f610c84987bfa9}, + {0x9f24b832e6b0f436, 0x0dd9ca7d2df4d7ca}, + {0xc6ede63fa05d3143, 0x91503d1c79720dbc}, + {0xf8a95fcf88747d94, 0x75a44c6397ce912b}, + {0x9b69dbe1b548ce7c, 0xc986afbe3ee11abb}, + {0xc24452da229b021b, 0xfbe85badce996169}, + {0xf2d56790ab41c2a2, 0xfae27299423fb9c4}, + {0x97c560ba6b0919a5, 0xdccd879fc967d41b}, + {0xbdb6b8e905cb600f, 0x5400e987bbc1c921}, + {0xed246723473e3813, 0x290123e9aab23b69}, + {0x9436c0760c86e30b, 0xf9a0b6720aaf6522}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0xe7958cb87392c2c2, 0xb60b1d1230b20e05}, + {0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c3}, + {0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af4}, + {0xe2280b6c20dd5232, 0x25c6da63c38de1b1}, + {0x8d590723948a535f, 0x579c487e5a38ad0f}, + {0xb0af48ec79ace837, 0x2d835a9df0c6d852}, + {0xdcdb1b2798182244, 0xf8e431456cf88e66}, + {0x8a08f0f8bf0f156b, 0x1b8e9ecb641b5900}, + {0xac8b2d36eed2dac5, 0xe272467e3d222f40}, + {0xd7adf884aa879177, 0x5b0ed81dcc6abb10}, + {0x86ccbb52ea94baea, 0x98e947129fc2b4ea}, + {0xa87fea27a539e9a5, 0x3f2398d747b36225}, + {0xd29fe4b18e88640e, 0x8eec7f0d19a03aae}, + {0x83a3eeeef9153e89, 0x1953cf68300424ad}, + {0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd8}, + {0xcdb02555653131b6, 0x3792f412cb06794e}, + {0x808e17555f3ebf11, 0xe2bbd88bbee40bd1}, + {0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec5}, + {0xc8de047564d20a8b, 0xf245825a5a445276}, + {0xfb158592be068d2e, 0xeed6e2f0f0d56713}, + {0x9ced737bb6c4183d, 0x55464dd69685606c}, + {0xc428d05aa4751e4c, 0xaa97e14c3c26b887}, + {0xf53304714d9265df, 0xd53dd99f4b3066a9}, + {0x993fe2c6d07b7fab, 0xe546a8038efe402a}, + {0xbf8fdb78849a5f96, 0xde98520472bdd034}, + {0xef73d256a5c0f77c, 0x963e66858f6d4441}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xbb127c53b17ec159, 0x5560c018580d5d53}, + {0xe9d71b689dde71af, 0xaab8f01e6e10b4a7}, + {0x9226712162ab070d, 0xcab3961304ca70e9}, + {0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d23}, + {0xe45c10c42a2b3b05, 0x8cb89a7db77c506b}, + {0x8eb98a7a9a5b04e3, 0x77f3608e92adb243}, + {0xb267ed1940f1c61c, 0x55f038b237591ed4}, + {0xdf01e85f912e37a3, 0x6b6c46dec52f6689}, + {0x8b61313bbabce2c6, 0x2323ac4b3b3da016}, + {0xae397d8aa96c1b77, 0xabec975e0a0d081b}, + {0xd9c7dced53c72255, 0x96e7bd358c904a22}, + {0x881cea14545c7575, 0x7e50d64177da2e55}, + {0xaa242499697392d2, 0xdde50bd1d5d0b9ea}, + {0xd4ad2dbfc3d07787, 0x955e4ec64b44e865}, + {0x84ec3c97da624ab4, 0xbd5af13bef0b113f}, + {0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58f}, + {0xcfb11ead453994ba, 0x67de18eda5814af3}, + {0x81ceb32c4b43fcf4, 0x80eacf948770ced8}, + {0xa2425ff75e14fc31, 0xa1258379a94d028e}, + {0xcad2f7f5359a3b3e, 0x096ee45813a04331}, + {0xfd87b5f28300ca0d, 0x8bca9d6e188853fd}, + {0x9e74d1b791e07e48, 0x775ea264cf55347e}, + {0xc612062576589dda, 0x95364afe032a819e}, + {0xf79687aed3eec551, 0x3a83ddbd83f52205}, + {0x9abe14cd44753b52, 0xc4926a9672793543}, + {0xc16d9a0095928a27, 0x75b7053c0f178294}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0x971da05074da7bee, 0xd3f6fc16ebca5e04}, + {0xbce5086492111aea, 0x88f4bb1ca6bcf585}, + {0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6}, + {0x9392ee8e921d5d07, 0x3aff322e62439fd0}, + {0xb877aa3236a4b449, 0x09befeb9fad487c3}, + {0xe69594bec44de15b, 0x4c2ebe687989a9b4}, + {0x901d7cf73ab0acd9, 0x0f9d37014bf60a11}, + {0xb424dc35095cd80f, 0x538484c19ef38c95}, + {0xe12e13424bb40e13, 0x2865a5f206b06fba}, + {0x8cbccc096f5088cb, 0xf93f87b7442e45d4}, + {0xafebff0bcb24aafe, 0xf78f69a51539d749}, + {0xdbe6fecebdedd5be, 0xb573440e5a884d1c}, + {0x89705f4136b4a597, 0x31680a88f8953031}, + {0xabcc77118461cefc, 0xfdc20d2b36ba7c3e}, + {0xd6bf94d5e57a42bc, 0x3d32907604691b4d}, + {0x8637bd05af6c69b5, 0xa63f9a49c2c1b110}, + {0xa7c5ac471b478423, 0x0fcf80dc33721d54}, + {0xd1b71758e219652b, 0xd3c36113404ea4a9}, + {0x83126e978d4fdf3b, 0x645a1cac083126ea}, + {0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4}, + {0xcccccccccccccccc, 0xcccccccccccccccd}, + {0x8000000000000000, 0x0000000000000000}, + {0xa000000000000000, 0x0000000000000000}, + {0xc800000000000000, 0x0000000000000000}, + {0xfa00000000000000, 0x0000000000000000}, + {0x9c40000000000000, 0x0000000000000000}, + {0xc350000000000000, 0x0000000000000000}, + {0xf424000000000000, 0x0000000000000000}, + {0x9896800000000000, 0x0000000000000000}, + {0xbebc200000000000, 0x0000000000000000}, + {0xee6b280000000000, 0x0000000000000000}, + {0x9502f90000000000, 0x0000000000000000}, + {0xba43b74000000000, 0x0000000000000000}, + {0xe8d4a51000000000, 0x0000000000000000}, + {0x9184e72a00000000, 0x0000000000000000}, + {0xb5e620f480000000, 0x0000000000000000}, + {0xe35fa931a0000000, 0x0000000000000000}, + {0x8e1bc9bf04000000, 0x0000000000000000}, + {0xb1a2bc2ec5000000, 0x0000000000000000}, + {0xde0b6b3a76400000, 0x0000000000000000}, + {0x8ac7230489e80000, 0x0000000000000000}, + {0xad78ebc5ac620000, 0x0000000000000000}, + {0xd8d726b7177a8000, 0x0000000000000000}, + {0x878678326eac9000, 0x0000000000000000}, + {0xa968163f0a57b400, 0x0000000000000000}, + {0xd3c21bcecceda100, 0x0000000000000000}, + {0x84595161401484a0, 0x0000000000000000}, + {0xa56fa5b99019a5c8, 0x0000000000000000}, + {0xcecb8f27f4200f3a, 0x0000000000000000}, + {0x813f3978f8940984, 0x4000000000000000}, + {0xa18f07d736b90be5, 0x5000000000000000}, + {0xc9f2c9cd04674ede, 0xa400000000000000}, + {0xfc6f7c4045812296, 0x4d00000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xc5371912364ce305, 0x6c28000000000000}, + {0xf684df56c3e01bc6, 0xc732000000000000}, + {0x9a130b963a6c115c, 0x3c7f400000000000}, + {0xc097ce7bc90715b3, 0x4b9f100000000000}, + {0xf0bdc21abb48db20, 0x1e86d40000000000}, + {0x96769950b50d88f4, 0x1314448000000000}, + {0xbc143fa4e250eb31, 0x17d955a000000000}, + {0xeb194f8e1ae525fd, 0x5dcfab0800000000}, + {0x92efd1b8d0cf37be, 0x5aa1cae500000000}, + {0xb7abc627050305ad, 0xf14a3d9e40000000}, + {0xe596b7b0c643c719, 0x6d9ccd05d0000000}, + {0x8f7e32ce7bea5c6f, 0xe4820023a2000000}, + {0xb35dbf821ae4f38b, 0xdda2802c8a800000}, + {0xe0352f62a19e306e, 0xd50b2037ad200000}, + {0x8c213d9da502de45, 0x4526f422cc340000}, + {0xaf298d050e4395d6, 0x9670b12b7f410000}, + {0xdaf3f04651d47b4c, 0x3c0cdd765f114000}, + {0x88d8762bf324cd0f, 0xa5880a69fb6ac800}, + {0xab0e93b6efee0053, 0x8eea0d047a457a00}, + {0xd5d238a4abe98068, 0x72a4904598d6d880}, + {0x85a36366eb71f041, 0x47a6da2b7f864750}, + {0xa70c3c40a64e6c51, 0x999090b65f67d924}, + {0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d}, + {0x82818f1281ed449f, 0xbff8f10e7a8921a5}, + {0xa321f2d7226895c7, 0xaff72d52192b6a0e}, + {0xcbea6f8ceb02bb39, 0x9bf4f8a69f764491}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0x9f4f2726179a2245, 0x01d762422c946591}, + {0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef6}, + {0xf8ebad2b84e0d58b, 0xd2e0898765a7deb3}, + {0x9b934c3b330c8577, 0x63cc55f49f88eb30}, + {0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fc}, + {0xf316271c7fc3908a, 0x8bef464e3945ef7b}, + {0x97edd871cfda3a56, 0x97758bf0e3cbb5ad}, + {0xbde94e8e43d0c8ec, 0x3d52eeed1cbea318}, + {0xed63a231d4c4fb27, 0x4ca7aaa863ee4bde}, + {0x945e455f24fb1cf8, 0x8fe8caa93e74ef6b}, + {0xb975d6b6ee39e436, 0xb3e2fd538e122b45}, + {0xe7d34c64a9c85d44, 0x60dbbca87196b617}, + {0x90e40fbeea1d3a4a, 0xbc8955e946fe31ce}, + {0xb51d13aea4a488dd, 0x6babab6398bdbe42}, + {0xe264589a4dcdab14, 0xc696963c7eed2dd2}, + {0x8d7eb76070a08aec, 0xfc1e1de5cf543ca3}, + {0xb0de65388cc8ada8, 0x3b25a55f43294bcc}, + {0xdd15fe86affad912, 0x49ef0eb713f39ebf}, + {0x8a2dbf142dfcc7ab, 0x6e3569326c784338}, + {0xacb92ed9397bf996, 0x49c2c37f07965405}, + {0xd7e77a8f87daf7fb, 0xdc33745ec97be907}, + {0x86f0ac99b4e8dafd, 0x69a028bb3ded71a4}, + {0xa8acd7c0222311bc, 0xc40832ea0d68ce0d}, + {0xd2d80db02aabd62b, 0xf50a3fa490c30191}, + {0x83c7088e1aab65db, 0x792667c6da79e0fb}, + {0xa4b8cab1a1563f52, 0x577001b891185939}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0x80b05e5ac60b6178, 0x544f8158315b05b5}, + {0xa0dc75f1778e39d6, 0x696361ae3db1c722}, + {0xc913936dd571c84c, 0x03bc3a19cd1e38ea}, + {0xfb5878494ace3a5f, 0x04ab48a04065c724}, + {0x9d174b2dcec0e47b, 0x62eb0d64283f9c77}, + {0xc45d1df942711d9a, 0x3ba5d0bd324f8395}, + {0xf5746577930d6500, 0xca8f44ec7ee3647a}, + {0x9968bf6abbe85f20, 0x7e998b13cf4e1ecc}, + {0xbfc2ef456ae276e8, 0x9e3fedd8c321a67f}, + {0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101f}, + {0x95d04aee3b80ece5, 0xbba1f1d158724a13}, + {0xbb445da9ca61281f, 0x2a8a6e45ae8edc98}, + {0xea1575143cf97226, 0xf52d09d71a3293be}, + {0x924d692ca61be758, 0x593c2626705f9c57}, + {0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836d}, + {0xe498f455c38b997a, 0x0b6dfb9c0f956448}, + {0x8edf98b59a373fec, 0x4724bd4189bd5ead}, + {0xb2977ee300c50fe7, 0x58edec91ec2cb658}, + {0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ee}, + {0x8b865b215899f46c, 0xbd79e0d20082ee75}, + {0xae67f1e9aec07187, 0xecd8590680a3aa12}, + {0xda01ee641a708de9, 0xe80e6f4820cc9496}, + {0x884134fe908658b2, 0x3109058d147fdcde}, + {0xaa51823e34a7eede, 0xbd4b46f0599fd416}, + {0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91b}, + {0x850fadc09923329e, 0x03e2cf6bc604ddb1}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0xcfe87f7cef46ff16, 0xe612641865679a64}, + {0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07f}, + {0xa26da3999aef7749, 0xe3be5e330f38f09e}, + {0xcb090c8001ab551c, 0x5cadf5bfd3072cc6}, + {0xfdcb4fa002162a63, 0x73d9732fc7c8f7f7}, + {0x9e9f11c4014dda7e, 0x2867e7fddcdd9afb}, + {0xc646d63501a1511d, 0xb281e1fd541501b9}, + {0xf7d88bc24209a565, 0x1f225a7ca91a4227}, + {0x9ae757596946075f, 0x3375788de9b06959}, + {0xc1a12d2fc3978937, 0x0052d6b1641c83af}, + {0xf209787bb47d6b84, 0xc0678c5dbd23a49b}, + {0x9745eb4d50ce6332, 0xf840b7ba963646e1}, + {0xbd176620a501fbff, 0xb650e5a93bc3d899}, + {0xec5d3fa8ce427aff, 0xa3e51f138ab4cebf}, + {0x93ba47c980e98cdf, 0xc66f336c36b10138}, + {0xb8a8d9bbe123f017, 0xb80b0047445d4185}, + {0xe6d3102ad96cec1d, 0xa60dc059157491e6}, + {0x9043ea1ac7e41392, 0x87c89837ad68db30}, + {0xb454e4a179dd1877, 0x29babe4598c311fc}, + {0xe16a1dc9d8545e94, 0xf4296dd6fef3d67b}, + {0x8ce2529e2734bb1d, 0x1899e4a65f58660d}, + {0xb01ae745b101e9e4, 0x5ec05dcff72e7f90}, + {0xdc21a1171d42645d, 0x76707543f4fa1f74}, + {0x899504ae72497eba, 0x6a06494a791c53a9}, + {0xabfa45da0edbde69, 0x0487db9d17636893}, + {0xd6f8d7509292d603, 0x45a9d2845d3c42b7}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xa7f26836f282b732, 0x8e6cac7768d7141f}, + {0xd1ef0244af2364ff, 0x3207d795430cd927}, + {0x8335616aed761f1f, 0x7f44e6bd49e807b9}, + {0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a7}, + {0xcd036837130890a1, 0x36dba887c37a8c10}, + {0x802221226be55a64, 0xc2494954da2c978a}, + {0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6d}, + {0xc83553c5c8965d3d, 0x6f92829494e5acc8}, + {0xfa42a8b73abbf48c, 0xcb772339ba1f17fa}, + {0x9c69a97284b578d7, 0xff2a760414536efc}, + {0xc38413cf25e2d70d, 0xfef5138519684abb}, + {0xf46518c2ef5b8cd1, 0x7eb258665fc25d6a}, + {0x98bf2f79d5993802, 0xef2f773ffbd97a62}, + {0xbeeefb584aff8603, 0xaafb550ffacfd8fb}, + {0xeeaaba2e5dbf6784, 0x95ba2a53f983cf39}, + {0x952ab45cfa97a0b2, 0xdd945a747bf26184}, + {0xba756174393d88df, 0x94f971119aeef9e5}, + {0xe912b9d1478ceb17, 0x7a37cd5601aab85e}, + {0x91abb422ccb812ee, 0xac62e055c10ab33b}, + {0xb616a12b7fe617aa, 0x577b986b314d600a}, + {0xe39c49765fdf9d94, 0xed5a7e85fda0b80c}, + {0x8e41ade9fbebc27d, 0x14588f13be847308}, + {0xb1d219647ae6b31c, 0x596eb2d8ae258fc9}, + {0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bc}, + {0x8aec23d680043bee, 0x25de7bb9480d5855}, + {0xada72ccc20054ae9, 0xaf561aa79a10ae6b}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0x87aa9aff79042286, 0x90fb44d2f05d0843}, + {0xa99541bf57452b28, 0x353a1607ac744a54}, + {0xd3fa922f2d1675f2, 0x42889b8997915ce9}, + {0x847c9b5d7c2e09b7, 0x69956135febada12}, + {0xa59bc234db398c25, 0x43fab9837e699096}, + {0xcf02b2c21207ef2e, 0x94f967e45e03f4bc}, + {0x8161afb94b44f57d, 0x1d1be0eebac278f6}, + {0xa1ba1ba79e1632dc, 0x6462d92a69731733}, + {0xca28a291859bbf93, 0x7d7b8f7503cfdcff}, + {0xfcb2cb35e702af78, 0x5cda735244c3d43f}, + {0x9defbf01b061adab, 0x3a0888136afa64a8}, + {0xc56baec21c7a1916, 0x088aaa1845b8fdd1}, + {0xf6c69a72a3989f5b, 0x8aad549e57273d46}, + {0x9a3c2087a63f6399, 0x36ac54e2f678864c}, + {0xc0cb28a98fcf3c7f, 0x84576a1bb416a7de}, + {0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d6}, + {0x969eb7c47859e743, 0x9f644ae5a4b1b326}, + {0xbc4665b596706114, 0x873d5d9f0dde1fef}, + {0xeb57ff22fc0c7959, 0xa90cb506d155a7eb}, + {0x9316ff75dd87cbd8, 0x09a7f12442d588f3}, + {0xb7dcbf5354e9bece, 0x0c11ed6d538aeb30}, + {0xe5d3ef282a242e81, 0x8f1668c8a86da5fb}, + {0x8fa475791a569d10, 0xf96e017d694487bd}, + {0xb38d92d760ec4455, 0x37c981dcc395a9ad}, + {0xe070f78d3927556a, 0x85bbe253f47b1418}, + {0x8c469ab843b89562, 0x93956d7478ccec8f}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0xdb2e51bfe9d0696a, 0x06997b05fcc0319f}, + {0x88fcf317f22241e2, 0x441fece3bdf81f04}, + {0xab3c2fddeeaad25a, 0xd527e81cad7626c4}, + {0xd60b3bd56a5586f1, 0x8a71e223d8d3b075}, + {0x85c7056562757456, 0xf6872d5667844e4a}, + {0xa738c6bebb12d16c, 0xb428f8ac016561dc}, + {0xd106f86e69d785c7, 0xe13336d701beba53}, + {0x82a45b450226b39c, 0xecc0024661173474}, + {0xa34d721642b06084, 0x27f002d7f95d0191}, + {0xcc20ce9bd35c78a5, 0x31ec038df7b441f5}, + {0xff290242c83396ce, 0x7e67047175a15272}, + {0x9f79a169bd203e41, 0x0f0062c6e984d387}, + {0xc75809c42c684dd1, 0x52c07b78a3e60869}, + {0xf92e0c3537826145, 0xa7709a56ccdf8a83}, + {0x9bbcc7a142b17ccb, 0x88a66076400bb692}, + {0xc2abf989935ddbfe, 0x6acff893d00ea436}, + {0xf356f7ebf83552fe, 0x0583f6b8c4124d44}, + {0x98165af37b2153de, 0xc3727a337a8b704b}, + {0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5d}, + {0xeda2ee1c7064130c, 0x1162def06f79df74}, + {0x9485d4d1c63e8be7, 0x8addcb5645ac2ba9}, + {0xb9a74a0637ce2ee1, 0x6d953e2bd7173693}, + {0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0438}, + {0x910ab1d4db9914a0, 0x1d9c9892400a22a3}, + {0xb54d5e4a127f59c8, 0x2503beb6d00cab4c}, + {0xe2a0b5dc971f303a, 0x2e44ae64840fd61e}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xb10d8e1456105dad, 0x7425a83e872c5f48}, + {0xdd50f1996b947518, 0xd12f124e28f7771a}, + {0x8a5296ffe33cc92f, 0x82bd6b70d99aaa70}, + {0xace73cbfdc0bfb7b, 0x636cc64d1001550c}, + {0xd8210befd30efa5a, 0x3c47f7e05401aa4f}, + {0x8714a775e3e95c78, 0x65acfaec34810a72}, + {0xa8d9d1535ce3b396, 0x7f1839a741a14d0e}, + {0xd31045a8341ca07c, 0x1ede48111209a051}, + {0x83ea2b892091e44d, 0x934aed0aab460433}, + {0xa4e4b66b68b65d60, 0xf81da84d56178540}, + {0xce1de40642e3f4b9, 0x36251260ab9d668f}, + {0x80d2ae83e9ce78f3, 0xc1d72b7c6b42601a}, + {0xa1075a24e4421730, 0xb24cf65b8612f820}, + {0xc94930ae1d529cfc, 0xdee033f26797b628}, + {0xfb9b7cd9a4a7443c, 0x169840ef017da3b2}, + {0x9d412e0806e88aa5, 0x8e1f289560ee864f}, + {0xc491798a08a2ad4e, 0xf1a6f2bab92a27e3}, + {0xf5b5d7ec8acb58a2, 0xae10af696774b1dc}, + {0x9991a6f3d6bf1765, 0xacca6da1e0a8ef2a}, + {0xbff610b0cc6edd3f, 0x17fd090a58d32af4}, + {0xeff394dcff8a948e, 0xddfc4b4cef07f5b1}, + {0x95f83d0a1fb69cd9, 0x4abdaf101564f98f}, + {0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f2}, + {0xea53df5fd18d5513, 0x84c86189216dc5ee}, + {0x92746b9be2f8552c, 0x32fd3cf5b4e49bb5}, + {0xb7118682dbb66a77, 0x3fbc8c33221dc2a2}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0x8f05b1163ba6832d, 0x29cb4d87f2a7400f}, + {0xb2c71d5bca9023f8, 0x743e20e9ef511013}, + {0xdf78e4b2bd342cf6, 0x914da9246b255417}, + {0x8bab8eefb6409c1a, 0x1ad089b6c2f7548f}, + {0xae9672aba3d0c320, 0xa184ac2473b529b2}, + {0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741f}, + {0x8865899617fb1871, 0x7e2fa67c7a658893}, + {0xaa7eebfb9df9de8d, 0xddbb901b98feeab8}, + {0xd51ea6fa85785631, 0x552a74227f3ea566}, + {0x8533285c936b35de, 0xd53a88958f872760}, + {0xa67ff273b8460356, 0x8a892abaf368f138}, + {0xd01fef10a657842c, 0x2d2b7569b0432d86}, + {0x8213f56a67f6b29b, 0x9c3b29620e29fc74}, + {0xa298f2c501f45f42, 0x8349f3ba91b47b90}, + {0xcb3f2f7642717713, 0x241c70a936219a74}, + {0xfe0efb53d30dd4d7, 0xed238cd383aa0111}, + {0x9ec95d1463e8a506, 0xf4363804324a40ab}, + {0xc67bb4597ce2ce48, 0xb143c6053edcd0d6}, + {0xf81aa16fdc1b81da, 0xdd94b7868e94050b}, + {0x9b10a4e5e9913128, 0xca7cf2b4191c8327}, + {0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f1}, + {0xf24a01a73cf2dccf, 0xbc633b39673c8ced}, + {0x976e41088617ca01, 0xd5be0503e085d814}, + {0xbd49d14aa79dbc82, 0x4b2d8644d8a74e19}, + {0xec9c459d51852ba2, 0xddf8e7d60ed1219f}, + {0x93e1ab8252f33b45, 0xcabb90e5c942b504}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + {0xe7109bfba19c0c9d, 0x0cc512670a783ad5}, + {0x906a617d450187e2, 0x27fb2b80668b24c6}, + {0xb484f9dc9641e9da, 0xb1f9f660802dedf7}, + {0xe1a63853bbd26451, 0x5e7873f8a0396974}, + {0x8d07e33455637eb2, 0xdb0b487b6423e1e9}, + {0xb049dc016abc5e5f, 0x91ce1a9a3d2cda63}, + {0xdc5c5301c56b75f7, 0x7641a140cc7810fc}, + {0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9e}, + {0xac2820d9623bf429, 0x546345fa9fbdcd45}, + {0xd732290fbacaf133, 0xa97c177947ad4096}, + {0x867f59a9d4bed6c0, 0x49ed8eabcccc485e}, + {0xa81f301449ee8c70, 0x5c68f256bfff5a75}, + {0xd226fc195c6a2f8c, 0x73832eec6fff3112}, + {0x83585d8fd9c25db7, 0xc831fd53c5ff7eac}, + {0xa42e74f3d032f525, 0xba3e7ca8b77f5e56}, + {0xcd3a1230c43fb26f, 0x28ce1bd2e55f35ec}, + {0x80444b5e7aa7cf85, 0x7980d163cf5b81b4}, + {0xa0555e361951c366, 0xd7e105bcc3326220}, + {0xc86ab5c39fa63440, 0x8dd9472bf3fefaa8}, + {0xfa856334878fc150, 0xb14f98f6f0feb952}, + {0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d4}, + {0xc3b8358109e84f07, 0x0a862f80ec4700c9}, + {0xf4a642e14c6262c8, 0xcd27bb612758c0fb}, + {0x98e7e9cccfbd7dbd, 0x8038d51cb897789d}, + {0xbf21e44003acdd2c, 0xe0470a63e6bd56c4}, + {0xeeea5d5004981478, 0x1858ccfce06cac75}, + {0x95527a5202df0ccb, 0x0f37801e0c43ebc9}, + {0xbaa718e68396cffd, 0xd30560258f54e6bb}, + {0xe950df20247c83fd, 0x47c6b82ef32a206a}, + {0x91d28b7416cdd27e, 0x4cdc331d57fa5442}, + {0xb6472e511c81471d, 0xe0133fe4adf8e953}, + {0xe3d8f9e563a198e5, 0x58180fddd97723a7}, + {0x8e679c2f5e44ff8f, 0x570f09eaa7ea7649}, + {0xb201833b35d63f73, 0x2cd2cc6551e513db}, + {0xde81e40a034bcf4f, 0xf8077f7ea65e58d2}, + {0x8b112e86420f6191, 0xfb04afaf27faf783}, + {0xadd57a27d29339f6, 0x79c5db9af1f9b564}, + {0xd94ad8b1c7380874, 0x18375281ae7822bd}, + {0x87cec76f1c830548, 0x8f2293910d0b15b6}, + {0xa9c2794ae3a3c69a, 0xb2eb3875504ddb23}, + {0xd433179d9c8cb841, 0x5fa60692a46151ec}, + {0x849feec281d7f328, 0xdbc7c41ba6bcd334}, + {0xa5c7ea73224deff3, 0x12b9b522906c0801}, + {0xcf39e50feae16bef, 0xd768226b34870a01}, + {0x81842f29f2cce375, 0xe6a1158300d46641}, + {0xa1e53af46f801c53, 0x60495ae3c1097fd1}, + {0xca5e89b18b602368, 0x385bb19cb14bdfc5}, + {0xfcf62c1dee382c42, 0x46729e03dd9ed7b6}, + {0x9e19db92b4e31ba9, 0x6c07a2c26a8346d2}, + {0xc5a05277621be293, 0xc7098b7305241886}, + { 0xf70867153aa2db38, + 0xb8cbee4fc66d1ea8 } +#else + {0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7b}, + {0xce5d73ff402d98e3, 0xfb0a3d212dc81290}, + {0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481f}, + {0x86a8d39ef77164bc, 0xae5dff9c02033198}, + {0xd98ddaee19068c76, 0x3badd624dd9b0958}, + {0xafbd2350644eeacf, 0xe5d1929ef90898fb}, + {0x8df5efabc5979c8f, 0xca8d3ffa1ef463c2}, + {0xe55990879ddcaabd, 0xcc420a6a101d0516}, + {0xb94470938fa89bce, 0xf808e40e8d5b3e6a}, + {0x95a8637627989aad, 0xdde7001379a44aa9}, + {0xf1c90080baf72cb1, 0x5324c68b12dd6339}, + {0xc350000000000000, 0x0000000000000000}, + {0x9dc5ada82b70b59d, 0xf020000000000000}, + {0xfee50b7025c36a08, 0x02f236d04753d5b5}, + {0xcde6fd5e09abcf26, 0xed4c0226b55e6f87}, + {0xa6539930bf6bff45, 0x84db8346b786151d}, + {0x865b86925b9bc5c2, 0x0b8a2392ba45a9b3}, + {0xd910f7ff28069da4, 0x1b2ba1518094da05}, + {0xaf58416654a6babb, 0x387ac8d1970027b3}, + {0x8da471a9de737e24, 0x5ceaecfed289e5d3}, + {0xe4d5e82392a40515, 0x0fabaf3feaa5334b}, + {0xb8da1662e7b00a17, 0x3d6a751f3b936244}, + { 0x95527a5202df0ccb, + 0x0f37801e0c43ebc9 } +#endif + }; + +#if FMT_USE_FULL_CACHE_DRAGONBOX + return pow10_significands[k - float_info::min_k]; +#else + static constexpr const uint64_t powers_of_5_64[] = { + 0x0000000000000001, 0x0000000000000005, 0x0000000000000019, + 0x000000000000007d, 0x0000000000000271, 0x0000000000000c35, + 0x0000000000003d09, 0x000000000001312d, 0x000000000005f5e1, + 0x00000000001dcd65, 0x00000000009502f9, 0x0000000002e90edd, + 0x000000000e8d4a51, 0x0000000048c27395, 0x000000016bcc41e9, + 0x000000071afd498d, 0x0000002386f26fc1, 0x000000b1a2bc2ec5, + 0x000003782dace9d9, 0x00001158e460913d, 0x000056bc75e2d631, + 0x0001b1ae4d6e2ef5, 0x000878678326eac9, 0x002a5a058fc295ed, + 0x00d3c21bcecceda1, 0x0422ca8b0a00a425, 0x14adf4b7320334b9}; + + static const int compression_ratio = 27; + + // Compute base index. + int cache_index = (k - float_info::min_k) / compression_ratio; + int kb = cache_index * compression_ratio + float_info::min_k; + int offset = k - kb; + + // Get base cache. + uint128_fallback base_cache = pow10_significands[cache_index]; + if (offset == 0) return base_cache; + + // Compute the required amount of bit-shift. + int alpha = floor_log2_pow10(kb + offset) - floor_log2_pow10(kb) - offset; + FMT_ASSERT(alpha > 0 && alpha < 64, "shifting error detected"); + + // Try to recover the real cache. + uint64_t pow5 = powers_of_5_64[offset]; + uint128_fallback recovered_cache = umul128(base_cache.high(), pow5); + uint128_fallback middle_low = umul128(base_cache.low(), pow5); + + recovered_cache += middle_low.high(); + + uint64_t high_to_middle = recovered_cache.high() << (64 - alpha); + uint64_t middle_to_low = recovered_cache.low() << (64 - alpha); + + recovered_cache = + uint128_fallback{(recovered_cache.low() >> alpha) | high_to_middle, + ((middle_low.low() >> alpha) | middle_to_low)}; + FMT_ASSERT(recovered_cache.low() + 1 != 0, ""); + return {recovered_cache.high(), recovered_cache.low() + 1}; +#endif + } + + struct compute_mul_result { + carrier_uint result; + bool is_integer; + }; + struct compute_mul_parity_result { + bool parity; + bool is_integer; + }; + + static compute_mul_result compute_mul( + carrier_uint u, const cache_entry_type& cache) noexcept { + auto r = umul192_upper128(u, cache); + return {r.high(), r.low() == 0}; + } + + static uint32_t compute_delta(cache_entry_type const& cache, + int beta) noexcept { + return static_cast(cache.high() >> (64 - 1 - beta)); + } + + static compute_mul_parity_result compute_mul_parity( + carrier_uint two_f, const cache_entry_type& cache, int beta) noexcept { + FMT_ASSERT(beta >= 1, ""); + FMT_ASSERT(beta < 64, ""); + + auto r = umul192_lower128(two_f, cache); + return {((r.high() >> (64 - beta)) & 1) != 0, + ((r.high() << beta) | (r.low() >> (64 - beta))) == 0}; + } + + static carrier_uint compute_left_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return (cache.high() - + (cache.high() >> (num_significand_bits() + 2))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static carrier_uint compute_right_endpoint_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return (cache.high() + + (cache.high() >> (num_significand_bits() + 1))) >> + (64 - num_significand_bits() - 1 - beta); + } + + static carrier_uint compute_round_up_for_shorter_interval_case( + const cache_entry_type& cache, int beta) noexcept { + return ((cache.high() >> (64 - num_significand_bits() - 2 - beta)) + + 1) / + 2; + } +}; + +// Various integer checks +template +bool is_left_endpoint_integer_shorter_interval(int exponent) noexcept { + const int case_shorter_interval_left_endpoint_lower_threshold = 2; + const int case_shorter_interval_left_endpoint_upper_threshold = 3; + return exponent >= case_shorter_interval_left_endpoint_lower_threshold && + exponent <= case_shorter_interval_left_endpoint_upper_threshold; +} + +// Remove trailing zeros from n and return the number of zeros removed (float) +FMT_INLINE int remove_trailing_zeros(uint32_t& n) noexcept { + FMT_ASSERT(n != 0, ""); + const uint32_t mod_inv_5 = 0xcccccccd; + const uint32_t mod_inv_25 = mod_inv_5 * mod_inv_5; + + int s = 0; + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + + return s; +} + +// Removes trailing zeros and returns the number of zeros removed (double) +FMT_INLINE int remove_trailing_zeros(uint64_t& n) noexcept { + FMT_ASSERT(n != 0, ""); + + // This magic number is ceil(2^90 / 10^8). + constexpr uint64_t magic_number = 12379400392853802749ull; + auto nm = umul128(n, magic_number); + + // Is n is divisible by 10^8? + if ((nm.high() & ((1ull << (90 - 64)) - 1)) == 0 && nm.low() < magic_number) { + // If yes, work with the quotient. + auto n32 = static_cast(nm.high() >> (90 - 64)); + + const uint32_t mod_inv_5 = 0xcccccccd; + const uint32_t mod_inv_25 = mod_inv_5 * mod_inv_5; + + int s = 8; + while (true) { + auto q = rotr(n32 * mod_inv_25, 2); + if (q > max_value() / 100) break; + n32 = q; + s += 2; + } + auto q = rotr(n32 * mod_inv_5, 1); + if (q <= max_value() / 10) { + n32 = q; + s |= 1; + } + + n = n32; + return s; + } + + // If n is not divisible by 10^8, work with n itself. + const uint64_t mod_inv_5 = 0xcccccccccccccccd; + const uint64_t mod_inv_25 = mod_inv_5 * mod_inv_5; + + int s = 0; + while (true) { + auto q = rotr(n * mod_inv_25, 2); + if (q > max_value() / 100) break; + n = q; + s += 2; + } + auto q = rotr(n * mod_inv_5, 1); + if (q <= max_value() / 10) { + n = q; + s |= 1; + } + + return s; +} + +// The main algorithm for shorter interval case +template +FMT_INLINE decimal_fp shorter_interval_case(int exponent) noexcept { + decimal_fp ret_value; + // Compute k and beta + const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute xi and zi + using cache_entry_type = typename cache_accessor::cache_entry_type; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + + auto xi = cache_accessor::compute_left_endpoint_for_shorter_interval_case( + cache, beta); + auto zi = cache_accessor::compute_right_endpoint_for_shorter_interval_case( + cache, beta); + + // If the left endpoint is not an integer, increase it + if (!is_left_endpoint_integer_shorter_interval(exponent)) ++xi; + + // Try bigger divisor + ret_value.significand = zi / 10; + + // If succeed, remove trailing zeros if necessary and return + if (ret_value.significand * 10 >= xi) { + ret_value.exponent = minus_k + 1; + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + } + + // Otherwise, compute the round-up of y + ret_value.significand = + cache_accessor::compute_round_up_for_shorter_interval_case(cache, + beta); + ret_value.exponent = minus_k; + + // When tie occurs, choose one of them according to the rule + if (exponent >= float_info::shorter_interval_tie_lower_threshold && + exponent <= float_info::shorter_interval_tie_upper_threshold) { + ret_value.significand = ret_value.significand % 2 == 0 + ? ret_value.significand + : ret_value.significand - 1; + } else if (ret_value.significand < xi) { + ++ret_value.significand; + } + return ret_value; +} + +template decimal_fp to_decimal(T x) noexcept { + // Step 1: integer promotion & Schubfach multiplier calculation. + + using carrier_uint = typename float_info::carrier_uint; + using cache_entry_type = typename cache_accessor::cache_entry_type; + auto br = bit_cast(x); + + // Extract significand bits and exponent bits. + const carrier_uint significand_mask = + (static_cast(1) << num_significand_bits()) - 1; + carrier_uint significand = (br & significand_mask); + int exponent = + static_cast((br & exponent_mask()) >> num_significand_bits()); + + if (exponent != 0) { // Check if normal. + exponent -= exponent_bias() + num_significand_bits(); + + // Shorter interval case; proceed like Schubfach. + // In fact, when exponent == 1 and significand == 0, the interval is + // regular. However, it can be shown that the end-results are anyway same. + if (significand == 0) return shorter_interval_case(exponent); + + significand |= (static_cast(1) << num_significand_bits()); + } else { + // Subnormal case; the interval is always regular. + if (significand == 0) return {0, 0}; + exponent = + std::numeric_limits::min_exponent - num_significand_bits() - 1; + } + + const bool include_left_endpoint = (significand % 2 == 0); + const bool include_right_endpoint = include_left_endpoint; + + // Compute k and beta. + const int minus_k = floor_log10_pow2(exponent) - float_info::kappa; + const cache_entry_type cache = cache_accessor::get_cached_power(-minus_k); + const int beta = exponent + floor_log2_pow10(-minus_k); + + // Compute zi and deltai. + // 10^kappa <= deltai < 10^(kappa + 1) + const uint32_t deltai = cache_accessor::compute_delta(cache, beta); + const carrier_uint two_fc = significand << 1; + + // For the case of binary32, the result of integer check is not correct for + // 29711844 * 2^-82 + // = 6.1442653300000000008655037797566933477355632930994033813476... * 10^-18 + // and 29711844 * 2^-81 + // = 1.2288530660000000001731007559513386695471126586198806762695... * 10^-17, + // and they are the unique counterexamples. However, since 29711844 is even, + // this does not cause any problem for the endpoints calculations; it can only + // cause a problem when we need to perform integer check for the center. + // Fortunately, with these inputs, that branch is never executed, so we are + // fine. + const typename cache_accessor::compute_mul_result z_mul = + cache_accessor::compute_mul((two_fc | 1) << beta, cache); + + // Step 2: Try larger divisor; remove trailing zeros if necessary. + + // Using an upper bound on zi, we might be able to optimize the division + // better than the compiler; we are computing zi / big_divisor here. + decimal_fp ret_value; + ret_value.significand = divide_by_10_to_kappa_plus_1(z_mul.result); + uint32_t r = static_cast(z_mul.result - float_info::big_divisor * + ret_value.significand); + + if (r < deltai) { + // Exclude the right endpoint if necessary. + if (r == 0 && z_mul.is_integer && !include_right_endpoint) { + --ret_value.significand; + r = float_info::big_divisor; + goto small_divisor_case_label; + } + } else if (r > deltai) { + goto small_divisor_case_label; + } else { + // r == deltai; compare fractional parts. + const carrier_uint two_fl = two_fc - 1; + + if (!include_left_endpoint || + exponent < float_info::case_fc_pm_half_lower_threshold || + exponent > float_info::divisibility_check_by_5_threshold) { + // If the left endpoint is not included, the condition for + // success is z^(f) < delta^(f) (odd parity). + // Otherwise, the inequalities on exponent ensure that + // x is not an integer, so if z^(f) >= delta^(f) (even parity), we in fact + // have strict inequality. + if (!cache_accessor::compute_mul_parity(two_fl, cache, beta).parity) { + goto small_divisor_case_label; + } + } else { + const typename cache_accessor::compute_mul_parity_result x_mul = + cache_accessor::compute_mul_parity(two_fl, cache, beta); + if (!x_mul.parity && !x_mul.is_integer) { + goto small_divisor_case_label; + } + } + } + ret_value.exponent = minus_k + float_info::kappa + 1; + + // We may need to remove trailing zeros. + ret_value.exponent += remove_trailing_zeros(ret_value.significand); + return ret_value; + + // Step 3: Find the significand with the smaller divisor. + +small_divisor_case_label: + ret_value.significand *= 10; + ret_value.exponent = minus_k + float_info::kappa; + + uint32_t dist = r - (deltai / 2) + (float_info::small_divisor / 2); + const bool approx_y_parity = + ((dist ^ (float_info::small_divisor / 2)) & 1) != 0; + + // Is dist divisible by 10^kappa? + const bool divisible_by_small_divisor = + check_divisibility_and_divide_by_pow10::kappa>(dist); + + // Add dist / 10^kappa to the significand. + ret_value.significand += dist; + + if (!divisible_by_small_divisor) return ret_value; + + // Check z^(f) >= epsilon^(f). + // We have either yi == zi - epsiloni or yi == (zi - epsiloni) - 1, + // where yi == zi - epsiloni if and only if z^(f) >= epsilon^(f). + // Since there are only 2 possibilities, we only need to care about the + // parity. Also, zi and r should have the same parity since the divisor + // is an even number. + const auto y_mul = cache_accessor::compute_mul_parity(two_fc, cache, beta); + + // If z^(f) >= epsilon^(f), we might have a tie when z^(f) == epsilon^(f), + // or equivalently, when y is an integer. + if (y_mul.parity != approx_y_parity) + --ret_value.significand; + else if (y_mul.is_integer && ret_value.significand % 2 != 0) + --ret_value.significand; + return ret_value; +} +} // namespace dragonbox + +#ifdef _MSC_VER +FMT_FUNC auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...) + -> int { + auto args = va_list(); + va_start(args, fmt); + int result = vsnprintf_s(buf, size, _TRUNCATE, fmt, args); + va_end(args); + return result; +} +#endif +} // namespace detail + +template <> struct formatter { + FMT_CONSTEXPR auto parse(format_parse_context& ctx) + -> format_parse_context::iterator { + return ctx.begin(); + } + + template + auto format(const detail::bigint& n, FormatContext& ctx) const -> + typename FormatContext::iterator { + auto out = ctx.out(); + bool first = true; + for (auto i = n.bigits_.size(); i > 0; --i) { + auto value = n.bigits_[i - 1u]; + if (first) { + out = format_to(out, FMT_STRING("{:x}"), value); + first = false; + continue; + } + out = format_to(out, FMT_STRING("{:08x}"), value); + } + if (n.exp_ > 0) + out = format_to(out, FMT_STRING("p{}"), + n.exp_ * detail::bigint::bigit_bits); + return out; + } +}; + +FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { + for_each_codepoint(s, [this](uint32_t cp, string_view) { + if (cp == invalid_code_point) log_error("invalid utf8"); + if (cp <= 0xFFFF) { + buffer_.push_back(static_cast(cp)); + } else { + cp -= 0x10000; + buffer_.push_back(static_cast(0xD800 + (cp >> 10))); + buffer_.push_back(static_cast(0xDC00 + (cp & 0x3FF))); + } + return true; + }); + buffer_.push_back(0); +} + +FMT_FUNC void format_system_error(detail::buffer& out, int error_code, + const char* message) noexcept { + FMT_TRY { + auto ec = std::error_code(error_code, std::generic_category()); + write(std::back_inserter(out), std::system_error(ec, message).what()); + return; + } + FMT_CATCH(...) {} + format_error_code(out, error_code, message); +} + +FMT_FUNC void report_system_error(int error_code, + const char* message) noexcept { + report_error(format_system_error, error_code, message); +} + +FMT_FUNC std::string vformat(string_view fmt, format_args args) { + // Don't optimize the "{}" case to keep the binary size small and because it + // can be better optimized in fmt::format anyway. + auto buffer = memory_buffer(); + detail::vformat_to(buffer, fmt, args); + return to_string(buffer); +} + +#ifdef _WIN32 +namespace detail { +using dword = conditional_t; +extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // + void*, const void*, dword, dword*, void*); +} // namespace detail +#endif + +namespace detail { +FMT_FUNC void print(std::FILE* f, string_view text) { +#ifdef _WIN32 + auto fd = _fileno(f); + if (_isatty(fd)) { + detail::utf8_to_utf16 u16(string_view(text.data(), text.size())); + auto written = detail::dword(); + if (detail::WriteConsoleW(reinterpret_cast(_get_osfhandle(fd)), + u16.c_str(), static_cast(u16.size()), + &written, nullptr)) { + return; + } + // Fallback to fwrite on failure. It can happen if the output has been + // redirected to NUL. + } +#endif + //detail::fwrite_fully(text.data(), 1, text.size(), f); + log_info(text.data()); +} +} // namespace detail + +FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, args); + buffer.push_back(L'\0'); + log_info(buffer.data()); +} + +#ifdef _WIN32 +// Print assuming legacy (non-Unicode) encoding. +FMT_FUNC void detail::vprint_mojibake(std::FILE* f, string_view format_str, + format_args args) { + memory_buffer buffer; + detail::vformat_to(buffer, format_str, + basic_format_args>(args)); + fwrite_fully(buffer.data(), 1, buffer.size(), f); +} +#endif + +FMT_FUNC void vprint(string_view format_str, format_args args) { + vprint(stdout, format_str, args); +} + +namespace detail { + +struct singleton { + unsigned char upper; + unsigned char lower_count; +}; + +inline auto is_printable(uint16_t x, const singleton* singletons, + size_t singletons_size, + const unsigned char* singleton_lowers, + const unsigned char* normal, size_t normal_size) + -> bool { + auto upper = x >> 8; + auto lower_start = 0; + for (size_t i = 0; i < singletons_size; ++i) { + auto s = singletons[i]; + auto lower_end = lower_start + s.lower_count; + if (upper < s.upper) break; + if (upper == s.upper) { + for (auto j = lower_start; j < lower_end; ++j) { + if (singleton_lowers[j] == (x & 0xff)) return false; + } + } + lower_start = lower_end; + } + + auto xsigned = static_cast(x); + auto current = true; + for (size_t i = 0; i < normal_size; ++i) { + auto v = static_cast(normal[i]); + auto len = (v & 0x80) != 0 ? (v & 0x7f) << 8 | normal[++i] : v; + xsigned -= len; + if (xsigned < 0) break; + current = !current; + } + return current; +} + +// This code is generated by support/printable.py. +FMT_FUNC auto is_printable(uint32_t cp) -> bool { + static constexpr singleton singletons0[] = { + {0x00, 1}, {0x03, 5}, {0x05, 6}, {0x06, 3}, {0x07, 6}, {0x08, 8}, + {0x09, 17}, {0x0a, 28}, {0x0b, 25}, {0x0c, 20}, {0x0d, 16}, {0x0e, 13}, + {0x0f, 4}, {0x10, 3}, {0x12, 18}, {0x13, 9}, {0x16, 1}, {0x17, 5}, + {0x18, 2}, {0x19, 3}, {0x1a, 7}, {0x1c, 2}, {0x1d, 1}, {0x1f, 22}, + {0x20, 3}, {0x2b, 3}, {0x2c, 2}, {0x2d, 11}, {0x2e, 1}, {0x30, 3}, + {0x31, 2}, {0x32, 1}, {0xa7, 2}, {0xa9, 2}, {0xaa, 4}, {0xab, 8}, + {0xfa, 2}, {0xfb, 5}, {0xfd, 4}, {0xfe, 3}, {0xff, 9}, + }; + static constexpr unsigned char singletons0_lower[] = { + 0xad, 0x78, 0x79, 0x8b, 0x8d, 0xa2, 0x30, 0x57, 0x58, 0x8b, 0x8c, 0x90, + 0x1c, 0x1d, 0xdd, 0x0e, 0x0f, 0x4b, 0x4c, 0xfb, 0xfc, 0x2e, 0x2f, 0x3f, + 0x5c, 0x5d, 0x5f, 0xb5, 0xe2, 0x84, 0x8d, 0x8e, 0x91, 0x92, 0xa9, 0xb1, + 0xba, 0xbb, 0xc5, 0xc6, 0xc9, 0xca, 0xde, 0xe4, 0xe5, 0xff, 0x00, 0x04, + 0x11, 0x12, 0x29, 0x31, 0x34, 0x37, 0x3a, 0x3b, 0x3d, 0x49, 0x4a, 0x5d, + 0x84, 0x8e, 0x92, 0xa9, 0xb1, 0xb4, 0xba, 0xbb, 0xc6, 0xca, 0xce, 0xcf, + 0xe4, 0xe5, 0x00, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x3b, 0x45, 0x46, 0x49, 0x4a, 0x5e, 0x64, 0x65, 0x84, 0x91, 0x9b, 0x9d, + 0xc9, 0xce, 0xcf, 0x0d, 0x11, 0x29, 0x45, 0x49, 0x57, 0x64, 0x65, 0x8d, + 0x91, 0xa9, 0xb4, 0xba, 0xbb, 0xc5, 0xc9, 0xdf, 0xe4, 0xe5, 0xf0, 0x0d, + 0x11, 0x45, 0x49, 0x64, 0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5, + 0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6, 0xbe, 0xbf, 0xc5, 0xc7, + 0xce, 0xcf, 0xda, 0xdb, 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, + 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f, 0xb1, 0xb6, 0xb7, + 0xbf, 0xc1, 0xc6, 0xc7, 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, + 0xfe, 0xff, 0x80, 0x0d, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x0f, 0x1f, 0x6e, + 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae, 0xaf, 0xbb, 0xbc, 0xfa, 0x16, + 0x17, 0x1e, 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e, 0x7e, + 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, + 0x74, 0x75, 0x96, 0x2f, 0x5f, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, + 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30, 0x8f, 0x1f, 0xc0, + 0xc1, 0xce, 0xff, 0x4e, 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, + 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42, 0x45, 0x90, 0x91, + 0xfe, 0xff, 0x53, 0x67, 0x75, 0xc8, 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, + 0xfe, 0xff, + }; + static constexpr singleton singletons1[] = { + {0x00, 6}, {0x01, 1}, {0x03, 1}, {0x04, 2}, {0x08, 8}, {0x09, 2}, + {0x0a, 5}, {0x0b, 2}, {0x0e, 4}, {0x10, 1}, {0x11, 2}, {0x12, 5}, + {0x13, 17}, {0x14, 1}, {0x15, 2}, {0x17, 2}, {0x19, 13}, {0x1c, 5}, + {0x1d, 8}, {0x24, 1}, {0x6a, 3}, {0x6b, 2}, {0xbc, 2}, {0xd1, 2}, + {0xd4, 12}, {0xd5, 9}, {0xd6, 2}, {0xd7, 2}, {0xda, 1}, {0xe0, 5}, + {0xe1, 2}, {0xe8, 2}, {0xee, 32}, {0xf0, 4}, {0xf8, 2}, {0xf9, 2}, + {0xfa, 2}, {0xfb, 1}, + }; + static constexpr unsigned char singletons1_lower[] = { + 0x0c, 0x27, 0x3b, 0x3e, 0x4e, 0x4f, 0x8f, 0x9e, 0x9e, 0x9f, 0x06, 0x07, + 0x09, 0x36, 0x3d, 0x3e, 0x56, 0xf3, 0xd0, 0xd1, 0x04, 0x14, 0x18, 0x36, + 0x37, 0x56, 0x57, 0x7f, 0xaa, 0xae, 0xaf, 0xbd, 0x35, 0xe0, 0x12, 0x87, + 0x89, 0x8e, 0x9e, 0x04, 0x0d, 0x0e, 0x11, 0x12, 0x29, 0x31, 0x34, 0x3a, + 0x45, 0x46, 0x49, 0x4a, 0x4e, 0x4f, 0x64, 0x65, 0x5c, 0xb6, 0xb7, 0x1b, + 0x1c, 0x07, 0x08, 0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8, 0xa9, + 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8, 0x07, 0x0a, 0x3b, 0x3e, 0x66, + 0x69, 0x8f, 0x92, 0x6f, 0x5f, 0xee, 0xef, 0x5a, 0x62, 0x9a, 0x9b, 0x27, + 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, + 0xc4, 0x06, 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, + 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e, 0x3f, 0xc5, 0xc6, + 0x04, 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, + 0x50, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, + 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, + 0xae, 0xaf, 0x79, 0xcc, 0x6e, 0x6f, 0x93, + }; + static constexpr unsigned char normal0[] = { + 0x00, 0x20, 0x5f, 0x22, 0x82, 0xdf, 0x04, 0x82, 0x44, 0x08, 0x1b, 0x04, + 0x06, 0x11, 0x81, 0xac, 0x0e, 0x80, 0xab, 0x35, 0x28, 0x0b, 0x80, 0xe0, + 0x03, 0x19, 0x08, 0x01, 0x04, 0x2f, 0x04, 0x34, 0x04, 0x07, 0x03, 0x01, + 0x07, 0x06, 0x07, 0x11, 0x0a, 0x50, 0x0f, 0x12, 0x07, 0x55, 0x07, 0x03, + 0x04, 0x1c, 0x0a, 0x09, 0x03, 0x08, 0x03, 0x07, 0x03, 0x02, 0x03, 0x03, + 0x03, 0x0c, 0x04, 0x05, 0x03, 0x0b, 0x06, 0x01, 0x0e, 0x15, 0x05, 0x3a, + 0x03, 0x11, 0x07, 0x06, 0x05, 0x10, 0x07, 0x57, 0x07, 0x02, 0x07, 0x15, + 0x0d, 0x50, 0x04, 0x43, 0x03, 0x2d, 0x03, 0x01, 0x04, 0x11, 0x06, 0x0f, + 0x0c, 0x3a, 0x04, 0x1d, 0x25, 0x5f, 0x20, 0x6d, 0x04, 0x6a, 0x25, 0x80, + 0xc8, 0x05, 0x82, 0xb0, 0x03, 0x1a, 0x06, 0x82, 0xfd, 0x03, 0x59, 0x07, + 0x15, 0x0b, 0x17, 0x09, 0x14, 0x0c, 0x14, 0x0c, 0x6a, 0x06, 0x0a, 0x06, + 0x1a, 0x06, 0x59, 0x07, 0x2b, 0x05, 0x46, 0x0a, 0x2c, 0x04, 0x0c, 0x04, + 0x01, 0x03, 0x31, 0x0b, 0x2c, 0x04, 0x1a, 0x06, 0x0b, 0x03, 0x80, 0xac, + 0x06, 0x0a, 0x06, 0x21, 0x3f, 0x4c, 0x04, 0x2d, 0x03, 0x74, 0x08, 0x3c, + 0x03, 0x0f, 0x03, 0x3c, 0x07, 0x38, 0x08, 0x2b, 0x05, 0x82, 0xff, 0x11, + 0x18, 0x08, 0x2f, 0x11, 0x2d, 0x03, 0x20, 0x10, 0x21, 0x0f, 0x80, 0x8c, + 0x04, 0x82, 0x97, 0x19, 0x0b, 0x15, 0x88, 0x94, 0x05, 0x2f, 0x05, 0x3b, + 0x07, 0x02, 0x0e, 0x18, 0x09, 0x80, 0xb3, 0x2d, 0x74, 0x0c, 0x80, 0xd6, + 0x1a, 0x0c, 0x05, 0x80, 0xff, 0x05, 0x80, 0xdf, 0x0c, 0xee, 0x0d, 0x03, + 0x84, 0x8d, 0x03, 0x37, 0x09, 0x81, 0x5c, 0x14, 0x80, 0xb8, 0x08, 0x80, + 0xcb, 0x2a, 0x38, 0x03, 0x0a, 0x06, 0x38, 0x08, 0x46, 0x08, 0x0c, 0x06, + 0x74, 0x0b, 0x1e, 0x03, 0x5a, 0x04, 0x59, 0x09, 0x80, 0x83, 0x18, 0x1c, + 0x0a, 0x16, 0x09, 0x4c, 0x04, 0x80, 0x8a, 0x06, 0xab, 0xa4, 0x0c, 0x17, + 0x04, 0x31, 0xa1, 0x04, 0x81, 0xda, 0x26, 0x07, 0x0c, 0x05, 0x05, 0x80, + 0xa5, 0x11, 0x81, 0x6d, 0x10, 0x78, 0x28, 0x2a, 0x06, 0x4c, 0x04, 0x80, + 0x8d, 0x04, 0x80, 0xbe, 0x03, 0x1b, 0x03, 0x0f, 0x0d, + }; + static constexpr unsigned char normal1[] = { + 0x5e, 0x22, 0x7b, 0x05, 0x03, 0x04, 0x2d, 0x03, 0x66, 0x03, 0x01, 0x2f, + 0x2e, 0x80, 0x82, 0x1d, 0x03, 0x31, 0x0f, 0x1c, 0x04, 0x24, 0x09, 0x1e, + 0x05, 0x2b, 0x05, 0x44, 0x04, 0x0e, 0x2a, 0x80, 0xaa, 0x06, 0x24, 0x04, + 0x24, 0x04, 0x28, 0x08, 0x34, 0x0b, 0x01, 0x80, 0x90, 0x81, 0x37, 0x09, + 0x16, 0x0a, 0x08, 0x80, 0x98, 0x39, 0x03, 0x63, 0x08, 0x09, 0x30, 0x16, + 0x05, 0x21, 0x03, 0x1b, 0x05, 0x01, 0x40, 0x38, 0x04, 0x4b, 0x05, 0x2f, + 0x04, 0x0a, 0x07, 0x09, 0x07, 0x40, 0x20, 0x27, 0x04, 0x0c, 0x09, 0x36, + 0x03, 0x3a, 0x05, 0x1a, 0x07, 0x04, 0x0c, 0x07, 0x50, 0x49, 0x37, 0x33, + 0x0d, 0x33, 0x07, 0x2e, 0x08, 0x0a, 0x81, 0x26, 0x52, 0x4e, 0x28, 0x08, + 0x2a, 0x56, 0x1c, 0x14, 0x17, 0x09, 0x4e, 0x04, 0x1e, 0x0f, 0x43, 0x0e, + 0x19, 0x07, 0x0a, 0x06, 0x48, 0x08, 0x27, 0x09, 0x75, 0x0b, 0x3f, 0x41, + 0x2a, 0x06, 0x3b, 0x05, 0x0a, 0x06, 0x51, 0x06, 0x01, 0x05, 0x10, 0x03, + 0x05, 0x80, 0x8b, 0x62, 0x1e, 0x48, 0x08, 0x0a, 0x80, 0xa6, 0x5e, 0x22, + 0x45, 0x0b, 0x0a, 0x06, 0x0d, 0x13, 0x39, 0x07, 0x0a, 0x36, 0x2c, 0x04, + 0x10, 0x80, 0xc0, 0x3c, 0x64, 0x53, 0x0c, 0x48, 0x09, 0x0a, 0x46, 0x45, + 0x1b, 0x48, 0x08, 0x53, 0x1d, 0x39, 0x81, 0x07, 0x46, 0x0a, 0x1d, 0x03, + 0x47, 0x49, 0x37, 0x03, 0x0e, 0x08, 0x0a, 0x06, 0x39, 0x07, 0x0a, 0x81, + 0x36, 0x19, 0x80, 0xb7, 0x01, 0x0f, 0x32, 0x0d, 0x83, 0x9b, 0x66, 0x75, + 0x0b, 0x80, 0xc4, 0x8a, 0xbc, 0x84, 0x2f, 0x8f, 0xd1, 0x82, 0x47, 0xa1, + 0xb9, 0x82, 0x39, 0x07, 0x2a, 0x04, 0x02, 0x60, 0x26, 0x0a, 0x46, 0x0a, + 0x28, 0x05, 0x13, 0x82, 0xb0, 0x5b, 0x65, 0x4b, 0x04, 0x39, 0x07, 0x11, + 0x40, 0x05, 0x0b, 0x02, 0x0e, 0x97, 0xf8, 0x08, 0x84, 0xd6, 0x2a, 0x09, + 0xa2, 0xf7, 0x81, 0x1f, 0x31, 0x03, 0x11, 0x04, 0x08, 0x81, 0x8c, 0x89, + 0x04, 0x6b, 0x05, 0x0d, 0x03, 0x09, 0x07, 0x10, 0x93, 0x60, 0x80, 0xf6, + 0x0a, 0x73, 0x08, 0x6e, 0x17, 0x46, 0x80, 0x9a, 0x14, 0x0c, 0x57, 0x09, + 0x19, 0x80, 0x87, 0x81, 0x47, 0x03, 0x85, 0x42, 0x0f, 0x15, 0x85, 0x50, + 0x2b, 0x80, 0xd5, 0x2d, 0x03, 0x1a, 0x04, 0x02, 0x81, 0x70, 0x3a, 0x05, + 0x01, 0x85, 0x00, 0x80, 0xd7, 0x29, 0x4c, 0x04, 0x0a, 0x04, 0x02, 0x83, + 0x11, 0x44, 0x4c, 0x3d, 0x80, 0xc2, 0x3c, 0x06, 0x01, 0x04, 0x55, 0x05, + 0x1b, 0x34, 0x02, 0x81, 0x0e, 0x2c, 0x04, 0x64, 0x0c, 0x56, 0x0a, 0x80, + 0xae, 0x38, 0x1d, 0x0d, 0x2c, 0x04, 0x09, 0x07, 0x02, 0x0e, 0x06, 0x80, + 0x9a, 0x83, 0xd8, 0x08, 0x0d, 0x03, 0x0d, 0x03, 0x74, 0x0c, 0x59, 0x07, + 0x0c, 0x14, 0x0c, 0x04, 0x38, 0x08, 0x0a, 0x06, 0x28, 0x08, 0x22, 0x4e, + 0x81, 0x54, 0x0c, 0x15, 0x03, 0x03, 0x05, 0x07, 0x09, 0x19, 0x07, 0x07, + 0x09, 0x03, 0x0d, 0x07, 0x29, 0x80, 0xcb, 0x25, 0x0a, 0x84, 0x06, + }; + auto lower = static_cast(cp); + if (cp < 0x10000) { + return is_printable(lower, singletons0, + sizeof(singletons0) / sizeof(*singletons0), + singletons0_lower, normal0, sizeof(normal0)); + } + if (cp < 0x20000) { + return is_printable(lower, singletons1, + sizeof(singletons1) / sizeof(*singletons1), + singletons1_lower, normal1, sizeof(normal1)); + } + if (0x2a6de <= cp && cp < 0x2a700) return false; + if (0x2b735 <= cp && cp < 0x2b740) return false; + if (0x2b81e <= cp && cp < 0x2b820) return false; + if (0x2cea2 <= cp && cp < 0x2ceb0) return false; + if (0x2ebe1 <= cp && cp < 0x2f800) return false; + if (0x2fa1e <= cp && cp < 0x30000) return false; + if (0x3134b <= cp && cp < 0xe0100) return false; + if (0xe01f0 <= cp && cp < 0x110000) return false; + return cp < 0x110000; +} + +} // namespace detail + +FMT_END_NAMESPACE + +#endif // FMT_FORMAT_INL_H_ diff --git a/itemzflow/include/fmt/format.h b/itemzflow/include/fmt/format.h new file mode 100644 index 0000000..c171857 --- /dev/null +++ b/itemzflow/include/fmt/format.h @@ -0,0 +1,4192 @@ +/* + Formatting library for C++ + + Copyright (c) 2012 - present, Victor Zverovich + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + --- Optional exception to the license --- + + As an exception, if, as a result of your compiling your source code, portions + of this Software are embedded into a machine-executable object form of such + source code, you may redistribute such embedded portions in such object form + without including the above copyright and permission notices. + */ + +#ifndef FMT_FORMAT_H_ +#define FMT_FORMAT_H_ + +#include // std::signbit +#include // uint32_t +#include // std::memcpy +#include // std::numeric_limits +#include // std::uninitialized_copy +#include // std::runtime_error +#include // std::system_error + +#ifdef __cpp_lib_bit_cast +# include // std::bitcast +#endif + +#include "core.h" + +#if FMT_GCC_VERSION +# define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) +#else +# define FMT_GCC_VISIBILITY_HIDDEN +#endif + +#ifdef __NVCC__ +# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__) +#else +# define FMT_CUDA_VERSION 0 +#endif + +#ifdef __has_builtin +# define FMT_HAS_BUILTIN(x) __has_builtin(x) +#else +# define FMT_HAS_BUILTIN(x) 0 +#endif + +#if FMT_GCC_VERSION || FMT_CLANG_VERSION +# define FMT_NOINLINE __attribute__((noinline)) +#else +# define FMT_NOINLINE +#endif + +#if FMT_MSC_VERSION +# define FMT_MSC_DEFAULT = default +#else +# define FMT_MSC_DEFAULT +#endif + +#ifndef FMT_THROW +# if FMT_EXCEPTIONS +# if FMT_MSC_VERSION || defined(__NVCC__) +FMT_BEGIN_NAMESPACE +namespace detail { +template inline void do_throw(const Exception& x) { + // Silence unreachable code warnings in MSVC and NVCC because these + // are nearly impossible to fix in a generic code. + volatile bool b = true; + if (b) throw x; +} +} // namespace detail +FMT_END_NAMESPACE +# define FMT_THROW(x) detail::do_throw(x) +# else +# define FMT_THROW(x) catch(x) +# endif +# else +# define FMT_THROW(x) \ + do { \ + FMT_ASSERT(false, (x).what()); \ + } while (false) +# endif +#endif + +#if FMT_EXCEPTIONS +# define FMT_TRY try +# define FMT_CATCH(x) catch (x) +#else +# define FMT_TRY if (true) +# define FMT_CATCH(x) if (false) +#endif + +#ifndef FMT_MAYBE_UNUSED +# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) +# define FMT_MAYBE_UNUSED [[maybe_unused]] +# else +# define FMT_MAYBE_UNUSED +# endif +#endif + +#ifndef FMT_USE_USER_DEFINED_LITERALS +// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. +# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \ + FMT_MSC_VERSION >= 1900) && \ + (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) +# define FMT_USE_USER_DEFINED_LITERALS 1 +# else +# define FMT_USE_USER_DEFINED_LITERALS 0 +# endif +#endif + +// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of +// integer formatter template instantiations to just one by only using the +// largest integer type. This results in a reduction in binary size but will +// cause a decrease in integer formatting performance. +#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) +# define FMT_REDUCE_INT_INSTANTIATIONS 0 +#endif + +// __builtin_clz is broken in clang with Microsoft CodeGen: +// https://github.com/fmtlib/fmt/issues/519. +#if !FMT_MSC_VERSION +# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION +# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) +# endif +#endif + +// __builtin_ctz is broken in Intel Compiler Classic on Windows: +// https://github.com/fmtlib/fmt/issues/2510. +#ifndef __ICL +# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \ + defined(__NVCOMPILER) +# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) +# endif +# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \ + FMT_ICC_VERSION || defined(__NVCOMPILER) +# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) +# endif +#endif + +#if FMT_MSC_VERSION +# include // _BitScanReverse[64], _BitScanForward[64], _umul128 +#endif + +// Some compilers masquerade as both MSVC and GCC-likes or otherwise support +// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the +// MSVC intrinsics if the clz and clzll builtins are not available. +#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \ + !defined(FMT_BUILTIN_CTZLL) +FMT_BEGIN_NAMESPACE +namespace detail { +// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. +# if !defined(__clang__) +# pragma intrinsic(_BitScanForward) +# pragma intrinsic(_BitScanReverse) +# if defined(_WIN64) +# pragma intrinsic(_BitScanForward64) +# pragma intrinsic(_BitScanReverse64) +# endif +# endif + +inline auto clz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanReverse(&r, x); + FMT_ASSERT(x != 0, ""); + // Static analysis complains about using uninitialized data + // "r", but the only way that can happen is if "x" is 0, + // which the callers guarantee to not happen. + FMT_MSC_WARNING(suppress : 6102) + return 31 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZ(n) detail::clz(n) + +inline auto clzll(uint64_t x) -> int { + unsigned long r = 0; +# ifdef _WIN64 + _BitScanReverse64(&r, x); +# else + // Scan the high 32 bits. + if (_BitScanReverse(&r, static_cast(x >> 32))) return 63 ^ (r + 32); + // Scan the low 32 bits. + _BitScanReverse(&r, static_cast(x)); +# endif + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return 63 ^ static_cast(r); +} +# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) + +inline auto ctz(uint32_t x) -> int { + unsigned long r = 0; + _BitScanForward(&r, x); + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. + return static_cast(r); +} +# define FMT_BUILTIN_CTZ(n) detail::ctz(n) + +inline auto ctzll(uint64_t x) -> int { + unsigned long r = 0; + FMT_ASSERT(x != 0, ""); + FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. +# ifdef _WIN64 + _BitScanForward64(&r, x); +# else + // Scan the low 32 bits. + if (_BitScanForward(&r, static_cast(x))) return static_cast(r); + // Scan the high 32 bits. + _BitScanForward(&r, static_cast(x >> 32)); + r += 32; +# endif + return static_cast(r); +} +# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) +} // namespace detail +FMT_END_NAMESPACE +#endif + +FMT_BEGIN_NAMESPACE +namespace detail { + +FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) { + ignore_unused(condition); +#ifdef FMT_FUZZ + if (condition) throw std::runtime_error("fuzzing limit reached"); +#endif +} + +template class formatbuf : public Streambuf { + private: + using char_type = typename Streambuf::char_type; + using streamsize = decltype(std::declval().sputn(nullptr, 0)); + using int_type = typename Streambuf::int_type; + using traits_type = typename Streambuf::traits_type; + + buffer& buffer_; + + public: + explicit formatbuf(buffer& buf) : buffer_(buf) {} + + protected: + // The put area is always empty. This makes the implementation simpler and has + // the advantage that the streambuf and the buffer are always in sync and + // sputc never writes into uninitialized memory. A disadvantage is that each + // call to sputc always results in a (virtual) call to overflow. There is no + // disadvantage here for sputn since this always results in a call to xsputn. + + auto overflow(int_type ch) -> int_type override { + if (!traits_type::eq_int_type(ch, traits_type::eof())) + buffer_.push_back(static_cast(ch)); + return ch; + } + + auto xsputn(const char_type* s, streamsize count) -> streamsize override { + buffer_.append(s, s + count); + return count; + } +}; + +// Implementation of std::bit_cast for pre-C++20. +template +FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { +#ifdef __cpp_lib_bit_cast + if (is_constant_evaluated()) return std::bit_cast(from); +#endif + auto to = To(); + std::memcpy(&to, &from, sizeof(to)); + return to; +} + +inline auto is_big_endian() -> bool { +#ifdef _WIN32 + return false; +#elif defined(__BIG_ENDIAN__) + return true; +#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) + return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; +#else + struct bytes { + char data[sizeof(int)]; + }; + return bit_cast(1).data[0] == 0; +#endif +} + +class uint128_fallback { + private: + uint64_t lo_, hi_; + + friend uint128_fallback umul128(uint64_t x, uint64_t y) noexcept; + + public: + constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} + constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} + + constexpr uint64_t high() const noexcept { return hi_; } + constexpr uint64_t low() const noexcept { return lo_; } + + template ::value)> + constexpr explicit operator T() const { + return static_cast(lo_); + } + + friend constexpr auto operator==(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; + } + friend constexpr auto operator!=(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return !(lhs == rhs); + } + friend constexpr auto operator>(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> bool { + return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_; + } + friend constexpr auto operator|(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_}; + } + friend constexpr auto operator&(const uint128_fallback& lhs, + const uint128_fallback& rhs) + -> uint128_fallback { + return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; + } + friend auto operator+(const uint128_fallback& lhs, + const uint128_fallback& rhs) -> uint128_fallback { + auto result = uint128_fallback(lhs); + result += rhs; + return result; + } + friend auto operator*(const uint128_fallback& lhs, uint32_t rhs) + -> uint128_fallback { + FMT_ASSERT(lhs.hi_ == 0, ""); + uint64_t hi = (lhs.lo_ >> 32) * rhs; + uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs; + uint64_t new_lo = (hi << 32) + lo; + return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo}; + } + friend auto operator-(const uint128_fallback& lhs, uint64_t rhs) + -> uint128_fallback { + return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs}; + } + FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { + if (shift == 64) return {0, hi_}; + return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; + } + FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { + if (shift == 64) return {lo_, 0}; + return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; + } + FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { + return *this = *this >> shift; + } + FMT_CONSTEXPR void operator+=(uint128_fallback n) { + uint64_t new_lo = lo_ + n.lo_; + uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0); + FMT_ASSERT(new_hi >= hi_, ""); + lo_ = new_lo; + hi_ = new_hi; + } + + FMT_CONSTEXPR20 uint128_fallback& operator+=(uint64_t n) noexcept { + if (is_constant_evaluated()) { + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); + return *this; + } +#if FMT_HAS_BUILTIN(__builtin_addcll) + unsigned long long carry; + lo_ = __builtin_addcll(lo_, n, 0, &carry); + hi_ += carry; +#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) + unsigned long long result; + auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result); + lo_ = result; + hi_ += carry; +#elif defined(_MSC_VER) && defined(_M_X64) + auto carry = _addcarry_u64(0, lo_, n, &lo_); + _addcarry_u64(carry, hi_, 0, &hi_); +#else + lo_ += n; + hi_ += (lo_ < n ? 1 : 0); +#endif + return *this; + } +}; + +using uint128_t = conditional_t; + +#ifdef UINTPTR_MAX +using uintptr_t = ::uintptr_t; +#else +using uintptr_t = uint128_t; +#endif + +// Returns the largest possible value for type T. Same as +// std::numeric_limits::max() but shorter and not affected by the max macro. +template constexpr auto max_value() -> T { + return (std::numeric_limits::max)(); +} +template constexpr auto num_bits() -> int { + return std::numeric_limits::digits; +} +// std::numeric_limits::digits may return 0 for 128-bit ints. +template <> constexpr auto num_bits() -> int { return 128; } +template <> constexpr auto num_bits() -> int { return 128; } + +// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t +// and 128-bit pointers to uint128_fallback. +template sizeof(From))> +inline auto bit_cast(const From& from) -> To { + constexpr auto size = static_cast(sizeof(From) / sizeof(unsigned)); + struct data_t { + unsigned value[static_cast(size)]; + } data = bit_cast(from); + auto result = To(); + if (const_check(is_big_endian())) { + for (int i = 0; i < size; ++i) + result = (result << num_bits()) | data.value[i]; + } else { + for (int i = size - 1; i >= 0; --i) + result = (result << num_bits()) | data.value[i]; + } + return result; +} + +FMT_INLINE void assume(bool condition) { + (void)condition; +#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION + __builtin_assume(condition); +#endif +} + +// An approximation of iterator_t for pre-C++20 systems. +template +using iterator_t = decltype(std::begin(std::declval())); +template using sentinel_t = decltype(std::end(std::declval())); + +// A workaround for std::string not having mutable data() until C++17. +template +inline auto get_data(std::basic_string& s) -> Char* { + return &s[0]; +} +template +inline auto get_data(Container& c) -> typename Container::value_type* { + return c.data(); +} + +#if defined(_SECURE_SCL) && _SECURE_SCL +// Make a checked iterator to avoid MSVC warnings. +template using checked_ptr = stdext::checked_array_iterator; +template +constexpr auto make_checked(T* p, size_t size) -> checked_ptr { + return {p, size}; +} +#else +template using checked_ptr = T*; +template constexpr auto make_checked(T* p, size_t) -> T* { + return p; +} +#endif + +// Attempts to reserve space for n extra characters in the output range. +// Returns a pointer to the reserved range or a reference to it. +template ::value)> +#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION +__attribute__((no_sanitize("undefined"))) +#endif +inline auto +reserve(std::back_insert_iterator it, size_t n) + -> checked_ptr { + Container& c = get_container(it); + size_t size = c.size(); + c.resize(size + n); + return make_checked(get_data(c) + size, n); +} + +template +inline auto reserve(buffer_appender it, size_t n) -> buffer_appender { + buffer& buf = get_container(it); + buf.try_reserve(buf.size() + n); + return it; +} + +template +constexpr auto reserve(Iterator& it, size_t) -> Iterator& { + return it; +} + +template +using reserve_iterator = + remove_reference_t(), 0))>; + +template +constexpr auto to_pointer(OutputIt, size_t) -> T* { + return nullptr; +} +template auto to_pointer(buffer_appender it, size_t n) -> T* { + buffer& buf = get_container(it); + auto size = buf.size(); + if (buf.capacity() < size + n) return nullptr; + buf.try_resize(size + n); + return buf.data() + size; +} + +template ::value)> +inline auto base_iterator(std::back_insert_iterator& it, + checked_ptr) + -> std::back_insert_iterator { + return it; +} + +template +constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { + return it; +} + +// is spectacularly slow to compile in C++20 so use a simple fill_n +// instead (#1998). +template +FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value) + -> OutputIt { + for (Size i = 0; i < count; ++i) *out++ = value; + return out; +} +template +FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { + if (is_constant_evaluated()) { + return fill_n(out, count, value); + } + std::memset(out, value, to_unsigned(count)); + return out + count; +} + +#ifdef __cpp_char8_t +using char8_type = char8_t; +#else +enum char8_type : unsigned char {}; +#endif + +template +FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, + OutputIt out) -> OutputIt { + return copy_str(begin, end, out); +} + +// A public domain branchless UTF-8 decoder by Christopher Wellons: +// https://github.com/skeeto/branchless-utf8 +/* Decode the next character, c, from s, reporting errors in e. + * + * Since this is a branchless decoder, four bytes will be read from the + * buffer regardless of the actual length of the next character. This + * means the buffer _must_ have at least three bytes of zero padding + * following the end of the data stream. + * + * Errors are reported in e, which will be non-zero if the parsed + * character was somehow invalid: invalid byte sequence, non-canonical + * encoding, or a surrogate half. + * + * The function returns a pointer to the next character. When an error + * occurs, this pointer will be a guess that depends on the particular + * error, but it will always advance at least one byte. + */ +FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) + -> const char* { + constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; + constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; + constexpr const int shiftc[] = {0, 18, 12, 6, 0}; + constexpr const int shifte[] = {0, 6, 4, 2, 0}; + + int len = code_point_length(s); + const char* next = s + len; + + // Assume a four-byte character and load four bytes. Unused bits are + // shifted out. + *c = uint32_t(s[0] & masks[len]) << 18; + *c |= uint32_t(s[1] & 0x3f) << 12; + *c |= uint32_t(s[2] & 0x3f) << 6; + *c |= uint32_t(s[3] & 0x3f) << 0; + *c >>= shiftc[len]; + + // Accumulate the various error conditions. + using uchar = unsigned char; + *e = (*c < mins[len]) << 6; // non-canonical encoding + *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? + *e |= (*c > 0x10FFFF) << 8; // out of range? + *e |= (uchar(s[1]) & 0xc0) >> 2; + *e |= (uchar(s[2]) & 0xc0) >> 4; + *e |= uchar(s[3]) >> 6; + *e ^= 0x2a; // top two bits of each tail byte correct? + *e >>= shifte[len]; + + return next; +} + +constexpr uint32_t invalid_code_point = ~uint32_t(); + +// Invokes f(cp, sv) for every code point cp in s with sv being the string view +// corresponding to the code point. cp is invalid_code_point on error. +template +FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { + auto decode = [f](const char* buf_ptr, const char* ptr) { + auto cp = uint32_t(); + auto error = 0; + auto end = utf8_decode(buf_ptr, &cp, &error); + bool result = f(error ? invalid_code_point : cp, + string_view(ptr, to_unsigned(end - buf_ptr))); + return result ? end : nullptr; + }; + auto p = s.data(); + const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. + if (s.size() >= block_size) { + for (auto end = p + s.size() - block_size + 1; p < end;) { + p = decode(p, p); + if (!p) return; + } + } + if (auto num_chars_left = s.data() + s.size() - p) { + char buf[2 * block_size - 1] = {}; + copy_str(p, p + num_chars_left, buf); + const char* buf_ptr = buf; + do { + auto end = decode(buf_ptr, p); + if (!end) return; + p += end - buf_ptr; + buf_ptr = end; + } while (buf_ptr - buf < num_chars_left); + } +} + +template +inline auto compute_width(basic_string_view s) -> size_t { + return s.size(); +} + +// Computes approximate display width of a UTF-8 string. +FMT_CONSTEXPR inline size_t compute_width(string_view s) { + size_t num_code_points = 0; + // It is not a lambda for compatibility with C++14. + struct count_code_points { + size_t* count; + FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool { + *count += detail::to_unsigned( + 1 + + (cp >= 0x1100 && + (cp <= 0x115f || // Hangul Jamo init. consonants + cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET + cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET + // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE: + (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) || + (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables + (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs + (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms + (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms + (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms + (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms + (cp >= 0x20000 && cp <= 0x2fffd) || // CJK + (cp >= 0x30000 && cp <= 0x3fffd) || + // Miscellaneous Symbols and Pictographs + Emoticons: + (cp >= 0x1f300 && cp <= 0x1f64f) || + // Supplemental Symbols and Pictographs: + (cp >= 0x1f900 && cp <= 0x1f9ff)))); + return true; + } + }; + for_each_codepoint(s, count_code_points{&num_code_points}); + return num_code_points; +} + +inline auto compute_width(basic_string_view s) -> size_t { + return compute_width( + string_view(reinterpret_cast(s.data()), s.size())); +} + +template +inline auto code_point_index(basic_string_view s, size_t n) -> size_t { + size_t size = s.size(); + return n < size ? n : size; +} + +// Calculates the index of the nth code point in a UTF-8 string. +inline auto code_point_index(string_view s, size_t n) -> size_t { + const char* data = s.data(); + size_t num_code_points = 0; + for (size_t i = 0, size = s.size(); i != size; ++i) { + if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i; + } + return s.size(); +} + +inline auto code_point_index(basic_string_view s, size_t n) + -> size_t { + return code_point_index( + string_view(reinterpret_cast(s.data()), s.size()), n); +} + +#ifndef FMT_USE_FLOAT128 +# ifdef __SIZEOF_FLOAT128__ +# define FMT_USE_FLOAT128 1 +# else +# define FMT_USE_FLOAT128 0 +# endif +#endif +#if FMT_USE_FLOAT128 +using float128 = __float128; +#else +using float128 = void; +#endif +template using is_float128 = std::is_same; + +template +using is_floating_point = + bool_constant::value || is_float128::value>; + +template ::value> +struct is_fast_float : bool_constant::is_iec559 && + sizeof(T) <= sizeof(double)> {}; +template struct is_fast_float : std::false_type {}; + +template +using is_double_double = bool_constant::digits == 106>; + +#ifndef FMT_USE_FULL_CACHE_DRAGONBOX +# define FMT_USE_FULL_CACHE_DRAGONBOX 0 +#endif + +template +template +void buffer::append(const U* begin, const U* end) { + while (begin != end) { + auto count = to_unsigned(end - begin); + try_reserve(size_ + count); + auto free_cap = capacity_ - size_; + if (free_cap < count) count = free_cap; + std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count)); + size_ += count; + begin += count; + } +} + +template +struct is_locale : std::false_type {}; +template +struct is_locale> : std::true_type {}; +} // namespace detail + +FMT_MODULE_EXPORT_BEGIN + +// The number of characters to store in the basic_memory_buffer object itself +// to avoid dynamic memory allocation. +enum { inline_buffer_size = 500 }; + +/** + \rst + A dynamically growing memory buffer for trivially copyable/constructible types + with the first ``SIZE`` elements stored in the object itself. + + You can use the ``memory_buffer`` type alias for ``char`` instead. + + **Example**:: + + auto out = fmt::memory_buffer(); + format_to(std::back_inserter(out), "The answer is {}.", 42); + + This will append the following output to the ``out`` object: + + .. code-block:: none + + The answer is 42. + + The output can be converted to an ``std::string`` with ``to_string(out)``. + \endrst + */ +template > +class basic_memory_buffer final : public detail::buffer { + private: + T store_[SIZE]; + + // Don't inherit from Allocator avoid generating type_info for it. + Allocator alloc_; + + // Deallocate memory allocated by the buffer. + FMT_CONSTEXPR20 void deallocate() { + T* data = this->data(); + if (data != store_) alloc_.deallocate(data, this->capacity()); + } + + protected: + FMT_CONSTEXPR20 void grow(size_t size) override; + + public: + using value_type = T; + using const_reference = const T&; + + FMT_CONSTEXPR20 explicit basic_memory_buffer( + const Allocator& alloc = Allocator()) + : alloc_(alloc) { + this->set(store_, SIZE); + if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T()); + } + FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); } + + private: + // Move data from other to this buffer. + FMT_CONSTEXPR20 void move(basic_memory_buffer& other) { + alloc_ = std::move(other.alloc_); + T* data = other.data(); + size_t size = other.size(), capacity = other.capacity(); + if (data == other.store_) { + this->set(store_, capacity); + detail::copy_str(other.store_, other.store_ + size, + detail::make_checked(store_, capacity)); + } else { + this->set(data, capacity); + // Set pointer to the inline array so that delete is not called + // when deallocating. + other.set(other.store_, 0); + other.clear(); + } + this->resize(size); + } + + public: + /** + \rst + Constructs a :class:`fmt::basic_memory_buffer` object moving the content + of the other object to it. + \endrst + */ + FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept { + move(other); + } + + /** + \rst + Moves the content of the other ``basic_memory_buffer`` object to this one. + \endrst + */ + auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& { + FMT_ASSERT(this != &other, ""); + deallocate(); + move(other); + return *this; + } + + // Returns a copy of the allocator associated with this buffer. + auto get_allocator() const -> Allocator { return alloc_; } + + /** + Resizes the buffer to contain *count* elements. If T is a POD type new + elements may not be initialized. + */ + FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } + + /** Increases the buffer capacity to *new_capacity*. */ + void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } + + // Directly append data into the buffer + using detail::buffer::append; + template + void append(const ContiguousRange& range) { + append(range.data(), range.data() + range.size()); + } +}; + +template +FMT_CONSTEXPR20 void basic_memory_buffer::grow( + size_t size) { + detail::abort_fuzzing_if(size > 5000); + const size_t max_size = std::allocator_traits::max_size(alloc_); + size_t old_capacity = this->capacity(); + size_t new_capacity = old_capacity + old_capacity / 2; + if (size > new_capacity) + new_capacity = size; + else if (new_capacity > max_size) + new_capacity = size > max_size ? size : max_size; + T* old_data = this->data(); + T* new_data = + std::allocator_traits::allocate(alloc_, new_capacity); + // The following code doesn't throw, so the raw pointer above doesn't leak. + std::uninitialized_copy(old_data, old_data + this->size(), + detail::make_checked(new_data, new_capacity)); + this->set(new_data, new_capacity); + // deallocate must not throw according to the standard, but even if it does, + // the buffer already uses the new storage and will deallocate it in + // destructor. + if (old_data != store_) alloc_.deallocate(old_data, old_capacity); +} + +using memory_buffer = basic_memory_buffer; + +template +struct is_contiguous> : std::true_type { +}; + +namespace detail { +FMT_API void print(std::FILE*, string_view); +} + +/** A formatting error such as invalid format string. */ +FMT_CLASS_API +class FMT_API format_error : public std::runtime_error { + public: + explicit format_error(const char* message) : std::runtime_error(message) {} + explicit format_error(const std::string& message) + : std::runtime_error(message) {} + format_error(const format_error&) = default; + format_error& operator=(const format_error&) = default; + format_error(format_error&&) = default; + format_error& operator=(format_error&&) = default; + ~format_error() noexcept override FMT_MSC_DEFAULT; +}; + +namespace detail_exported { +#if FMT_USE_NONTYPE_TEMPLATE_ARGS +template struct fixed_string { + constexpr fixed_string(const Char (&str)[N]) { + detail::copy_str(static_cast(str), + str + N, data); + } + Char data[N] = {}; +}; +#endif + +// Converts a compile-time string to basic_string_view. +template +constexpr auto compile_string_to_view(const Char (&s)[N]) + -> basic_string_view { + // Remove trailing NUL character if needed. Won't be present if this is used + // with a raw character array (i.e. not defined as a string). + return {s, N - (std::char_traits::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; +} +template +constexpr auto compile_string_to_view(detail::std_string_view s) + -> basic_string_view { + return {s.data(), s.size()}; +} +} // namespace detail_exported + +FMT_BEGIN_DETAIL_NAMESPACE + +template struct is_integral : std::is_integral {}; +template <> struct is_integral : std::true_type {}; +template <> struct is_integral : std::true_type {}; + +template +using is_signed = + std::integral_constant::is_signed || + std::is_same::value>; + +// Returns true if value is negative, false otherwise. +// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. +template ::value)> +constexpr auto is_negative(T value) -> bool { + return value < 0; +} +template ::value)> +constexpr auto is_negative(T) -> bool { + return false; +} + +template +FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool { + if (std::is_same()) return FMT_USE_FLOAT; + if (std::is_same()) return FMT_USE_DOUBLE; + if (std::is_same()) return FMT_USE_LONG_DOUBLE; + return true; +} + +// Smallest of uint32_t, uint64_t, uint128_t that is large enough to +// represent all values of an integral type T. +template +using uint32_or_64_or_128_t = + conditional_t() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, + uint32_t, + conditional_t() <= 64, uint64_t, uint128_t>>; +template +using uint64_or_128_t = conditional_t() <= 64, uint64_t, uint128_t>; + +#define FMT_POWERS_OF_10(factor) \ + factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ + (factor)*1000000, (factor)*10000000, (factor)*100000000, \ + (factor)*1000000000 + +// Converts value in the range [0, 100) to a string. +constexpr const char* digits2(size_t value) { + // GCC generates slightly better code when value is pointer-size. + return &"0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"[value * 2]; +} + +// Sign is a template parameter to workaround a bug in gcc 4.8. +template constexpr Char sign(Sign s) { +#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 + static_assert(std::is_same::value, ""); +#endif + return static_cast("\0-+ "[s]); +} + +template FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { + int count = 1; + for (;;) { + // Integer division is slow so do it for a group of four digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + if (n < 10) return count; + if (n < 100) return count + 1; + if (n < 1000) return count + 2; + if (n < 10000) return count + 3; + n /= 10000u; + count += 4; + } +} +#if FMT_USE_INT128 +FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int { + return count_digits_fallback(n); +} +#endif + +#ifdef FMT_BUILTIN_CLZLL +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +inline auto do_count_digits(uint64_t n) -> int { + // This has comparable performance to the version by Kendall Willets + // (https://github.com/fmtlib/format-benchmark/blob/master/digits10) + // but uses smaller tables. + // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). + static constexpr uint8_t bsr2log10[] = { + 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, + 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, + 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; + auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63]; + static constexpr const uint64_t zero_or_powers_of_10[] = { + 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; + return t - (n < zero_or_powers_of_10[t]); +} +#endif + +// Returns the number of decimal digits in n. Leading zeros are not counted +// except for n == 0 in which case count_digits returns 1. +FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { +#ifdef FMT_BUILTIN_CLZLL + if (!is_constant_evaluated()) { + return do_count_digits(n); + } +#endif + return count_digits_fallback(n); +} + +// Counts the number of digits in n. BITS = log2(radix). +template +FMT_CONSTEXPR auto count_digits(UInt n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated() && num_bits() == 32) + return (FMT_BUILTIN_CLZ(static_cast(n) | 1) ^ 31) / BITS + 1; +#endif + // Lambda avoids unreachable code warnings from NVHPC. + return [](UInt m) { + int num_digits = 0; + do { + ++num_digits; + } while ((m >>= BITS) != 0); + return num_digits; + }(n); +} + +#ifdef FMT_BUILTIN_CLZ +// It is a separate function rather than a part of count_digits to workaround +// the lack of static constexpr in constexpr functions. +FMT_INLINE auto do_count_digits(uint32_t n) -> int { +// An optimization by Kendall Willets from https://bit.ly/3uOIQrB. +// This increments the upper 32 bits (log10(T) - 1) when >= T is added. +# define FMT_INC(T) (((sizeof(# T) - 1ull) << 32) - T) + static constexpr uint64_t table[] = { + FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8 + FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64 + FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512 + FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096 + FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k + FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k + FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k + FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M + FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M + FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M + FMT_INC(1000000000), FMT_INC(1000000000) // 4B + }; + auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31]; + return static_cast((n + inc) >> 32); +} +#endif + +// Optional version of count_digits for better performance on 32-bit platforms. +FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { +#ifdef FMT_BUILTIN_CLZ + if (!is_constant_evaluated()) { + return do_count_digits(n); + } +#endif + return count_digits_fallback(n); +} + +template constexpr auto digits10() noexcept -> int { + return std::numeric_limits::digits10; +} +template <> constexpr auto digits10() noexcept -> int { return 38; } +template <> constexpr auto digits10() noexcept -> int { return 38; } + +template struct thousands_sep_result { + std::string grouping; + Char thousands_sep; +}; + +template +FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result; +template +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + auto result = thousands_sep_impl(loc); + return {result.grouping, Char(result.thousands_sep)}; +} +template <> +inline auto thousands_sep(locale_ref loc) -> thousands_sep_result { + return thousands_sep_impl(loc); +} + +template +FMT_API auto decimal_point_impl(locale_ref loc) -> Char; +template inline auto decimal_point(locale_ref loc) -> Char { + return Char(decimal_point_impl(loc)); +} +template <> inline auto decimal_point(locale_ref loc) -> wchar_t { + return decimal_point_impl(loc); +} + +// Compares two characters for equality. +template auto equal2(const Char* lhs, const char* rhs) -> bool { + return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); +} +inline auto equal2(const char* lhs, const char* rhs) -> bool { + return memcmp(lhs, rhs, 2) == 0; +} + +// Copies two characters from src to dst. +template +FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) { + if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) { + memcpy(dst, src, 2); + return; + } + *dst++ = static_cast(*src++); + *dst = static_cast(*src); +} + +template struct format_decimal_result { + Iterator begin; + Iterator end; +}; + +// Formats a decimal unsigned integer value writing into out pointing to a +// buffer of specified size. The caller must ensure that the buffer is large +// enough. +template +FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) + -> format_decimal_result { + FMT_ASSERT(size >= count_digits(value), "invalid digit count"); + out += size; + Char* end = out; + while (value >= 100) { + // Integer division is slow so do it for a group of two digits instead + // of for every digit. The idea comes from the talk by Alexandrescu + // "Three Optimization Tips for C++". See speed-test for a comparison. + out -= 2; + copy2(out, digits2(static_cast(value % 100))); + value /= 100; + } + if (value < 10) { + *--out = static_cast('0' + value); + return {out, end}; + } + out -= 2; + copy2(out, digits2(static_cast(value))); + return {out, end}; +} + +template >::value)> +inline auto format_decimal(Iterator out, UInt value, int size) + -> format_decimal_result { + // Buffer is large enough to hold all digits (digits10 + 1). + Char buffer[digits10() + 1]; + auto end = format_decimal(buffer, value, size).end; + return {out, detail::copy_str_noinline(buffer, end, out)}; +} + +template +FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits, + bool upper = false) -> Char* { + buffer += num_digits; + Char* end = buffer; + do { + const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; + unsigned digit = static_cast(value & ((1 << BASE_BITS) - 1)); + *--buffer = static_cast(BASE_BITS < 4 ? static_cast('0' + digit) + : digits[digit]); + } while ((value >>= BASE_BITS) != 0); + return end; +} + +template +inline auto format_uint(It out, UInt value, int num_digits, bool upper = false) + -> It { + if (auto ptr = to_pointer(out, to_unsigned(num_digits))) { + format_uint(ptr, value, num_digits, upper); + return out; + } + // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). + char buffer[num_bits() / BASE_BITS + 1]; + format_uint(buffer, value, num_digits, upper); + return detail::copy_str_noinline(buffer, buffer + num_digits, out); +} + +// A converter from UTF-8 to UTF-16. +class utf8_to_utf16 { + private: + basic_memory_buffer buffer_; + + public: + FMT_API explicit utf8_to_utf16(string_view s); + operator basic_string_view() const { return {&buffer_[0], size()}; } + auto size() const -> size_t { return buffer_.size() - 1; } + auto c_str() const -> const wchar_t* { return &buffer_[0]; } + auto str() const -> std::wstring { return {&buffer_[0], size()}; } +}; + +namespace dragonbox { + +// Type-specific information that Dragonbox uses. +template struct float_info; + +template <> struct float_info { + using carrier_uint = uint32_t; + static const int exponent_bits = 8; + static const int kappa = 1; + static const int big_divisor = 100; + static const int small_divisor = 10; + static const int min_k = -31; + static const int max_k = 46; + static const int divisibility_check_by_5_threshold = 39; + static const int case_fc_pm_half_lower_threshold = -1; + static const int shorter_interval_tie_lower_threshold = -35; + static const int shorter_interval_tie_upper_threshold = -35; +}; + +template <> struct float_info { + using carrier_uint = uint64_t; + static const int exponent_bits = 11; + static const int kappa = 2; + static const int big_divisor = 1000; + static const int small_divisor = 100; + static const int min_k = -292; + static const int max_k = 326; + static const int divisibility_check_by_5_threshold = 86; + static const int case_fc_pm_half_lower_threshold = -2; + static const int shorter_interval_tie_lower_threshold = -77; + static const int shorter_interval_tie_upper_threshold = -77; +}; + +// An 80- or 128-bit floating point number. +template +struct float_info::digits == 64 || + std::numeric_limits::digits == 113 || + is_float128::value>> { + using carrier_uint = detail::uint128_t; + static const int exponent_bits = 15; +}; + +// A double-double floating point number. +template +struct float_info::value>> { + using carrier_uint = detail::uint128_t; +}; + +template struct decimal_fp { + using significand_type = typename float_info::carrier_uint; + significand_type significand; + int exponent; +}; + +template FMT_API auto to_decimal(T x) noexcept -> decimal_fp; +} // namespace dragonbox + +// Returns true iff Float has the implicit bit which is not stored. +template constexpr bool has_implicit_bit() { + // An 80-bit FP number has a 64-bit significand an no implicit bit. + return std::numeric_limits::digits != 64; +} + +// Returns the number of significand bits stored in Float. The implicit bit is +// not counted since it is not stored. +template constexpr int num_significand_bits() { + // std::numeric_limits may not support __float128. + return is_float128() ? 112 + : (std::numeric_limits::digits - + (has_implicit_bit() ? 1 : 0)); +} + +template +constexpr auto exponent_mask() -> + typename dragonbox::float_info::carrier_uint { + using uint = typename dragonbox::float_info::carrier_uint; + return ((uint(1) << dragonbox::float_info::exponent_bits) - 1) + << num_significand_bits(); +} +template constexpr auto exponent_bias() -> int { + // std::numeric_limits may not support __float128. + return is_float128() ? 16383 + : std::numeric_limits::max_exponent - 1; +} + +// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. +template +FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It { + FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); + if (exp < 0) { + *it++ = static_cast('-'); + exp = -exp; + } else { + *it++ = static_cast('+'); + } + if (exp >= 100) { + const char* top = digits2(to_unsigned(exp / 100)); + if (exp >= 1000) *it++ = static_cast(top[0]); + *it++ = static_cast(top[1]); + exp %= 100; + } + const char* d = digits2(to_unsigned(exp)); + *it++ = static_cast(d[0]); + *it++ = static_cast(d[1]); + return it; +} + +// A floating-point number f * pow(2, e) where F is an unsigned type. +template struct basic_fp { + F f; + int e; + + static constexpr const int num_significand_bits = + static_cast(sizeof(F) * num_bits()); + + constexpr basic_fp() : f(0), e(0) {} + constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} + + // Constructs fp from an IEEE754 floating-point number. + template FMT_CONSTEXPR basic_fp(Float n) { assign(n); } + + // Assigns n to this and return true iff predecessor is closer than successor. + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::digits <= 113, "unsupported FP"); + // Assume Float is in the format [sign][exponent][significand]. + using carrier_uint = typename dragonbox::float_info::carrier_uint; + const auto num_float_significand_bits = + detail::num_significand_bits(); + const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; + const auto significand_mask = implicit_bit - 1; + auto u = bit_cast(n); + f = static_cast(u & significand_mask); + auto biased_e = static_cast((u & exponent_mask()) >> + num_float_significand_bits); + // The predecessor is closer if n is a normalized power of 2 (f == 0) + // other than the smallest normalized number (biased_e > 1). + auto is_predecessor_closer = f == 0 && biased_e > 1; + if (biased_e == 0) + biased_e = 1; // Subnormals use biased exponent 1 (min exponent). + else if (has_implicit_bit()) + f += static_cast(implicit_bit); + e = biased_e - exponent_bias() - num_float_significand_bits; + if (!has_implicit_bit()) ++e; + return is_predecessor_closer; + } + + template ::value)> + FMT_CONSTEXPR auto assign(Float n) -> bool { + static_assert(std::numeric_limits::is_iec559, "unsupported FP"); + return assign(static_cast(n)); + } +}; + +using fp = basic_fp; + +// Normalizes the value converted from double and multiplied by (1 << SHIFT). +template +FMT_CONSTEXPR basic_fp normalize(basic_fp value) { + // Handle subnormals. + const auto implicit_bit = F(1) << num_significand_bits(); + const auto shifted_implicit_bit = implicit_bit << SHIFT; + while ((value.f & shifted_implicit_bit) == 0) { + value.f <<= 1; + --value.e; + } + // Subtract 1 to account for hidden bit. + const auto offset = basic_fp::num_significand_bits - + num_significand_bits() - SHIFT - 1; + value.f <<= offset; + value.e -= offset; + return value; +} + +// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. +FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) { +#if FMT_USE_INT128 + auto product = static_cast<__uint128_t>(lhs) * rhs; + auto f = static_cast(product >> 64); + return (static_cast(product) & (1ULL << 63)) != 0 ? f + 1 : f; +#else + // Multiply 32-bit parts of significands. + uint64_t mask = (1ULL << 32) - 1; + uint64_t a = lhs >> 32, b = lhs & mask; + uint64_t c = rhs >> 32, d = rhs & mask; + uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; + // Compute mid 64-bit of result and round. + uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); + return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); +#endif +} + +FMT_CONSTEXPR inline fp operator*(fp x, fp y) { + return {multiply(x.f, y.f), x.e + y.e + 64}; +} + +template struct basic_data { + // Normalized 64-bit significands of pow(10, k), for k = -348, -340, ..., 340. + // These are generated by support/compute-powers.py. + static constexpr uint64_t pow10_significands[87] = { + 0xfa8fd5a0081c0288, 0xbaaee17fa23ebf76, 0x8b16fb203055ac76, + 0xcf42894a5dce35ea, 0x9a6bb0aa55653b2d, 0xe61acf033d1a45df, + 0xab70fe17c79ac6ca, 0xff77b1fcbebcdc4f, 0xbe5691ef416bd60c, + 0x8dd01fad907ffc3c, 0xd3515c2831559a83, 0x9d71ac8fada6c9b5, + 0xea9c227723ee8bcb, 0xaecc49914078536d, 0x823c12795db6ce57, + 0xc21094364dfb5637, 0x9096ea6f3848984f, 0xd77485cb25823ac7, + 0xa086cfcd97bf97f4, 0xef340a98172aace5, 0xb23867fb2a35b28e, + 0x84c8d4dfd2c63f3b, 0xc5dd44271ad3cdba, 0x936b9fcebb25c996, + 0xdbac6c247d62a584, 0xa3ab66580d5fdaf6, 0xf3e2f893dec3f126, + 0xb5b5ada8aaff80b8, 0x87625f056c7c4a8b, 0xc9bcff6034c13053, + 0x964e858c91ba2655, 0xdff9772470297ebd, 0xa6dfbd9fb8e5b88f, + 0xf8a95fcf88747d94, 0xb94470938fa89bcf, 0x8a08f0f8bf0f156b, + 0xcdb02555653131b6, 0x993fe2c6d07b7fac, 0xe45c10c42a2b3b06, + 0xaa242499697392d3, 0xfd87b5f28300ca0e, 0xbce5086492111aeb, + 0x8cbccc096f5088cc, 0xd1b71758e219652c, 0x9c40000000000000, + 0xe8d4a51000000000, 0xad78ebc5ac620000, 0x813f3978f8940984, + 0xc097ce7bc90715b3, 0x8f7e32ce7bea5c70, 0xd5d238a4abe98068, + 0x9f4f2726179a2245, 0xed63a231d4c4fb27, 0xb0de65388cc8ada8, + 0x83c7088e1aab65db, 0xc45d1df942711d9a, 0x924d692ca61be758, + 0xda01ee641a708dea, 0xa26da3999aef774a, 0xf209787bb47d6b85, + 0xb454e4a179dd1877, 0x865b86925b9bc5c2, 0xc83553c5c8965d3d, + 0x952ab45cfa97a0b3, 0xde469fbd99a05fe3, 0xa59bc234db398c25, + 0xf6c69a72a3989f5c, 0xb7dcbf5354e9bece, 0x88fcf317f22241e2, + 0xcc20ce9bd35c78a5, 0x98165af37b2153df, 0xe2a0b5dc971f303a, + 0xa8d9d1535ce3b396, 0xfb9b7cd9a4a7443c, 0xbb764c4ca7a44410, + 0x8bab8eefb6409c1a, 0xd01fef10a657842c, 0x9b10a4e5e9913129, + 0xe7109bfba19c0c9d, 0xac2820d9623bf429, 0x80444b5e7aa7cf85, + 0xbf21e44003acdd2d, 0x8e679c2f5e44ff8f, 0xd433179d9c8cb841, + 0x9e19db92b4e31ba9, 0xeb96bf6ebadf77d9, 0xaf87023b9bf0ee6b, + }; + +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wnarrowing" +#endif + // Binary exponents of pow(10, k), for k = -348, -340, ..., 340, corresponding + // to significands above. + static constexpr int16_t pow10_exponents[87] = { + -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, -954, + -927, -901, -874, -847, -821, -794, -768, -741, -715, -688, -661, + -635, -608, -582, -555, -529, -502, -475, -449, -422, -396, -369, + -343, -316, -289, -263, -236, -210, -183, -157, -130, -103, -77, + -50, -24, 3, 30, 56, 83, 109, 136, 162, 189, 216, + 242, 269, 295, 322, 348, 375, 402, 428, 455, 481, 508, + 534, 561, 588, 614, 641, 667, 694, 720, 747, 774, 800, + 827, 853, 880, 907, 933, 960, 986, 1013, 1039, 1066}; +#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 +# pragma GCC diagnostic pop +#endif + + static constexpr uint64_t power_of_10_64[20] = { + 1, FMT_POWERS_OF_10(1ULL), FMT_POWERS_OF_10(1000000000ULL), + 10000000000000000000ULL}; +}; + +#if FMT_CPLUSPLUS < 201703L +template constexpr uint64_t basic_data::pow10_significands[]; +template constexpr int16_t basic_data::pow10_exponents[]; +template constexpr uint64_t basic_data::power_of_10_64[]; +#endif + +// This is a struct rather than an alias to avoid shadowing warnings in gcc. +struct data : basic_data<> {}; + +// Returns a cached power of 10 `c_k = c_k.f * pow(2, c_k.e)` such that its +// (binary) exponent satisfies `min_exponent <= c_k.e <= min_exponent + 28`. +FMT_CONSTEXPR inline fp get_cached_power(int min_exponent, + int& pow10_exponent) { + const int shift = 32; + // log10(2) = 0x0.4d104d427de7fbcc... + const int64_t significand = 0x4d104d427de7fbcc; + int index = static_cast( + ((min_exponent + fp::num_significand_bits - 1) * (significand >> shift) + + ((int64_t(1) << shift) - 1)) // ceil + >> 32 // arithmetic shift + ); + // Decimal exponent of the first (smallest) cached power of 10. + const int first_dec_exp = -348; + // Difference between 2 consecutive decimal exponents in cached powers of 10. + const int dec_exp_step = 8; + index = (index - first_dec_exp - 1) / dec_exp_step + 1; + pow10_exponent = first_dec_exp + index * dec_exp_step; + return {data::pow10_significands[index], data::pow10_exponents[index]}; +} + +#ifndef _MSC_VER +# define FMT_SNPRINTF snprintf +#else +FMT_API auto fmt_snprintf(char* buf, size_t size, const char* fmt, ...) -> int; +# define FMT_SNPRINTF fmt_snprintf +#endif // _MSC_VER + +// Formats a floating-point number with snprintf using the hexfloat format. +template +auto snprintf_float(T value, int precision, float_specs specs, + buffer& buf) -> int { + // Buffer capacity must be non-zero, otherwise MSVC's vsnprintf_s will fail. + FMT_ASSERT(buf.capacity() > buf.size(), "empty buffer"); + FMT_ASSERT(specs.format == float_format::hex, ""); + static_assert(!std::is_same::value, ""); + + // Build the format string. + char format[7]; // The longest format is "%#.*Le". + char* format_ptr = format; + *format_ptr++ = '%'; + if (specs.showpoint) *format_ptr++ = '#'; + if (precision >= 0) { + *format_ptr++ = '.'; + *format_ptr++ = '*'; + } + if (std::is_same()) *format_ptr++ = 'L'; + *format_ptr++ = specs.upper ? 'A' : 'a'; + *format_ptr = '\0'; + + // Format using snprintf. + auto offset = buf.size(); + for (;;) { + auto begin = buf.data() + offset; + auto capacity = buf.capacity() - offset; + abort_fuzzing_if(precision > 100000); + // Suppress the warning about a nonliteral format string. + // Cannot use auto because of a bug in MinGW (#1532). + int (*snprintf_ptr)(char*, size_t, const char*, ...) = FMT_SNPRINTF; + int result = precision >= 0 + ? snprintf_ptr(begin, capacity, format, precision, value) + : snprintf_ptr(begin, capacity, format, value); + if (result < 0) { + // The buffer will grow exponentially. + buf.try_reserve(buf.capacity() + 1); + continue; + } + auto size = to_unsigned(result); + // Size equal to capacity means that the last character was truncated. + if (size < capacity) { + buf.try_resize(size + offset); + return 0; + } + buf.try_reserve(size + offset + 1); // Add 1 for the terminating '\0'. + } +} + +template +using convert_float_result = + conditional_t::value || sizeof(T) == sizeof(double), + double, T>; + +template +constexpr auto convert_float(T value) -> convert_float_result { + return static_cast>(value); +} + +template +FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, + const fill_t& fill) -> OutputIt { + auto fill_size = fill.size(); + if (fill_size == 1) return detail::fill_n(it, n, fill[0]); + auto data = fill.data(); + for (size_t i = 0; i < n; ++i) + it = copy_str(data, data + fill_size, it); + return it; +} + +// Writes the output of f, padded according to format specifications in specs. +// size: output size in code units. +// width: output display width in (terminal) column positions. +template +FMT_CONSTEXPR auto write_padded(OutputIt out, + const basic_format_specs& specs, + size_t size, size_t width, F&& f) -> OutputIt { + static_assert(align == align::left || align == align::right, ""); + unsigned spec_width = to_unsigned(specs.width); + size_t padding = spec_width > width ? spec_width - width : 0; + // Shifts are encoded as string literals because static constexpr is not + // supported in constexpr functions. + auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01"; + size_t left_padding = padding >> shifts[specs.align]; + size_t right_padding = padding - left_padding; + auto it = reserve(out, size + padding * specs.fill.size()); + if (left_padding != 0) it = fill(it, left_padding, specs.fill); + it = f(it); + if (right_padding != 0) it = fill(it, right_padding, specs.fill); + return base_iterator(out, it); +} + +template +constexpr auto write_padded(OutputIt out, const basic_format_specs& specs, + size_t size, F&& f) -> OutputIt { + return write_padded(out, specs, size, size, f); +} + +template +FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, + const basic_format_specs& specs) + -> OutputIt { + return write_padded( + out, specs, bytes.size(), [bytes](reserve_iterator it) { + const char* data = bytes.data(); + return copy_str(data, data + bytes.size(), it); + }); +} + +template +auto write_ptr(OutputIt out, UIntPtr value, + const basic_format_specs* specs) -> OutputIt { + int num_digits = count_digits<4>(value); + auto size = to_unsigned(num_digits) + size_t(2); + auto write = [=](reserve_iterator it) { + *it++ = static_cast('0'); + *it++ = static_cast('x'); + return format_uint<4, Char>(it, value, num_digits); + }; + return specs ? write_padded(out, *specs, size, write) + : base_iterator(out, write(reserve(out, size))); +} + +// Returns true iff the code point cp is printable. +FMT_API auto is_printable(uint32_t cp) -> bool; + +inline auto needs_escape(uint32_t cp) -> bool { + return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' || + !is_printable(cp); +} + +template struct find_escape_result { + const Char* begin; + const Char* end; + uint32_t cp; +}; + +template +using make_unsigned_char = + typename conditional_t::value, + std::make_unsigned, + type_identity>::type; + +template +auto find_escape(const Char* begin, const Char* end) + -> find_escape_result { + for (; begin != end; ++begin) { + uint32_t cp = static_cast>(*begin); + if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue; + if (needs_escape(cp)) return {begin, begin + 1, cp}; + } + return {begin, nullptr, 0}; +} + +inline auto find_escape(const char* begin, const char* end) + -> find_escape_result { + if (!is_utf8()) return find_escape(begin, end); + auto result = find_escape_result{end, nullptr, 0}; + for_each_codepoint(string_view(begin, to_unsigned(end - begin)), + [&](uint32_t cp, string_view sv) { + if (needs_escape(cp)) { + result = {sv.begin(), sv.end(), cp}; + return false; + } + return true; + }); + return result; +} + +#define FMT_STRING_IMPL(s, base, explicit) \ + [] { \ + /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ + /* Use a macro-like name to avoid shadowing warnings. */ \ + struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \ + using char_type = fmt::remove_cvref_t; \ + FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ + operator fmt::basic_string_view() const { \ + return fmt::detail_exported::compile_string_to_view(s); \ + } \ + }; \ + return FMT_COMPILE_STRING(); \ + }() + +/** + \rst + Constructs a compile-time format string from a string literal *s*. + + **Example**:: + + // A compile-time error because 'd' is an invalid specifier for strings. + std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); + \endrst + */ +#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) + +template +auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt { + *out++ = static_cast('\\'); + *out++ = static_cast(prefix); + Char buf[width]; + fill_n(buf, width, static_cast('0')); + format_uint<4>(buf, cp, width); + return copy_str(buf, buf + width, out); +} + +template +auto write_escaped_cp(OutputIt out, const find_escape_result& escape) + -> OutputIt { + auto c = static_cast(escape.cp); + switch (escape.cp) { + case '\n': + *out++ = static_cast('\\'); + c = static_cast('n'); + break; + case '\r': + *out++ = static_cast('\\'); + c = static_cast('r'); + break; + case '\t': + *out++ = static_cast('\\'); + c = static_cast('t'); + break; + case '"': + FMT_FALLTHROUGH; + case '\'': + FMT_FALLTHROUGH; + case '\\': + *out++ = static_cast('\\'); + break; + default: + if (is_utf8()) { + if (escape.cp < 0x100) { + return write_codepoint<2, Char>(out, 'x', escape.cp); + } + if (escape.cp < 0x10000) { + return write_codepoint<4, Char>(out, 'u', escape.cp); + } + if (escape.cp < 0x110000) { + return write_codepoint<8, Char>(out, 'U', escape.cp); + } + } + for (Char escape_char : basic_string_view( + escape.begin, to_unsigned(escape.end - escape.begin))) { + out = write_codepoint<2, Char>(out, 'x', + static_cast(escape_char) & 0xFF); + } + return out; + } + *out++ = c; + return out; +} + +template +auto write_escaped_string(OutputIt out, basic_string_view str) + -> OutputIt { + *out++ = static_cast('"'); + auto begin = str.begin(), end = str.end(); + do { + auto escape = find_escape(begin, end); + out = copy_str(begin, escape.begin, out); + begin = escape.end; + if (!begin) break; + out = write_escaped_cp(out, escape); + } while (begin != end); + *out++ = static_cast('"'); + return out; +} + +template +auto write_escaped_char(OutputIt out, Char v) -> OutputIt { + *out++ = static_cast('\''); + if ((needs_escape(static_cast(v)) && v != static_cast('"')) || + v == static_cast('\'')) { + out = write_escaped_cp( + out, find_escape_result{&v, &v + 1, static_cast(v)}); + } else { + *out++ = v; + } + *out++ = static_cast('\''); + return out; +} + +template +FMT_CONSTEXPR auto write_char(OutputIt out, Char value, + const basic_format_specs& specs) + -> OutputIt { + bool is_debug = specs.type == presentation_type::debug; + return write_padded(out, specs, 1, [=](reserve_iterator it) { + if (is_debug) return write_escaped_char(it, value); + *it++ = value; + return it; + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, Char value, + const basic_format_specs& specs, + locale_ref loc = {}) -> OutputIt { + return check_char_specs(specs) + ? write_char(out, value, specs) + : write(out, static_cast(value), specs, loc); +} + +// Data for write_int that doesn't depend on output iterator type. It is used to +// avoid template code bloat. +template struct write_int_data { + size_t size; + size_t padding; + + FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, + const basic_format_specs& specs) + : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { + if (specs.align == align::numeric) { + auto width = to_unsigned(specs.width); + if (width > size) { + padding = width - size; + size = width; + } + } else if (specs.precision > num_digits) { + size = (prefix >> 24) + to_unsigned(specs.precision); + padding = to_unsigned(specs.precision - num_digits); + } + } +}; + +// Writes an integer in the format +// +// where are written by write_digits(it). +// prefix contains chars in three lower bytes and the size in the fourth byte. +template +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, + unsigned prefix, + const basic_format_specs& specs, + W write_digits) -> OutputIt { + // Slightly faster check for specs.width == 0 && specs.precision == -1. + if ((specs.width | (specs.precision + 1)) == 0) { + auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24)); + if (prefix != 0) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + } + return base_iterator(out, write_digits(it)); + } + auto data = write_int_data(num_digits, prefix, specs); + return write_padded( + out, specs, data.size, [=](reserve_iterator it) { + for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) + *it++ = static_cast(p & 0xff); + it = detail::fill_n(it, data.padding, static_cast('0')); + return write_digits(it); + }); +} + +template class digit_grouping { + private: + thousands_sep_result sep_; + + struct next_state { + std::string::const_iterator group; + int pos; + }; + next_state initial_state() const { return {sep_.grouping.begin(), 0}; } + + // Returns the next digit group separator position. + int next(next_state& state) const { + if (!sep_.thousands_sep) return max_value(); + if (state.group == sep_.grouping.end()) + return state.pos += sep_.grouping.back(); + if (*state.group <= 0 || *state.group == max_value()) + return max_value(); + state.pos += *state.group++; + return state.pos; + } + + public: + explicit digit_grouping(locale_ref loc, bool localized = true) { + if (localized) + sep_ = thousands_sep(loc); + else + sep_.thousands_sep = Char(); + } + explicit digit_grouping(thousands_sep_result sep) : sep_(sep) {} + + Char separator() const { return sep_.thousands_sep; } + + int count_separators(int num_digits) const { + int count = 0; + auto state = initial_state(); + while (num_digits > next(state)) ++count; + return count; + } + + // Applies grouping to digits and write the output to out. + template + Out apply(Out out, basic_string_view digits) const { + auto num_digits = static_cast(digits.size()); + auto separators = basic_memory_buffer(); + separators.push_back(0); + auto state = initial_state(); + while (int i = next(state)) { + if (i >= num_digits) break; + separators.push_back(i); + } + for (int i = 0, sep_index = static_cast(separators.size() - 1); + i < num_digits; ++i) { + if (num_digits - i == separators[sep_index]) { + *out++ = separator(); + --sep_index; + } + *out++ = static_cast(digits[to_unsigned(i)]); + } + return out; + } +}; + +template +auto write_int_localized(OutputIt out, UInt value, unsigned prefix, + const basic_format_specs& specs, + const digit_grouping& grouping) -> OutputIt { + static_assert(std::is_same, UInt>::value, ""); + int num_digits = count_digits(value); + char digits[40]; + format_decimal(digits, value, num_digits); + unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits + + grouping.count_separators(num_digits)); + return write_padded( + out, specs, size, size, [&](reserve_iterator it) { + if (prefix != 0) *it++ = static_cast(prefix); + return grouping.apply(it, string_view(digits, to_unsigned(num_digits))); + }); +} + +template +auto write_int_localized(OutputIt& out, UInt value, unsigned prefix, + const basic_format_specs& specs, locale_ref loc) + -> bool { + auto grouping = digit_grouping(loc); + out = write_int_localized(out, value, prefix, specs, grouping); + return true; +} + +FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { + prefix |= prefix != 0 ? value << 8 : value; + prefix += (1u + (value > 0xff ? 1 : 0)) << 24; +} + +template struct write_int_arg { + UInt abs_value; + unsigned prefix; +}; + +template +FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) + -> write_int_arg> { + auto prefix = 0u; + auto abs_value = static_cast>(value); + if (is_negative(value)) { + prefix = 0x01000000 | '-'; + abs_value = 0 - abs_value; + } else { + constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', + 0x1000000u | ' '}; + prefix = prefixes[sign]; + } + return {abs_value, prefix}; +} + +template +FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg arg, + const basic_format_specs& specs, + locale_ref loc) -> OutputIt { + static_assert(std::is_same>::value, ""); + auto abs_value = arg.abs_value; + auto prefix = arg.prefix; + switch (specs.type) { + case presentation_type::none: + case presentation_type::dec: { + if (specs.localized && + write_int_localized(out, static_cast>(abs_value), + prefix, specs, loc)) { + return out; + } + auto num_digits = count_digits(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_decimal(it, abs_value, num_digits).end; + }); + } + case presentation_type::hex_lower: + case presentation_type::hex_upper: { + bool upper = specs.type == presentation_type::hex_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0'); + int num_digits = count_digits<4>(abs_value); + return write_int( + out, num_digits, prefix, specs, [=](reserve_iterator it) { + return format_uint<4, Char>(it, abs_value, num_digits, upper); + }); + } + case presentation_type::bin_lower: + case presentation_type::bin_upper: { + bool upper = specs.type == presentation_type::bin_upper; + if (specs.alt) + prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0'); + int num_digits = count_digits<1>(abs_value); + return write_int(out, num_digits, prefix, specs, + [=](reserve_iterator it) { + return format_uint<1, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::oct: { + int num_digits = count_digits<3>(abs_value); + // Octal prefix '0' is counted as a digit, so only add it if precision + // is not greater than the number of digits. + if (specs.alt && specs.precision <= num_digits && abs_value != 0) + prefix_append(prefix, '0'); + return write_int(out, num_digits, prefix, specs, + [=](reserve_iterator it) { + return format_uint<3, Char>(it, abs_value, num_digits); + }); + } + case presentation_type::chr: + return write_char(out, static_cast(abs_value), specs); + default: + throw_format_error("invalid type specifier"); + } + return out; +} +template +FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline( + OutputIt out, write_int_arg arg, const basic_format_specs& specs, + locale_ref loc) -> OutputIt { + return write_int(out, arg, specs, loc); +} +template ::value && + !std::is_same::value && + std::is_same>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs& specs, + locale_ref loc) -> OutputIt { + return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs, + loc); +} +// An inlined version of write used in format string compilation. +template ::value && + !std::is_same::value && + !std::is_same>::value)> +FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, + const basic_format_specs& specs, + locale_ref loc) -> OutputIt { + return write_int(out, make_write_int_arg(value, specs.sign), specs, loc); +} + +// An output iterator that counts the number of objects written to it and +// discards them. +class counting_iterator { + private: + size_t count_; + + public: + using iterator_category = std::output_iterator_tag; + using difference_type = std::ptrdiff_t; + using pointer = void; + using reference = void; + FMT_UNCHECKED_ITERATOR(counting_iterator); + + struct value_type { + template void operator=(const T&) {} + }; + + counting_iterator() : count_(0) {} + + size_t count() const { return count_; } + + counting_iterator& operator++() { + ++count_; + return *this; + } + counting_iterator operator++(int) { + auto it = *this; + ++*this; + return it; + } + + friend counting_iterator operator+(counting_iterator it, difference_type n) { + it.count_ += static_cast(n); + return it; + } + + value_type operator*() const { return {}; } +}; + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view s, + const basic_format_specs& specs) -> OutputIt { + auto data = s.data(); + auto size = s.size(); + if (specs.precision >= 0 && to_unsigned(specs.precision) < size) + size = code_point_index(s, to_unsigned(specs.precision)); + bool is_debug = specs.type == presentation_type::debug; + size_t width = 0; + if (specs.width != 0) { + if (is_debug) + width = write_escaped_string(counting_iterator{}, s).count(); + else + width = compute_width(basic_string_view(data, size)); + } + return write_padded(out, specs, size, width, + [=](reserve_iterator it) { + if (is_debug) return write_escaped_string(it, s); + return copy_str(data, data + size, it); + }); +} +template +FMT_CONSTEXPR auto write(OutputIt out, + basic_string_view> s, + const basic_format_specs& specs, locale_ref) + -> OutputIt { + check_string_type_spec(specs.type); + return write(out, s, specs); +} +template +FMT_CONSTEXPR auto write(OutputIt out, const Char* s, + const basic_format_specs& specs, locale_ref) + -> OutputIt { + return check_cstring_type_spec(specs.type) + ? write(out, basic_string_view(s), specs, {}) + : write_ptr(out, bit_cast(s), &specs); +} + +template ::value && + !std::is_same::value && + !std::is_same::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + auto abs_value = static_cast>(value); + bool negative = is_negative(value); + // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. + if (negative) abs_value = ~abs_value + 1; + int num_digits = count_digits(abs_value); + auto size = (negative ? 1 : 0) + static_cast(num_digits); + auto it = reserve(out, size); + if (auto ptr = to_pointer(it, size)) { + if (negative) *ptr++ = static_cast('-'); + format_decimal(ptr, abs_value, num_digits); + return out; + } + if (negative) *it++ = static_cast('-'); + it = format_decimal(it, abs_value, num_digits).end; + return base_iterator(out, it); +} + +template +FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, + basic_format_specs specs, + const float_specs& fspecs) -> OutputIt { + auto str = + isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf"); + constexpr size_t str_size = 3; + auto sign = fspecs.sign; + auto size = str_size + (sign ? 1 : 0); + // Replace '0'-padding with space for non-finite values. + const bool is_zero_fill = + specs.fill.size() == 1 && *specs.fill.data() == static_cast('0'); + if (is_zero_fill) specs.fill[0] = static_cast(' '); + return write_padded(out, specs, size, [=](reserve_iterator it) { + if (sign) *it++ = detail::sign(sign); + return copy_str(str, str + str_size, it); + }); +} + +// A decimal floating-point number significand * pow(10, exp). +struct big_decimal_fp { + const char* significand; + int significand_size; + int exponent; +}; + +constexpr auto get_significand_size(const big_decimal_fp& f) -> int { + return f.significand_size; +} +template +inline auto get_significand_size(const dragonbox::decimal_fp& f) -> int { + return count_digits(f.significand); +} + +template +constexpr auto write_significand(OutputIt out, const char* significand, + int significand_size) -> OutputIt { + return copy_str(significand, significand + significand_size, out); +} +template +inline auto write_significand(OutputIt out, UInt significand, + int significand_size) -> OutputIt { + return format_decimal(out, significand, significand_size).end; +} +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int exponent, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + out = write_significand(out, significand, significand_size); + return detail::fill_n(out, exponent, static_cast('0')); + } + auto buffer = memory_buffer(); + write_significand(appender(buffer), significand, significand_size); + detail::fill_n(appender(buffer), exponent, '0'); + return grouping.apply(out, string_view(buffer.data(), buffer.size())); +} + +template ::value)> +inline auto write_significand(Char* out, UInt significand, int significand_size, + int integral_size, Char decimal_point) -> Char* { + if (!decimal_point) + return format_decimal(out, significand, significand_size).end; + out += significand_size + 1; + Char* end = out; + int floating_size = significand_size - integral_size; + for (int i = floating_size / 2; i > 0; --i) { + out -= 2; + copy2(out, digits2(static_cast(significand % 100))); + significand /= 100; + } + if (floating_size % 2 != 0) { + *--out = static_cast('0' + significand % 10); + significand /= 10; + } + *--out = decimal_point; + format_decimal(out - integral_size, significand, integral_size); + return end; +} + +template >::value)> +inline auto write_significand(OutputIt out, UInt significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + // Buffer is large enough to hold digits (digits10 + 1) and a decimal point. + Char buffer[digits10() + 2]; + auto end = write_significand(buffer, significand, significand_size, + integral_size, decimal_point); + return detail::copy_str_noinline(buffer, end, out); +} + +template +FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, + int significand_size, int integral_size, + Char decimal_point) -> OutputIt { + out = detail::copy_str_noinline(significand, + significand + integral_size, out); + if (!decimal_point) return out; + *out++ = decimal_point; + return detail::copy_str_noinline(significand + integral_size, + significand + significand_size, out); +} + +template +FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, + int significand_size, int integral_size, + Char decimal_point, + const Grouping& grouping) -> OutputIt { + if (!grouping.separator()) { + return write_significand(out, significand, significand_size, integral_size, + decimal_point); + } + auto buffer = basic_memory_buffer(); + write_significand(buffer_appender(buffer), significand, + significand_size, integral_size, decimal_point); + grouping.apply( + out, basic_string_view(buffer.data(), to_unsigned(integral_size))); + return detail::copy_str_noinline(buffer.data() + integral_size, + buffer.end(), out); +} + +template > +FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, + const basic_format_specs& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + auto significand = f.significand; + int significand_size = get_significand_size(f); + const Char zero = static_cast('0'); + auto sign = fspecs.sign; + size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); + using iterator = reserve_iterator; + + Char decimal_point = + fspecs.locale ? detail::decimal_point(loc) : static_cast('.'); + + int output_exp = f.exponent + significand_size - 1; + auto use_exp_format = [=]() { + if (fspecs.format == float_format::exp) return true; + if (fspecs.format != float_format::general) return false; + // Use the fixed notation if the exponent is in [exp_lower, exp_upper), + // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. + const int exp_lower = -4, exp_upper = 16; + return output_exp < exp_lower || + output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); + }; + if (use_exp_format()) { + int num_zeros = 0; + if (fspecs.showpoint) { + num_zeros = fspecs.precision - significand_size; + if (num_zeros < 0) num_zeros = 0; + size += to_unsigned(num_zeros); + } else if (significand_size == 1) { + decimal_point = Char(); + } + auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; + int exp_digits = 2; + if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; + + size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); + char exp_char = fspecs.upper ? 'E' : 'e'; + auto write = [=](iterator it) { + if (sign) *it++ = detail::sign(sign); + // Insert a decimal point after the first digit and add an exponent. + it = write_significand(it, significand, significand_size, 1, + decimal_point); + if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); + *it++ = static_cast(exp_char); + return write_exponent(output_exp, it); + }; + return specs.width > 0 ? write_padded(out, specs, size, write) + : base_iterator(out, write(reserve(out, size))); + } + + int exp = f.exponent + significand_size; + if (f.exponent >= 0) { + // 1234e5 -> 123400000[.0+] + size += to_unsigned(f.exponent); + int num_zeros = fspecs.precision - exp; + abort_fuzzing_if(num_zeros > 5000); + if (fspecs.showpoint) { + ++size; + if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1; + if (num_zeros > 0) size += to_unsigned(num_zeros); + } + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(exp)); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + it = write_significand(it, significand, significand_size, + f.exponent, grouping); + if (!fspecs.showpoint) return it; + *it++ = decimal_point; + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } else if (exp > 0) { + // 1234e-2 -> 12.34[0+] + int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0; + size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0); + auto grouping = Grouping(loc, fspecs.locale); + size += to_unsigned(grouping.count_separators(significand_size)); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + it = write_significand(it, significand, significand_size, exp, + decimal_point, grouping); + return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; + }); + } + // 1234e-6 -> 0.001234 + int num_zeros = -exp; + if (significand_size == 0 && fspecs.precision >= 0 && + fspecs.precision < num_zeros) { + num_zeros = fspecs.precision; + } + bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint; + size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros); + return write_padded(out, specs, size, [&](iterator it) { + if (sign) *it++ = detail::sign(sign); + *it++ = zero; + if (!pointy) return it; + *it++ = decimal_point; + it = detail::fill_n(it, num_zeros, zero); + return write_significand(it, significand, significand_size); + }); +} + +template class fallback_digit_grouping { + public: + constexpr fallback_digit_grouping(locale_ref, bool) {} + + constexpr Char separator() const { return Char(); } + + constexpr int count_separators(int) const { return 0; } + + template + constexpr Out apply(Out out, basic_string_view) const { + return out; + } +}; + +template +FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, + const basic_format_specs& specs, + float_specs fspecs, locale_ref loc) + -> OutputIt { + if (is_constant_evaluated()) { + return do_write_float>(out, f, specs, fspecs, + loc); + } else { + return do_write_float(out, f, specs, fspecs, loc); + } +} + +template constexpr bool isnan(T value) { + return !(value >= value); // std::isnan doesn't support __float128. +} + +template +struct has_isfinite : std::false_type {}; + +template +struct has_isfinite> + : std::true_type {}; + +template ::value&& + has_isfinite::value)> +FMT_CONSTEXPR20 bool isfinite(T value) { + constexpr T inf = T(std::numeric_limits::infinity()); + if (is_constant_evaluated()) + return !detail::isnan(value) && value != inf && value != -inf; + return std::isfinite(value); +} +template ::value)> +FMT_CONSTEXPR bool isfinite(T value) { + T inf = T(std::numeric_limits::infinity()); + // std::isfinite doesn't support __float128. + return !detail::isnan(value) && value != inf && value != -inf; +} + +template ::value)> +FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { + if (is_constant_evaluated()) { +#ifdef __cpp_if_constexpr + if constexpr (std::numeric_limits::is_iec559) { + auto bits = detail::bit_cast(static_cast(value)); + return (bits >> (num_bits() - 1)) != 0; + } +#endif + } + return std::signbit(static_cast(value)); +} + +enum class round_direction { unknown, up, down }; + +// Given the divisor (normally a power of 10), the remainder = v % divisor for +// some number v and the error, returns whether v should be rounded up, down, or +// whether the rounding direction can't be determined due to error. +// error should be less than divisor / 2. +FMT_CONSTEXPR inline round_direction get_round_direction(uint64_t divisor, + uint64_t remainder, + uint64_t error) { + FMT_ASSERT(remainder < divisor, ""); // divisor - remainder won't overflow. + FMT_ASSERT(error < divisor, ""); // divisor - error won't overflow. + FMT_ASSERT(error < divisor - error, ""); // error * 2 won't overflow. + // Round down if (remainder + error) * 2 <= divisor. + if (remainder <= divisor - remainder && error * 2 <= divisor - remainder * 2) + return round_direction::down; + // Round up if (remainder - error) * 2 >= divisor. + if (remainder >= error && + remainder - error >= divisor - (remainder - error)) { + return round_direction::up; + } + return round_direction::unknown; +} + +namespace digits { +enum result { + more, // Generate more digits. + done, // Done generating digits. + error // Digit generation cancelled due to an error. +}; +} + +struct gen_digits_handler { + char* buf; + int size; + int precision; + int exp10; + bool fixed; + + FMT_CONSTEXPR digits::result on_digit(char digit, uint64_t divisor, + uint64_t remainder, uint64_t error, + bool integral) { + FMT_ASSERT(remainder < divisor, ""); + buf[size++] = digit; + if (!integral && error >= remainder) return digits::error; + if (size < precision) return digits::more; + if (!integral) { + // Check if error * 2 < divisor with overflow prevention. + // The check is not needed for the integral part because error = 1 + // and divisor > (1 << 32) there. + if (error >= divisor || error >= divisor - error) return digits::error; + } else { + FMT_ASSERT(error == 1 && divisor > 2, ""); + } + auto dir = get_round_direction(divisor, remainder, error); + if (dir != round_direction::up) + return dir == round_direction::down ? digits::done : digits::error; + ++buf[size - 1]; + for (int i = size - 1; i > 0 && buf[i] > '9'; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] > '9') { + buf[0] = '1'; + if (fixed) + buf[size++] = '0'; + else + ++exp10; + } + return digits::done; + } +}; + +inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) { + // Adjust fixed precision by exponent because it is relative to decimal + // point. + if (exp10 > 0 && precision > max_value() - exp10) + log_error("number is too big"); + precision += exp10; +} + +// Generates output using the Grisu digit-gen algorithm. +// error: the size of the region (lower, upper) outside of which numbers +// definitely do not round to value (Delta in Grisu3). +FMT_INLINE FMT_CONSTEXPR20 auto grisu_gen_digits(fp value, uint64_t error, + int& exp, + gen_digits_handler& handler) + -> digits::result { + const fp one(1ULL << -value.e, value.e); + // The integral part of scaled value (p1 in Grisu) = value / one. It cannot be + // zero because it contains a product of two 64-bit numbers with MSB set (due + // to normalization) - 1, shifted right by at most 60 bits. + auto integral = static_cast(value.f >> -one.e); + FMT_ASSERT(integral != 0, ""); + FMT_ASSERT(integral == value.f >> -one.e, ""); + // The fractional part of scaled value (p2 in Grisu) c = value % one. + uint64_t fractional = value.f & (one.f - 1); + exp = count_digits(integral); // kappa in Grisu. + // Non-fixed formats require at least one digit and no precision adjustment. + if (handler.fixed) { + adjust_precision(handler.precision, exp + handler.exp10); + // Check if precision is satisfied just by leading zeros, e.g. + // format("{:.2f}", 0.001) gives "0.00" without generating any digits. + if (handler.precision <= 0) { + if (handler.precision < 0) return digits::done; + // Divide by 10 to prevent overflow. + uint64_t divisor = data::power_of_10_64[exp - 1] << -one.e; + auto dir = get_round_direction(divisor, value.f / 10, error * 10); + if (dir == round_direction::unknown) return digits::error; + handler.buf[handler.size++] = dir == round_direction::up ? '1' : '0'; + return digits::done; + } + } + // Generate digits for the integral part. This can produce up to 10 digits. + do { + uint32_t digit = 0; + auto divmod_integral = [&](uint32_t divisor) { + digit = integral / divisor; + integral %= divisor; + }; + // This optimization by Milo Yip reduces the number of integer divisions by + // one per iteration. + switch (exp) { + case 10: + divmod_integral(1000000000); + break; + case 9: + divmod_integral(100000000); + break; + case 8: + divmod_integral(10000000); + break; + case 7: + divmod_integral(1000000); + break; + case 6: + divmod_integral(100000); + break; + case 5: + divmod_integral(10000); + break; + case 4: + divmod_integral(1000); + break; + case 3: + divmod_integral(100); + break; + case 2: + divmod_integral(10); + break; + case 1: + digit = integral; + integral = 0; + break; + default: + FMT_ASSERT(false, "invalid number of digits"); + } + --exp; + auto remainder = (static_cast(integral) << -one.e) + fractional; + auto result = handler.on_digit(static_cast('0' + digit), + data::power_of_10_64[exp] << -one.e, + remainder, error, true); + if (result != digits::more) return result; + } while (exp > 0); + // Generate digits for the fractional part. + for (;;) { + fractional *= 10; + error *= 10; + char digit = static_cast('0' + (fractional >> -one.e)); + fractional &= one.f - 1; + --exp; + auto result = handler.on_digit(digit, one.f, fractional, error, false); + if (result != digits::more) return result; + } +} + +class bigint { + private: + // A bigint is stored as an array of bigits (big digits), with bigit at index + // 0 being the least significant one. + using bigit = uint32_t; + using double_bigit = uint64_t; + enum { bigits_capacity = 32 }; + basic_memory_buffer bigits_; + int exp_; + + FMT_CONSTEXPR20 bigit operator[](int index) const { + return bigits_[to_unsigned(index)]; + } + FMT_CONSTEXPR20 bigit& operator[](int index) { + return bigits_[to_unsigned(index)]; + } + + static constexpr const int bigit_bits = num_bits(); + + friend struct formatter; + + FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { + auto result = static_cast((*this)[index]) - other - borrow; + (*this)[index] = static_cast(result); + borrow = static_cast(result >> (bigit_bits * 2 - 1)); + } + + FMT_CONSTEXPR20 void remove_leading_zeros() { + int num_bigits = static_cast(bigits_.size()) - 1; + while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; + bigits_.resize(to_unsigned(num_bigits + 1)); + } + + // Computes *this -= other assuming aligned bigints and *this >= other. + FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) { + FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); + FMT_ASSERT(compare(*this, other) >= 0, ""); + bigit borrow = 0; + int i = other.exp_ - exp_; + for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) + subtract_bigits(i, other.bigits_[j], borrow); + while (borrow > 0) subtract_bigits(i, 0, borrow); + remove_leading_zeros(); + } + + FMT_CONSTEXPR20 void multiply(uint32_t value) { + const double_bigit wide_value = value; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + double_bigit result = bigits_[i] * wide_value + carry; + bigits_[i] = static_cast(result); + carry = static_cast(result >> bigit_bits); + } + if (carry != 0) bigits_.push_back(carry); + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR20 void multiply(UInt value) { + using half_uint = + conditional_t::value, uint64_t, uint32_t>; + const int shift = num_bits() - bigit_bits; + const UInt lower = static_cast(value); + const UInt upper = value >> num_bits(); + UInt carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + UInt result = lower * bigits_[i] + static_cast(carry); + carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) + + (carry >> bigit_bits); + bigits_[i] = static_cast(result); + } + while (carry != 0) { + bigits_.push_back(static_cast(carry)); + carry >>= bigit_bits; + } + } + + template ::value || + std::is_same::value)> + FMT_CONSTEXPR20 void assign(UInt n) { + size_t num_bigits = 0; + do { + bigits_[num_bigits++] = static_cast(n); + n >>= bigit_bits; + } while (n != 0); + bigits_.resize(num_bigits); + exp_ = 0; + } + + public: + FMT_CONSTEXPR20 bigint() : exp_(0) {} + explicit bigint(uint64_t n) { assign(n); } + + bigint(const bigint&) = delete; + void operator=(const bigint&) = delete; + + FMT_CONSTEXPR20 void assign(const bigint& other) { + auto size = other.bigits_.size(); + bigits_.resize(size); + auto data = other.bigits_.data(); + std::copy(data, data + size, make_checked(bigits_.data(), size)); + exp_ = other.exp_; + } + + template FMT_CONSTEXPR20 void operator=(Int n) { + FMT_ASSERT(n > 0, ""); + assign(uint64_or_128_t(n)); + } + + FMT_CONSTEXPR20 int num_bigits() const { + return static_cast(bigits_.size()) + exp_; + } + + FMT_NOINLINE FMT_CONSTEXPR20 bigint& operator<<=(int shift) { + FMT_ASSERT(shift >= 0, ""); + exp_ += shift / bigit_bits; + shift %= bigit_bits; + if (shift == 0) return *this; + bigit carry = 0; + for (size_t i = 0, n = bigits_.size(); i < n; ++i) { + bigit c = bigits_[i] >> (bigit_bits - shift); + bigits_[i] = (bigits_[i] << shift) + carry; + carry = c; + } + if (carry != 0) bigits_.push_back(carry); + return *this; + } + + template FMT_CONSTEXPR20 bigint& operator*=(Int value) { + FMT_ASSERT(value > 0, ""); + multiply(uint32_or_64_or_128_t(value)); + return *this; + } + + friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) { + int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); + if (num_lhs_bigits != num_rhs_bigits) + return num_lhs_bigits > num_rhs_bigits ? 1 : -1; + int i = static_cast(lhs.bigits_.size()) - 1; + int j = static_cast(rhs.bigits_.size()) - 1; + int end = i - j; + if (end < 0) end = 0; + for (; i >= end; --i, --j) { + bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j]; + if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1; + } + if (i != j) return i > j ? 1 : -1; + return 0; + } + + // Returns compare(lhs1 + lhs2, rhs). + friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2, + const bigint& rhs) { + auto minimum = [](int a, int b) { return a < b ? a : b; }; + auto maximum = [](int a, int b) { return a > b ? a : b; }; + int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits()); + int num_rhs_bigits = rhs.num_bigits(); + if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; + if (max_lhs_bigits > num_rhs_bigits) return 1; + auto get_bigit = [](const bigint& n, int i) -> bigit { + return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; + }; + double_bigit borrow = 0; + int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_); + for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { + double_bigit sum = + static_cast(get_bigit(lhs1, i)) + get_bigit(lhs2, i); + bigit rhs_bigit = get_bigit(rhs, i); + if (sum > rhs_bigit + borrow) return 1; + borrow = rhs_bigit + borrow - sum; + if (borrow > 1) return -1; + borrow <<= bigit_bits; + } + return borrow != 0 ? -1 : 0; + } + + // Assigns pow(10, exp) to this bigint. + FMT_CONSTEXPR20 void assign_pow10(int exp) { + FMT_ASSERT(exp >= 0, ""); + if (exp == 0) return *this = 1; + // Find the top bit. + int bitmask = 1; + while (exp >= bitmask) bitmask <<= 1; + bitmask >>= 1; + // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by + // repeated squaring and multiplication. + *this = 5; + bitmask >>= 1; + while (bitmask != 0) { + square(); + if ((exp & bitmask) != 0) *this *= 5; + bitmask >>= 1; + } + *this <<= exp; // Multiply by pow(2, exp) by shifting. + } + + FMT_CONSTEXPR20 void square() { + int num_bigits = static_cast(bigits_.size()); + int num_result_bigits = 2 * num_bigits; + basic_memory_buffer n(std::move(bigits_)); + bigits_.resize(to_unsigned(num_result_bigits)); + auto sum = uint128_t(); + for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { + // Compute bigit at position bigit_index of the result by adding + // cross-product terms n[i] * n[j] such that i + j == bigit_index. + for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { + // Most terms are multiplied twice which can be optimized in the future. + sum += static_cast(n[i]) * n[j]; + } + (*this)[bigit_index] = static_cast(sum); + sum >>= num_bits(); // Compute the carry. + } + // Do the same for the top half. + for (int bigit_index = num_bigits; bigit_index < num_result_bigits; + ++bigit_index) { + for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) + sum += static_cast(n[i++]) * n[j--]; + (*this)[bigit_index] = static_cast(sum); + sum >>= num_bits(); + } + remove_leading_zeros(); + exp_ *= 2; + } + + // If this bigint has a bigger exponent than other, adds trailing zero to make + // exponents equal. This simplifies some operations such as subtraction. + FMT_CONSTEXPR20 void align(const bigint& other) { + int exp_difference = exp_ - other.exp_; + if (exp_difference <= 0) return; + int num_bigits = static_cast(bigits_.size()); + bigits_.resize(to_unsigned(num_bigits + exp_difference)); + for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) + bigits_[j] = bigits_[i]; + std::uninitialized_fill_n(bigits_.data(), exp_difference, 0); + exp_ -= exp_difference; + } + + // Divides this bignum by divisor, assigning the remainder to this and + // returning the quotient. + FMT_CONSTEXPR20 int divmod_assign(const bigint& divisor) { + FMT_ASSERT(this != &divisor, ""); + if (compare(*this, divisor) < 0) return 0; + FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); + align(divisor); + int quotient = 0; + do { + subtract_aligned(divisor); + ++quotient; + } while (compare(*this, divisor) >= 0); + return quotient; + } +}; + +// format_dragon flags. +enum dragon { + predecessor_closer = 1, + fixup = 2, // Run fixup to correct exp10 which can be off by one. + fixed = 4, +}; + +// Formats a floating-point number using a variation of the Fixed-Precision +// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White: +// https://fmt.dev/papers/p372-steele.pdf. +FMT_CONSTEXPR20 inline void format_dragon(basic_fp value, + unsigned flags, int num_digits, + buffer& buf, int& exp10) { + bigint numerator; // 2 * R in (FPP)^2. + bigint denominator; // 2 * S in (FPP)^2. + // lower and upper are differences between value and corresponding boundaries. + bigint lower; // (M^- in (FPP)^2). + bigint upper_store; // upper's value if different from lower. + bigint* upper = nullptr; // (M^+ in (FPP)^2). + // Shift numerator and denominator by an extra bit or two (if lower boundary + // is closer) to make lower and upper integers. This eliminates multiplication + // by 2 during later computations. + bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0; + int shift = is_predecessor_closer ? 2 : 1; + if (value.e >= 0) { + numerator = value.f; + numerator <<= value.e + shift; + lower = 1; + lower <<= value.e; + if (is_predecessor_closer) { + upper_store = 1; + upper_store <<= value.e + 1; + upper = &upper_store; + } + denominator.assign_pow10(exp10); + denominator <<= shift; + } else if (exp10 < 0) { + numerator.assign_pow10(-exp10); + lower.assign(numerator); + if (is_predecessor_closer) { + upper_store.assign(numerator); + upper_store <<= 1; + upper = &upper_store; + } + numerator *= value.f; + numerator <<= shift; + denominator = 1; + denominator <<= shift - value.e; + } else { + numerator = value.f; + numerator <<= shift; + denominator.assign_pow10(exp10); + denominator <<= shift - value.e; + lower = 1; + if (is_predecessor_closer) { + upper_store = 1ULL << 1; + upper = &upper_store; + } + } + bool even = (value.f & 1) == 0; + if (!upper) upper = &lower; + if ((flags & dragon::fixup) != 0) { + if (add_compare(numerator, *upper, denominator) + even <= 0) { + --exp10; + numerator *= 10; + if (num_digits < 0) { + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1); + } + // Invariant: value == (numerator / denominator) * pow(10, exp10). + if (num_digits < 0) { + // Generate the shortest representation. + num_digits = 0; + char* data = buf.data(); + for (;;) { + int digit = numerator.divmod_assign(denominator); + bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. + // numerator + upper >[=] pow10: + bool high = add_compare(numerator, *upper, denominator) + even > 0; + data[num_digits++] = static_cast('0' + digit); + if (low || high) { + if (!low) { + ++data[num_digits - 1]; + } else if (high) { + int result = add_compare(numerator, numerator, denominator); + // Round half to even. + if (result > 0 || (result == 0 && (digit % 2) != 0)) + ++data[num_digits - 1]; + } + buf.try_resize(to_unsigned(num_digits)); + exp10 -= num_digits - 1; + return; + } + numerator *= 10; + lower *= 10; + if (upper != &lower) *upper *= 10; + } + } + // Generate the given number of digits. + exp10 -= num_digits - 1; + if (num_digits == 0) { + denominator *= 10; + auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; + buf.push_back(digit); + return; + } + buf.try_resize(to_unsigned(num_digits)); + for (int i = 0; i < num_digits - 1; ++i) { + int digit = numerator.divmod_assign(denominator); + buf[i] = static_cast('0' + digit); + numerator *= 10; + } + int digit = numerator.divmod_assign(denominator); + auto result = add_compare(numerator, numerator, denominator); + if (result > 0 || (result == 0 && (digit % 2) != 0)) { + if (digit == 9) { + const auto overflow = '0' + 10; + buf[num_digits - 1] = overflow; + // Propagate the carry. + for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { + buf[i] = '0'; + ++buf[i - 1]; + } + if (buf[0] == overflow) { + buf[0] = '1'; + ++exp10; + } + return; + } + ++digit; + } + buf[num_digits - 1] = static_cast('0' + digit); +} + +template +FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, + buffer& buf) -> int { + // float is passed as double to reduce the number of instantiations. + static_assert(!std::is_same::value, ""); + FMT_ASSERT(value >= 0, "value is negative"); + auto converted_value = convert_float(value); + + const bool fixed = specs.format == float_format::fixed; + if (value <= 0) { // <= instead of == to silence a warning. + if (precision <= 0 || !fixed) { + buf.push_back('0'); + return 0; + } + buf.try_resize(to_unsigned(precision)); + fill_n(buf.data(), precision, '0'); + return -precision; + } + + int exp = 0; + bool use_dragon = true; + unsigned dragon_flags = 0; + if (!is_fast_float()) { + const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10) + using info = dragonbox::float_info; + const auto f = basic_fp(converted_value); + // Compute exp, an approximate power of 10, such that + // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1). + // This is based on log10(value) == log2(value) / log2(10) and approximation + // of log2(value) by e + num_fraction_bits idea from double-conversion. + exp = static_cast( + std::ceil((f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10)); + dragon_flags = dragon::fixup; + } else if (!is_constant_evaluated() && precision < 0) { + // Use Dragonbox for the shortest format. + if (specs.binary32) { + auto dec = dragonbox::to_decimal(static_cast(value)); + write(buffer_appender(buf), dec.significand); + return dec.exponent; + } + auto dec = dragonbox::to_decimal(static_cast(value)); + write(buffer_appender(buf), dec.significand); + return dec.exponent; + } else { + // Use Grisu + Dragon4 for the given precision: + // https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf. + const int min_exp = -60; // alpha in Grisu. + int cached_exp10 = 0; // K in Grisu. + fp normalized = normalize(fp(converted_value)); + const auto cached_pow = get_cached_power( + min_exp - (normalized.e + fp::num_significand_bits), cached_exp10); + normalized = normalized * cached_pow; + gen_digits_handler handler{buf.data(), 0, precision, -cached_exp10, fixed}; + if (grisu_gen_digits(normalized, 1, exp, handler) != digits::error && + !is_constant_evaluated()) { + exp += handler.exp10; + buf.try_resize(to_unsigned(handler.size)); + use_dragon = false; + } else { + exp += handler.size - cached_exp10 - 1; + precision = handler.precision; + } + } + if (use_dragon) { + auto f = basic_fp(); + bool is_predecessor_closer = specs.binary32 + ? f.assign(static_cast(value)) + : f.assign(converted_value); + if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer; + if (fixed) dragon_flags |= dragon::fixed; + // Limit precision to the maximum possible number of significant digits in + // an IEEE754 double because we don't need to generate zeros. + const int max_double_digits = 767; + if (precision > max_double_digits) precision = max_double_digits; + format_dragon(f, dragon_flags, precision, buf, exp); + } + if (!fixed && !specs.showpoint) { + // Remove trailing zeros. + auto num_digits = buf.size(); + while (num_digits > 0 && buf[num_digits - 1] == '0') { + --num_digits; + ++exp; + } + buf.try_resize(num_digits); + } + return exp; +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value, + basic_format_specs specs, locale_ref loc = {}) + -> OutputIt { + if (const_check(!is_supported_floating_point(value))) return out; + float_specs fspecs = parse_float_type_spec(specs); + fspecs.sign = specs.sign; + if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. + fspecs.sign = sign::minus; + value = -value; + } else if (fspecs.sign == sign::minus) { + fspecs.sign = sign::none; + } + + if (!detail::isfinite(value)) + return write_nonfinite(out, detail::isnan(value), specs, fspecs); + + if (specs.align == align::numeric && fspecs.sign) { + auto it = reserve(out, 1); + *it++ = detail::sign(fspecs.sign); + out = base_iterator(out, it); + fspecs.sign = sign::none; + if (specs.width != 0) --specs.width; + } + + memory_buffer buffer; + if (fspecs.format == float_format::hex) { + if (fspecs.sign) buffer.push_back(detail::sign(fspecs.sign)); + snprintf_float(convert_float(value), specs.precision, fspecs, buffer); + return write_bytes(out, {buffer.data(), buffer.size()}, + specs); + } + int precision = specs.precision >= 0 || specs.type == presentation_type::none + ? specs.precision + : 6; + if (fspecs.format == float_format::exp) { + if (precision == max_value()) + throw_format_error("number is too big"); + else + ++precision; + } else if (fspecs.format != float_format::fixed && precision == 0) { + precision = 1; + } + if (const_check(std::is_same())) fspecs.binary32 = true; + int exp = format_float(convert_float(value), precision, fspecs, buffer); + fspecs.precision = precision; + auto f = big_decimal_fp{buffer.data(), static_cast(buffer.size()), exp}; + return write_float(out, f, specs, fspecs, loc); +} + +template ::value)> +FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { + if (is_constant_evaluated()) + return write(out, value, basic_format_specs()); + if (const_check(!is_supported_floating_point(value))) return out; + + auto fspecs = float_specs(); + if (detail::signbit(value)) { + fspecs.sign = sign::minus; + value = -value; + } + + constexpr auto specs = basic_format_specs(); + using floaty = conditional_t::value, double, T>; + using uint = typename dragonbox::float_info::carrier_uint; + uint mask = exponent_mask(); + if ((bit_cast(value) & mask) == mask) + return write_nonfinite(out, std::isnan(value), specs, fspecs); + + auto dec = dragonbox::to_decimal(static_cast(value)); + return write_float(out, dec, specs, fspecs, {}); +} + +template ::value && + !is_fast_float::value)> +inline auto write(OutputIt out, T value) -> OutputIt { + return write(out, value, basic_format_specs()); +} + +template +auto write(OutputIt out, monostate, basic_format_specs = {}, + locale_ref = {}) -> OutputIt { + FMT_ASSERT(false, ""); + return out; +} + +template +FMT_CONSTEXPR auto write(OutputIt out, basic_string_view value) + -> OutputIt { + auto it = reserve(out, value.size()); + it = copy_str_noinline(value.begin(), value.end(), it); + return base_iterator(out, it); +} + +template ::value)> +constexpr auto write(OutputIt out, const T& value) -> OutputIt { + return write(out, to_string_view(value)); +} + +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. +template < + typename Char, typename OutputIt, typename T, + bool check = + std::is_enum::value && !std::is_same::value && + mapped_type_constant>::value != + type::custom_type, + FMT_ENABLE_IF(check)> +FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { + return write(out, static_cast>(value)); +} + +template ::value)> +FMT_CONSTEXPR auto write(OutputIt out, T value, + const basic_format_specs& specs = {}, + locale_ref = {}) -> OutputIt { + return specs.type != presentation_type::none && + specs.type != presentation_type::string + ? write(out, value ? 1 : 0, specs, {}) + : write_bytes(out, value ? "true" : "false", specs); +} + +template +FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { + auto it = reserve(out, 1); + *it++ = value; + return base_iterator(out, it); +} + +template +FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value) + -> OutputIt { + if (!value) { + throw_format_error("string pointer is null"); + } else { + out = write(out, basic_string_view(value)); + } + return out; +} + +template ::value)> +auto write(OutputIt out, const T* value, + const basic_format_specs& specs = {}, locale_ref = {}) + -> OutputIt { + check_pointer_type_spec(specs.type, error_handler()); + return write_ptr(out, bit_cast(value), &specs); +} + +// A write overload that handles implicit conversions. +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< + std::is_class::value && !is_string::value && + !is_floating_point::value && !std::is_same::value && + !std::is_same().map(value))>::value, + OutputIt> { + return write(out, arg_mapper().map(value)); +} + +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) + -> enable_if_t::value == type::custom_type, + OutputIt> { + using formatter_type = + conditional_t::value, + typename Context::template formatter_type, + fallback_formatter>; + auto ctx = Context(out, {}, {}); + return formatter_type().format(value, ctx); +} + +// An argument visitor that formats the argument and writes it via the output +// iterator. It's a class and not a generic lambda for compatibility with C++11. +template struct default_arg_formatter { + using iterator = buffer_appender; + using context = buffer_context; + + iterator out; + basic_format_args args; + locale_ref loc; + + template auto operator()(T value) -> iterator { + return write(out, value); + } + auto operator()(typename basic_format_arg::handle h) -> iterator { + basic_format_parse_context parse_ctx({}); + context format_ctx(out, args, loc); + h.format(parse_ctx, format_ctx); + return format_ctx.out(); + } +}; + +template struct arg_formatter { + using iterator = buffer_appender; + using context = buffer_context; + + iterator out; + const basic_format_specs& specs; + locale_ref locale; + + template + FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator { + return detail::write(out, value, specs, locale); + } + auto operator()(typename basic_format_arg::handle) -> iterator { + // User-defined types are handled separately because they require access + // to the parse context. + return out; + } +}; + +template struct custom_formatter { + basic_format_parse_context& parse_ctx; + buffer_context& ctx; + + void operator()( + typename basic_format_arg>::handle h) const { + h.format(parse_ctx, ctx); + } + template void operator()(T) const {} +}; + +template +using is_integer = + bool_constant::value && !std::is_same::value && + !std::is_same::value && + !std::is_same::value>; + +template class width_checker { + public: + explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {} + + template ::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative width"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("width is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template class precision_checker { + public: + explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {} + + template ::value)> + FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { + if (is_negative(value)) handler_.on_error("negative precision"); + return static_cast(value); + } + + template ::value)> + FMT_CONSTEXPR auto operator()(T) -> unsigned long long { + handler_.on_error("precision is not integer"); + return 0; + } + + private: + ErrorHandler& handler_; +}; + +template