Add composer.json so we can validate php extension requirements master github/master
authorChristian Weiske <cweiske@cweiske.de>
Mon, 27 Feb 2023 20:48:39 +0000 (21:48 +0100)
committerChristian Weiske <cweiske@cweiske.de>
Mon, 27 Feb 2023 20:48:39 +0000 (21:48 +0100)
with "composer check-platform-reqs"

.gitignore
ChangeLog
README.rst
build.xml
composer.json [new file with mode: 0644]
composer.lock [new file with mode: 0644]
data/surrogator.config.php.dist
surrogator.php
www/avatar.php

index 951f07870d13c5a827aeb77bd7e40771de0afec3..b3d2101bb02e657ecca5db51e1e723c7ffe08145 100644 (file)
@@ -7,3 +7,4 @@ www/favicon.ico
 www/robots.txt
 build.properties
 dist/
+/vendor/
index cffcc6f31151b8120c39d26769f4945849f68ca4..6752f85ff6b5c14fc6bf8a7d57f12715facfc016 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2021-11-26  Christian Weiske  <cweiske@cweiske.de>
+
+       * Fix open redirect security issue (CWE-601).
+         You have to white-list allowed default URLs now.
+       * Add support for .svg source files
+       * Version 0.3.0
+
+2012-08-27  Christian Weiske  <cweiske@bogo>
+
+       * Add support for OpenIDs
+       * Version 0.2.0
+
 2012-08-17  Christian Weiske  <cweiske@cweiske.de>
 
        * Version 0.1.0
index 64677b03f198728db89dacf3feee55567f85fdb2..6f3575fb5660f6bb5ffc6e23ba427fa6e623b6e6 100644 (file)
@@ -6,7 +6,7 @@ Simple open source Libravatar__ compatible avatar image server written in PHP.
 
 Features:
 
-- Delivers images for email addresses
+- Delivers images for email addresses and OpenIDs
 - Very easy to setup.
 - No graphics processing is done on the server, keeping the CPU load low.
   All avatar images get pre-generated for a set of sizes
@@ -54,7 +54,13 @@ Usage
 1. Put images in ``raw/`` folder.
    Name has to be email address + image file extension, for example
    ``foo@example.org.png``.
-   Surrogator supports ``.png`` and ``.jpg``.
+   Surrogator supports ``.png``, ``.jpg`` and ``svg`` files.
+
+   For OpenIDs, use the url-encoded URL + extension as filename, for example
+   replace ``/`` with ``%2F``.
+   The filename for ``http://example.org/~foo`` would be
+   ``http:%2F%2Fexample.org%2F~foo.jpg``.
+
 2. Run ``php surrogator.php``.
    The small files get generated.
 3. You will get more information with ``-v``
@@ -62,6 +68,8 @@ Usage
    when the raw file is newer than the "square" file in the var folder.
    You can force the update with ``--force``.
 
+Note: PHP imagick extension is required for ``svg`` files.
+
 
 ====
 Test
index 6bcd68ae6e597cf5c680ea47d6102e91efe5ad02..7d2f1ac0b864452380df1649886d67df7a694d13 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -8,8 +8,8 @@
   -->
   <property file="build.properties" />
 
-  <property name="version-m"  value="0.1" />
-  <property name="version"    value="0.1.0" />
+  <property name="version-m"  value="0.3" />
+  <property name="version"    value="0.3.0" />
   <property name="stability"  value="alpha" />
   <property name="zipfile"     value="${phing.project.name}-${version}.tar.bz2" />
   <property name="distfile"    value="dist/${zipfile}" />
diff --git a/composer.json b/composer.json
new file mode 100644 (file)
index 0000000..9c920d0
--- /dev/null
@@ -0,0 +1,9 @@
+{
+    "name": "cweiske/surrogator",
+    "description": "Libravatar compatible avatar image server",
+    "license": "AGPL-3.0-only",
+    "require": {
+        "ext-gd": "*",
+        "ext-imagick": "*"
+    }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644 (file)
index 0000000..7513e4a
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "c94e11a46a1283a678a79c9807c2b641",
+    "packages": [],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "ext-gd": "*",
+        "ext-imagick": "*"
+    },
+    "platform-dev": [],
+    "plugin-api-version": "2.3.0"
+}
index 23a1e8ab74f68a288a28408f06f1219d9017997f..f43372774a3f08c6b866257296c65d6b2b26ce36 100644 (file)
@@ -43,4 +43,20 @@ $logLevel = 1;
  * to true, the images will always be regenerated.
  */
 $forceUpdate = false;
+
+/**
+ * URL prefixes that may be used as "default" parameter.
+ *
+ * Taken from https://git.linux-kernel.at/oliver/ivatar/-/blob/master/config.py
+ */
+$trustedDefaultUrls = [
+    'http://gravatar.com/avatar/',
+    'http://www.planet-libre.org/themes/planetlibre/images/',
+    'https://avatars.dicebear.com/api/',
+    'https://badges.fedoraproject.org/static/img/',
+    'https://gravatar.com/avatar/',
+    'https://secure.gravatar.com/avatar/',
+    'https://ui-avatars.com/api/',
+    'https://www.azuracast.com/img/',
+];
 ?>
index fdbd38412aa983e06eb9aee4453793b438a18808..b397042d1603d24c129ee9adaa94fed8aea2a8de 100755 (executable)
@@ -136,7 +136,7 @@ if (count($files)) {
 } else {
     $fileInfos = new \RegexIterator(
         new \DirectoryIterator($rawDir),
-        '#^.+\.(png|jpg)$#'
+        '#^.+\.(png|jpg|svg|svgz)$#'
     );
 }
 foreach ($fileInfos as $fileInfo) {
@@ -202,6 +202,9 @@ foreach ($fileInfos as $fileInfo) {
  */
 function getHashes($fileName)
 {
+    //OpenIDs have their slashes "/" url-encoded
+    $fileName = rawurldecode($fileName);
+
     $fileNameNoExt = substr($fileName, 0, -strlen(strrpos($fileName, '.')) - 2);
     $emailAddress  = trim(strtolower($fileNameNoExt));
 
@@ -227,8 +230,15 @@ function createSquare($origPath, $ext, $targetPath, $maxSize)
         $imgOrig = imagecreatefrompng($origPath);
     } else if ($ext == 'jpg' || $ext == 'jpeg') {
         $imgOrig = imagecreatefromjpeg($origPath);
+    } else if ($ext == 'svg' || $ext == 'svgz') {
+        $imagickImg = new \Imagick();
+        $imagickImg->setBackgroundColor(new \ImagickPixel('transparent'));
+        $imagickImg->readImage($origPath);
+        $imagickImg->setImageFormat('png32');
+        $imgOrig = imagecreatefromstring($imagickImg->getImageBlob());
     } else {
         //unsupported format
+        logErr('Unsupported image format: ' . $origPath);
         return false;
     }
 
index e707dc40f7955b5cfb8912ae8b896896cca49056..e20ddda763d5146881527b0bf178c8c4daef5bcc 100644 (file)
@@ -96,7 +96,19 @@ if (isset($_GET['default'])) {
         //url
         $defaultMode = 'redirect';
         $default     = $_GET['default'];
-        //FIXME: validate?
+
+        $allowed = false;
+        foreach ($trustedDefaultUrls ?? [] as $urlPrefix) {
+            if (substr($default, 0, strlen($urlPrefix))  == $urlPrefix) {
+                $allowed = true;
+                break;
+            }
+        }
+        if (!$allowed) {
+            header('X-Info: default parameter URL not allowed');
+            $defaultMode = 'local';
+            $default     = 'default.png';
+        }
     }
 }
 
@@ -149,4 +161,4 @@ header('Content-Type: image/png');
 header('Content-Length:' . $stat['size']);
 
 readfile($imgFile);
-?>
\ No newline at end of file
+?>