@@ -7,6 +7,8 @@ class Restic
7
7
private $ append_only = false ;
8
8
private $ block_size = 8192 ;
9
9
private $ basePath = "restic " ;
10
+ private $ currentSize = 0 ;
11
+ private $ maxRepoSize = 0 ;
10
12
public $ private_repos = false ;
11
13
12
14
@@ -24,6 +26,9 @@ private function __construct($opts)
24
26
if (array_key_exists ("block_size " , $ opts )) {
25
27
$ this ->block_size = $ opts ["block_size " ];
26
28
}
29
+ if (array_key_exists ("max_size " , $ opts )) {
30
+ $ this ->maxRepoSize = $ opts ["max_size " ];
31
+ }
27
32
}
28
33
public static function Instance ($ opts = Array ())
29
34
{
@@ -51,6 +56,12 @@ public function sendStatus($status)
51
56
case 404 :
52
57
header ($ _SERVER ["SERVER_PROTOCOL " ] . " 404 Not Found " );
53
58
break ;
59
+ case 411 ;
60
+ header ($ _SERVER ["SERVER_PROTOCOL " ] . " 411 Length Required " );
61
+ break ;
62
+ case 413 :
63
+ header ($ _SERVER ["SERVER_PROTOCOL " ] . " 413 Request Entity Too Large " );
64
+ break ;
54
65
case 416 :
55
66
header ($ _SERVER ["SERVER_PROTOCOL " ] . " 416 Requested Range Not Satisfiable " );
56
67
break ;
@@ -61,6 +72,28 @@ public function sendStatus($status)
61
72
header ($ _SERVER ["SERVER_PROTOCOL " ] . " 200 OK " );
62
73
}
63
74
}
75
+
76
+ private function tallySize ($ path , $ firstrun = false )
77
+ {
78
+ $ size = 0 ;
79
+ $ items = $ firstrun
80
+ ? $ this ->validTypes
81
+ : scandir ($ path );
82
+ foreach ($ items as $ i ) {
83
+ if ($ i === ". " || $ i === ".. " ) {
84
+ continue ;
85
+ }
86
+ $ fullpath = $ this ->pathResolve ($ path , $ i );
87
+ if (is_dir ($ fullpath )) {
88
+ $ size += $ this ->tallySize ($ fullpath );
89
+ } else {
90
+ $ st = stat ($ fullpath );
91
+ $ size += $ st ["size " ];
92
+ }
93
+ }
94
+ return $ size ;
95
+ }
96
+
64
97
private function pathResolve ()
65
98
{
66
99
$ sep = DIRECTORY_SEPARATOR ;
@@ -263,6 +296,24 @@ public function saveBlob($repo_name, $type, $name = "")
263
296
$ type = func_get_arg (0 );
264
297
$ repo_name = ". " ;
265
298
}
299
+
300
+ if ($ this ->maxRepoSize != 0 ) {
301
+ // We never update currentSize after this, because the server will execute
302
+ // an instance of the script per request anyway. The stat cache helps with the speed.
303
+ $ this ->currentSize = $ this ->tallySize ($ this ->pathResolve ($ this ->basePath , $ repo_name ), true );
304
+
305
+ if (array_key_exists ("CONTENT_LENGTH " , $ _SERVER ) && $ _SERVER ["CONTENT_LENGTH " ] != "" ) {
306
+ $ contentLen = intval ($ _SERVER ["CONTENT_LENGTH " ]);
307
+ if (($ this ->currentSize + $ contentLen ) > $ this ->maxRepoSize ) {
308
+ $ this ->sendStatus (413 ); // payload too large
309
+ exit ;
310
+ }
311
+ } else {
312
+ $ this ->sendStatus (411 ); // length required
313
+ exit ;
314
+ }
315
+ }
316
+
266
317
if ($ this ->isHashed ($ type )) {
267
318
$ path = $ this ->pathResolve ($ this ->basePath , $ repo_name , $ type , substr ($ name , 0 , 2 ), $ name );
268
319
} else {
0 commit comments