diff --git a/README.md b/README.md index 19cd589..91c854a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ Then open http://localhost:8080 in your browser ## New Features in v2 +- Generate placeholder images by specifying the size in the URL. [example](https://pictshare.net/placeholder/555x250/color-white-blue) - Added support for external storage - [Encryption of files in external storage](/rtfm/ENCRYPTION.md) - Added text hosting (like pastebin) @@ -105,13 +106,13 @@ Read [here](/rtfm/CONFIG.md) what those options do - [x] MASTER_DELETE_CODE - [x] MASTER_DELETE_IP - [x] UPLOAD_FORM_LOCATION +- [x] S3 Backend - [ ] UPLOAD_QUOTA - [ ] UPLOAD_CODE - [ ] LOW_PROFILE - [ ] IMAGE_CHANGE_CODE - [ ] MAX_RESIZED_IMAGES - [ ] ALLOW_BLOATING -- [ ] BACKBLAZE ### Image hosting - [x] Resizing diff --git a/content-controllers/image/image.controller.php b/content-controllers/image/image.controller.php index 6c92102..319820d 100644 --- a/content-controllers/image/image.controller.php +++ b/content-controllers/image/image.controller.php @@ -10,6 +10,7 @@ class ImageController implements ContentController { + public const ctype = 'static'; //returns all extensions registered by this type of content public function getRegisteredExtensions(){return array('png','bmp','gif','jpg','jpeg','x-png','webp');} diff --git a/content-controllers/placeholder/fonts/RonysiswadiArchitect5-1GErv.ttf b/content-controllers/placeholder/fonts/RonysiswadiArchitect5-1GErv.ttf new file mode 100644 index 0000000..25800e9 Binary files /dev/null and b/content-controllers/placeholder/fonts/RonysiswadiArchitect5-1GErv.ttf differ diff --git a/content-controllers/placeholder/placeholder.controller.php b/content-controllers/placeholder/placeholder.controller.php new file mode 100644 index 0000000..3395d41 --- /dev/null +++ b/content-controllers/placeholder/placeholder.controller.php @@ -0,0 +1,52 @@ +4) + $modifiers['colors'] = array_slice($modifiers['colors'],0,4); + } + } + + $img = $pg->generateImage($modifiers); + + $img = $pg->gradient($img, $modifiers['colors']); + $img = $pg->addSizeText($img,$modifiers); + + header ("Content-type: image/jpeg"); + header ("ETag: $hash"); + header('Cache-control: public, max-age=31536000'); + + imagejpeg($img,null,(defined('JPEG_COMPRESSION')?JPEG_COMPRESSION:90)); + } + + public function handleUpload($tmpfile,$hash=false) + { + return array('status'=>'err','hash'=>$hash,'reason'=>'Cannot upload to placeholder image'); + } + + +} \ No newline at end of file diff --git a/content-controllers/placeholder/placeholdergenerator.php b/content-controllers/placeholder/placeholdergenerator.php new file mode 100644 index 0000000..1701ad0 --- /dev/null +++ b/content-controllers/placeholder/placeholdergenerator.php @@ -0,0 +1,88 @@ + imagesx($im) || $textheight > imagesy($im)) + return $im; + + $x = (imagesx($im) - $textwidth) / 2; + $y = (imagesy($im) - $textheight) / 2 + $textheight; + imagettftext($im, $fontsize, 0, $x, $y, $textcolor, $font, $text); + + return $im; + } + + function gradient($im, $c) { + + $w = imagesx($im); + $h = imagesy($im); + + if(!$c[0]) $c = ['ffffff','ffffff','ffffff','ffffff']; + else if(!$c[1]) $c = [$c[0],$c[0],$c[0],$c[0]]; + else if(!$c[2]) $c = [$c[0],$c[0],$c[1],$c[1]]; + else if(!$c[3]) $c = [$c[0],$c[1],$c[2],$c[0]]; + + for($i=0;$i<=3;$i++) { + $c[$i]=$this->hex2rgb($c[$i]); + } + + $rgb=$c[0]; // start with top left color + for($x=0;$x<=$w;$x++) { // loop columns + for($y=0;$y<=$h;$y++) { // loop rows + // set pixel color + $col=imagecolorallocate($im,$rgb[0],$rgb[1],$rgb[2]); + imagesetpixel($im,$x-1,$y-1,$col); + // calculate new color + for($i=0;$i<=2;$i++) { + $rgb[$i]= + $c[0][$i]*(($w-$x)*($h-$y)/($w*$h)) + + $c[1][$i]*($x *($h-$y)/($w*$h)) + + $c[2][$i]*(($w-$x)*$y /($w*$h)) + + $c[3][$i]*($x *$y /($w*$h)); + } + } + } + return $im; + } + + function hex2rgb($hex) + { + $rgb[0]=hexdec(substr($hex,0,2)); + $rgb[1]=hexdec(substr($hex,2,2)); + $rgb[2]=hexdec(substr($hex,4,2)); + return($rgb); + } +} \ No newline at end of file diff --git a/content-controllers/text/text.controller.php b/content-controllers/text/text.controller.php index 8d4c54a..6644ce8 100644 --- a/content-controllers/text/text.controller.php +++ b/content-controllers/text/text.controller.php @@ -2,6 +2,8 @@ class TextController implements ContentController { + public const ctype = 'static'; + //returns all extensions registered by this type of content public function getRegisteredExtensions(){return array('txt','text','csv');} diff --git a/content-controllers/url/url.controller.php b/content-controllers/url/url.controller.php index d113f30..8f382be 100644 --- a/content-controllers/url/url.controller.php +++ b/content-controllers/url/url.controller.php @@ -2,6 +2,8 @@ class UrlController implements ContentController { + public const ctype = 'static'; + //returns all extensions registered by this type of content public function getRegisteredExtensions(){return array('url');} public function handleHash($hash,$url){} diff --git a/content-controllers/video/video.controller.php b/content-controllers/video/video.controller.php index 61b4449..959f997 100644 --- a/content-controllers/video/video.controller.php +++ b/content-controllers/video/video.controller.php @@ -2,6 +2,8 @@ class VideoController implements ContentController { + public const ctype = 'static'; + //returns all extensions registered by this type of content public function getRegisteredExtensions(){return array('mp4');} diff --git a/inc/core.php b/inc/core.php index efe20a4..86c3c0b 100644 --- a/inc/core.php +++ b/inc/core.php @@ -76,7 +76,21 @@ function architect($url) break; // we break here because we already have the file. no need to check other storage controllers } } - } + + + } + // if it's still false, we only have one hope: Maybe it's from a dynamic controller and the cache hasn't been created yet + else if($hash===false) + { + foreach(loadAllContentControllers(true) as $cc) + { + if((new $cc)::ctype=='dynamic' && in_array((new $cc)->getRegisteredExtensions()[0],$u) ) + { + $hash = true; + break; + } + } + } } @@ -112,7 +126,10 @@ function architect($url) foreach(loadAllContentControllers(true) as $cc) { - if(in_array($extension,(new $cc)->getRegisteredExtensions())) + if( + ((new $cc)::ctype=='dynamic' && in_array((new $cc)->getRegisteredExtensions()[0],$u)) || + ((new $cc)::ctype=='static' && in_array($extension,(new $cc)->getRegisteredExtensions())) + ) { (new $cc())->handleHash($hash,$u); return; @@ -464,6 +481,176 @@ function isSize($var) return true; } +function isColor($var) +{ + if(strlen($var)==6 && ctype_xdigit($var)) return true; + else + { + $col = color_name_to_hex($var); + if($col) return true; + else return false; + } +} + +function color_name_to_hex($color_name) + { + // standard 147 HTML color names + $colors = array( + 'aliceblue'=>'F0F8FF', + 'antiquewhite'=>'FAEBD7', + 'aqua'=>'00FFFF', + 'aquamarine'=>'7FFFD4', + 'azure'=>'F0FFFF', + 'beige'=>'F5F5DC', + 'bisque'=>'FFE4C4', + 'black'=>'000000', + 'blanchedalmond '=>'FFEBCD', + 'blue'=>'0000FF', + 'blueviolet'=>'8A2BE2', + 'brown'=>'A52A2A', + 'burlywood'=>'DEB887', + 'cadetblue'=>'5F9EA0', + 'chartreuse'=>'7FFF00', + 'chocolate'=>'D2691E', + 'coral'=>'FF7F50', + 'cornflowerblue'=>'6495ED', + 'cornsilk'=>'FFF8DC', + 'crimson'=>'DC143C', + 'cyan'=>'00FFFF', + 'darkblue'=>'00008B', + 'darkcyan'=>'008B8B', + 'darkgoldenrod'=>'B8860B', + 'darkgray'=>'A9A9A9', + 'darkgreen'=>'006400', + 'darkgrey'=>'A9A9A9', + 'darkkhaki'=>'BDB76B', + 'darkmagenta'=>'8B008B', + 'darkolivegreen'=>'556B2F', + 'darkorange'=>'FF8C00', + 'darkorchid'=>'9932CC', + 'darkred'=>'8B0000', + 'darksalmon'=>'E9967A', + 'darkseagreen'=>'8FBC8F', + 'darkslateblue'=>'483D8B', + 'darkslategray'=>'2F4F4F', + 'darkslategrey'=>'2F4F4F', + 'darkturquoise'=>'00CED1', + 'darkviolet'=>'9400D3', + 'deeppink'=>'FF1493', + 'deepskyblue'=>'00BFFF', + 'dimgray'=>'696969', + 'dimgrey'=>'696969', + 'dodgerblue'=>'1E90FF', + 'firebrick'=>'B22222', + 'floralwhite'=>'FFFAF0', + 'forestgreen'=>'228B22', + 'fuchsia'=>'FF00FF', + 'gainsboro'=>'DCDCDC', + 'ghostwhite'=>'F8F8FF', + 'gold'=>'FFD700', + 'goldenrod'=>'DAA520', + 'gray'=>'808080', + 'green'=>'008000', + 'greenyellow'=>'ADFF2F', + 'grey'=>'808080', + 'honeydew'=>'F0FFF0', + 'hotpink'=>'FF69B4', + 'indianred'=>'CD5C5C', + 'indigo'=>'4B0082', + 'ivory'=>'FFFFF0', + 'khaki'=>'F0E68C', + 'lavender'=>'E6E6FA', + 'lavenderblush'=>'FFF0F5', + 'lawngreen'=>'7CFC00', + 'lemonchiffon'=>'FFFACD', + 'lightblue'=>'ADD8E6', + 'lightcoral'=>'F08080', + 'lightcyan'=>'E0FFFF', + 'lightgoldenrodyellow'=>'FAFAD2', + 'lightgray'=>'D3D3D3', + 'lightgreen'=>'90EE90', + 'lightgrey'=>'D3D3D3', + 'lightpink'=>'FFB6C1', + 'lightsalmon'=>'FFA07A', + 'lightseagreen'=>'20B2AA', + 'lightskyblue'=>'87CEFA', + 'lightslategray'=>'778899', + 'lightslategrey'=>'778899', + 'lightsteelblue'=>'B0C4DE', + 'lightyellow'=>'FFFFE0', + 'lime'=>'00FF00', + 'limegreen'=>'32CD32', + 'linen'=>'FAF0E6', + 'magenta'=>'FF00FF', + 'maroon'=>'800000', + 'mediumaquamarine'=>'66CDAA', + 'mediumblue'=>'0000CD', + 'mediumorchid'=>'BA55D3', + 'mediumpurple'=>'9370D0', + 'mediumseagreen'=>'3CB371', + 'mediumslateblue'=>'7B68EE', + 'mediumspringgreen'=>'00FA9A', + 'mediumturquoise'=>'48D1CC', + 'mediumvioletred'=>'C71585', + 'midnightblue'=>'191970', + 'mintcream'=>'F5FFFA', + 'mistyrose'=>'FFE4E1', + 'moccasin'=>'FFE4B5', + 'navajowhite'=>'FFDEAD', + 'navy'=>'000080', + 'oldlace'=>'FDF5E6', + 'olive'=>'808000', + 'olivedrab'=>'6B8E23', + 'orange'=>'FFA500', + 'orangered'=>'FF4500', + 'orchid'=>'DA70D6', + 'palegoldenrod'=>'EEE8AA', + 'palegreen'=>'98FB98', + 'paleturquoise'=>'AFEEEE', + 'palevioletred'=>'DB7093', + 'papayawhip'=>'FFEFD5', + 'peachpuff'=>'FFDAB9', + 'peru'=>'CD853F', + 'pink'=>'FFC0CB', + 'plum'=>'DDA0DD', + 'powderblue'=>'B0E0E6', + 'purple'=>'800080', + 'red'=>'FF0000', + 'rosybrown'=>'BC8F8F', + 'royalblue'=>'4169E1', + 'saddlebrown'=>'8B4513', + 'salmon'=>'FA8072', + 'sandybrown'=>'F4A460', + 'seagreen'=>'2E8B57', + 'seashell'=>'FFF5EE', + 'sienna'=>'A0522D', + 'silver'=>'C0C0C0', + 'skyblue'=>'87CEEB', + 'slateblue'=>'6A5ACD', + 'slategray'=>'708090', + 'slategrey'=>'708090', + 'snow'=>'FFFAFA', + 'springgreen'=>'00FF7F', + 'steelblue'=>'4682B4', + 'tan'=>'D2B48C', + 'teal'=>'008080', + 'thistle'=>'D8BFD8', + 'tomato'=>'FF6347', + 'turquoise'=>'40E0D0', + 'violet'=>'EE82EE', + 'wheat'=>'F5DEB3', + 'white'=>'FFFFFF', + 'whitesmoke'=>'F5F5F5', + 'yellow'=>'FFFF00', + 'yellowgreen'=>'9ACD32'); + + $color_name = strtolower($color_name); + if (isset($colors[$color_name])) + return $colors[$color_name]; + else + return false; + } + function getStorageControllers() { $controllers = array(); diff --git a/interfaces/contentcontroller.interface.php b/interfaces/contentcontroller.interface.php index c358ab5..c51307c 100644 --- a/interfaces/contentcontroller.interface.php +++ b/interfaces/contentcontroller.interface.php @@ -6,6 +6,14 @@ interface ContentController { + /** + * When implementing a new content controller, you must specify a constant with the name of "ctype" + * This constant will be used to distinguish static controllers (which have files on disk) from dynamic ones (which don't, like the placeholder controller) + * + * Possible values: 'static' or 'dynamic' + */ + //const ctype = 'static'; + /** This method will return all file extensions that will be associated with this content type * for example 'pdf' but it could be anything really. You just need a way later to confirm that a type is what it says it is *