add cli options
[surrogator.git] / surrogator.php
1 #!/usr/bin/env php
2 <?php
3 namespace surrogator;
4 $cfgFile = __DIR__ . '/data/surrogator.config.php';
5 if (!file_exists($cfgFile)) {
6     $cfgFile = '/etc/surrogator.config.php';
7     if (!file_exists($cfgFile)) {
8         logErr(
9             "Configuration file does not exist.\n"
10             . "Copy data/surrogator.config.php.dist to data/surrogator.config.php"
11         );
12         exit(2);
13     }
14 }
15 require $cfgFile;
16
17 array_shift($argv);
18 $files = array();
19 foreach ($argv as $arg) {
20     if ($arg == '-v' || $arg == '--verbose') {
21         ++$logLevel;
22     } else if ($arg == '-vv') {
23         $logLevel += 2;
24     } else if ($arg == '-q' || $arg == '--quiet') {
25         $logLevel = 0;
26     } else if ($arg == '-f' || $arg == '--force') {
27         $forceUpdate = true;
28     } else if ($arg == '-h' || $arg == '--help') {
29         showHelp();
30         exit(4);
31     } else if ($arg == '--version') {
32         echo "surrogator 0.0.1\n";
33         exit();
34     } else if (file_exists($arg)) {
35         $files[] = $arg;
36     } else {
37         logErr('Unknown argument: ' . $arg);
38         exit(3);
39     }
40 }
41
42 function showHelp()
43 {
44     echo <<<HLP
45 Usage: php surrogator.php [options] [filename(s)]
46
47 surrogator - a simple libravatar server
48  Put files in raw/ dir and run surrogator.php to generate different sizes
49
50 Options:
51
52  -h, --help     Show help
53  -v, --verbose  Be verbose (more log messages, also -vv)
54  -q, --quiet    Be quiet (no log messages)
55  -f, --force    Force update of all files
56      --version  Show program version
57
58 filenames       One or several files whose small images shall get generated.
59                 If none given, all will be checked
60
61 HLP;
62 }
63
64 if (!isset($rawDir)) {
65     logErr('$rawDir not set');
66     exit(1);
67 }
68 if (!isset($varDir)) {
69     logErr('$varDir not set');
70     exit(1);
71 }
72 if (!isset($sizes)) {
73     logErr('$sizes not set');
74     exit(1);
75 }
76 if (!isset($maxSize)) {
77     logErr('$maxSize not set');
78     exit(1);
79 }
80 if (!isset($logLevel)) {
81     logErr('$logLevel not set');
82     exit(1);
83 }
84
85
86 if (!is_dir($varDir . '/square')) {
87     log('creating square dir: ' . $varDir . '/square');
88     mkdir($varDir . '/square', 0755, true);
89 }
90 log('sizes: ' . implode(', ', $sizes), 2);
91 foreach ($sizes as $size) {
92     if (!is_dir($varDir . '/' . $size)) {
93         log('creating size dir: ' . $varDir . '/' . $size);
94         mkdir($varDir . '/' . $size, 0755);
95     }
96 }
97
98 $dir = new \RegexIterator(
99     new \DirectoryIterator($rawDir),
100     '#^.+\.(png|jpg)$#'
101 );
102 foreach ($dir as $fileInfo) {
103     $origPath   = $fileInfo->getPathname();
104     $fileName   = $fileInfo->getFilename();
105     $ext        = strtolower(substr($fileName, strrpos($fileName, '.') + 1));
106     $squarePath = $varDir . '/square/'
107         . substr($fileName, 0, -strlen($ext)) . 'png';
108
109     log('processing ' . $fileName, 1);
110     if (image_uptodate($origPath, $squarePath)) {
111         log(' image up to date', 2);
112         continue;
113     }
114
115     if (!createSquare($origPath, $ext, $squarePath, $maxSize)) {
116         continue;
117     }
118
119     if ($fileName == 'default.png') {
120         $md5 = $sha256 = 'default';
121     } else {
122         list($md5, $sha256) = getHashes($fileName);
123     }
124
125     log(' creating sizes for ' . $fileName, 2);
126     log(' md5:    ' . $md5, 3);
127     log(' sha256: ' . $sha256, 3);
128     $imgSquare = imagecreatefrompng($squarePath);
129     foreach ($sizes as $size) {
130         $sizePathMd5    = $varDir . '/' . $size . '/' . $md5 . '.png';
131         $sizePathSha256 = $varDir . '/' . $size . '/' . $sha256 . '.png';
132
133         $imgSize = imagecreatetruecolor($size, $size);
134         imagealphablending($imgSize, false);
135         imagefilledrectangle(
136             $imgSize, 0, 0, $size - 1, $size - 1,
137             imagecolorallocatealpha($imgSize, 0, 0, 0, 127)
138         );
139         imagecopyresampled(
140             $imgSize, $imgSquare, 
141             0, 0, 0, 0,
142             $size, $size, $maxSize, $maxSize
143         );
144         imagesavealpha($imgSize, true);
145         imagepng($imgSize, $sizePathMd5);
146         imagepng($imgSize, $sizePathSha256);
147         imagedestroy($imgSize);
148         
149     }
150     imagedestroy($imgSquare);
151 }
152
153 function getHashes($fileName)
154 {
155     $fileNameNoExt = substr($fileName, 0, -strlen(strrpos($fileName, '.')) - 2);
156     $emailAddress  = trim(strtolower($fileNameNoExt));
157
158     return array(
159         md5($emailAddress), hash('sha256', $emailAddress)
160     );
161 }
162
163
164 function createSquare($origPath, $ext, $targetPath, $maxSize)
165 {
166     if ($ext == 'png') {
167         $imgOrig = imagecreatefrompng($origPath);
168     } else if ($ext == 'jpg' || $ext == 'jpeg') {
169         $imgOrig = imagecreatefromjpeg($origPath);
170     } else {
171         //unsupported format
172         return false;
173     }
174
175     if ($imgOrig === false) {
176         logErr('Error loading image file: ' . $origPath);
177         return false;
178     }
179
180     $imgSquare = imagecreatetruecolor($maxSize, $maxSize);
181     imagealphablending($imgSquare, false);
182     imagefilledrectangle(
183         $imgSquare, 0, 0, $maxSize - 1, $maxSize - 1,
184         imagecolorallocatealpha($imgSquare, 0, 0, 0, 127)
185     );
186     imagealphablending($imgSquare, true);
187
188     $oWidth    = imagesx($imgOrig);
189     $oHeight   = imagesy($imgOrig);
190     if ($oWidth > $oHeight) {
191         $flScale = $maxSize / $oWidth;
192     } else {
193         $flScale = $maxSize / $oHeight;
194     }
195     $nWidth  = (int)($oWidth * $flScale);
196     $nHeight = (int)($oHeight * $flScale);
197
198     imagecopyresampled(
199         $imgSquare, $imgOrig, 
200         ($maxSize - $nWidth) / 2, ($maxSize - $nHeight) / 2,
201         0, 0,
202         $nWidth, $nHeight,
203         $oWidth, $oHeight
204     );
205
206     imagesavealpha($imgSquare, true);
207     imagepng($imgSquare, $targetPath);
208
209     imagedestroy($imgSquare);
210     imagedestroy($imgOrig);
211     return true;
212 }
213
214 function image_uptodate($sourcePath, $targetPath)
215 {
216     global $forceUpdate;
217     if ($forceUpdate) {
218         return false;
219     }
220     if (!file_exists($targetPath)) {
221         return false;
222     }
223     if (filemtime($sourcePath) > filemtime($targetPath)) {
224         //source newer
225         return false;
226     }
227
228     return true;
229 }
230
231 function log($msg, $level = 1)
232 {
233     global $logLevel;
234     if ($level <= $logLevel) {
235         echo $msg . "\n";
236     }
237 }
238
239 function logErr($msg)
240 {
241     file_put_contents('php://stderr', $msg . "\n");
242 }
243
244 ?>