Browse Source

Initial commit

Oppaitime 1 year ago
commit
20c8794fda
6 changed files with 117 additions and 0 deletions
  1. 10
    0
      LICENSE
  2. 13
    0
      README.md
  3. BIN
      imgs/invalid.png
  4. BIN
      imgs/unauthorized.png
  5. 70
    0
      index.php
  6. 24
    0
      nginx.conf.example

+ 10
- 0
LICENSE View File

@@ -0,0 +1,10 @@
1
+This is free and unencumbered software released into the public domain.
2
+
3
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.
4
+
5
+In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and
6
+successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.
7
+
8
+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 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.
9
+
10
+For more information, please refer to <http://unlicense.org/>

+ 13
- 0
README.md View File

@@ -0,0 +1,13 @@
1
+This is a simple script used to serve and manage the images for an Oppaitime-Gazelle based tracker
2
+
3
+It is an image host, but it works more like a proxy with a permanent cache. Users are expected to upload their images to any host they desire, including temporary hosts, or find an image already available on the web and use the links to those images normally (as if the tracker has no host at all). Oppaitime-Gazelle will pass those image URLs to this host script, which will download them the first time access is attempted and continue serving the image from its cache from then on.
4
+
5
+The primary purposes of this script are: 
6
+* Longevity
7
+  * The original image source becoming unavailable does not affect this host's ability to continue serving the image.
8
+* Privacy
9
+  * The original image url is never directly embedded on any page served to users. The first time an image is accessed, the host acts as a proxy between the user and the source. All subsequent accesses are exclusively between the user and this host. In this way, the source is never able to identify any users.
10
+
11
+Because of the way this script works, it can be dropped into place at any Gazelle tracker with minimal effort, and it will start seamlessly proxying and caching existing images as they are accessed.
12
+
13
+Note: This script does not handle thumbnailing, instead preferring to use the highly performant nginx-image-filter module to thumbnail on the fly. An example nginx configuration for handling thumbnailing in a way expected by Oppaitime-Gazelle is provided in this repo.

BIN
imgs/invalid.png View File


BIN
imgs/unauthorized.png View File


+ 70
- 0
index.php View File

@@ -0,0 +1,70 @@
1
+<?php
2
+
3
+// Location where hosted images will be stored
4
+define('IMG_ROOT', '/var/images/');
5
+// Pre-shared key - must match IMAGE_PSK in gazelle config
6
+define('PSK', 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
7
+
8
+ini_set('memory_limit', '256M');
9
+
10
+function image_type($Data) {
11
+  if (!strncmp($Data, pack('H*', '89504E47'), 4)) return 'png';
12
+  if (!strncmp($Data, pack('H*', 'FFD8'), 2)) return 'jpeg';
13
+  if (!strncmp($Data, 'GIF', 3)) return 'gif';
14
+  if (strlen($Data) > 35 && !substr_compare($Data, 'webm', 31, 4)) return 'webm';
15
+  if (!strncmp($Data, 'BM', 2)) return 'bmp';
16
+  if (!strncmp($Data, 'II', 2) || !strncmp($Data, 'MM', 2)) return 'tiff';
17
+  return '';
18
+}
19
+
20
+$ImgURL = $_GET['i'];
21
+$Auth = rawurldecode($_GET['h']);
22
+$ImgURLHash = hash('sha256', $ImgURL);
23
+
24
+// Deletion
25
+if (!empty($_GET['d'])) {
26
+  $ImgURL = $_GET['d'];
27
+  $ImgURLHash = hash('sha256', $ImgURL);
28
+  if (base64_encode(hash_hmac('sha256', $ImgURL, strrev(PSK), true)) != $Auth) {
29
+    echo 'Auth failure';
30
+    die();
31
+  }
32
+  if (file_exists(IMG_ROOT.substr($ImgURLHash,0,2).'/'.$ImgURLHash)) {
33
+    unlink(IMG_ROOT.substr($ImgURLHash,0,2).'/'.$ImgURLHash);
34
+    echo 'Success';
35
+  } else {
36
+    echo 'File does not exist';
37
+  }
38
+  die();
39
+}
40
+
41
+// Normal use
42
+if (base64_encode(hash_hmac('sha256', $ImgURL, PSK, true)) != $Auth) {
43
+  // Authentication is incorrect. Something other than the paired Gazelle instance is attempting to use the host.
44
+  header('Content-type: image/png');
45
+  echo file_get_contents('imgs/unauthorized.png');
46
+  die();
47
+}
48
+if (file_exists(IMG_ROOT.substr($ImgURLHash,0,2).'/'.$ImgURLHash)) {
49
+  // The file is cached. Serve it.
50
+  $Img = file_get_contents(IMG_ROOT.substr($ImgURLHash,0,2).'/'.$ImgURLHash);
51
+  $FileType = image_type($Img);
52
+  header('Content-type: '.(($FileType=='webm')?'video':'image').'/'.$FileType);
53
+  echo $Img;
54
+} else {
55
+  // The file is not cached. Fetch it, cache it, and serve it.
56
+  $Img = @file_get_contents($ImgURL, 0, stream_context_create(['http' => ['user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.2987.133 Safari/537.36'], 'ssl' => ['verify_peer' => false]]), 0, 134217728);
57
+  $FileType = image_type($Img);
58
+  if (!empty($FileType)) {
59
+    if (!file_exists(IMG_ROOT.substr($ImgURLHash,0,2))) {
60
+      mkdir(IMG_ROOT.substr($ImgURLHash,0,2));
61
+    }
62
+    file_put_contents(IMG_ROOT.substr($ImgURLHash,0,2).'/'.$ImgURLHash, $Img);
63
+    header('Content-type: '.(($FileType=='webm')?'video':'image').'/'.$FileType);
64
+    echo $Img;
65
+  } else {
66
+    header('Content-type: image/png');
67
+    echo file_get_contents('imgs/invalid.png');
68
+  }
69
+}
70
+?>

+ 24
- 0
nginx.conf.example View File

@@ -0,0 +1,24 @@
1
+server {
2
+	listen 80;
3
+	server_name img.your.domain;
4
+	root /var/www/img.your.domain;
5
+
6
+	location / {
7
+	  try_files /index.php =500;
8
+		fastcgi_split_path_info ^(.+\.php)(/.+)$;
9
+		fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
10
+		fastcgi_index index.php;
11
+		include fastcgi_params;
12
+		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
13
+	}
14
+	location /thumb/ {
15
+	  try_files /index.php =500;
16
+		fastcgi_split_path_info ^(.+\.php)(/.+)$;
17
+		fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
18
+		fastcgi_index index.php;
19
+		include fastcgi_params;
20
+		fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21
+		image_filter_buffer 50M;
22
+		image_filter resize 400 400;
23
+	}
24
+}

Loading…
Cancel
Save