-
88.89% covered (success)
+
95.85%
+
208 / 217
+
+
+ 77.78% covered (warning)
-
88.89%
-
8 / 9
-
CRAP
+
77.78%
+
7 / 9
+
CRAP
0.00% covered (danger)
@@ -73,22 +73,22 @@
Controller
-
-
99.05% covered (success)
+
+ 95.85% covered (success)
- 99.05%
- 208 / 210
-
-
-
88.89% covered (success)
+
95.85%
+
208 / 217
+
+
+ 77.78% covered (warning)
-
88.89%
-
8 / 9
-
48
+
77.78%
+
7 / 9
+
49
0.00% covered (danger)
@@ -102,13 +102,13 @@
__construct
-
-
93.55% covered (success)
+
+ 87.88% covered (success)
- 93.55%
- 29 / 31
+ 87.88%
+ 29 / 33
0.00% covered (danger)
@@ -117,12 +117,12 @@
0.00%
0 / 1
- 10.03
+ 10.18
- _init
+ _init
100.00% covered (success)
@@ -144,29 +144,29 @@
- _create
+ _create
-
-
100.00% covered (success)
+
+ 89.58% covered (success)
- 100.00%
- 43 / 43
-
-
-
100.00% covered (success)
+
89.58%
+
43 / 48
+
+
+ 0.00% covered (danger)
-
100.00%
-
1 / 1
-
11
-
+
0.00%
+
0 / 1
+
12.16
+
- _delete
+ _delete
100.00% covered (success)
@@ -188,7 +188,7 @@
- _read
+ _read
100.00% covered (success)
@@ -210,7 +210,7 @@
- _view
+ _view
100.00% covered (success)
@@ -232,7 +232,7 @@
- _jsonld
+ _jsonld
100.00% covered (success)
@@ -254,7 +254,7 @@
- _yourlsproxy
+ _yourlsproxy
100.00% covered (success)
@@ -276,7 +276,7 @@
- _return_message
+ _return_message
100.00% covered (success)
@@ -312,7 +312,7 @@
7
8
9
-
10
+
10
11
12
13 namespace PrivateBin ;
@@ -333,7 +333,7 @@
28
29
30
-
31 const VERSION = '1.6.0' ;
+
31 const VERSION = '1.7.0' ;
32
33
34
@@ -416,390 +416,399 @@
111 public function __construct ( )
112 {
113 if ( version_compare ( PHP_VERSION , self :: MIN_PHP_VERSION ) < 0 ) {
-
114 throw new Exception ( I18n :: _ ( '%s requires php %s or above to work. Sorry.' , I18n :: _ ( 'PrivateBin' ) , self :: MIN_PHP_VERSION ) , 1 ) ;
-
115 }
-
116 if ( strlen ( PATH ) < 0 && substr ( PATH , - 1 ) !== DIRECTORY_SEPARATOR ) {
-
117 throw new Exception ( I18n :: _ ( '%s requires the PATH to end in a "%s". Please update the PATH in your index.php.' , I18n :: _ ( 'PrivateBin' ) , DIRECTORY_SEPARATOR ) , 5 ) ;
-
118 }
-
119
-
120
-
121 $this -> _init ( ) ;
-
122
-
123 switch ( $this -> _request -> getOperation ( ) ) {
-
124 case 'create' :
-
125 $this -> _create ( ) ;
-
126 break ;
-
127 case 'delete' :
-
128 $this -> _delete (
-
129 $this -> _request -> getParam ( 'pasteid' ) ,
-
130 $this -> _request -> getParam ( 'deletetoken' )
-
131 ) ;
-
132 break ;
-
133 case 'read' :
-
134 $this -> _read ( $this -> _request -> getParam ( 'pasteid' ) ) ;
-
135 break ;
-
136 case 'jsonld' :
-
137 $this -> _jsonld ( $this -> _request -> getParam ( 'jsonld' ) ) ;
-
138 return ;
-
139 case 'yourlsproxy' :
-
140 $this -> _yourlsproxy ( $this -> _request -> getParam ( 'link' ) ) ;
-
141 break ;
-
142 }
-
143
-
144
-
145 if ( $this -> _request -> isJsonApiCall ( ) ) {
-
146 header ( 'Content-type: ' . Request :: MIME_JSON ) ;
-
147 header ( 'Access-Control-Allow-Origin: *' ) ;
-
148 header ( 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE' ) ;
-
149 header ( 'Access-Control-Allow-Headers: X-Requested-With, Content-Type' ) ;
-
150 echo $this -> _json ;
-
151 } else {
-
152 $this -> _view ( ) ;
-
153 }
-
154 }
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162 private function _init ( )
-
163 {
-
164 $this -> _conf = new Configuration ;
-
165 $this -> _model = new Model ( $this -> _conf ) ;
-
166 $this -> _request = new Request ;
-
167 $this -> _urlBase = $this -> _request -> getRequestUri ( ) ;
-
168
-
169
-
170 $lang = $this -> _conf -> getKey ( 'languagedefault' ) ;
-
171 I18n :: setLanguageFallback ( $lang ) ;
-
172
-
173 if ( ! $this -> _conf -> getKey ( 'languageselection' ) && strlen ( $lang ) == 2 ) {
-
174 $_COOKIE [ 'lang' ] = $lang ;
-
175 setcookie ( 'lang' , $lang , 0 , '' , '' , true ) ;
-
176 }
-
177 }
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199 private function _create ( )
-
200 {
-
201
-
202 ServerSalt :: setStore ( $this -> _model -> getStore ( ) ) ;
-
203 TrafficLimiter :: setConfiguration ( $this -> _conf ) ;
-
204 TrafficLimiter :: setStore ( $this -> _model -> getStore ( ) ) ;
-
205 try {
-
206 TrafficLimiter :: canPass ( ) ;
-
207 } catch ( Exception $e ) {
-
208 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
-
209 return ;
-
210 }
-
211
-
212 $data = $this -> _request -> getData ( ) ;
-
213 $isComment = array_key_exists ( 'pasteid' , $data ) &&
-
214 ! empty ( $data [ 'pasteid' ] ) &&
-
215 array_key_exists ( 'parentid' , $data ) &&
-
216 ! empty ( $data [ 'parentid' ] ) ;
-
217 if ( ! FormatV2 :: isValid ( $data , $isComment ) ) {
-
218 $this -> _return_message ( 1 , I18n :: _ ( 'Invalid data.' ) ) ;
-
219 return ;
-
220 }
-
221 $sizelimit = $this -> _conf -> getKey ( 'sizelimit' ) ;
-
222
-
223 if ( strlen ( $data [ 'ct' ] ) > $sizelimit ) {
-
224 $this -> _return_message (
-
225 1 ,
-
226 I18n :: _ (
-
227 'Paste is limited to %s of encrypted data.' ,
-
228 Filter :: formatHumanReadableSize ( $sizelimit )
-
229 )
-
230 ) ;
-
231 return ;
-
232 }
-
233
-
234
-
235 if ( $isComment ) {
-
236 $paste = $this -> _model -> getPaste ( $data [ 'pasteid' ] ) ;
-
237 if ( $paste -> exists ( ) ) {
-
238 try {
-
239 $comment = $paste -> getComment ( $data [ 'parentid' ] ) ;
-
240 $comment -> setData ( $data ) ;
-
241 $comment -> store ( ) ;
-
242 } catch ( Exception $e ) {
-
243 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
-
244 return ;
-
245 }
-
246 $this -> _return_message ( 0 , $comment -> getId ( ) ) ;
-
247 } else {
-
248 $this -> _return_message ( 1 , I18n :: _ ( 'Invalid data.' ) ) ;
-
249 }
-
250 }
-
251
-
252 else {
-
253 $this -> _model -> purge ( ) ;
-
254 $paste = $this -> _model -> getPaste ( ) ;
+
114 error_log ( I18n :: _ ( '%s requires php %s or above to work. Sorry.' , I18n :: _ ( 'PrivateBin' ) , self :: MIN_PHP_VERSION ) ) ;
+
115 return ;
+
116 }
+
117 if ( strlen ( PATH ) < 0 && substr ( PATH , - 1 ) !== DIRECTORY_SEPARATOR ) {
+
118 error_log ( I18n :: _ ( '%s requires the PATH to end in a "%s". Please update the PATH in your index.php.' , I18n :: _ ( 'PrivateBin' ) , DIRECTORY_SEPARATOR ) ) ;
+
119 return ;
+
120 }
+
121
+
122
+
123 $this -> _init ( ) ;
+
124
+
125 switch ( $this -> _request -> getOperation ( ) ) {
+
126 case 'create' :
+
127 $this -> _create ( ) ;
+
128 break ;
+
129 case 'delete' :
+
130 $this -> _delete (
+
131 $this -> _request -> getParam ( 'pasteid' ) ,
+
132 $this -> _request -> getParam ( 'deletetoken' )
+
133 ) ;
+
134 break ;
+
135 case 'read' :
+
136 $this -> _read ( $this -> _request -> getParam ( 'pasteid' ) ) ;
+
137 break ;
+
138 case 'jsonld' :
+
139 $this -> _jsonld ( $this -> _request -> getParam ( 'jsonld' ) ) ;
+
140 return ;
+
141 case 'yourlsproxy' :
+
142 $this -> _yourlsproxy ( $this -> _request -> getParam ( 'link' ) ) ;
+
143 break ;
+
144 }
+
145
+
146
+
147 if ( $this -> _request -> isJsonApiCall ( ) ) {
+
148 header ( 'Content-type: ' . Request :: MIME_JSON ) ;
+
149 header ( 'Access-Control-Allow-Origin: *' ) ;
+
150 header ( 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE' ) ;
+
151 header ( 'Access-Control-Allow-Headers: X-Requested-With, Content-Type' ) ;
+
152 echo $this -> _json ;
+
153 } else {
+
154 $this -> _view ( ) ;
+
155 }
+
156 }
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164 private function _init ( )
+
165 {
+
166 $this -> _conf = new Configuration ;
+
167 $this -> _model = new Model ( $this -> _conf ) ;
+
168 $this -> _request = new Request ;
+
169 $this -> _urlBase = $this -> _request -> getRequestUri ( ) ;
+
170
+
171
+
172 $lang = $this -> _conf -> getKey ( 'languagedefault' ) ;
+
173 I18n :: setLanguageFallback ( $lang ) ;
+
174
+
175 if ( ! $this -> _conf -> getKey ( 'languageselection' ) && strlen ( $lang ) == 2 ) {
+
176 $_COOKIE [ 'lang' ] = $lang ;
+
177 setcookie ( 'lang' , $lang , 0 , '' , '' , true ) ;
+
178 }
+
179 }
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201 private function _create ( )
+
202 {
+
203
+
204 ServerSalt :: setStore ( $this -> _model -> getStore ( ) ) ;
+
205 TrafficLimiter :: setConfiguration ( $this -> _conf ) ;
+
206 TrafficLimiter :: setStore ( $this -> _model -> getStore ( ) ) ;
+
207 try {
+
208 TrafficLimiter :: canPass ( ) ;
+
209 } catch ( Exception $e ) {
+
210 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
+
211 return ;
+
212 }
+
213
+
214 $data = $this -> _request -> getData ( ) ;
+
215 $isComment = array_key_exists ( 'pasteid' , $data ) &&
+
216 ! empty ( $data [ 'pasteid' ] ) &&
+
217 array_key_exists ( 'parentid' , $data ) &&
+
218 ! empty ( $data [ 'parentid' ] ) ;
+
219 if ( ! FormatV2 :: isValid ( $data , $isComment ) ) {
+
220 $this -> _return_message ( 1 , I18n :: _ ( 'Invalid data.' ) ) ;
+
221 return ;
+
222 }
+
223 $sizelimit = $this -> _conf -> getKey ( 'sizelimit' ) ;
+
224
+
225 if ( strlen ( $data [ 'ct' ] ) > $sizelimit ) {
+
226 $this -> _return_message (
+
227 1 ,
+
228 I18n :: _ (
+
229 'Paste is limited to %s of encrypted data.' ,
+
230 Filter :: formatHumanReadableSize ( $sizelimit )
+
231 )
+
232 ) ;
+
233 return ;
+
234 }
+
235
+
236
+
237 if ( $isComment ) {
+
238 $paste = $this -> _model -> getPaste ( $data [ 'pasteid' ] ) ;
+
239 if ( $paste -> exists ( ) ) {
+
240 try {
+
241 $comment = $paste -> getComment ( $data [ 'parentid' ] ) ;
+
242 $comment -> setData ( $data ) ;
+
243 $comment -> store ( ) ;
+
244 } catch ( Exception $e ) {
+
245 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
+
246 return ;
+
247 }
+
248 $this -> _return_message ( 0 , $comment -> getId ( ) ) ;
+
249 } else {
+
250 $this -> _return_message ( 1 , I18n :: _ ( 'Invalid data.' ) ) ;
+
251 }
+
252 }
+
253
+
254 else {
255 try {
-
256 $paste -> setData ( $data ) ;
-
257 $paste -> store ( ) ;
-
258 } catch ( Exception $e ) {
-
259 return $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
-
260 }
-
261 $this -> _return_message ( 0 , $paste -> getId ( ) , array ( 'deletetoken' => $paste -> getDeleteToken ( ) ) ) ;
-
262 }
-
263 }
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272 private function _delete ( $dataid , $deletetoken )
-
273 {
-
274 try {
-
275 $paste = $this -> _model -> getPaste ( $dataid ) ;
-
276 if ( $paste -> exists ( ) ) {
-
277
-
278
-
279 $paste -> get ( ) ;
-
280 if ( hash_equals ( $paste -> getDeleteToken ( ) , $deletetoken ) ) {
-
281
-
282 $paste -> delete ( ) ;
-
283 $this -> _status = 'Paste was properly deleted.' ;
-
284 } else {
-
285 $this -> _error = 'Wrong deletion token. Paste was not deleted.' ;
-
286 }
-
287 } else {
-
288 $this -> _error = self :: GENERIC_ERROR ;
-
289 }
-
290 } catch ( Exception $e ) {
-
291 $this -> _error = $e -> getMessage ( ) ;
-
292 }
-
293 if ( $this -> _request -> isJsonApiCall ( ) ) {
-
294 if ( strlen ( $this -> _error ) ) {
-
295 $this -> _return_message ( 1 , $this -> _error ) ;
+
256 $this -> _model -> purge ( ) ;
+
257 } catch ( Exception $e ) {
+
258 error_log ( 'Error purging pastes: ' . $e -> getMessage ( ) . PHP_EOL .
+
259 'Use the administration scripts statistics to find ' .
+
260 'damaged paste IDs and either delete them or restore them ' .
+
261 'from backup.' ) ;
+
262 }
+
263 $paste = $this -> _model -> getPaste ( ) ;
+
264 try {
+
265 $paste -> setData ( $data ) ;
+
266 $paste -> store ( ) ;
+
267 } catch ( Exception $e ) {
+
268 return $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
+
269 }
+
270 $this -> _return_message ( 0 , $paste -> getId ( ) , array ( 'deletetoken' => $paste -> getDeleteToken ( ) ) ) ;
+
271 }
+
272 }
+
273
+
274
+
275
+
276
+
277
+
278
+
279
+
280
+
281 private function _delete ( $dataid , $deletetoken )
+
282 {
+
283 try {
+
284 $paste = $this -> _model -> getPaste ( $dataid ) ;
+
285 if ( $paste -> exists ( ) ) {
+
286
+
287
+
288 $paste -> get ( ) ;
+
289 if ( hash_equals ( $paste -> getDeleteToken ( ) , $deletetoken ) ) {
+
290
+
291 $paste -> delete ( ) ;
+
292 $this -> _status = 'Paste was properly deleted.' ;
+
293 } else {
+
294 $this -> _error = 'Wrong deletion token. Paste was not deleted.' ;
+
295 }
296 } else {
-
297 $this -> _return_message ( 0 , $dataid ) ;
+
297 $this -> _error = self :: GENERIC_ERROR ;
298 }
-
299 }
-
300 }
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308 private function _read ( $dataid )
-
309 {
-
310 if ( ! $this -> _request -> isJsonApiCall ( ) ) {
-
311 return ;
-
312 }
-
313
-
314 try {
-
315 $paste = $this -> _model -> getPaste ( $dataid ) ;
-
316 if ( $paste -> exists ( ) ) {
-
317 $data = $paste -> get ( ) ;
-
318 if ( array_key_exists ( 'salt' , $data [ 'meta' ] ) ) {
-
319 unset ( $data [ 'meta' ] [ 'salt' ] ) ;
-
320 }
-
321 $this -> _return_message ( 0 , $dataid , (array) $data ) ;
-
322 } else {
-
323 $this -> _return_message ( 1 , self :: GENERIC_ERROR ) ;
-
324 }
-
325 } catch ( Exception $e ) {
-
326 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
-
327 }
-
328 }
-
329
-
330
-
331
-
332
-
333
-
334
-
335 private function _view ( )
-
336 {
-
337
-
338 $time = gmdate ( 'D, d M Y H:i:s \G\M\T' ) ;
-
339 header ( 'Cache-Control: no-store, no-cache, no-transform, must-revalidate' ) ;
-
340 header ( 'Pragma: no-cache' ) ;
-
341 header ( 'Expires: ' . $time ) ;
-
342 header ( 'Last-Modified: ' . $time ) ;
-
343 header ( 'Vary: Accept' ) ;
-
344 header ( 'Content-Security-Policy: ' . $this -> _conf -> getKey ( 'cspheader' ) ) ;
-
345 header ( 'Cross-Origin-Resource-Policy: same-origin' ) ;
-
346 header ( 'Cross-Origin-Embedder-Policy: require-corp' ) ;
-
347
-
348
-
349
-
350
-
351 header ( 'Permissions-Policy: browsing-topics=()' ) ;
-
352 header ( 'Referrer-Policy: no-referrer' ) ;
-
353 header ( 'X-Content-Type-Options: nosniff' ) ;
-
354 header ( 'X-Frame-Options: deny' ) ;
-
355 header ( 'X-XSS-Protection: 1; mode=block' ) ;
-
356
-
357
-
358 $expire = array ( ) ;
-
359 foreach ( $this -> _conf -> getSection ( 'expire_options' ) as $time => $seconds ) {
-
360 $expire [ $time ] = ( $seconds == 0 ) ? I18n :: _ ( ucfirst ( $time ) ) : Filter :: formatHumanReadableTime ( $time ) ;
-
361 }
-
362
-
363
-
364 $formatters = array_map ( 'PrivateBin\\I18n::_' , $this -> _conf -> getSection ( 'formatter_options' ) ) ;
+
299 } catch ( Exception $e ) {
+
300 $this -> _error = $e -> getMessage ( ) ;
+
301 }
+
302 if ( $this -> _request -> isJsonApiCall ( ) ) {
+
303 if ( strlen ( $this -> _error ) ) {
+
304 $this -> _return_message ( 1 , $this -> _error ) ;
+
305 } else {
+
306 $this -> _return_message ( 0 , $dataid ) ;
+
307 }
+
308 }
+
309 }
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317 private function _read ( $dataid )
+
318 {
+
319 if ( ! $this -> _request -> isJsonApiCall ( ) ) {
+
320 return ;
+
321 }
+
322
+
323 try {
+
324 $paste = $this -> _model -> getPaste ( $dataid ) ;
+
325 if ( $paste -> exists ( ) ) {
+
326 $data = $paste -> get ( ) ;
+
327 if ( array_key_exists ( 'salt' , $data [ 'meta' ] ) ) {
+
328 unset ( $data [ 'meta' ] [ 'salt' ] ) ;
+
329 }
+
330 $this -> _return_message ( 0 , $dataid , (array) $data ) ;
+
331 } else {
+
332 $this -> _return_message ( 1 , self :: GENERIC_ERROR ) ;
+
333 }
+
334 } catch ( Exception $e ) {
+
335 $this -> _return_message ( 1 , $e -> getMessage ( ) ) ;
+
336 }
+
337 }
+
338
+
339
+
340
+
341
+
342
+
343
+
344 private function _view ( )
+
345 {
+
346
+
347 $time = gmdate ( 'D, d M Y H:i:s \G\M\T' ) ;
+
348 header ( 'Cache-Control: no-store, no-cache, no-transform, must-revalidate' ) ;
+
349 header ( 'Pragma: no-cache' ) ;
+
350 header ( 'Expires: ' . $time ) ;
+
351 header ( 'Last-Modified: ' . $time ) ;
+
352 header ( 'Vary: Accept' ) ;
+
353 header ( 'Content-Security-Policy: ' . $this -> _conf -> getKey ( 'cspheader' ) ) ;
+
354 header ( 'Cross-Origin-Resource-Policy: same-origin' ) ;
+
355 header ( 'Cross-Origin-Embedder-Policy: require-corp' ) ;
+
356
+
357
+
358
+
359
+
360 header ( 'Permissions-Policy: browsing-topics=()' ) ;
+
361 header ( 'Referrer-Policy: no-referrer' ) ;
+
362 header ( 'X-Content-Type-Options: nosniff' ) ;
+
363 header ( 'X-Frame-Options: deny' ) ;
+
364 header ( 'X-XSS-Protection: 1; mode=block' ) ;
365
-
366
-
367 $languageselection = '' ;
-
368 if ( $this -> _conf -> getKey ( 'languageselection' ) ) {
-
369 $languageselection = I18n :: getLanguage ( ) ;
-
370 setcookie ( 'lang' , $languageselection , 0 , '' , '' , true ) ;
-
371 }
-
372
-
373
-
374 $metacspheader = str_replace (
-
375 array (
-
376 'frame-ancestors \'none\'; ' ,
-
377 '; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads' ,
-
378 ) ,
-
379 '' ,
-
380 $this -> _conf -> getKey ( 'cspheader' )
-
381 ) ;
-
382
-
383 $page = new View ;
-
384 $page -> assign ( 'CSPHEADER' , $metacspheader ) ;
-
385 $page -> assign ( 'ERROR' , I18n :: _ ( $this -> _error ) ) ;
-
386 $page -> assign ( 'NAME' , $this -> _conf -> getKey ( 'name' ) ) ;
-
387 if ( $this -> _request -> getOperation ( ) === 'yourlsproxy' ) {
-
388 $page -> assign ( 'SHORTURL' , $this -> _status ) ;
-
389 $page -> draw ( 'yourlsproxy' ) ;
-
390 return ;
-
391 }
-
392 $page -> assign ( 'BASEPATH' , I18n :: _ ( $this -> _conf -> getKey ( 'basepath' ) ) ) ;
-
393 $page -> assign ( 'STATUS' , I18n :: _ ( $this -> _status ) ) ;
-
394 $page -> assign ( 'VERSION' , self :: VERSION ) ;
-
395 $page -> assign ( 'DISCUSSION' , $this -> _conf -> getKey ( 'discussion' ) ) ;
-
396 $page -> assign ( 'OPENDISCUSSION' , $this -> _conf -> getKey ( 'opendiscussion' ) ) ;
-
397 $page -> assign ( 'MARKDOWN' , array_key_exists ( 'markdown' , $formatters ) ) ;
-
398 $page -> assign ( 'SYNTAXHIGHLIGHTING' , array_key_exists ( 'syntaxhighlighting' , $formatters ) ) ;
-
399 $page -> assign ( 'SYNTAXHIGHLIGHTINGTHEME' , $this -> _conf -> getKey ( 'syntaxhighlightingtheme' ) ) ;
-
400 $page -> assign ( 'FORMATTER' , $formatters ) ;
-
401 $page -> assign ( 'FORMATTERDEFAULT' , $this -> _conf -> getKey ( 'defaultformatter' ) ) ;
-
402 $page -> assign ( 'INFO' , I18n :: _ ( str_replace ( "'" , '"' , $this -> _conf -> getKey ( 'info' ) ) ) ) ;
-
403 $page -> assign ( 'NOTICE' , I18n :: _ ( $this -> _conf -> getKey ( 'notice' ) ) ) ;
-
404 $page -> assign ( 'BURNAFTERREADINGSELECTED' , $this -> _conf -> getKey ( 'burnafterreadingselected' ) ) ;
-
405 $page -> assign ( 'PASSWORD' , $this -> _conf -> getKey ( 'password' ) ) ;
-
406 $page -> assign ( 'FILEUPLOAD' , $this -> _conf -> getKey ( 'fileupload' ) ) ;
-
407 $page -> assign ( 'ZEROBINCOMPATIBILITY' , $this -> _conf -> getKey ( 'zerobincompatibility' ) ) ;
-
408 $page -> assign ( 'LANGUAGESELECTION' , $languageselection ) ;
-
409 $page -> assign ( 'LANGUAGES' , I18n :: getLanguageLabels ( I18n :: getAvailableLanguages ( ) ) ) ;
-
410 $page -> assign ( 'EXPIRE' , $expire ) ;
-
411 $page -> assign ( 'EXPIREDEFAULT' , $this -> _conf -> getKey ( 'default' , 'expire' ) ) ;
-
412 $page -> assign ( 'URLSHORTENER' , $this -> _conf -> getKey ( 'urlshortener' ) ) ;
-
413 $page -> assign ( 'QRCODE' , $this -> _conf -> getKey ( 'qrcode' ) ) ;
-
414 $page -> assign ( 'EMAIL' , $this -> _conf -> getKey ( 'email' ) ) ;
-
415 $page -> assign ( 'HTTPWARNING' , $this -> _conf -> getKey ( 'httpwarning' ) ) ;
-
416 $page -> assign ( 'HTTPSLINK' , 'https://' . $this -> _request -> getHost ( ) . $this -> _request -> getRequestUri ( ) ) ;
-
417 $page -> assign ( 'COMPRESSION' , $this -> _conf -> getKey ( 'compression' ) ) ;
-
418 $page -> draw ( $this -> _conf -> getKey ( 'template' ) ) ;
-
419 }
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427 private function _jsonld ( $type )
-
428 {
-
429 if ( ! in_array ( $type , array (
-
430 'comment' ,
-
431 'commentmeta' ,
-
432 'paste' ,
-
433 'pastemeta' ,
-
434 'types' ,
-
435 ) ) ) {
-
436 $type = '' ;
-
437 }
-
438 $content = '{}' ;
-
439 $file = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR . $type . '.jsonld' ;
-
440 if ( is_readable ( $file ) ) {
-
441 $content = str_replace (
-
442 '?jsonld=' ,
-
443 $this -> _urlBase . '?jsonld=' ,
-
444 file_get_contents ( $file )
-
445 ) ;
+
366
+
367 $expire = array ( ) ;
+
368 foreach ( $this -> _conf -> getSection ( 'expire_options' ) as $time => $seconds ) {
+
369 $expire [ $time ] = ( $seconds == 0 ) ? I18n :: _ ( ucfirst ( $time ) ) : Filter :: formatHumanReadableTime ( $time ) ;
+
370 }
+
371
+
372
+
373 $formatters = array_map ( 'PrivateBin\\I18n::_' , $this -> _conf -> getSection ( 'formatter_options' ) ) ;
+
374
+
375
+
376 $languageselection = '' ;
+
377 if ( $this -> _conf -> getKey ( 'languageselection' ) ) {
+
378 $languageselection = I18n :: getLanguage ( ) ;
+
379 setcookie ( 'lang' , $languageselection , 0 , '' , '' , true ) ;
+
380 }
+
381
+
382
+
383 $metacspheader = str_replace (
+
384 array (
+
385 'frame-ancestors \'none\'; ' ,
+
386 '; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads' ,
+
387 ) ,
+
388 '' ,
+
389 $this -> _conf -> getKey ( 'cspheader' )
+
390 ) ;
+
391
+
392 $page = new View ;
+
393 $page -> assign ( 'CSPHEADER' , $metacspheader ) ;
+
394 $page -> assign ( 'ERROR' , I18n :: _ ( $this -> _error ) ) ;
+
395 $page -> assign ( 'NAME' , $this -> _conf -> getKey ( 'name' ) ) ;
+
396 if ( $this -> _request -> getOperation ( ) === 'yourlsproxy' ) {
+
397 $page -> assign ( 'SHORTURL' , $this -> _status ) ;
+
398 $page -> draw ( 'yourlsproxy' ) ;
+
399 return ;
+
400 }
+
401 $page -> assign ( 'BASEPATH' , I18n :: _ ( $this -> _conf -> getKey ( 'basepath' ) ) ) ;
+
402 $page -> assign ( 'STATUS' , I18n :: _ ( $this -> _status ) ) ;
+
403 $page -> assign ( 'VERSION' , self :: VERSION ) ;
+
404 $page -> assign ( 'DISCUSSION' , $this -> _conf -> getKey ( 'discussion' ) ) ;
+
405 $page -> assign ( 'OPENDISCUSSION' , $this -> _conf -> getKey ( 'opendiscussion' ) ) ;
+
406 $page -> assign ( 'MARKDOWN' , array_key_exists ( 'markdown' , $formatters ) ) ;
+
407 $page -> assign ( 'SYNTAXHIGHLIGHTING' , array_key_exists ( 'syntaxhighlighting' , $formatters ) ) ;
+
408 $page -> assign ( 'SYNTAXHIGHLIGHTINGTHEME' , $this -> _conf -> getKey ( 'syntaxhighlightingtheme' ) ) ;
+
409 $page -> assign ( 'FORMATTER' , $formatters ) ;
+
410 $page -> assign ( 'FORMATTERDEFAULT' , $this -> _conf -> getKey ( 'defaultformatter' ) ) ;
+
411 $page -> assign ( 'INFO' , I18n :: _ ( str_replace ( "'" , '"' , $this -> _conf -> getKey ( 'info' ) ) ) ) ;
+
412 $page -> assign ( 'NOTICE' , I18n :: _ ( $this -> _conf -> getKey ( 'notice' ) ) ) ;
+
413 $page -> assign ( 'BURNAFTERREADINGSELECTED' , $this -> _conf -> getKey ( 'burnafterreadingselected' ) ) ;
+
414 $page -> assign ( 'PASSWORD' , $this -> _conf -> getKey ( 'password' ) ) ;
+
415 $page -> assign ( 'FILEUPLOAD' , $this -> _conf -> getKey ( 'fileupload' ) ) ;
+
416 $page -> assign ( 'ZEROBINCOMPATIBILITY' , $this -> _conf -> getKey ( 'zerobincompatibility' ) ) ;
+
417 $page -> assign ( 'LANGUAGESELECTION' , $languageselection ) ;
+
418 $page -> assign ( 'LANGUAGES' , I18n :: getLanguageLabels ( I18n :: getAvailableLanguages ( ) ) ) ;
+
419 $page -> assign ( 'EXPIRE' , $expire ) ;
+
420 $page -> assign ( 'EXPIREDEFAULT' , $this -> _conf -> getKey ( 'default' , 'expire' ) ) ;
+
421 $page -> assign ( 'URLSHORTENER' , $this -> _conf -> getKey ( 'urlshortener' ) ) ;
+
422 $page -> assign ( 'QRCODE' , $this -> _conf -> getKey ( 'qrcode' ) ) ;
+
423 $page -> assign ( 'EMAIL' , $this -> _conf -> getKey ( 'email' ) ) ;
+
424 $page -> assign ( 'HTTPWARNING' , $this -> _conf -> getKey ( 'httpwarning' ) ) ;
+
425 $page -> assign ( 'HTTPSLINK' , 'https://' . $this -> _request -> getHost ( ) . $this -> _request -> getRequestUri ( ) ) ;
+
426 $page -> assign ( 'COMPRESSION' , $this -> _conf -> getKey ( 'compression' ) ) ;
+
427 $page -> draw ( $this -> _conf -> getKey ( 'template' ) ) ;
+
428 }
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436 private function _jsonld ( $type )
+
437 {
+
438 if ( ! in_array ( $type , array (
+
439 'comment' ,
+
440 'commentmeta' ,
+
441 'paste' ,
+
442 'pastemeta' ,
+
443 'types' ,
+
444 ) ) ) {
+
445 $type = '' ;
446 }
-
447 if ( $type === 'types' ) {
-
448 $content = str_replace (
-
449 implode ( '", "' , array_keys ( $this -> _conf -> getDefaults ( ) [ 'expire_options' ] ) ) ,
-
450 implode ( '", "' , array_keys ( $this -> _conf -> getSection ( 'expire_options' ) ) ) ,
-
451 $content
-
452 ) ;
-
453 }
-
454
-
455 header ( 'Content-type: application/ld+json' ) ;
-
456 header ( 'Access-Control-Allow-Origin: *' ) ;
-
457 header ( 'Access-Control-Allow-Methods: GET' ) ;
-
458 echo $content ;
-
459 }
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467 private function _yourlsproxy ( $link )
-
468 {
-
469 $yourls = new YourlsProxy ( $this -> _conf , $link ) ;
-
470 if ( $yourls -> isError ( ) ) {
-
471 $this -> _error = $yourls -> getError ( ) ;
-
472 } else {
-
473 $this -> _status = $yourls -> getUrl ( ) ;
-
474 }
-
475 }
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485 private function _return_message ( $status , $message , $other = array ( ) )
-
486 {
-
487 $result = array ( 'status' => $status ) ;
-
488 if ( $status ) {
-
489 $result [ 'message' ] = I18n :: _ ( $message ) ;
-
490 } else {
-
491 $result [ 'id' ] = $message ;
-
492 $result [ 'url' ] = $this -> _urlBase . '?' . $message ;
-
493 }
-
494 $result += $other ;
-
495 $this -> _json = Json :: encode ( $result ) ;
-
496 }
-
497 }
+
447 $content = '{}' ;
+
448 $file = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'js' . DIRECTORY_SEPARATOR . $type . '.jsonld' ;
+
449 if ( is_readable ( $file ) ) {
+
450 $content = str_replace (
+
451 '?jsonld=' ,
+
452 $this -> _urlBase . '?jsonld=' ,
+
453 file_get_contents ( $file )
+
454 ) ;
+
455 }
+
456 if ( $type === 'types' ) {
+
457 $content = str_replace (
+
458 implode ( '", "' , array_keys ( $this -> _conf -> getDefaults ( ) [ 'expire_options' ] ) ) ,
+
459 implode ( '", "' , array_keys ( $this -> _conf -> getSection ( 'expire_options' ) ) ) ,
+
460 $content
+
461 ) ;
+
462 }
+
463
+
464 header ( 'Content-type: application/ld+json' ) ;
+
465 header ( 'Access-Control-Allow-Origin: *' ) ;
+
466 header ( 'Access-Control-Allow-Methods: GET' ) ;
+
467 echo $content ;
+
468 }
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+
476 private function _yourlsproxy ( $link )
+
477 {
+
478 $yourls = new YourlsProxy ( $this -> _conf , $link ) ;
+
479 if ( $yourls -> isError ( ) ) {
+
480 $this -> _error = $yourls -> getError ( ) ;
+
481 } else {
+
482 $this -> _status = $yourls -> getUrl ( ) ;
+
483 }
+
484 }
+
485
+
486
+
487
+
488
+
489
+
490
+
491
+
492
+
493
+
494 private function _return_message ( $status , $message , $other = array ( ) )
+
495 {
+
496 $result = array ( 'status' => $status ) ;
+
497 if ( $status ) {
+
498 $result [ 'message' ] = I18n :: _ ( $message ) ;
+
499 } else {
+
500 $result [ 'id' ] = $message ;
+
501 $result [ 'url' ] = $this -> _urlBase . '?' . $message ;
+
502 }
+
503 $result += $other ;
+
504 $this -> _json = Json :: encode ( $result ) ;
+
505 }
+
506 }
@@ -810,16 +819,16 @@
Legend
Covered by small (and larger) tests Covered by medium (and large) tests Covered by large tests (and tests of unknown size) Not covered Not coverable
- Generated by php-code-coverage 9.2.29 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Dec 3 10:40:51 UTC 2023.
+ Generated by php-code-coverage 9.2.30 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Feb 11 13:44:20 UTC 2024.
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Data/Database.php.html b/content/coverage/Data/Database.php.html
index 6ffc7dc..e4d8683 100644
--- a/content/coverage/Data/Database.php.html
+++ b/content/coverage/Data/Database.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Data/Database.php
+
Code Coverage for lib/Data/Database.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Data/Filesystem.php.html b/content/coverage/Data/Filesystem.php.html
index 6a7d463..20bab1b 100644
--- a/content/coverage/Data/Filesystem.php.html
+++ b/content/coverage/Data/Filesystem.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Data/Filesystem.php
+
Code Coverage for lib/Data/Filesystem.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- __construct
+ __construct
100.00% covered (success)
@@ -123,7 +123,7 @@
- create
+ create
100.00% covered (success)
@@ -145,7 +145,7 @@
- read
+ read
100.00% covered (success)
@@ -167,7 +167,7 @@
- delete
+ delete
100.00% covered (success)
@@ -189,7 +189,7 @@
- exists
+ exists
100.00% covered (success)
@@ -211,7 +211,7 @@
- createComment
+ createComment
100.00% covered (success)
@@ -233,7 +233,7 @@
- readComments
+ readComments
100.00% covered (success)
@@ -255,7 +255,7 @@
- existsComment
+ existsComment
100.00% covered (success)
@@ -277,7 +277,7 @@
- setValue
+ setValue
100.00% covered (success)
@@ -299,7 +299,7 @@
- getValue
+ getValue
100.00% covered (success)
@@ -321,7 +321,7 @@
- _get
+ _get
100.00% covered (success)
@@ -343,7 +343,7 @@
- _getExpiredPastes
+ _getExpiredPastes
88.89% covered (success)
@@ -365,7 +365,7 @@
- getAllPastes
+ getAllPastes
100.00% covered (success)
@@ -387,7 +387,7 @@
- _dataid2path
+ _dataid2path
100.00% covered (success)
@@ -409,7 +409,7 @@
- _dataid2discussionpath
+ _dataid2discussionpath
100.00% covered (success)
@@ -431,7 +431,7 @@
- _store
+ _store
100.00% covered (success)
@@ -453,7 +453,7 @@
- _storeString
+ _storeString
96.15% covered (success)
@@ -475,7 +475,7 @@
- _prependRename
+ _prependRename
100.00% covered (success)
@@ -511,527 +511,528 @@
7
8
9
-
10
+
10
11
12
13 namespace PrivateBin\Data ;
14
15 use Exception ;
-
16 use PrivateBin\Json ;
-
17
-
18
-
19
-
20
-
21
-
22
-
23 class Filesystem extends AbstractData
-
24 {
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36 const PASTE_FILE_PATTERN = DIRECTORY_SEPARATOR . '[a-f0-9][a-f0-9]' .
-
37 DIRECTORY_SEPARATOR . '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR .
-
38 '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]' .
-
39 '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*' ;
-
40
-
41
-
42
-
43
-
44
-
45
-
46 const PROTECTION_LINE = '<?php http_response_code(403); /*' ;
-
47
-
48
-
49
-
50
-
51
-
52
-
53 const HTACCESS_LINE = 'Require all denied' ;
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61 private $_path = 'data' ;
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70 public function __construct ( array $options )
-
71 {
-
72
-
73 if (
-
74 is_array ( $options ) &&
-
75 array_key_exists ( 'dir' , $options )
-
76 ) {
-
77 $this -> _path = $options [ 'dir' ] ;
-
78 }
-
79 }
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89 public function create ( $pasteid , array $paste )
-
90 {
-
91 $storagedir = $this -> _dataid2path ( $pasteid ) ;
-
92 $file = $storagedir . $pasteid . '.php' ;
-
93 if ( is_file ( $file ) ) {
-
94 return false ;
-
95 }
-
96 if ( ! is_dir ( $storagedir ) ) {
-
97 mkdir ( $storagedir , 0700 , true ) ;
-
98 }
-
99 return $this -> _store ( $file , $paste ) ;
-
100 }
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109 public function read ( $pasteid )
-
110 {
-
111 if (
-
112 ! $this -> exists ( $pasteid ) ||
-
113 ! $paste = $this -> _get ( $this -> _dataid2path ( $pasteid ) . $pasteid . '.php' )
-
114 ) {
-
115 return false ;
-
116 }
-
117 return self :: upgradePreV1Format ( $paste ) ;
-
118 }
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126 public function delete ( $pasteid )
-
127 {
-
128 $pastedir = $this -> _dataid2path ( $pasteid ) ;
-
129 if ( is_dir ( $pastedir ) ) {
-
130
-
131 if ( is_file ( $pastedir . $pasteid . '.php' ) ) {
-
132 unlink ( $pastedir . $pasteid . '.php' ) ;
-
133 }
-
134
-
135
-
136 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
-
137 if ( is_dir ( $discdir ) ) {
-
138
-
139 $dir = dir ( $discdir ) ;
-
140 while ( false !== ( $filename = $dir -> read ( ) ) ) {
-
141 if ( is_file ( $discdir . $filename ) ) {
-
142 unlink ( $discdir . $filename ) ;
-
143 }
-
144 }
-
145 $dir -> close ( ) ;
-
146 rmdir ( $discdir ) ;
-
147 }
-
148 }
-
149 }
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158 public function exists ( $pasteid )
-
159 {
-
160 $basePath = $this -> _dataid2path ( $pasteid ) . $pasteid ;
-
161 $pastePath = $basePath . '.php' ;
-
162
-
163 if ( is_readable ( $basePath ) ) {
-
164 $this -> _prependRename ( $basePath , $pastePath ) ;
-
165
-
166
-
167 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
-
168 if ( is_dir ( $discdir ) ) {
-
169 $dir = dir ( $discdir ) ;
-
170 while ( false !== ( $filename = $dir -> read ( ) ) ) {
-
171 if ( substr ( $filename , - 4 ) !== '.php' && strlen ( $filename ) >= 16 ) {
-
172 $commentFilename = $discdir . $filename . '.php' ;
-
173 $this -> _prependRename ( $discdir . $filename , $commentFilename ) ;
-
174 }
-
175 }
-
176 $dir -> close ( ) ;
-
177 }
-
178 }
-
179 return is_readable ( $pastePath ) ;
-
180 }
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192 public function createComment ( $pasteid , $parentid , $commentid , array $comment )
-
193 {
-
194 $storagedir = $this -> _dataid2discussionpath ( $pasteid ) ;
-
195 $file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php' ;
-
196 if ( is_file ( $file ) ) {
-
197 return false ;
-
198 }
-
199 if ( ! is_dir ( $storagedir ) ) {
-
200 mkdir ( $storagedir , 0700 , true ) ;
-
201 }
-
202 return $this -> _store ( $file , $comment ) ;
-
203 }
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212 public function readComments ( $pasteid )
-
213 {
-
214 $comments = array ( ) ;
-
215 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
-
216 if ( is_dir ( $discdir ) ) {
-
217 $dir = dir ( $discdir ) ;
-
218 while ( false !== ( $filename = $dir -> read ( ) ) ) {
-
219
-
220
-
221
-
222
-
223 if ( is_file ( $discdir . $filename ) ) {
-
224 $comment = $this -> _get ( $discdir . $filename ) ;
-
225 $items = explode ( '.' , $filename ) ;
-
226
-
227 $comment [ 'id' ] = $items [ 1 ] ;
-
228 $comment [ 'parentid' ] = $items [ 2 ] ;
-
229
-
230
-
231 $key = $this -> getOpenSlot (
-
232 $comments ,
-
233 (int) array_key_exists ( 'created' , $comment [ 'meta' ] ) ?
-
234 $comment [ 'meta' ] [ 'created' ] :
-
235 $comment [ 'meta' ] [ 'postdate' ]
-
236 ) ;
-
237 $comments [ $key ] = $comment ;
-
238 }
-
239 }
-
240 $dir -> close ( ) ;
-
241
-
242
-
243 ksort ( $comments ) ;
-
244 }
-
245 return $comments ;
-
246 }
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257 public function existsComment ( $pasteid , $parentid , $commentid )
-
258 {
-
259 return is_file (
-
260 $this -> _dataid2discussionpath ( $pasteid ) .
-
261 $pasteid . '.' . $commentid . '.' . $parentid . '.php'
-
262 ) ;
-
263 }
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274 public function setValue ( $value , $namespace , $key = '' )
-
275 {
-
276 switch ( $namespace ) {
-
277 case 'purge_limiter' :
-
278 return $this -> _storeString (
-
279 $this -> _path . DIRECTORY_SEPARATOR . 'purge_limiter.php' ,
-
280 '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
-
281 ) ;
-
282 case 'salt' :
-
283 return $this -> _storeString (
-
284 $this -> _path . DIRECTORY_SEPARATOR . 'salt.php' ,
-
285 '<?php # |' . $value . '|'
-
286 ) ;
-
287 case 'traffic_limiter' :
-
288 $this -> _last_cache [ $key ] = $value ;
-
289 return $this -> _storeString (
-
290 $this -> _path . DIRECTORY_SEPARATOR . 'traffic_limiter.php' ,
-
291 '<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export ( $this -> _last_cache , true ) . ';'
-
292 ) ;
-
293 }
-
294 return false ;
-
295 }
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305 public function getValue ( $namespace , $key = '' )
-
306 {
-
307 switch ( $namespace ) {
-
308 case 'purge_limiter' :
-
309 $file = $this -> _path . DIRECTORY_SEPARATOR . 'purge_limiter.php' ;
-
310 if ( is_readable ( $file ) ) {
-
311 require $file ;
-
312 return $GLOBALS [ 'purge_limiter' ] ;
-
313 }
-
314 break ;
-
315 case 'salt' :
-
316 $file = $this -> _path . DIRECTORY_SEPARATOR . 'salt.php' ;
-
317 if ( is_readable ( $file ) ) {
-
318 $items = explode ( '|' , file_get_contents ( $file ) ) ;
-
319 if ( is_array ( $items ) && count ( $items ) == 3 ) {
-
320 return $items [ 1 ] ;
-
321 }
-
322 }
-
323 break ;
-
324 case 'traffic_limiter' :
-
325 $file = $this -> _path . DIRECTORY_SEPARATOR . 'traffic_limiter.php' ;
-
326 if ( is_readable ( $file ) ) {
-
327 require $file ;
-
328 $this -> _last_cache = $GLOBALS [ 'traffic_limiter' ] ;
-
329 if ( array_key_exists ( $key , $this -> _last_cache ) ) {
-
330 return $this -> _last_cache [ $key ] ;
-
331 }
-
332 }
-
333 break ;
-
334 }
-
335 return '' ;
-
336 }
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345 private function _get ( $filename )
-
346 {
-
347 return Json :: decode (
-
348 substr (
-
349 file_get_contents ( $filename ) ,
-
350 strlen ( self :: PROTECTION_LINE . PHP_EOL )
-
351 )
-
352 ) ;
-
353 }
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362 protected function _getExpiredPastes ( $batchsize )
-
363 {
-
364 $pastes = array ( ) ;
-
365 $count = 0 ;
-
366 $opened = 0 ;
-
367 $limit = $batchsize * 10 ;
-
368 $time = time ( ) ;
-
369 $files = $this -> getAllPastes ( ) ;
-
370 shuffle ( $files ) ;
-
371 foreach ( $files as $pasteid ) {
-
372 if ( $this -> exists ( $pasteid ) ) {
-
373 $data = $this -> read ( $pasteid ) ;
-
374 if (
-
375 array_key_exists ( 'expire_date' , $data [ 'meta' ] ) &&
-
376 $data [ 'meta' ] [ 'expire_date' ] < $time
-
377 ) {
-
378 $pastes [ ] = $pasteid ;
-
379 if ( ++ $count >= $batchsize ) {
-
380 break ;
-
381 }
-
382 }
-
383 if ( ++ $opened >= $limit ) {
-
384 break ;
-
385 }
-
386 }
-
387 }
-
388 return $pastes ;
-
389 }
-
390
-
391
-
392
-
393
-
394 public function getAllPastes ( )
-
395 {
-
396 $pastes = array ( ) ;
-
397 foreach ( new \GlobIterator ( $this -> _path . self :: PASTE_FILE_PATTERN ) as $file ) {
-
398 if ( $file -> isFile ( ) ) {
-
399 $pastes [ ] = $file -> getBasename ( '.php' ) ;
-
400 }
-
401 }
-
402 return $pastes ;
-
403 }
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419 private function _dataid2path ( $dataid )
-
420 {
-
421 return $this -> _path . DIRECTORY_SEPARATOR .
-
422 substr ( $dataid , 0 , 2 ) . DIRECTORY_SEPARATOR .
-
423 substr ( $dataid , 2 , 2 ) . DIRECTORY_SEPARATOR ;
-
424 }
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435 private function _dataid2discussionpath ( $dataid )
-
436 {
-
437 return $this -> _dataid2path ( $dataid ) . $dataid .
-
438 '.discussion' . DIRECTORY_SEPARATOR ;
-
439 }
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449 private function _store ( $filename , array $data )
-
450 {
-
451 try {
-
452 return $this -> _storeString (
-
453 $filename ,
-
454 self :: PROTECTION_LINE . PHP_EOL . Json :: encode ( $data )
-
455 ) ;
-
456 } catch ( Exception $e ) {
-
457 return false ;
-
458 }
-
459 }
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469 private function _storeString ( $filename , $data )
-
470 {
-
471
-
472 if ( ! is_dir ( $this -> _path ) ) {
-
473 if ( ! @ mkdir ( $this -> _path , 0700 ) ) {
-
474 return false ;
-
475 }
-
476 }
-
477 $file = $this -> _path . DIRECTORY_SEPARATOR . '.htaccess' ;
-
478 if ( ! is_file ( $file ) ) {
-
479 $writtenBytes = 0 ;
-
480 if ( $fileCreated = @ touch ( $file ) ) {
-
481 $writtenBytes = @ file_put_contents (
-
482 $file ,
-
483 self :: HTACCESS_LINE . PHP_EOL ,
-
484 LOCK_EX
-
485 ) ;
-
486 }
-
487 if (
-
488 $fileCreated === false ||
-
489 $writtenBytes === false ||
-
490 $writtenBytes < strlen ( self :: HTACCESS_LINE . PHP_EOL )
-
491 ) {
-
492 return false ;
-
493 }
-
494 }
-
495
-
496 $fileCreated = true ;
-
497 $writtenBytes = 0 ;
-
498 if ( ! is_file ( $filename ) ) {
-
499 $fileCreated = @ touch ( $filename ) ;
-
500 }
-
501 if ( $fileCreated ) {
-
502 $writtenBytes = @ file_put_contents ( $filename , $data , LOCK_EX ) ;
-
503 }
-
504 if ( $fileCreated === false || $writtenBytes === false || $writtenBytes < strlen ( $data ) ) {
-
505 return false ;
-
506 }
-
507 @ chmod ( $filename , 0640 ) ;
-
508 return true ;
-
509 }
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519 private function _prependRename ( $srcFile , $destFile )
-
520 {
-
521
-
522 if ( ! is_readable ( $destFile ) ) {
-
523 $handle = fopen ( $srcFile , 'r' , false , stream_context_create ( ) ) ;
-
524 file_put_contents ( $destFile , self :: PROTECTION_LINE . PHP_EOL ) ;
-
525 file_put_contents ( $destFile , $handle , FILE_APPEND ) ;
-
526 fclose ( $handle ) ;
-
527 }
-
528 unlink ( $srcFile ) ;
-
529 }
-
530 }
+
16 use GlobIterator ;
+
17 use PrivateBin\Json ;
+
18
+
19
+
20
+
21
+
22
+
23
+
24 class Filesystem extends AbstractData
+
25 {
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37 const PASTE_FILE_PATTERN = DIRECTORY_SEPARATOR . '[a-f0-9][a-f0-9]' .
+
38 DIRECTORY_SEPARATOR . '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR .
+
39 '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]' .
+
40 '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*' ;
+
41
+
42
+
43
+
44
+
45
+
46
+
47 const PROTECTION_LINE = '<?php http_response_code(403); /*' ;
+
48
+
49
+
50
+
51
+
52
+
53
+
54 const HTACCESS_LINE = 'Require all denied' ;
+
55
+
56
+
57
+
58
+
59
+
60
+
61
+
62 private $_path = 'data' ;
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71 public function __construct ( array $options )
+
72 {
+
73
+
74 if (
+
75 is_array ( $options ) &&
+
76 array_key_exists ( 'dir' , $options )
+
77 ) {
+
78 $this -> _path = $options [ 'dir' ] ;
+
79 }
+
80 }
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90 public function create ( $pasteid , array $paste )
+
91 {
+
92 $storagedir = $this -> _dataid2path ( $pasteid ) ;
+
93 $file = $storagedir . $pasteid . '.php' ;
+
94 if ( is_file ( $file ) ) {
+
95 return false ;
+
96 }
+
97 if ( ! is_dir ( $storagedir ) ) {
+
98 mkdir ( $storagedir , 0700 , true ) ;
+
99 }
+
100 return $this -> _store ( $file , $paste ) ;
+
101 }
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110 public function read ( $pasteid )
+
111 {
+
112 if (
+
113 ! $this -> exists ( $pasteid ) ||
+
114 ! $paste = $this -> _get ( $this -> _dataid2path ( $pasteid ) . $pasteid . '.php' )
+
115 ) {
+
116 return false ;
+
117 }
+
118 return self :: upgradePreV1Format ( $paste ) ;
+
119 }
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127 public function delete ( $pasteid )
+
128 {
+
129 $pastedir = $this -> _dataid2path ( $pasteid ) ;
+
130 if ( is_dir ( $pastedir ) ) {
+
131
+
132 if ( is_file ( $pastedir . $pasteid . '.php' ) ) {
+
133 unlink ( $pastedir . $pasteid . '.php' ) ;
+
134 }
+
135
+
136
+
137 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
+
138 if ( is_dir ( $discdir ) ) {
+
139
+
140 $dir = dir ( $discdir ) ;
+
141 while ( false !== ( $filename = $dir -> read ( ) ) ) {
+
142 if ( is_file ( $discdir . $filename ) ) {
+
143 unlink ( $discdir . $filename ) ;
+
144 }
+
145 }
+
146 $dir -> close ( ) ;
+
147 rmdir ( $discdir ) ;
+
148 }
+
149 }
+
150 }
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159 public function exists ( $pasteid )
+
160 {
+
161 $basePath = $this -> _dataid2path ( $pasteid ) . $pasteid ;
+
162 $pastePath = $basePath . '.php' ;
+
163
+
164 if ( is_readable ( $basePath ) ) {
+
165 $this -> _prependRename ( $basePath , $pastePath ) ;
+
166
+
167
+
168 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
+
169 if ( is_dir ( $discdir ) ) {
+
170 $dir = dir ( $discdir ) ;
+
171 while ( false !== ( $filename = $dir -> read ( ) ) ) {
+
172 if ( substr ( $filename , - 4 ) !== '.php' && strlen ( $filename ) >= 16 ) {
+
173 $commentFilename = $discdir . $filename . '.php' ;
+
174 $this -> _prependRename ( $discdir . $filename , $commentFilename ) ;
+
175 }
+
176 }
+
177 $dir -> close ( ) ;
+
178 }
+
179 }
+
180 return is_readable ( $pastePath ) ;
+
181 }
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193 public function createComment ( $pasteid , $parentid , $commentid , array $comment )
+
194 {
+
195 $storagedir = $this -> _dataid2discussionpath ( $pasteid ) ;
+
196 $file = $storagedir . $pasteid . '.' . $commentid . '.' . $parentid . '.php' ;
+
197 if ( is_file ( $file ) ) {
+
198 return false ;
+
199 }
+
200 if ( ! is_dir ( $storagedir ) ) {
+
201 mkdir ( $storagedir , 0700 , true ) ;
+
202 }
+
203 return $this -> _store ( $file , $comment ) ;
+
204 }
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213 public function readComments ( $pasteid )
+
214 {
+
215 $comments = array ( ) ;
+
216 $discdir = $this -> _dataid2discussionpath ( $pasteid ) ;
+
217 if ( is_dir ( $discdir ) ) {
+
218 $dir = dir ( $discdir ) ;
+
219 while ( false !== ( $filename = $dir -> read ( ) ) ) {
+
220
+
221
+
222
+
223
+
224 if ( is_file ( $discdir . $filename ) ) {
+
225 $comment = $this -> _get ( $discdir . $filename ) ;
+
226 $items = explode ( '.' , $filename ) ;
+
227
+
228 $comment [ 'id' ] = $items [ 1 ] ;
+
229 $comment [ 'parentid' ] = $items [ 2 ] ;
+
230
+
231
+
232 $key = $this -> getOpenSlot (
+
233 $comments ,
+
234 (int) array_key_exists ( 'created' , $comment [ 'meta' ] ) ?
+
235 $comment [ 'meta' ] [ 'created' ] :
+
236 $comment [ 'meta' ] [ 'postdate' ]
+
237 ) ;
+
238 $comments [ $key ] = $comment ;
+
239 }
+
240 }
+
241 $dir -> close ( ) ;
+
242
+
243
+
244 ksort ( $comments ) ;
+
245 }
+
246 return $comments ;
+
247 }
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258 public function existsComment ( $pasteid , $parentid , $commentid )
+
259 {
+
260 return is_file (
+
261 $this -> _dataid2discussionpath ( $pasteid ) .
+
262 $pasteid . '.' . $commentid . '.' . $parentid . '.php'
+
263 ) ;
+
264 }
+
265
+
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+
275 public function setValue ( $value , $namespace , $key = '' )
+
276 {
+
277 switch ( $namespace ) {
+
278 case 'purge_limiter' :
+
279 return $this -> _storeString (
+
280 $this -> _path . DIRECTORY_SEPARATOR . 'purge_limiter.php' ,
+
281 '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
+
282 ) ;
+
283 case 'salt' :
+
284 return $this -> _storeString (
+
285 $this -> _path . DIRECTORY_SEPARATOR . 'salt.php' ,
+
286 '<?php # |' . $value . '|'
+
287 ) ;
+
288 case 'traffic_limiter' :
+
289 $this -> _last_cache [ $key ] = $value ;
+
290 return $this -> _storeString (
+
291 $this -> _path . DIRECTORY_SEPARATOR . 'traffic_limiter.php' ,
+
292 '<?php' . PHP_EOL . '$GLOBALS[\'traffic_limiter\'] = ' . var_export ( $this -> _last_cache , true ) . ';'
+
293 ) ;
+
294 }
+
295 return false ;
+
296 }
+
297
+
298
+
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306 public function getValue ( $namespace , $key = '' )
+
307 {
+
308 switch ( $namespace ) {
+
309 case 'purge_limiter' :
+
310 $file = $this -> _path . DIRECTORY_SEPARATOR . 'purge_limiter.php' ;
+
311 if ( is_readable ( $file ) ) {
+
312 require $file ;
+
313 return $GLOBALS [ 'purge_limiter' ] ;
+
314 }
+
315 break ;
+
316 case 'salt' :
+
317 $file = $this -> _path . DIRECTORY_SEPARATOR . 'salt.php' ;
+
318 if ( is_readable ( $file ) ) {
+
319 $items = explode ( '|' , file_get_contents ( $file ) ) ;
+
320 if ( is_array ( $items ) && count ( $items ) == 3 ) {
+
321 return $items [ 1 ] ;
+
322 }
+
323 }
+
324 break ;
+
325 case 'traffic_limiter' :
+
326 $file = $this -> _path . DIRECTORY_SEPARATOR . 'traffic_limiter.php' ;
+
327 if ( is_readable ( $file ) ) {
+
328 require $file ;
+
329 $this -> _last_cache = $GLOBALS [ 'traffic_limiter' ] ;
+
330 if ( array_key_exists ( $key , $this -> _last_cache ) ) {
+
331 return $this -> _last_cache [ $key ] ;
+
332 }
+
333 }
+
334 break ;
+
335 }
+
336 return '' ;
+
337 }
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346 private function _get ( $filename )
+
347 {
+
348 return Json :: decode (
+
349 substr (
+
350 file_get_contents ( $filename ) ,
+
351 strlen ( self :: PROTECTION_LINE . PHP_EOL )
+
352 )
+
353 ) ;
+
354 }
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363 protected function _getExpiredPastes ( $batchsize )
+
364 {
+
365 $pastes = array ( ) ;
+
366 $count = 0 ;
+
367 $opened = 0 ;
+
368 $limit = $batchsize * 10 ;
+
369 $time = time ( ) ;
+
370 $files = $this -> getAllPastes ( ) ;
+
371 shuffle ( $files ) ;
+
372 foreach ( $files as $pasteid ) {
+
373 if ( $this -> exists ( $pasteid ) ) {
+
374 $data = $this -> read ( $pasteid ) ;
+
375 if (
+
376 array_key_exists ( 'expire_date' , $data [ 'meta' ] ) &&
+
377 $data [ 'meta' ] [ 'expire_date' ] < $time
+
378 ) {
+
379 $pastes [ ] = $pasteid ;
+
380 if ( ++ $count >= $batchsize ) {
+
381 break ;
+
382 }
+
383 }
+
384 if ( ++ $opened >= $limit ) {
+
385 break ;
+
386 }
+
387 }
+
388 }
+
389 return $pastes ;
+
390 }
+
391
+
392
+
393
+
394
+
395 public function getAllPastes ( )
+
396 {
+
397 $pastes = array ( ) ;
+
398 foreach ( new GlobIterator ( $this -> _path . self :: PASTE_FILE_PATTERN ) as $file ) {
+
399 if ( $file -> isFile ( ) ) {
+
400 $pastes [ ] = $file -> getBasename ( '.php' ) ;
+
401 }
+
402 }
+
403 return $pastes ;
+
404 }
+
405
+
406
+
407
+
408
+
409
+
410
+
411
+
412
+
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420 private function _dataid2path ( $dataid )
+
421 {
+
422 return $this -> _path . DIRECTORY_SEPARATOR .
+
423 substr ( $dataid , 0 , 2 ) . DIRECTORY_SEPARATOR .
+
424 substr ( $dataid , 2 , 2 ) . DIRECTORY_SEPARATOR ;
+
425 }
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435
+
436 private function _dataid2discussionpath ( $dataid )
+
437 {
+
438 return $this -> _dataid2path ( $dataid ) . $dataid .
+
439 '.discussion' . DIRECTORY_SEPARATOR ;
+
440 }
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+
450 private function _store ( $filename , array $data )
+
451 {
+
452 try {
+
453 return $this -> _storeString (
+
454 $filename ,
+
455 self :: PROTECTION_LINE . PHP_EOL . Json :: encode ( $data )
+
456 ) ;
+
457 } catch ( Exception $e ) {
+
458 return false ;
+
459 }
+
460 }
+
461
+
462
+
463
+
464
+
465
+
466
+
467
+
468
+
469
+
470 private function _storeString ( $filename , $data )
+
471 {
+
472
+
473 if ( ! is_dir ( $this -> _path ) ) {
+
474 if ( ! @ mkdir ( $this -> _path , 0700 ) ) {
+
475 return false ;
+
476 }
+
477 }
+
478 $file = $this -> _path . DIRECTORY_SEPARATOR . '.htaccess' ;
+
479 if ( ! is_file ( $file ) ) {
+
480 $writtenBytes = 0 ;
+
481 if ( $fileCreated = @ touch ( $file ) ) {
+
482 $writtenBytes = @ file_put_contents (
+
483 $file ,
+
484 self :: HTACCESS_LINE . PHP_EOL ,
+
485 LOCK_EX
+
486 ) ;
+
487 }
+
488 if (
+
489 $fileCreated === false ||
+
490 $writtenBytes === false ||
+
491 $writtenBytes < strlen ( self :: HTACCESS_LINE . PHP_EOL )
+
492 ) {
+
493 return false ;
+
494 }
+
495 }
+
496
+
497 $fileCreated = true ;
+
498 $writtenBytes = 0 ;
+
499 if ( ! is_file ( $filename ) ) {
+
500 $fileCreated = @ touch ( $filename ) ;
+
501 }
+
502 if ( $fileCreated ) {
+
503 $writtenBytes = @ file_put_contents ( $filename , $data , LOCK_EX ) ;
+
504 }
+
505 if ( $fileCreated === false || $writtenBytes === false || $writtenBytes < strlen ( $data ) ) {
+
506 return false ;
+
507 }
+
508 @ chmod ( $filename , 0640 ) ;
+
509 return true ;
+
510 }
+
511
+
512
+
513
+
514
+
515
+
516
+
517
+
518
+
519
+
520 private function _prependRename ( $srcFile , $destFile )
+
521 {
+
522
+
523 if ( ! is_readable ( $destFile ) ) {
+
524 $handle = fopen ( $srcFile , 'r' , false , stream_context_create ( ) ) ;
+
525 file_put_contents ( $destFile , self :: PROTECTION_LINE . PHP_EOL ) ;
+
526 file_put_contents ( $destFile , $handle , FILE_APPEND ) ;
+
527 fclose ( $handle ) ;
+
528 }
+
529 unlink ( $srcFile ) ;
+
530 }
+
531 }
@@ -1042,16 +1043,16 @@
Legend
Covered by small (and larger) tests Covered by medium (and large) tests Covered by large tests (and tests of unknown size) Not covered Not coverable
- Generated by php-code-coverage 9.2.29 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Dec 3 10:40:51 UTC 2023.
+ Generated by php-code-coverage 9.2.30 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Feb 11 13:44:20 UTC 2024.
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Data/GoogleCloudStorage.php.html b/content/coverage/Data/GoogleCloudStorage.php.html
index c62e2a3..dedb061 100644
--- a/content/coverage/Data/GoogleCloudStorage.php.html
+++ b/content/coverage/Data/GoogleCloudStorage.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Data/GoogleCloudStorage.php
+
Code Coverage for lib/Data/GoogleCloudStorage.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Data/S3Storage.php.html b/content/coverage/Data/S3Storage.php.html
index 8683217..7d9bc70 100644
--- a/content/coverage/Data/S3Storage.php.html
+++ b/content/coverage/Data/S3Storage.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Data/S3Storage.php
+
Code Coverage for lib/Data/S3Storage.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Data/dashboard.html b/content/coverage/Data/dashboard.html
index 7d08a57..71b5bbe 100644
--- a/content/coverage/Data/dashboard.html
+++ b/content/coverage/Data/dashboard.html
@@ -2,11 +2,11 @@
-
Dashboard for /lib/Data
+
Dashboard for lib/Data
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
Data
(Dashboard)
@@ -197,13 +197,13 @@ Project Risks
-
-
-
+
+
+
-
-
-
+
+
+
+
diff --git a/content/coverage/FormatV2.php.html b/content/coverage/FormatV2.php.html
index dcfaa4c..ef2616c 100644
--- a/content/coverage/FormatV2.php.html
+++ b/content/coverage/FormatV2.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/FormatV2.php
+
Code Coverage for lib/FormatV2.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/I18n.php.html b/content/coverage/I18n.php.html
index 08871b7..ebd4e68 100644
--- a/content/coverage/I18n.php.html
+++ b/content/coverage/I18n.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/I18n.php
+
Code Coverage for lib/I18n.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
I18n.php
@@ -44,13 +44,13 @@
Total
-
-
96.27% covered (success)
+
+ 95.71% covered (success)
- 96.27%
- 129 / 134
+ 95.71%
+ 134 / 140
85.71% covered (success)
@@ -73,13 +73,13 @@
I18n
-
-
96.27% covered (success)
+
+ 95.71% covered (success)
- 96.27%
- 129 / 134
+ 95.71%
+ 134 / 140
85.71% covered (success)
@@ -88,7 +88,7 @@
85.71%
12 / 14
- 113
+ 118
0.00% covered (danger)
@@ -100,7 +100,7 @@
- _
+ _
100.00% covered (success)
@@ -122,7 +122,7 @@
- translate
+ translate
96.00% covered (success)
@@ -144,7 +144,7 @@
- encode
+ encode
100.00% covered (success)
@@ -166,7 +166,7 @@
- loadTranslations
+ loadTranslations
100.00% covered (success)
@@ -188,7 +188,7 @@
- getAvailableLanguages
+ getAvailableLanguages
100.00% covered (success)
@@ -196,7 +196,7 @@
100.00%
- 6 / 6
+ 10 / 10
100.00% covered (success)
@@ -210,7 +210,7 @@
- getBrowserLanguages
+ getBrowserLanguages
100.00% covered (success)
@@ -232,7 +232,7 @@
- getLanguage
+ getLanguage
100.00% covered (success)
@@ -254,7 +254,7 @@
- getLanguageLabels
+ getLanguageLabels
100.00% covered (success)
@@ -276,7 +276,7 @@
- isRtl
+ isRtl
100.00% covered (success)
@@ -298,7 +298,7 @@
- setLanguageFallback
+ setLanguageFallback
100.00% covered (success)
@@ -320,7 +320,7 @@
- _getPath
+ _getPath
100.00% covered (success)
@@ -342,15 +342,15 @@
- _getPluralForm
+ _getPluralForm
-
-
86.21% covered (success)
+
+ 83.87% covered (success)
- 86.21%
- 25 / 29
+ 83.87%
+ 26 / 31
0.00% covered (danger)
@@ -359,12 +359,12 @@
0.00%
0 / 1
- 64.23
+ 76.61
- _getMatchingLanguage
+ _getMatchingLanguage
100.00% covered (success)
@@ -386,7 +386,7 @@
- _matchLanguage
+ _matchLanguage
100.00% covered (success)
@@ -422,434 +422,443 @@
7
8
9
-
10
+
10
11
12
13 namespace PrivateBin ;
14
-
15
-
16
-
17
-
18
-
19
-
20 class I18n
-
21 {
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29 protected static $_language = 'en' ;
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38 protected static $_languageFallback = 'en' ;
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47 protected static $_languageLabels = array ( ) ;
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56 protected static $_availableLanguages = array ( ) ;
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65 protected static $_path = '' ;
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74 protected static $_translations = array ( ) ;
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85 public static function _ ( $messageId )
-
86 {
-
87 return forward_static_call_array ( 'PrivateBin\I18n::translate' , func_get_args ( ) ) ;
-
88 }
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99 public static function translate ( $messageId )
-
100 {
-
101 if ( empty ( $messageId ) ) {
-
102 return $messageId ;
-
103 }
-
104 if ( count ( self :: $_translations ) === 0 ) {
-
105 self :: loadTranslations ( ) ;
+
15 use AppendIterator ;
+
16 use GlobIterator ;
+
17
+
18
+
19
+
20
+
21
+
22
+
23 class I18n
+
24 {
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32 protected static $_language = 'en' ;
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41 protected static $_languageFallback = 'en' ;
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50 protected static $_languageLabels = array ( ) ;
+
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59 protected static $_availableLanguages = array ( ) ;
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68 protected static $_path = '' ;
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77 protected static $_translations = array ( ) ;
+
78
+
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88 public static function _ ( $messageId )
+
89 {
+
90 return forward_static_call_array ( 'PrivateBin\I18n::translate' , func_get_args ( ) ) ;
+
91 }
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102 public static function translate ( $messageId )
+
103 {
+
104 if ( empty ( $messageId ) ) {
+
105 return $messageId ;
106 }
-
107 $messages = $messageId ;
-
108 if ( is_array ( $messageId ) ) {
-
109 $messageId = count ( $messageId ) > 1 ? $messageId [ 1 ] : $messageId [ 0 ] ;
-
110 }
-
111 if ( ! array_key_exists ( $messageId , self :: $_translations ) ) {
-
112 self :: $_translations [ $messageId ] = $messages ;
+
107 if ( count ( self :: $_translations ) === 0 ) {
+
108 self :: loadTranslations ( ) ;
+
109 }
+
110 $messages = $messageId ;
+
111 if ( is_array ( $messageId ) ) {
+
112 $messageId = count ( $messageId ) > 1 ? $messageId [ 1 ] : $messageId [ 0 ] ;
113 }
-
114 $args = func_get_args ( ) ;
-
115 if ( is_array ( self :: $_translations [ $messageId ] ) ) {
-
116 $number = (int) $args [ 1 ] ;
-
117 $key = self :: _getPluralForm ( $number ) ;
-
118 $max = count ( self :: $_translations [ $messageId ] ) - 1 ;
-
119 if ( $key > $max ) {
-
120 $key = $max ;
-
121 }
-
122
-
123 $args [ 0 ] = self :: $_translations [ $messageId ] [ $key ] ;
-
124 $args [ 1 ] = $number ;
-
125 } else {
-
126 $args [ 0 ] = self :: $_translations [ $messageId ] ;
-
127 }
-
128
-
129 $argsCount = count ( $args ) ;
-
130 if ( $argsCount > 1 ) {
-
131 for ( $i = 0 ; $i < $argsCount ; ++ $i ) {
-
132 if ( ( $i > 0 && ! is_int ( $args [ $i ] ) ) || strpos ( $args [ 0 ] , '<a' ) === false ) {
-
133 $args [ $i ] = self :: encode ( $args [ $i ] ) ;
-
134 }
-
135 }
-
136 }
-
137 return call_user_func_array ( 'sprintf' , $args ) ;
-
138 }
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148 public static function encode ( $string )
-
149 {
-
150 return htmlspecialchars ( $string , ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED , 'UTF-8' , false ) ;
-
151 }
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161 public static function loadTranslations ( )
-
162 {
-
163 $availableLanguages = self :: getAvailableLanguages ( ) ;
-
164
-
165
-
166 if (
-
167 array_key_exists ( 'lang' , $_COOKIE ) &&
-
168 ( $key = array_search ( $_COOKIE [ 'lang' ] , $availableLanguages ) ) !== false
-
169 ) {
-
170 $match = $availableLanguages [ $key ] ;
-
171 }
-
172
-
173 else {
-
174 $match = self :: _getMatchingLanguage (
-
175 self :: getBrowserLanguages ( ) , $availableLanguages
-
176 ) ;
-
177 }
-
178
-
179
-
180 self :: $_language = $match ;
-
181 self :: $_translations = ( $match == 'en' ) ? array ( ) : Json :: decode (
-
182 file_get_contents ( self :: _getPath ( $match . '.json' ) )
-
183 ) ;
-
184 }
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193 public static function getAvailableLanguages ( )
-
194 {
-
195 if ( count ( self :: $_availableLanguages ) == 0 ) {
-
196 $i18n = dir ( self :: _getPath ( ) ) ;
-
197 while ( false !== ( $file = $i18n -> read ( ) ) ) {
-
198 if ( preg_match ( '/^([a-z]{2,3}).json$/' , $file , $match ) === 1 ) {
-
199 self :: $_availableLanguages [ ] = $match [ 1 ] ;
-
200 }
-
201 }
-
202 }
-
203 return self :: $_availableLanguages ;
-
204 }
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215 public static function getBrowserLanguages ( )
-
216 {
-
217 $languages = array ( ) ;
-
218 if ( array_key_exists ( 'HTTP_ACCEPT_LANGUAGE' , $_SERVER ) ) {
-
219 $languageRanges = explode ( ',' , trim ( $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ] ) ) ;
-
220 foreach ( $languageRanges as $languageRange ) {
-
221 if ( preg_match (
-
222 '/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/' ,
-
223 trim ( $languageRange ) , $match
-
224 ) ) {
-
225 if ( ! isset ( $match [ 2 ] ) ) {
-
226 $match [ 2 ] = '1.0' ;
-
227 } else {
-
228 $match [ 2 ] = (string) floatval ( $match [ 2 ] ) ;
-
229 }
-
230 if ( ! isset ( $languages [ $match [ 2 ] ] ) ) {
-
231 $languages [ $match [ 2 ] ] = array ( ) ;
-
232 }
-
233 $languages [ $match [ 2 ] ] [ ] = strtolower ( $match [ 1 ] ) ;
-
234 }
-
235 }
-
236 krsort ( $languages ) ;
-
237 }
-
238 return $languages ;
-
239 }
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248 public static function getLanguage ( )
-
249 {
-
250 return self :: $_language ;
-
251 }
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263 public static function getLanguageLabels ( $languages = array ( ) )
-
264 {
-
265 $file = self :: _getPath ( 'languages.json' ) ;
-
266 if ( count ( self :: $_languageLabels ) == 0 && is_readable ( $file ) ) {
-
267 self :: $_languageLabels = Json :: decode ( file_get_contents ( $file ) ) ;
-
268 }
-
269 if ( count ( $languages ) == 0 ) {
-
270 return self :: $_languageLabels ;
-
271 }
-
272 return array_intersect_key ( self :: $_languageLabels , array_flip ( $languages ) ) ;
-
273 }
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282 public static function isRtl ( )
-
283 {
-
284 return in_array ( self :: $_language , array ( 'ar' , 'he' ) ) ;
-
285 }
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294 public static function setLanguageFallback ( $lang )
-
295 {
-
296 if ( in_array ( $lang , self :: getAvailableLanguages ( ) ) ) {
-
297 self :: $_languageFallback = $lang ;
-
298 }
-
299 }
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309 protected static function _getPath ( $file = '' )
-
310 {
-
311 if ( strlen ( self :: $_path ) == 0 ) {
-
312 self :: $_path = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'i18n' ;
-
313 }
-
314 return self :: $_path . ( strlen ( $file ) ? DIRECTORY_SEPARATOR . $file : '' ) ;
-
315 }
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327 protected static function _getPluralForm ( $n )
-
328 {
-
329 switch ( self :: $_language ) {
-
330 case 'ar' :
-
331 return $n === 0 ? 0 : ( $n === 1 ? 1 : ( $n === 2 ? 2 : ( $n % 100 >= 3 && $n % 100 <= 10 ? 3 : ( $n % 100 >= 11 ? 4 : 5 ) ) ) ) ;
-
332 case 'cs' :
-
333 case 'sk' :
-
334 return $n === 1 ? 0 : ( $n >= 2 && $n <= 4 ? 1 : 2 ) ;
-
335 case 'co' :
-
336 case 'fr' :
-
337 case 'oc' :
-
338 case 'tr' :
-
339 case 'zh' :
-
340 return $n > 1 ? 1 : 0 ;
-
341 case 'he' :
-
342 return $n === 1 ? 0 : ( $n === 2 ? 1 : ( ( $n < 0 || $n > 10 ) && ( $n % 10 === 0 ) ? 2 : 3 ) ) ;
-
343 case 'id' :
-
344 case 'ja' :
-
345 case 'jbo' :
-
346 case 'th' :
-
347 return 0 ;
-
348 case 'lt' :
-
349 return $n % 10 === 1 && $n % 100 !== 11 ? 0 : ( ( $n % 10 >= 2 && $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
-
350 case 'pl' :
-
351 return $n === 1 ? 0 : ( $n % 10 >= 2 && $n % 10 <= 4 && ( $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
-
352 case 'ru' :
-
353 case 'uk' :
-
354 return $n % 10 === 1 && $n % 100 != 11 ? 0 : ( $n % 10 >= 2 && $n % 10 <= 4 && ( $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
-
355 case 'sl' :
-
356 return $n % 100 === 1 ? 1 : ( $n % 100 === 2 ? 2 : ( $n % 100 === 3 || $n % 100 === 4 ? 3 : 0 ) ) ;
-
357 default :
-
358
-
359 return $n !== 1 ? 1 : 0 ;
-
360 }
-
361 }
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374 protected static function _getMatchingLanguage ( $acceptedLanguages , $availableLanguages )
-
375 {
-
376 $matches = array ( ) ;
-
377 $any = false ;
-
378 foreach ( $acceptedLanguages as $acceptedQuality => $acceptedValues ) {
-
379 $acceptedQuality = floatval ( $acceptedQuality ) ;
-
380 if ( $acceptedQuality === 0.0 ) {
-
381 continue ;
-
382 }
-
383 foreach ( $availableLanguages as $availableValue ) {
-
384 $availableQuality = 1.0 ;
-
385 foreach ( $acceptedValues as $acceptedValue ) {
-
386 if ( $acceptedValue === '*' ) {
-
387 $any = true ;
-
388 }
-
389 $matchingGrade = self :: _matchLanguage ( $acceptedValue , $availableValue ) ;
-
390 if ( $matchingGrade > 0 ) {
-
391 $q = (string) ( $acceptedQuality * $availableQuality * $matchingGrade ) ;
-
392 if ( ! isset ( $matches [ $q ] ) ) {
-
393 $matches [ $q ] = array ( ) ;
-
394 }
-
395 if ( ! in_array ( $availableValue , $matches [ $q ] ) ) {
-
396 $matches [ $q ] [ ] = $availableValue ;
-
397 }
-
398 }
-
399 }
-
400 }
-
401 }
-
402 if ( count ( $matches ) === 0 && $any ) {
-
403 if ( count ( $availableLanguages ) > 0 ) {
-
404 $matches [ '1.0' ] = $availableLanguages ;
-
405 }
-
406 }
-
407 if ( count ( $matches ) === 0 ) {
-
408 return self :: $_languageFallback ;
-
409 }
-
410 krsort ( $matches ) ;
-
411 $topmatches = current ( $matches ) ;
-
412 return current ( $topmatches ) ;
-
413 }
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426 protected static function _matchLanguage ( $a , $b )
-
427 {
-
428 $a = explode ( '-' , $a ) ;
-
429 $b = explode ( '-' , $b ) ;
-
430 for ( $i = 0 , $n = min ( count ( $a ) , count ( $b ) ) ; $i < $n ; ++ $i ) {
-
431 if ( $a [ $i ] !== $b [ $i ] ) {
-
432 break ;
-
433 }
-
434 }
-
435 return $i === 0 ? 0 : (float) $i / count ( $a ) ;
-
436 }
-
437 }
+
114 if ( ! array_key_exists ( $messageId , self :: $_translations ) ) {
+
115 self :: $_translations [ $messageId ] = $messages ;
+
116 }
+
117 $args = func_get_args ( ) ;
+
118 if ( is_array ( self :: $_translations [ $messageId ] ) ) {
+
119 $number = (int) $args [ 1 ] ;
+
120 $key = self :: _getPluralForm ( $number ) ;
+
121 $max = count ( self :: $_translations [ $messageId ] ) - 1 ;
+
122 if ( $key > $max ) {
+
123 $key = $max ;
+
124 }
+
125
+
126 $args [ 0 ] = self :: $_translations [ $messageId ] [ $key ] ;
+
127 $args [ 1 ] = $number ;
+
128 } else {
+
129 $args [ 0 ] = self :: $_translations [ $messageId ] ;
+
130 }
+
131
+
132 $argsCount = count ( $args ) ;
+
133 if ( $argsCount > 1 ) {
+
134 for ( $i = 0 ; $i < $argsCount ; ++ $i ) {
+
135 if ( ( $i > 0 && ! is_int ( $args [ $i ] ) ) || strpos ( $args [ 0 ] , '<a' ) === false ) {
+
136 $args [ $i ] = self :: encode ( $args [ $i ] ) ;
+
137 }
+
138 }
+
139 }
+
140 return call_user_func_array ( 'sprintf' , $args ) ;
+
141 }
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151 public static function encode ( $string )
+
152 {
+
153 return htmlspecialchars ( $string , ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED , 'UTF-8' , false ) ;
+
154 }
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164 public static function loadTranslations ( )
+
165 {
+
166 $availableLanguages = self :: getAvailableLanguages ( ) ;
+
167
+
168
+
169 if (
+
170 array_key_exists ( 'lang' , $_COOKIE ) &&
+
171 ( $key = array_search ( $_COOKIE [ 'lang' ] , $availableLanguages ) ) !== false
+
172 ) {
+
173 $match = $availableLanguages [ $key ] ;
+
174 }
+
175
+
176 else {
+
177 $match = self :: _getMatchingLanguage (
+
178 self :: getBrowserLanguages ( ) , $availableLanguages
+
179 ) ;
+
180 }
+
181
+
182
+
183 self :: $_language = $match ;
+
184 self :: $_translations = ( $match == 'en' ) ? array ( ) : Json :: decode (
+
185 file_get_contents ( self :: _getPath ( $match . '.json' ) )
+
186 ) ;
+
187 }
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196 public static function getAvailableLanguages ( )
+
197 {
+
198 if ( count ( self :: $_availableLanguages ) == 0 ) {
+
199 self :: $_availableLanguages [ ] = 'en' ;
+
200 $languageIterator = new AppendIterator ( ) ;
+
201 $languageIterator -> append ( new GlobIterator ( self :: _getPath ( '??.json' ) ) ) ;
+
202 $languageIterator -> append ( new GlobIterator ( self :: _getPath ( '???.json' ) ) ) ;
+
203 foreach ( $languageIterator as $file ) {
+
204 $language = $file -> getBasename ( '.json' ) ;
+
205 if ( $language != 'en' ) {
+
206 self :: $_availableLanguages [ ] = $language ;
+
207 }
+
208 }
+
209 }
+
210 return self :: $_availableLanguages ;
+
211 }
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222 public static function getBrowserLanguages ( )
+
223 {
+
224 $languages = array ( ) ;
+
225 if ( array_key_exists ( 'HTTP_ACCEPT_LANGUAGE' , $_SERVER ) ) {
+
226 $languageRanges = explode ( ',' , trim ( $_SERVER [ 'HTTP_ACCEPT_LANGUAGE' ] ) ) ;
+
227 foreach ( $languageRanges as $languageRange ) {
+
228 if ( preg_match (
+
229 '/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/' ,
+
230 trim ( $languageRange ) , $match
+
231 ) ) {
+
232 if ( ! isset ( $match [ 2 ] ) ) {
+
233 $match [ 2 ] = '1.0' ;
+
234 } else {
+
235 $match [ 2 ] = (string) floatval ( $match [ 2 ] ) ;
+
236 }
+
237 if ( ! isset ( $languages [ $match [ 2 ] ] ) ) {
+
238 $languages [ $match [ 2 ] ] = array ( ) ;
+
239 }
+
240 $languages [ $match [ 2 ] ] [ ] = strtolower ( $match [ 1 ] ) ;
+
241 }
+
242 }
+
243 krsort ( $languages ) ;
+
244 }
+
245 return $languages ;
+
246 }
+
247
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255 public static function getLanguage ( )
+
256 {
+
257 return self :: $_language ;
+
258 }
+
259
+
260
+
261
+
262
+
263
+
264
+
265
+
266
+
267
+
268
+
269
+
270 public static function getLanguageLabels ( $languages = array ( ) )
+
271 {
+
272 $file = self :: _getPath ( 'languages.json' ) ;
+
273 if ( count ( self :: $_languageLabels ) == 0 && is_readable ( $file ) ) {
+
274 self :: $_languageLabels = Json :: decode ( file_get_contents ( $file ) ) ;
+
275 }
+
276 if ( count ( $languages ) == 0 ) {
+
277 return self :: $_languageLabels ;
+
278 }
+
279 return array_intersect_key ( self :: $_languageLabels , array_flip ( $languages ) ) ;
+
280 }
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289 public static function isRtl ( )
+
290 {
+
291 return in_array ( self :: $_language , array ( 'ar' , 'he' ) ) ;
+
292 }
+
293
+
294
+
295
+
296
+
297
+
298
+
299
+
300
+
301 public static function setLanguageFallback ( $lang )
+
302 {
+
303 if ( in_array ( $lang , self :: getAvailableLanguages ( ) ) ) {
+
304 self :: $_languageFallback = $lang ;
+
305 }
+
306 }
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316 protected static function _getPath ( $file = '' )
+
317 {
+
318 if ( empty ( self :: $_path ) ) {
+
319 self :: $_path = PUBLIC_PATH . DIRECTORY_SEPARATOR . 'i18n' ;
+
320 }
+
321 return self :: $_path . ( empty ( $file ) ? '' : DIRECTORY_SEPARATOR . $file ) ;
+
322 }
+
323
+
324
+
325
+
326
+
327
+
328
+
329
+
330
+
331
+
332
+
333
+
334 protected static function _getPluralForm ( $n )
+
335 {
+
336 switch ( self :: $_language ) {
+
337 case 'ar' :
+
338 return $n === 0 ? 0 : ( $n === 1 ? 1 : ( $n === 2 ? 2 : ( $n % 100 >= 3 && $n % 100 <= 10 ? 3 : ( $n % 100 >= 11 ? 4 : 5 ) ) ) ) ;
+
339 case 'cs' :
+
340 case 'sk' :
+
341 return $n === 1 ? 0 : ( $n >= 2 && $n <= 4 ? 1 : 2 ) ;
+
342 case 'co' :
+
343 case 'fr' :
+
344 case 'oc' :
+
345 case 'tr' :
+
346 case 'zh' :
+
347 return $n > 1 ? 1 : 0 ;
+
348 case 'he' :
+
349 return $n === 1 ? 0 : ( $n === 2 ? 1 : ( ( $n < 0 || $n > 10 ) && ( $n % 10 === 0 ) ? 2 : 3 ) ) ;
+
350 case 'id' :
+
351 case 'ja' :
+
352 case 'jbo' :
+
353 case 'th' :
+
354 return 0 ;
+
355 case 'lt' :
+
356 return $n % 10 === 1 && $n % 100 !== 11 ? 0 : ( ( $n % 10 >= 2 && $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
+
357 case 'pl' :
+
358 return $n === 1 ? 0 : ( $n % 10 >= 2 && $n % 10 <= 4 && ( $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
+
359 case 'ro' :
+
360 return $n === 1 ? 0 : ( ( $n === 0 || ( $n % 100 > 0 && $n % 100 < 20 ) ) ? 1 : 2 ) ;
+
361 case 'ru' :
+
362 case 'uk' :
+
363 return $n % 10 === 1 && $n % 100 != 11 ? 0 : ( $n % 10 >= 2 && $n % 10 <= 4 && ( $n % 100 < 10 || $n % 100 >= 20 ) ? 1 : 2 ) ;
+
364 case 'sl' :
+
365 return $n % 100 === 1 ? 1 : ( $n % 100 === 2 ? 2 : ( $n % 100 === 3 || $n % 100 === 4 ? 3 : 0 ) ) ;
+
366 default :
+
367
+
368 return $n !== 1 ? 1 : 0 ;
+
369 }
+
370 }
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383 protected static function _getMatchingLanguage ( $acceptedLanguages , $availableLanguages )
+
384 {
+
385 $matches = array ( ) ;
+
386 $any = false ;
+
387 foreach ( $acceptedLanguages as $acceptedQuality => $acceptedValues ) {
+
388 $acceptedQuality = floatval ( $acceptedQuality ) ;
+
389 if ( $acceptedQuality === 0.0 ) {
+
390 continue ;
+
391 }
+
392 foreach ( $availableLanguages as $availableValue ) {
+
393 $availableQuality = 1.0 ;
+
394 foreach ( $acceptedValues as $acceptedValue ) {
+
395 if ( $acceptedValue === '*' ) {
+
396 $any = true ;
+
397 }
+
398 $matchingGrade = self :: _matchLanguage ( $acceptedValue , $availableValue ) ;
+
399 if ( $matchingGrade > 0 ) {
+
400 $q = (string) ( $acceptedQuality * $availableQuality * $matchingGrade ) ;
+
401 if ( ! isset ( $matches [ $q ] ) ) {
+
402 $matches [ $q ] = array ( ) ;
+
403 }
+
404 if ( ! in_array ( $availableValue , $matches [ $q ] ) ) {
+
405 $matches [ $q ] [ ] = $availableValue ;
+
406 }
+
407 }
+
408 }
+
409 }
+
410 }
+
411 if ( count ( $matches ) === 0 && $any ) {
+
412 if ( count ( $availableLanguages ) > 0 ) {
+
413 $matches [ '1.0' ] = $availableLanguages ;
+
414 }
+
415 }
+
416 if ( count ( $matches ) === 0 ) {
+
417 return self :: $_languageFallback ;
+
418 }
+
419 krsort ( $matches ) ;
+
420 $topmatches = current ( $matches ) ;
+
421 return current ( $topmatches ) ;
+
422 }
+
423
+
424
+
425
+
426
+
427
+
428
+
429
+
430
+
431
+
432
+
433
+
434
+
435 protected static function _matchLanguage ( $a , $b )
+
436 {
+
437 $a = explode ( '-' , $a ) ;
+
438 $b = explode ( '-' , $b ) ;
+
439 for ( $i = 0 , $n = min ( count ( $a ) , count ( $b ) ) ; $i < $n ; ++ $i ) {
+
440 if ( $a [ $i ] !== $b [ $i ] ) {
+
441 break ;
+
442 }
+
443 }
+
444 return $i === 0 ? 0 : (float) $i / count ( $a ) ;
+
445 }
+
446 }
@@ -860,16 +869,16 @@
Legend
Covered by small (and larger) tests Covered by medium (and large) tests Covered by large tests (and tests of unknown size) Not covered Not coverable
- Generated by php-code-coverage 9.2.29 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Dec 3 10:40:51 UTC 2023.
+ Generated by php-code-coverage 9.2.30 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Feb 11 13:44:20 UTC 2024.
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Json.php.html b/content/coverage/Json.php.html
index 21901ae..a98eead 100644
--- a/content/coverage/Json.php.html
+++ b/content/coverage/Json.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Json.php
+
Code Coverage for lib/Json.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
Json.php
@@ -180,7 +180,7 @@
7
8
9
- 10
+ 10
11
12
13 namespace PrivateBin ;
@@ -221,9 +221,9 @@
48
49 public static function decode ( $input )
50 {
- 51 $output = json_decode ( $input , true ) ;
- 52 self :: _detectError ( ) ;
- 53 return $output ;
+ 51 $output = json_decode ( $input , true ) ;
+ 52 self :: _detectError ( ) ;
+ 53 return $output ;
54 }
55
56
@@ -236,9 +236,9 @@
63
64 private static function _detectError ( )
65 {
- 66 $errorCode = json_last_error ( ) ;
- 67 if ( $errorCode === JSON_ERROR_NONE ) {
- 68 return ;
+ 66 $errorCode = json_last_error ( ) ;
+ 67 if ( $errorCode === JSON_ERROR_NONE ) {
+ 68 return ;
69 }
70
71 $message = 'A JSON error occurred' ;
@@ -259,16 +259,16 @@
Legend
Covered by small (and larger) tests Covered by medium (and large) tests Covered by large tests (and tests of unknown size) Not covered Not coverable
- Generated by php-code-coverage 9.2.29 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Dec 3 10:40:51 UTC 2023.
+ Generated by php-code-coverage 9.2.30 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Feb 11 13:44:20 UTC 2024.
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Model.php.html b/content/coverage/Model.php.html
index 653b177..dcc4559 100644
--- a/content/coverage/Model.php.html
+++ b/content/coverage/Model.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Model.php
+
Code Coverage for lib/Model.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Model/AbstractModel.php.html b/content/coverage/Model/AbstractModel.php.html
index 2c8986d..458956e 100644
--- a/content/coverage/Model/AbstractModel.php.html
+++ b/content/coverage/Model/AbstractModel.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Model/AbstractModel.php
+
Code Coverage for lib/Model/AbstractModel.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Model/Comment.php.html b/content/coverage/Model/Comment.php.html
index 00bfbfd..7971e6f 100644
--- a/content/coverage/Model/Comment.php.html
+++ b/content/coverage/Model/Comment.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Model/Comment.php
+
Code Coverage for lib/Model/Comment.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Model/Paste.php.html b/content/coverage/Model/Paste.php.html
index 5b5a3e0..e6b28a3 100644
--- a/content/coverage/Model/Paste.php.html
+++ b/content/coverage/Model/Paste.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Model/Paste.php
+
Code Coverage for lib/Model/Paste.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Model/dashboard.html b/content/coverage/Model/dashboard.html
index de89199..f58e879 100644
--- a/content/coverage/Model/dashboard.html
+++ b/content/coverage/Model/dashboard.html
@@ -2,11 +2,11 @@
-
Dashboard for /lib/Model
+
Dashboard for lib/Model
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
Model
(Dashboard)
@@ -138,13 +138,13 @@ Project Risks
-
-
-
+
+
+
-
-
-
+
+
+
+
diff --git a/content/coverage/Persistence/PurgeLimiter.php.html b/content/coverage/Persistence/PurgeLimiter.php.html
index 66ba232..29b0f76 100644
--- a/content/coverage/Persistence/PurgeLimiter.php.html
+++ b/content/coverage/Persistence/PurgeLimiter.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Persistence/PurgeLimiter.php
+
Code Coverage for lib/Persistence/PurgeLimiter.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Persistence/ServerSalt.php.html b/content/coverage/Persistence/ServerSalt.php.html
index 0a327b4..5488528 100644
--- a/content/coverage/Persistence/ServerSalt.php.html
+++ b/content/coverage/Persistence/ServerSalt.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Persistence/ServerSalt.php
+
Code Coverage for lib/Persistence/ServerSalt.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Persistence/TrafficLimiter.php.html b/content/coverage/Persistence/TrafficLimiter.php.html
index 7e53138..49bae16 100644
--- a/content/coverage/Persistence/TrafficLimiter.php.html
+++ b/content/coverage/Persistence/TrafficLimiter.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Persistence/TrafficLimiter.php
+
Code Coverage for lib/Persistence/TrafficLimiter.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Persistence/dashboard.html b/content/coverage/Persistence/dashboard.html
index fb70f09..11d4da3 100644
--- a/content/coverage/Persistence/dashboard.html
+++ b/content/coverage/Persistence/dashboard.html
@@ -2,11 +2,11 @@
-
Dashboard for /lib/Persistence
+
Dashboard for lib/Persistence
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
+
+
+
-
-
-
+
+
+
+
diff --git a/content/coverage/View.php.html b/content/coverage/View.php.html
index 5ada218..9a740ac 100644
--- a/content/coverage/View.php.html
+++ b/content/coverage/View.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/View.php
+
Code Coverage for lib/View.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/Vizhash16x16.php.html b/content/coverage/Vizhash16x16.php.html
index 99f80f5..ae6e9b7 100644
--- a/content/coverage/Vizhash16x16.php.html
+++ b/content/coverage/Vizhash16x16.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/Vizhash16x16.php
+
Code Coverage for lib/Vizhash16x16.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
Vizhash16x16.php
@@ -269,7 +269,7 @@
8
9
10
- 11
+ 11
12
13
14 namespace PrivateBin ;
@@ -363,7 +363,7 @@
102
103 $op = 'v' ;
104 if ( ( $this -> getInt ( ) % 2 ) == 0 ) {
- 105 $op = 'h' ;
+ 105 $op = 'h' ;
106 }
107 $image = $this -> degrade ( $image , $op , array ( $r0 , $g0 , $b0 ) , array ( 0 , 0 , 0 ) ) ;
108
@@ -439,11 +439,11 @@
178 private function degrade ( $img , $direction , $color1 , $color2 )
179 {
180 if ( $direction == 'h' ) {
- 181 $size = imagesx ( $img ) ;
- 182 $sizeinv = imagesy ( $img ) ;
+ 181 $size = imagesx ( $img ) ;
+ 182 $sizeinv = imagesy ( $img ) ;
183 } else {
- 184 $size = imagesy ( $img ) ;
- 185 $sizeinv = imagesx ( $img ) ;
+ 184 $size = imagesy ( $img ) ;
+ 185 $sizeinv = imagesx ( $img ) ;
186 }
187 $diffs = array (
188 ( $color2 [ 0 ] - $color1 [ 0 ] ) / $size ,
@@ -455,9 +455,9 @@
194 $g = $color1 [ 1 ] + ( $diffs [ 1 ] * $i ) ;
195 $b = $color1 [ 2 ] + ( $diffs [ 2 ] * $i ) ;
196 if ( $direction == 'h' ) {
- 197 imageline ( $img , $i , 0 , $i , $sizeinv , imagecolorallocate ( $img , $r , $g , $b ) ) ;
+ 197 imageline ( $img , $i , 0 , $i , $sizeinv , imagecolorallocate ( $img , $r , $g , $b ) ) ;
198 } else {
- 199 imageline ( $img , 0 , $i , $sizeinv , $i , imagecolorallocate ( $img , $r , $g , $b ) ) ;
+ 199 imageline ( $img , 0 , $i , $sizeinv , $i , imagecolorallocate ( $img , $r , $g , $b ) ) ;
200 }
201 }
202 return $img ;
@@ -475,16 +475,16 @@
214 {
215 switch ( $action % 7 ) {
216 case 0 :
- 217 imagefilledrectangle ( $image , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $color ) ;
- 218 break ;
+ 217 imagefilledrectangle ( $image , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $color ) ;
+ 218 break ;
219 case 1 :
220 case 2 :
221 imagefilledellipse ( $image , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $color ) ;
222 break ;
223 case 3 :
- 224 $points = array ( $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) ) ;
- 225 imagefilledpolygon ( $image , $points , 4 , $color ) ;
- 226 break ;
+ 224 $points = array ( $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) , $this -> getX ( ) , $this -> getY ( ) ) ;
+ 225 imagefilledpolygon ( $image , $points , 4 , $color ) ;
+ 226 break ;
227 default :
228 $start = $this -> getInt ( ) * 360 / 256 ;
229 $end = $start + $this -> getInt ( ) * 180 / 256 ;
@@ -502,16 +502,16 @@
Legend
Covered by small (and larger) tests Covered by medium (and large) tests Covered by large tests (and tests of unknown size) Not covered Not coverable
- Generated by php-code-coverage 9.2.29 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Dec 3 10:40:51 UTC 2023.
+ Generated by php-code-coverage 9.2.30 using PHP 8.1.2-1ubuntu2.14 and PHPUnit 9.5.10 at Sun Feb 11 13:44:20 UTC 2024.
-
-
-
-
+
+
+
+
diff --git a/content/coverage/YourlsProxy.php.html b/content/coverage/YourlsProxy.php.html
index 047b483..89fad35 100644
--- a/content/coverage/YourlsProxy.php.html
+++ b/content/coverage/YourlsProxy.php.html
@@ -2,11 +2,11 @@
-
Code Coverage for /lib/YourlsProxy.php
+
Code Coverage for lib/YourlsProxy.php
-
-
-
+
+
+
@@ -16,7 +16,7 @@
-
-
-
-
+
+
+
+
diff --git a/content/coverage/_css/style.css b/content/coverage/_css/style.css
index 526cac0..2edd609 100644
--- a/content/coverage/_css/style.css
+++ b/content/coverage/_css/style.css
@@ -120,7 +120,7 @@ svg text {
.scrollbox {
height:245px;
- overflow-x:hidden;
+ overflow-x:scroll;
overflow-y:scroll;
}
diff --git a/content/coverage/dashboard.html b/content/coverage/dashboard.html
index 7c1d403..b348f9e 100644
--- a/content/coverage/dashboard.html
+++ b/content/coverage/dashboard.html
@@ -2,11 +2,11 @@
-
Dashboard for /lib
+
Dashboard for lib
-
-
-
+
+
+
@@ -16,7 +16,7 @@
- /lib
+ lib
(Dashboard)
@@ -198,13 +198,13 @@ Project Risks
-
-
-
+
+
+
diff --git a/content/jsdoc/AttachmentViewer.html b/content/jsdoc/AttachmentViewer.html
index aacd647..ad51528 100644
--- a/content/jsdoc/AttachmentViewer.html
+++ b/content/jsdoc/AttachmentViewer.html
@@ -93,7 +93,7 @@