NagiSeries

NagiSeriesNagiManga

NagiManga(漫画ビューアー)

NagiSeries(NagiSwipe・NagiManga・NagiLog)の漫画ビューアーです。

ブログやサイトに タグを 1 つ貼るだけ で、クリックしたときに漫画ビューアーが開きます。作品の管理は、データベースのいらない小さな管理画面(PHP)で行います。

v0.4.0 から、文章・画像・漫画を投稿できる個人用LOG「NagiLog」を同梱しています。スマホの投稿画面、太字、画像の差し替え、漫画カード、分類、6種類のデザイン、日時から作るURLに対応します。使い方、メリット・デメリット、設置と検証結果は NagiLog の README にまとめています。

デモ#

https://notebook.lichiphen.com/nagimanga/demo.html

  • いろいろな読み方(右から左・見開き/左から右/縦読みのページ漫画・ウェブトゥーン)を試せます
  • パスワード付きの見本(パスワードは demo)、CLIP STUDIO PAINT の EPUB から取り込んだ作品もあります
  • 「ゲストとして管理画面を見る」から、作者が使う管理画面を閲覧のみで見られます(変更はできません)

NagiLog のデモ: https://notebook.lichiphen.com/nagimanga/

  • 作者が実際に使っているLOGです。投稿、スマホのメニュー、メールのダイアログ、404(ブラックホールの中)を見られます
  • 画面のスクリーンショットと説明は NagiLog の README にあります

使うかどうか迷っている方、長く使い続けたい方へ: メリット・デメリット、使っている技術、データの取り出し方を docs/overview.md にまとめています(開発者でない方向け)。

できること#

読む人(ビューアー)

  • 右から左(漫画)/左から右/縦読み(1 ページずつ画面に収める「ページ漫画」と、横幅いっぱいの「ウェブトゥーン」)
  • 横長の画面では見開き表示(表紙だけ単独にする/しない)。横長の 1 枚絵は自動で単独ページ
  • ページ送り: スワイプ、画面の端のタップ、下のバーの ◀ ▶ ボタン、キーボード、マウスホイール(縦読みはマウスでつかんでスクロールもできます)
  • 拡大: ピンチ、ダブルタップ、パソコンでは上のバーの「− 100% +」ボタン、+ - 0 キー、Ctrl+ホイール(マウスを画面の上端か下端に近づけるとバーが出ます)
  • しおり(次に開いたときは続きから)、ブラウザの「戻る」で閉じる
  • スマホでは小さい画像(小容量版)、パソコンや拡大したときは大きい画像(通常版)を自動で読み分け

作る人(管理画面)

  • 画像のドラッグ&ドロップ、並べ替え、共有タグの発行(URL は設置したドメインから自動で作られます)
  • CLIP STUDIO PAINT などの 漫画 EPUB からそのまま作品を作る
  • パスワード付きの限定公開(読む人はクリックしたときにパスワードを入力)
  • バックアップと復元(ZIP 1 つ)
  • ゲスト(閲覧のみ)で管理画面を見せるプラグイン(デモ向け)

データベースも外部のライブラリも使っていません(PHP と JavaScript の標準機能だけ)。

2 つの使い方#

管理画面(PHP)を使うPHP なし(FTP だけ)
向いている人作品を管理画面で扱いたい人(FTP を使うのは最初の設置だけ)フォルダと URL が分かる人
画像の追加管理画面でドラッグ&ドロップ、または EPUB からFTP で置く
パスワード付き公開できるできない(画像の URL を知っていれば誰でも見られます)
必要なものPHP 8.1 以上(GD・fileinfo・mbstring・ZipArchive)、.htaccess が効くサーバー(Apache 系)推奨静的なファイルを置けるサーバーなら何でも

管理画面(PHP)を使う#

1. 設置#

リリースページ の nagimanga-*.zip(または、このリポジトリの manga/server フォルダの中身)を、サーバーの好きな場所に nagimanga などの名前でアップロードします。

nagimanga/
├── read.php          読者向けの窓口(読み取り専用)
├── index.php         NagiLog の公開入口(URLにファイル名は不要)
├── log.php           LOG本体・以前のURLから新URLへの転送
├── .htaccess
├── admin/            管理画面
├── viewer/           ビューアー(NagiManga.js / NagiManga.css)
├── plugins/          プラグインを置く場所(最初は空)
├── lib/              プログラム本体(外からは見えません)
└── data/             作品の画像と設定(外からは見えません)
  • .htaccess を忘れずに送ってください。 FTP ソフトによっては、. で始まるファイルが隠れていて送られないことがあります(「隠しファイルを表示」をオンにすると見えます)。nagimanga/・admin/・lib/・data/・plugins/ の 5 か所にあります。
  • data フォルダは書き込みできるようにしてください(多くのサーバーでは 755 のままで大丈夫です)。

2. セットアップ(30 分以内に)#

ブラウザで https://あなたのサイト/nagimanga/admin/ を開き、管理者パスワード(10 文字以上)を決めます。

  • この画面は、最初に開いてから 30 分だけ 表示されます(他人に先にセットアップされないようにするため)。過ぎてしまったら、FTP で data/install.lock を削除してから開き直してください。
  • 「今の IP アドレスからだけ管理画面を開けるようにする」は、できるだけオンにしてください。

完了すると ログイン用の URL が表示されます。必ずブックマークしてください。 管理画面を直接開こうとすると「Not Found」になります。v0.4.0 からは、公開サイトの「ログイン」からもパスワード付きの入口へ進めます。IP制限と試行回数の制限は、この入口でも適用します。

3. 設置したら確認すること#

  • ブックマークした URL でログインし、作品一覧に 「data フォルダがインターネットから見える状態です」という警告が出ていない こと(出ていたら .htaccess が届いていないか、効いていません。下の「data フォルダを守る」を見てください)
  • https://あなたのサイト/nagimanga/data/ を開くと、中身ではなく「Forbidden」などのエラーになること
  • https://あなたのサイト/nagimanga/admin/ をそのまま開くと「Not Found」になること(セットアップが済んでいる証拠です)

4. 作品を作って共有する#

  1. 管理画面で作品を作り、ページ画像をまとめてドラッグ&ドロップします(ファイル名の順 001, 002, … に並びます)。EPUB がある場合は「EPUB から作る」を使います。
  2. 作品ページの「共有用のタグ」で読み方・見開きを選び、「コピー」してブログの HTML に貼ります。
<a href="#" data-nagimanga="Ab3dE5gH7jK9" data-endpoint="https://example.com/nagimanga/read.php"
   data-direction="rtl" data-view="auto" data-cover="1">第1話を読む</a>
<script src="https://example.com/nagimanga/viewer/NagiManga.js?v=..." defer></script>
属性値
data-directionrtl(右から左)/ ltr(左から右)/ vertical(縦読み)
data-viewauto(横長の画面なら見開き)/ single(常に 1 ページ)
data-cover1(1 ページ目は単独=奇数ページ始まり)/ 0(1 ページ目から見開き)
data-vertical縦読みのとき: 省略(ページ漫画: 1 ページが画面の縦に収まる)/ webtoon(横幅いっぱい、最大 900px)
  • <script> の行は 1 ページに 1 回で十分です。リンクはいくつ並べても構いません。
  • タグの URL は、管理画面を開いているアドレスから自動で作られます。別の URL にしたいときだけ「設定 → 設置 URL」に入力してください。
  • 別のサイト(ドメイン)に埋め込むとき は、「設定 → 別のサイトに埋め込む場合」にそのサイトのアドレス(例: https://blog.example.com)を登録してください。

てがろぐに載せる#

てがろぐの投稿には、ブログ用の HTML タグは使えません。代わりに、作品ページのいちばん上にある 「共有リンク」 を使います。

  1. てがろぐの管理画面で [設定] → [システム設定] → 【画像拡大スクリプトの選択】 を開き、「他のスクリプトを使う:URLを指定」を選びます。

  2. 「JavaScriptのURL」欄に、NagiManga の URL を書いて保存します。管理画面の 「設置用コード」 に、この欄にそのまま貼れる 1 行(NagiSwipe と NagiManga の両方、キャッシュバスター付き)があります。画像の拡大表示に NagiSwipe を使っている場合は、NagiSwipe の URL の うしろに半角スペースを 1 つ入れて 続けて書きます(1 行のまま続けます)。

    https://cdn.jsdelivr.net/gh/Lichiphen/NagiSwipe@ab44ada/NagiSwipe-main.js https://example.com/nagimanga/viewer/NagiManga.js

    ※ URL の @ の後ろ(@93db749 など)は、ファイルのバージョンを表す値です。NagiSwipe が更新されると、README の値も新しくなります。新しい版を使いたいときは、ここの URL を貼り直してください(貼り直すまでは、今の版のまま表示が変わりません)。 NagiManga を更新したときも、「設置用コード」の新しい 1 行に貼り替えてください。

  1. 画像のない投稿でも 漫画を開けるように設定します。てがろぐは、画像のない投稿のページでは上の欄のファイルを読み込まないためです。[設定] → [ページの表示] → 【投稿本文の表示/URL処理】 の「▼画像URLを画像として埋め込む表示」にある 「画像リンクに独自のclass属性値を追加する」 にチェックを入れ、class=" と " の間の欄に nagimanga と入力して保存します。

  2. NagiManga の管理画面で作品を開き、「共有リンク」の「コピー」を押します。

  3. てがろぐに、リンクの文字(下の例では「第1話を読む」)を付けて投稿します。

    [第1話を読む]https://example.com/nagimanga/read.php?nagimanga=Ab3dE5gH7jK9&dir=rtl

投稿の「第1話を読む」を押すと、その場で漫画が開きます。読み方や見開きの選び方も、この URL の中に入っています。

  • この URL は、RSS リーダーなど、ほかの場所で開いても大丈夫です(作品を読むためのページが開きます)。
  • てがろぐと NagiManga のアドレスの始まり(https://〜/ の部分)が違う場合は、「設定 → 別のサイトに埋め込む場合」に、てがろぐのアドレスを登録してください。
  • HTML を書けるブログなら、今までどおり「共有用のタグ」を使ってください。

機能の説明#

EPUB から作る#

CLIP STUDIO PAINT などで書き出した 漫画の EPUB(固定レイアウト=画像のページだけのもの)を、作品一覧の「EPUB から作る」で取り込めます。

  • ページの順番・読む向き(右から左/左から右)・タイトルは EPUB の設定をそのまま使います(タイトルは入力すれば置き換えられます)。
  • 「小容量版 EPUB(任意)」も一緒に選ぶと、同じ順番で小容量版として割り当てます。あとから作品ページの「小容量版 EPUB から割り当てる」でも追加できます。
  • 画像は通常のアップロードと同じく、中身を確かめてから描き直して保存します。見開きをそろえるための白紙ページもそのまま残ります。
  • DRM(コピー防止)付きの EPUB、文章だけの EPUB は読めません。
  • サーバーの「アップロード上限」(upload_max_filesize / post_max_size)より大きい EPUB は取り込めません。上限は管理画面に表示されます。

小容量版(スマホ用)#

各ページに、小さく書き出した「小容量版」を付けられます。作品ページの「ページ」欄には、アップロードする場所が 2 つあります。

  • 通常版(パソコン・拡大用): いつものページ画像
  • 小容量版(スマホ用・任意): 同じページを小さくした画像。ファイル名の順に、1 ページ目から順番に割り当てます(001 → 1 ページ目)。枚数がページ数と違うときは確認が出ます

ビューアーは、表示する大きさと画面の細かさから「小容量版で足りる」ときは小容量版を読み、パソコンの大きな画面や拡大したときは通常版に切り替えます(裏で読み込んでから差し替えるので、一瞬白くなることはありません)。端末の「データセーバー」がオンなら小容量版を優先します。小容量版がないページは通常版だけで表示します。

  • 小容量版があるページには、作品ページの一覧で「小」の印が付きます
  • 「小容量版をすべて外す」で外せます(通常版は残ります)
  • パスワード付き作品では、小容量版も鍵がないと読めません
  • バックアップ・復元にも含まれます

パスワード(限定公開)#

作品ページの「パスワード」で設定します。読む人はリンクをクリックしたときにパスワードを入力します。

  • パスワードは ビューアーを開くたびに 入力します(正しく入力すると、開いている間だけ有効な「閲覧用の鍵」が渡され、閉じると捨てられます。鍵そのものも 2 時間で無効になります)。
  • パスワードを変えると、それまでの鍵はすべて無効になります。
  • 設定したパスワードは、作品ページの「現在のパスワード」で「表示」を押すと確認できます(サーバーの秘密鍵で暗号化して保存しています。別のサーバーへ復元した場合は表示できないので、設定し直してください)。
  • 5 回間違えると、その作品は 15 分間入力できなくなります(総当たり対策)。

バックアップ#

「バックアップ」から、すべての作品を 1 つの ZIP にまとめてダウンロードできます。定期的にダウンロードしてパソコンなどに保存しておいてください。

  • 作品(ページ画像・小容量版・並び順・タイトル・読む向き・読者向けパスワード)が入ります。作品の ID も変わらないので、ブログに貼ったタグはそのまま使えます。
  • 管理者パスワード・ログイン URL・IP 制限などの設定と、秘密の鍵は入りません(引っ越し先ではセットアップし直します)。
  • 復元は同じ画面から ZIP をアップロードします。ZIP の中身はすべて検査してから戻します。
  • サーバーの PHP に ZipArchive がない場合は、FTP で data/works フォルダをまるごとコピーしてください。

更新(v0.2.0 以降)#

新しいバージョンが出ると、ログインしたときに作品一覧の上にお知らせが出ます(メニューの「更新」にも「新」の印が付きます)。「更新」画面のボタンを押すと、その場で更新できます。

  • GitHub の公式リリースから nagimanga-vX.Y.Z.zip をダウンロードし、GitHub が公開している確認用の値(SHA-256)と一致したときだけ使います。中身も 1 つずつ検査します。
  • 入れ替えるのはプログラムのファイルだけです。作品・設定(data フォルダ)、プラグイン、lib/paths.php はそのままです。
  • 入れ替える前のファイルは data/update/ に保管され(実行できない .bak として)、「元に戻す」で戻せます。直近 3 回分を残します。
  • 確認は 12 時間に 1 回までです。「更新」画面で、ログイン時の確認をオフにしたり、今すぐ確認したりできます。
  • サーバーから GitHub に接続できない(PHP の curl も allow_url_fopen も使えない)、ZipArchive がない、プログラムのファイルに書き込めない場合は自動で更新できません。画面の「手動で更新する」の手順(data フォルダ以外を上書きアップロード)で更新してください。
  • v0.1.0 から v0.2.0 へは、手動で更新してください(v0.1.0 には更新機能がありません)。

設置用コード#

メニューの「設置用コード」に、ビューアーを読み込むためのコードがまとまっています。

  • ビューアーの URL(末尾の ?v=… が キャッシュバスター。NagiManga を更新すると値が変わり、読む人のブラウザに古いビューアーが残らないようにします)
  • てがろぐの「JavaScriptのURL」欄にそのまま貼れる 1 行(NagiSwipe と一緒)と、てがろぐ側の設定の手順
  • ブログ・HTML 用の <script> タグ

NagiManga を更新したら、この画面を開き直して、新しい値を貼り直してください。

個別ページ(共有リンク・v0.3.0 以降)#

作品ページのいちばん上の 「共有リンク」(read.php?nagimanga=…)を開くと、その作品を読むためのページが開き、ビューアーが自動で開きます。

  • note・アメブロ・Instagram・X など、漫画を埋め込めない場所にはこのリンクを貼ります。貼ると 表紙付きのカード(OGP)で表示されます。パスワード付きの作品は表紙を出さず、NagiManga の共通の画像になります。
  • ページには表紙・タイトル・「読む」ボタンと、「戻る」ボタン があります。行き先は「設定 → 個別ページ」で決められます(空欄なら自動:来たページに戻ります。Instagram などのアプリから来て戻る先がわからないときは、ボタンを出しません)。
  • 作品ページの「非公開にする」で、作品ごとに個別ページを出さないようにできます。ブログやてがろぐに埋め込んだビューアーは今までどおり読めます。
  • 作品の ID は推測できないランダムな文字列です。すでにある作品もそのまま使えます(作り直しは不要です)。

直リンク防止(上級者向け・v0.3.0 以降)#

「設定 → 上級者向けの設定 → 直リンク防止」をオンにすると、漫画の画像は「このサイト」「別のサイトに埋め込む場合に登録したサイト」「許可リストに書いたサイト」のページからしか読めなくなります。ほかのサイトに画像を貼られてサーバーの通信量が増えるのを防ぎます。初期設定はオフです。

  • .htaccess は書き換えません(判定は read.php の中で行うので、nginx のサーバーでも使えます)。
  • 共有リンクの個別ページと、リンクのカード用の表紙は、オンでもそのまま使えます。
  • 許可リストはサイト単位(例: https://note.com)で書きます。ブラウザは、ほかのサイトからの読み込みでは URL の途中(/ユーザー名/ など)を送らないため、途中までの一致では判定できません。

プラグイン(ゲストモード)#

nagimanga/plugins/ フォルダに PHP のプラグインを置くと、機能を足せます(置いたファイルだけが読み込まれます)。同梱のプラグインは次の 1 つです。

plugins/guest-mode.php(ゲスト・閲覧のみ): デモなどで、訪問者に管理画面の中を見せたいときに使います。このファイルを nagimanga/plugins/ にコピーすると、admin/index.php?guest からゲストとして入れるようになります。

  • ゲストは作品・ページ・共有タグ・試し読みを見られますが、アップロード・並べ替え・削除・パスワード・小容量版・EPUB・バックアップ・設定の変更はすべて拒否されます。設定画面(ログイン URL・IP・ログ)と読者向けパスワードは表示されません。
  • この制限はプラグインではなく NagiManga 本体が行っています。プラグインが決めるのは「入口を開けるか」「合言葉」「案内の文」「終了後のリンク先」だけです。
  • あなた自身のログイン(秘密の URL + パスワード + IP 制限)は今までどおりです。
  • ファイルを消せば入口は閉じ、中にいたゲストも締め出されます。

困ったとき#

症状対処
セットアップ画面が「Not Found」になった(30 分過ぎた)FTP で data/install.lock を削除してから開き直す
ログイン URL を忘れたFTP で data/config.php を開き、login_key の値を admin/index.php?k= の後ろに付けて開く
IP アドレスが変わって締め出されたFTP で data/config.php の allowed_ips を array ( ) にする(admin/.htaccess で IP 制限を書いた場合はその行も)
ログインを何度も間違えた15 分待つ(その間はログイン画面も「Not Found」になります)
管理画面に「data フォルダがインターネットから見える状態です」と出る下の「data フォルダを守る」を参照
EPUB が取り込めないDRM 付き・文章だけの EPUB ではないか、アップロード上限(管理画面に表示)を超えていないかを確認

data フォルダを守る#

data フォルダは .htaccess で外から見えないようにしています。.htaccess が効かないサーバー(nginx など)では、次のどちらかをしてください。

  1. おすすめ: data フォルダを公開フォルダの外(例: /home/you/nagimanga-data)へ移し、lib/paths.php を作って場所を書く

    <?php return '/home/you/nagimanga-data';
  1. nginx なら location ~ /nagimanga/(data|lib|plugins)/ { deny all; } を設定する

保存フォルダの名前は秘密の鍵から作りますが、暗号化ではありません。.htaccess が効かず画像の実パスが判明した場合は、画像へ直接アクセスできてしまいます。保存先を公開フォルダの外へ移すか、サーバー側でアクセスを拒否してください。

  • 設定ファイルは PHP なので、中身は表示されません。
  • 作品フォルダの名前は秘密の鍵から作ってあり、公開 ID からは推測できません。
  • 各フォルダには空の index.html を置いてあり、中身の一覧は表示されません。

LOGの内部記録は直接開くと404になるPHP形式です。静的な画像の保護には、上記の保存先・サーバー設定が必要です。

管理画面の IP 制限をさらに固くする(任意)#

admin/.htaccess の IP 制限の行の # を外して、自分の IP アドレスを書きます。管理画面の設定の IP 制限と二重に守られます。


PHP なし(FTP だけ)で使う#

  1. server/viewer/NagiManga.js と NagiManga.css を同じフォルダに置きます。
  2. tools/manifest-maker.html をブラウザで開き、ページ画像を選んで manifest.json を作ります(画像はどこにも送信されません)。
  3. manifest.json と画像をサーバーに置き、ページに次のタグを貼ります。
<a href="#" data-nagimanga-manifest="/manga/ep1/manifest.json" data-direction="rtl">第1話を読む</a>
<script src="/manga/NagiManga.js" defer></script>

manifest.json の中の画像の場所は、manifest.json の場所から見た相対パス(または完全な URL)です。

{ "title": "第1話", "direction": "rtl", "pages": [ { "src": "001.jpg", "w": 1200, "h": 1700 } ] }

セキュリティの考え方#

  • 公開側は読み取り専用。 read.php ができるのは「作品のページ一覧」「パスワードの確認」「画像を返す」だけです。おかしな要求にはすべて同じ「Not Found」を返し、何があるかを教えません。
  • 管理画面は 5 重の鍵。 IP 制限 → 秘密のログイン URL → パスワード(5 回失敗でロック。全体でも 1 時間 40 回まで)→ ブラウザに結び付いたセッション(最後のログインから 30 日、設定で 1 年まで)→ すべての操作に CSRF 対策。
  • アップロードされた画像は必ず描き直す。 ファイル名ではなく中身で画像かどうかを判定し、GD で読み込んで新しいファイルに書き出します。画像に仕込まれたプログラムや撮影場所などの情報は残りません。ファイル名もこちらで付け直します。SVG は受け付けません。EPUB やバックアップの ZIP も、中身を 1 つずつ検査してから使います。
  • 画像の保存フォルダではプログラムが動かない。 data は外から見えず、保存するのは .webp / .jpg だけです。
  • エラー内容を画面に出さない。 サーバーのパスなどが漏れないようにしています。記録は data/logs/security.log に残り、管理画面の設定ページで見られます。

攻撃テスト#

dev/attack_test.py で、通常の動作確認と攻撃の再現をまとめて実行できます。Python 3 と PHP 8.1 以上(GD・fileinfo・zip・mbstring・sodium または openssl)があれば、追加のインストールは不要です。LOGの確認は dev/log_test.py で実行できます。

python dev/attack_test.py

主な内容: 画像に偽装した PHP、.htaccess / SVG / HTML のアップロード、ピクセル数の爆弾、../ によるフォルダの抜け出し、ZIP スリップと ZIP 爆弾、悪意のある EPUB(XXE・DRM・本の外を指すパス)、CSRF、XSS、閲覧用の鍵の偽造・改ざん・期限切れ・使い回し、総当たり(X-Forwarded-For の偽装を含む)、IP 制限の回避、おかしな Host ヘッダー、ゲストによる変更(19 種類)、.htaccess が効かないサーバーでの情報漏れ。結果は dev/results/attack-report.md に書き出されます。

開発#

dev\serve.cmd              # http://127.0.0.1:5190 (データは dev/data)
python dev/seed.py         # 見本の作品を登録し、dev/results/demo.html を作る
python dev/build_release.py  # 配布用 ZIP(dev/results/nagimanga-vX.Y.Z.zip)を作る

README の jsDelivr の URL は、そのファイルを最後に変更したコミットに固定しています(例: …/NagiSwipe@93db749/NagiSwipe-main.js)。コミットの URL は中身が変わらず、ファイルを変えるたびに URL も変わるので、ブラウザや jsDelivr に古いファイルが残りません。cp scripts/post-commit.sh .git/hooks/post-commit でフックを入れておくと、NagiSwipe-main.js / .css を変更したコミットのあとに README の URL を自動で書き換え、ドキュメントサイト のページ(python site/build.py)も作り直してコミットします(手動なら python scripts/cachebust.py README.md manga/README.md のあと python site/build.py)。

リリースするときは、lib/bootstrap.php の NM_VERSION と viewer/NagiManga.js の VERSION を同じ番号に上げてから dev/build_release.py で ZIP を作り、GitHub のリリースに添付します。設置済みの NagiManga は、リリースの nagimanga-vX.Y.Z.zip(中身は nagimanga/ フォルダ)を見て更新を知らせます。

ライセンス#

MIT License (c) 2026 Lichiphen