1 <?php
2
3 4 5 6 7 8 9 10
11
12 namespace Icybee\Modules\Files;
13
14 use ICanBoogie\HTTP\HTTPError;
15
16 17 18 19 20 21 22 23 24
25 class GetOperation extends \ICanBoogie\Operation
26 {
27 const CACHE_MAX_AGE = 2592000;
28
29 30 31
32 protected function get_controls()
33 {
34 return array
35 (
36 self::CONTROL_RECORD => true
37 )
38
39 + parent::get_controls();
40 }
41
42 43 44 45 46 47
48 protected function control_record()
49 {
50 global $core;
51
52 $record = parent::control_record();
53
54 if ($core->user->is_guest && !$record->is_online)
55 {
56 throw new HTTPError
57 (
58 \ICanBoogie\format('The requested resource requires authentication: %resource', array
59 (
60 '%resource' => $record->constructor . '/' . $this->key
61 )),
62
63 401
64 );
65 }
66
67 return $record;
68 }
69
70 protected function validate(\ICanboogie\Errors $errors)
71 {
72 return true;
73 }
74
75
76 protected function process()
77 {
78
79 $record = $this->record;
80 $pathname = \ICanBoogie\DOCUMENT_ROOT . $record->path;
81 $hash = sha1_file($pathname);
82 $modified_time = filemtime($pathname);
83
84 $response = $this->response;
85 $response->cache_control->cacheable = 'public';
86 $response->cache_control->max_age = self::CACHE_MAX_AGE;
87 $response->etag = $hash;
88 $response->expires = '+1 month';
89
90 $request = $this->request;
91
92 if ($request->cache_control->cacheable != 'no-cache')
93 {
94 $if_none_match = $request->headers['If-None-Match'];
95 $if_modified_since = $request->headers['If-Modified-Since'];
96
97 if (!$if_modified_since->is_empty && $if_modified_since->timestamp >= $modified_time
98 && $if_none_match == $hash)
99 {
100 $response->status = 304;
101
102
103
104
105
106 return true;
107 }
108 }
109
110 $response->content_type = $record->mime;
111 $response->content_length = $record->size;
112 $response->last_modified = $modified_time;
113
114 $fh = fopen($pathname, 'rb');
115
116 if (!$fh)
117 {
118 throw new HTTPError("Unable to lock file.");
119 }
120
121 return function() use ($fh)
122 {
123
124
125
126
127 if (!ini_get('safe_mode'))
128 {
129 set_time_limit(0);
130 }
131
132 while (!feof($fh) && !connection_aborted())
133 {
134 echo fread($fh, 1024 * 8);
135
136
137
138
139
140 flush();
141 }
142
143 fclose($fh);
144 };
145 }
146 }