| 1 | <?php |
| 2 | /************************************************************* |
| 3 | # 076 License |
| 4 | |
| 5 | Copyright (c) テクニカル諏訪子 |
| 6 | |
| 7 | Permission is hereby granted to any person obtaining a copy of the software |
| 8 | Little Beast (the "Software") to use, modify, merge, copy, publish, distribute, |
| 9 | sublicense, and/or sell copies of the Software, subject to the following conditions: |
| 10 | |
| 11 | 1. **Origin Attribution**: |
| 12 | - You must not misrepresent the origin of the Software; you must not claim |
| 13 | you created the original Software. |
| 14 | - If the Software is used in a product, you must either: |
| 15 | a. Provide clear attribution in the product's documentation, user interface, |
| 16 | or other visible areas, **OR** |
| 17 | b. Pay the original developers a fee they specify in writing. |
| 18 | 2. **Usage Restriction**: |
| 19 | - The Software, or any derivative works, dependencies, or libraries |
| 20 | incorporating it, must not be used for censorship or to suppress freedom of |
| 21 | speech, expression, or creativity. Prohibited uses include, but are not |
| 22 | limited to: |
| 23 | - Censorship of so-called "hate speech", visuals, non-mainstream opinions, |
| 24 | ideas, or objective reality. |
| 25 | - Tools or systems designed to restrict access to information or |
| 26 | artistic works. |
| 27 | 3. **Notice Preservation**: |
| 28 | - This license and the above copyright notice must remain intact in all copies |
| 29 | of the source code. |
| 30 | |
| 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
| 32 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A |
| 33 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| 34 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| 35 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE |
| 36 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 37 | */ |
| 38 | |
| 39 | require_once __DIR__.DIRECTORY_SEPARATOR.'/autoload.php'; |
| 40 | |
| 41 | use Std\Lib\Route; |
| 42 | |
| 43 | use Site\Controller\Admin; |
| 44 | use Site\Controller\Atom; |
| 45 | use Site\Controller\Comment; |
| 46 | use Site\Controller\Fediverse; |
| 47 | use Site\Controller\Gitler; |
| 48 | use Site\Controller\Home; |
| 49 | use Site\Controller\Microblog; |
| 50 | use Site\Controller\Notfound; |
| 51 | use Site\Controller\Op; |
| 52 | use Site\Controller\Page; |
| 53 | use Site\Controller\User; |
| 54 | |
| 55 | define('ROOT', realpath(__DIR__)); |
| 56 | |
| 57 | include(ROOT.'/config/config.php'); |
| 58 | if (DEBUG_MODE) { |
| 59 | error_reporting(E_ALL); |
| 60 | ini_set('display_errors', 1); |
| 61 | } |
| 62 | include(ROOT.'/util.php'); |
| 63 | |
| 64 | $routes = [ |
| 65 | Route::add('GET', 'robots.txt', Home::class.'@robots'), |
| 66 | Route::add('GET', 'blog/{page}', Home::class.'@article'), |
| 67 | Route::add('GET', 'test', Page::class.'@test'), |
| 68 | Route::add('GET', 'about', Page::class.'@about'), |
| 69 | Route::add('GET', 'monero', Page::class.'@monero'), |
| 70 | Route::add('GET', 'secret', Page::class.'@secret'), |
| 71 | ]; |
| 72 | |
| 73 | if (ACTIVITYPUB_ENABLED) { |
| 74 | $routes[] = Route::add('GET', '.well-known/webfinger', Fediverse::class.'@apfinger'); |
| 75 | $routes[] = Route::add('GET', 'ap/following', Fediverse::class.'@apfollowing'); |
| 76 | $routes[] = Route::add('GET', 'ap/followers', Fediverse::class.'@apfollowers'); |
| 77 | $routes[] = Route::add('GET', 'ap/outbox', Fediverse::class.'@apoutbox'); |
| 78 | $routes[] = Route::add('GET', 'ap/activities/create/{uuid}', |
| 79 | Fediverse::class.'@apactivity'); |
| 80 | $routes[] = Route::add('GET', 'ap/activities/create/{section}/{uuid}', |
| 81 | Fediverse::class.'@apactivity'); |
| 82 | $routes[] = Route::add('GET', 'ap/objects/{uuid}', Fediverse::class.'@apobject'); |
| 83 | // 「{section}/{uuid}」より先に(「{uuid}/replies」もそれに一致するので) |
| 84 | $routes[] = Route::add('GET', 'ap/objects/{uuid}/replies', Fediverse::class.'@apreplies'); |
| 85 | $routes[] = Route::add('GET', 'ap/objects/{section}/{uuid}/replies', Fediverse::class.'@apreplies'); |
| 86 | $routes[] = Route::add('GET', 'ap/objects/{section}/{uuid}', Fediverse::class.'@apobject'); |
| 87 | $routes[] = Route::add('POST', 'ap/inbox', Fediverse::class.'@apinbox'); |
| 88 | $routes[] = Route::add('GET', 'ap/actor', Fediverse::class.'@apactor'); |
| 89 | } |
| 90 | |
| 91 | if (ACTIVITYPUB_MULTIUSER) { |
| 92 | $routes[] = Route::add('GET', '.well-known/nodeinfo', Fediverse::class.'@nodeinfo'); |
| 93 | $routes[] = Route::add('GET', 'nodeinfo/2.0', Fediverse::class.'@nodeinfoSchema'); |
| 94 | $routes[] = Route::add('GET', 'ap/users/{name}', Fediverse::class.'@apuser'); |
| 95 | $routes[] = Route::add('POST', 'ap/users/{name}/inbox', Fediverse::class.'@apuserinbox'); |
| 96 | $routes[] = Route::add('GET', 'ap/users/{name}/outbox', Fediverse::class.'@apuseroutbox'); |
| 97 | $routes[] = Route::add('GET', 'ap/users/{name}/followers', Fediverse::class.'@apuserfollowers'); |
| 98 | $routes[] = Route::add('GET', 'ap/users/{name}/following', Fediverse::class.'@apuserfollowing'); |
| 99 | $routes[] = Route::add('GET', 'ap/users/{name}/notes/{id}', Fediverse::class.'@apnote'); |
| 100 | $routes[] = Route::add('GET', 'ap/users/{name}/notes/{id}/activity', Fediverse::class.'@apnoteactivity'); |
| 101 | |
| 102 | $routes[] = Route::add('GET', 'microblog', Microblog::class.'@home'); |
| 103 | $routes[] = Route::add('GET', 'microblog/local', Microblog::class.'@local'); |
| 104 | $routes[] = Route::add('GET', 'microblog/federated', Microblog::class.'@federated'); |
| 105 | $routes[] = Route::add('GET', 'microblog/tag/{tag}', Microblog::class.'@tag'); |
| 106 | $routes[] = Route::add('GET', 'microblog/user/{name}', Microblog::class.'@user'); |
| 107 | $routes[] = Route::add('GET', 'microblog/remote', Microblog::class.'@remote'); |
| 108 | $routes[] = Route::add('GET', 'microblog/note', Microblog::class.'@note'); |
| 109 | $routes[] = Route::add('GET', 'microblog/media', Microblog::class.'@media'); |
| 110 | $routes[] = Route::add('GET', 'microblog/search', Microblog::class.'@search'); |
| 111 | $routes[] = Route::add('GET', 'microblog/notifications', Microblog::class.'@notifications'); |
| 112 | $routes[] = Route::add('GET', 'microblog/blocks', Microblog::class.'@blocks'); |
| 113 | $routes[] = Route::add('GET', 'microblog/follows', Microblog::class.'@follows'); |
| 114 | $routes[] = Route::add('GET', 'microblog/edit', Microblog::class.'@edit'); |
| 115 | $routes[] = Route::add('POST', 'microblog/edit', Microblog::class.'@edit'); |
| 116 | $routes[] = Route::add('POST', 'microblog/post', Microblog::class.'@post'); |
| 117 | $routes[] = Route::add('POST', 'microblog/action', Microblog::class.'@action'); |
| 118 | $routes[] = Route::add('GET', 'microblog/admin', Microblog::class.'@admin'); |
| 119 | $routes[] = Route::add('POST', 'microblog/admin', Microblog::class.'@admin'); |
| 120 | } |
| 121 | |
| 122 | if (AUTH_ENABLED) { |
| 123 | $routes[] = Route::add('POST', 'login', User::class.'@login'); |
| 124 | $routes[] = Route::add('GET', 'login', User::class.'@login'); |
| 125 | if (AUTH_REGISTER_ENABLED) { |
| 126 | $routes[] = Route::add('POST', 'register', User::class.'@register'); |
| 127 | $routes[] = Route::add('GET', 'register', User::class.'@register'); |
| 128 | } |
| 129 | $routes[] = Route::add('GET', 'logout', User::class.'@logout'); |
| 130 | $routes[] = Route::add('GET', 'verify/{token}', User::class.'@verify'); |
| 131 | $routes[] = Route::add('GET', 'profile/{name}', User::class.'@profile'); |
| 132 | $routes[] = Route::add('GET', 'profile/{name}/edit', User::class.'@editProfile'); |
| 133 | $routes[] = Route::add('POST', 'profile/{name}/edit', User::class.'@editProfile'); |
| 134 | $routes[] = Route::add('GET', 'profile/{name}/2fa', User::class.'@twoFactor'); |
| 135 | $routes[] = Route::add('POST', 'profile/{name}/2fa', User::class.'@twoFactor'); |
| 136 | $routes[] = Route::add('GET', 'profile/{name}/2fa/qr', User::class.'@twoFactorQr'); |
| 137 | |
| 138 | $routes[] = Route::add('GET', 'memberonly', Page::class.'@memberonly'); |
| 139 | $routes[] = Route::add('GET', 'staffonly', Page::class.'@staffonly'); |
| 140 | } |
| 141 | |
| 142 | // 管理画面(管理者のロールが必要) |
| 143 | if (AUTH_ENABLED && defined('ADMIN_ENABLED') && ADMIN_ENABLED) { |
| 144 | $routes[] = Route::add('GET', 'admin', Admin::class.'@index'); |
| 145 | $routes[] = Route::add('GET', 'admin/setup', Admin::class.'@setup'); |
| 146 | $routes[] = Route::add('POST', 'admin/setup', Admin::class.'@setup'); |
| 147 | $routes[] = Route::add('GET', 'admin/users', Admin::class.'@users'); |
| 148 | $routes[] = Route::add('POST', 'admin/users', Admin::class.'@users'); |
| 149 | $routes[] = Route::add('GET', 'admin/users/{name}', Admin::class.'@user'); |
| 150 | $routes[] = Route::add('POST', 'admin/users/{name}', Admin::class.'@user'); |
| 151 | $routes[] = Route::add('GET', 'admin/logs', Admin::class.'@logs'); |
| 152 | $routes[] = Route::add('POST', 'admin/logs', Admin::class.'@logs'); |
| 153 | $routes[] = Route::add('GET', 'admin/cron', Admin::class.'@cron'); |
| 154 | $routes[] = Route::add('POST', 'admin/cron', Admin::class.'@cron'); |
| 155 | $routes[] = Route::add('GET', 'admin/cache', Admin::class.'@cache'); |
| 156 | $routes[] = Route::add('POST', 'admin/cache', Admin::class.'@cache'); |
| 157 | $routes[] = Route::add('GET', 'admin/convert', Admin::class.'@convert'); |
| 158 | $routes[] = Route::add('POST', 'admin/convert', Admin::class.'@convert'); |
| 159 | } |
| 160 | |
| 161 | // Gitler(Gitのホスティング)。具体的なパスを先に |
| 162 | if (\Std\Lib\Gitler\Gitler::enabled()) { |
| 163 | $routes[] = Route::add('GET', 'gitler', Gitler::class.'@index'); |
| 164 | $routes[] = Route::add('GET', 'gitler/-/new', Gitler::class.'@create'); |
| 165 | $routes[] = Route::add('POST', 'gitler/-/new', Gitler::class.'@create'); |
| 166 | $routes[] = Route::add('GET', 'gitler/-/keys', Gitler::class.'@keys'); |
| 167 | $routes[] = Route::add('POST', 'gitler/-/keys', Gitler::class.'@keys'); |
| 168 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/info/refs', Gitler::class.'@git', ['action' => 'info/refs']); |
| 169 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/git-upload-pack', Gitler::class.'@git', ['action' => 'git-upload-pack']); |
| 170 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/git-receive-pack', Gitler::class.'@git', ['action' => 'git-receive-pack']); |
| 171 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/commit/{id}', Gitler::class.'@commit'); |
| 172 | // イシューとFediverse(inbox等) |
| 173 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/issues/new', Gitler::class.'@newIssue'); |
| 174 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/issues/new', Gitler::class.'@newIssue'); |
| 175 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/issues/{n}/ticket', Gitler::class.'@issueTicket'); |
| 176 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/issues/{n}/comments/{c}', Gitler::class.'@issueComment'); |
| 177 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/issues/{n}', Gitler::class.'@issue'); |
| 178 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/issues/{n}', Gitler::class.'@issue'); |
| 179 | // プルリクエストとフォーク |
| 180 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/pulls', Gitler::class.'@issues', ['pull' => true]); |
| 181 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/pulls/{n}/commits', Gitler::class.'@pullCommits'); |
| 182 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/pulls/{n}/files', Gitler::class.'@pullFiles'); |
| 183 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/pulls/{n}/files', Gitler::class.'@pullFiles'); |
| 184 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}/pulls/{n}', Gitler::class.'@issue', ['pull' => true]); |
| 185 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/pulls/{n}', Gitler::class.'@issue', ['pull' => true]); |
| 186 | foreach (['issues', 'labels', 'milestones', 'outbox', 'followers', 'compare', 'forks'] as $page) { |
| 187 | $routes[] = Route::add('GET', "gitler/{owner}/{repo}/{$page}", Gitler::class.'@'.$page); |
| 188 | } |
| 189 | foreach (['labels', 'milestones', 'inbox', 'watch', 'compare', 'fork'] as $page) { |
| 190 | $routes[] = Route::add('POST', "gitler/{owner}/{repo}/{$page}", Gitler::class.'@'.$page); |
| 191 | } |
| 192 | foreach (['tree', 'blob', 'raw', 'blame', 'commits', 'branches', 'tags', 'archive', 'settings'] as $page) { |
| 193 | $routes[] = Route::add('GET', "gitler/{owner}/{repo}/{$page}", Gitler::class.'@'.$page); |
| 194 | } |
| 195 | $routes[] = Route::add('POST', 'gitler/{owner}/{repo}/settings', Gitler::class.'@settings'); |
| 196 | $routes[] = Route::add('GET', 'gitler/{owner}/{repo}', Gitler::class.'@repo'); |
| 197 | $routes[] = Route::add('GET', 'gitler/{owner}', Gitler::class.'@owner'); |
| 198 | } |
| 199 | |
| 200 | if (AUTH_ENABLED && \Std\Lib\Comments::enabled()) { |
| 201 | $routes[] = Route::add('POST', 'comments', Comment::class.'@post'); |
| 202 | $routes[] = Route::add('POST', 'comments/like', Comment::class.'@like'); |
| 203 | $routes[] = Route::add('POST', 'comments/delete', Comment::class.'@delete'); |
| 204 | } |
| 205 | |
| 206 | // 通知(記事のコメント、Gitler等) |
| 207 | if (AUTH_ENABLED) { |
| 208 | $routes[] = Route::add('GET', 'notifications', Comment::class.'@notifications'); |
| 209 | } |
| 210 | |
| 211 | if (ATOM_ENABLED) { |
| 212 | foreach (array_keys(blogs()) as $blog) { |
| 213 | $routes[] = Route::add('GET', $blog.'.atom', Atom::class.'@feed', ['section' => $blog]); |
| 214 | } |
| 215 | } |
| 216 | |
| 217 | if (OPENPROVIDER_ENABLED) { |
| 218 | $routes[] = Route::add('GET', 'openprovider', Op::class.'@index'); |
| 219 | $routes[] = Route::add('GET', 'openprovider/listinvoices', Op::class.'@opListInvoices'); |
| 220 | $routes[] = Route::add('GET', 'openprovider/listpayments', Op::class.'@opListPayments'); |
| 221 | $routes[] = Route::add('GET', 'openprovider/listtransactions', Op::class.'@opListTransactions'); |
| 222 | $routes[] = Route::add('GET', 'openprovider/listcustomers', Op::class.'@opListCustomers'); |
| 223 | $routes[] = Route::add('GET', 'openprovider/createcustomer', Op::class.'@opCreateCustomer'); |
| 224 | $routes[] = Route::add('GET', 'openprovider/deletecustomer/{handle}', Op::class.'@opDeleteCustomer'); |
| 225 | $routes[] = Route::add('GET', 'openprovider/getcustomer/{handle}', Op::class.'@opGetCustomer'); |
| 226 | $routes[] = Route::add('GET', 'openprovider/listtlds', Op::class.'@opListTlds'); |
| 227 | $routes[] = Route::add('GET', 'openprovider/gettld/{tld}', Op::class.'@opGetTld'); |
| 228 | $routes[] = Route::add('GET', 'openprovider/checkdomain', Op::class.'@opCheckDomainAvailable'); |
| 229 | $routes[] = Route::add('GET', 'openprovider/getdomainprices', Op::class.'@opGetDomainPrices'); |
| 230 | $routes[] = Route::add('GET', 'openprovider/listdnszones', Op::class.'@opListDns'); |
| 231 | $routes[] = Route::add('GET', 'openprovider/getdns/{domain}', Op::class.'@opGetDns'); |
| 232 | } |
| 233 | |
| 234 | $routes[] = Route::add('GET', '', Home::class.'@show'); |
| 235 | |
| 236 | Route::init($routes); |
| 237 | Route::setFallback([new Notfound(), 'show']); |
| 238 | |
| 239 | $uri = urldecode($_SERVER['REQUEST_URI']); |
| 240 | |
| 241 | // .xhtmlで終わるURLのリダイレクト処理 |
| 242 | if (preg_match('/(.+)\.xhtml$/', $uri, $matches)) { |
| 243 | // 末尾の.xhtmlを取り除く |
| 244 | $newUri = safe_local_path($matches[1]); |
| 245 | header('HTTP/1.1 301 Moved Permanently'); |
| 246 | header('Location: ' . $newUri); |
| 247 | exit(); |
| 248 | } |
| 249 | |
| 250 | $uri = urldecode($_SERVER['REQUEST_URI']); |
| 251 | if ($uri == '/index.php' || $uri == '/index.html') { |
| 252 | header('Location: /'); |
| 253 | exit(); |
| 254 | } |
| 255 | |
| 256 | Route::dispatch($uri); |