diff options
Diffstat (limited to 'application')
-rwxr-xr-x | application/Config.php | 129 | ||||
-rw-r--r-- | application/LinkDB.php | 129 | ||||
-rw-r--r-- | application/Utils.php | 15 |
3 files changed, 210 insertions, 63 deletions
diff --git a/application/Config.php b/application/Config.php new file mode 100755 index 00000000..0b01b524 --- /dev/null +++ b/application/Config.php | |||
@@ -0,0 +1,129 @@ | |||
1 | <?php | ||
2 | /** | ||
3 | * Functions related to configuration management. | ||
4 | */ | ||
5 | |||
6 | /** | ||
7 | * Re-write configuration file according to given array. | ||
8 | * Requires mandatory fields listed in $MANDATORY_FIELDS. | ||
9 | * | ||
10 | * @param array $config contains all configuration fields. | ||
11 | * @param bool $isLoggedIn true if user is logged in. | ||
12 | * | ||
13 | * @return void | ||
14 | * | ||
15 | * @throws MissingFieldConfigException: a mandatory field has not been provided in $config. | ||
16 | * @throws UnauthorizedConfigException: user is not authorize to change configuration. | ||
17 | * @throws Exception: an error occured while writing the new config file. | ||
18 | */ | ||
19 | function writeConfig($config, $isLoggedIn) | ||
20 | { | ||
21 | // These fields are required in configuration. | ||
22 | $MANDATORY_FIELDS = [ | ||
23 | 'login', 'hash', 'salt', 'timezone', 'title', 'titleLink', | ||
24 | 'redirector', 'disablesessionprotection', 'privateLinkByDefault' | ||
25 | ]; | ||
26 | |||
27 | if (!isset($config['config']['CONFIG_FILE'])) { | ||
28 | throw new MissingFieldConfigException('CONFIG_FILE'); | ||
29 | } | ||
30 | |||
31 | // Only logged in user can alter config. | ||
32 | if (is_file($config['config']['CONFIG_FILE']) && !$isLoggedIn) { | ||
33 | throw new UnauthorizedConfigException(); | ||
34 | } | ||
35 | |||
36 | // Check that all mandatory fields are provided in $config. | ||
37 | foreach ($MANDATORY_FIELDS as $field) { | ||
38 | if (!isset($config[$field])) { | ||
39 | throw new MissingFieldConfigException($field); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | $configStr = '<?php '. PHP_EOL; | ||
44 | $configStr .= '$GLOBALS[\'login\'] = '.var_export($config['login'], true).';'. PHP_EOL; | ||
45 | $configStr .= '$GLOBALS[\'hash\'] = '.var_export($config['hash'], true).';'. PHP_EOL; | ||
46 | $configStr .= '$GLOBALS[\'salt\'] = '.var_export($config['salt'], true).'; '. PHP_EOL; | ||
47 | $configStr .= '$GLOBALS[\'timezone\'] = '.var_export($config['timezone'], true).';'. PHP_EOL; | ||
48 | $configStr .= 'date_default_timezone_set('.var_export($config['timezone'], true).');'. PHP_EOL; | ||
49 | $configStr .= '$GLOBALS[\'title\'] = '.var_export($config['title'], true).';'. PHP_EOL; | ||
50 | $configStr .= '$GLOBALS[\'titleLink\'] = '.var_export($config['titleLink'], true).'; '. PHP_EOL; | ||
51 | $configStr .= '$GLOBALS[\'redirector\'] = '.var_export($config['redirector'], true).'; '. PHP_EOL; | ||
52 | $configStr .= '$GLOBALS[\'disablesessionprotection\'] = '.var_export($config['disablesessionprotection'], true).'; '. PHP_EOL; | ||
53 | $configStr .= '$GLOBALS[\'privateLinkByDefault\'] = '.var_export($config['privateLinkByDefault'], true).'; '. PHP_EOL; | ||
54 | |||
55 | // Store all $config['config'] | ||
56 | foreach ($config['config'] as $key => $value) { | ||
57 | $configStr .= '$GLOBALS[\'config\'][\''. $key .'\'] = '.var_export($config['config'][$key], true).';'. PHP_EOL; | ||
58 | } | ||
59 | $configStr .= '?>'; | ||
60 | |||
61 | if (!file_put_contents($config['config']['CONFIG_FILE'], $configStr) | ||
62 | || strcmp(file_get_contents($config['config']['CONFIG_FILE']), $configStr) != 0 | ||
63 | ) { | ||
64 | throw new Exception( | ||
65 | 'Shaarli could not create the config file. | ||
66 | Please make sure Shaarli has the right to write in the folder is it installed in.' | ||
67 | ); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Milestone 0.9 - shaarli/Shaarli#41: options.php is not supported anymore. | ||
73 | * ==> if user is loggedIn, merge its content with config.php, then delete options.php. | ||
74 | * | ||
75 | * @param array $config contains all configuration fields. | ||
76 | * @param bool $isLoggedIn true if user is logged in. | ||
77 | * | ||
78 | * @return void | ||
79 | */ | ||
80 | function mergeDeprecatedConfig($config, $isLoggedIn) | ||
81 | { | ||
82 | $config_file = $config['config']['CONFIG_FILE']; | ||
83 | |||
84 | if (is_file($config['config']['DATADIR'].'/options.php') && $isLoggedIn) { | ||
85 | include $config['config']['DATADIR'].'/options.php'; | ||
86 | |||
87 | // Load GLOBALS into config | ||
88 | foreach ($GLOBALS as $key => $value) { | ||
89 | $config[$key] = $value; | ||
90 | } | ||
91 | $config['config']['CONFIG_FILE'] = $config_file; | ||
92 | writeConfig($config, $isLoggedIn); | ||
93 | |||
94 | unlink($config['config']['DATADIR'].'/options.php'); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * Exception used if a mandatory field is missing in given configuration. | ||
100 | */ | ||
101 | class MissingFieldConfigException extends Exception | ||
102 | { | ||
103 | public $field; | ||
104 | |||
105 | /** | ||
106 | * Construct exception. | ||
107 | * | ||
108 | * @param string $field field name missing. | ||
109 | */ | ||
110 | public function __construct($field) | ||
111 | { | ||
112 | $this->field = $field; | ||
113 | $this->message = 'Configuration value is required for '. $this->field; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * Exception used if an unauthorized attempt to edit configuration has been made. | ||
119 | */ | ||
120 | class UnauthorizedConfigException extends Exception | ||
121 | { | ||
122 | /** | ||
123 | * Construct exception. | ||
124 | */ | ||
125 | public function __construct() | ||
126 | { | ||
127 | $this->message = 'You are not authorized to alter config.'; | ||
128 | } | ||
129 | } \ No newline at end of file | ||
diff --git a/application/LinkDB.php b/application/LinkDB.php index a673b086..1e16fef1 100644 --- a/application/LinkDB.php +++ b/application/LinkDB.php | |||
@@ -28,7 +28,7 @@ | |||
28 | class LinkDB implements Iterator, Countable, ArrayAccess | 28 | class LinkDB implements Iterator, Countable, ArrayAccess |
29 | { | 29 | { |
30 | // Links are stored as a PHP serialized string | 30 | // Links are stored as a PHP serialized string |
31 | private $datastore; | 31 | private $_datastore; |
32 | 32 | ||
33 | // Datastore PHP prefix | 33 | // Datastore PHP prefix |
34 | protected static $phpPrefix = '<?php /* '; | 34 | protected static $phpPrefix = '<?php /* '; |
@@ -39,23 +39,23 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
39 | // List of links (associative array) | 39 | // List of links (associative array) |
40 | // - key: link date (e.g. "20110823_124546"), | 40 | // - key: link date (e.g. "20110823_124546"), |
41 | // - value: associative array (keys: title, description...) | 41 | // - value: associative array (keys: title, description...) |
42 | private $links; | 42 | private $_links; |
43 | 43 | ||
44 | // List of all recorded URLs (key=url, value=linkdate) | 44 | // List of all recorded URLs (key=url, value=linkdate) |
45 | // for fast reserve search (url-->linkdate) | 45 | // for fast reserve search (url-->linkdate) |
46 | private $urls; | 46 | private $_urls; |
47 | 47 | ||
48 | // List of linkdate keys (for the Iterator interface implementation) | 48 | // List of linkdate keys (for the Iterator interface implementation) |
49 | private $keys; | 49 | private $_keys; |
50 | 50 | ||
51 | // Position in the $this->keys array (for the Iterator interface) | 51 | // Position in the $this->_keys array (for the Iterator interface) |
52 | private $position; | 52 | private $_position; |
53 | 53 | ||
54 | // Is the user logged in? (used to filter private links) | 54 | // Is the user logged in? (used to filter private links) |
55 | private $loggedIn; | 55 | private $_loggedIn; |
56 | 56 | ||
57 | // Hide public links | 57 | // Hide public links |
58 | private $hidePublicLinks; | 58 | private $_hidePublicLinks; |
59 | 59 | ||
60 | /** | 60 | /** |
61 | * Creates a new LinkDB | 61 | * Creates a new LinkDB |
@@ -66,11 +66,11 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
66 | */ | 66 | */ |
67 | function __construct($datastore, $isLoggedIn, $hidePublicLinks) | 67 | function __construct($datastore, $isLoggedIn, $hidePublicLinks) |
68 | { | 68 | { |
69 | $this->datastore = $datastore; | 69 | $this->_datastore = $datastore; |
70 | $this->loggedIn = $isLoggedIn; | 70 | $this->_loggedIn = $isLoggedIn; |
71 | $this->hidePublicLinks = $hidePublicLinks; | 71 | $this->_hidePublicLinks = $hidePublicLinks; |
72 | $this->checkDB(); | 72 | $this->_checkDB(); |
73 | $this->readdb(); | 73 | $this->_readDB(); |
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
@@ -78,7 +78,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
78 | */ | 78 | */ |
79 | public function count() | 79 | public function count() |
80 | { | 80 | { |
81 | return count($this->links); | 81 | return count($this->_links); |
82 | } | 82 | } |
83 | 83 | ||
84 | /** | 84 | /** |
@@ -87,7 +87,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
87 | public function offsetSet($offset, $value) | 87 | public function offsetSet($offset, $value) |
88 | { | 88 | { |
89 | // TODO: use exceptions instead of "die" | 89 | // TODO: use exceptions instead of "die" |
90 | if (!$this->loggedIn) { | 90 | if (!$this->_loggedIn) { |
91 | die('You are not authorized to add a link.'); | 91 | die('You are not authorized to add a link.'); |
92 | } | 92 | } |
93 | if (empty($value['linkdate']) || empty($value['url'])) { | 93 | if (empty($value['linkdate']) || empty($value['url'])) { |
@@ -96,8 +96,8 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
96 | if (empty($offset)) { | 96 | if (empty($offset)) { |
97 | die('You must specify a key.'); | 97 | die('You must specify a key.'); |
98 | } | 98 | } |
99 | $this->links[$offset] = $value; | 99 | $this->_links[$offset] = $value; |
100 | $this->urls[$value['url']]=$offset; | 100 | $this->_urls[$value['url']]=$offset; |
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
@@ -105,7 +105,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
105 | */ | 105 | */ |
106 | public function offsetExists($offset) | 106 | public function offsetExists($offset) |
107 | { | 107 | { |
108 | return array_key_exists($offset, $this->links); | 108 | return array_key_exists($offset, $this->_links); |
109 | } | 109 | } |
110 | 110 | ||
111 | /** | 111 | /** |
@@ -113,13 +113,13 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
113 | */ | 113 | */ |
114 | public function offsetUnset($offset) | 114 | public function offsetUnset($offset) |
115 | { | 115 | { |
116 | if (!$this->loggedIn) { | 116 | if (!$this->_loggedIn) { |
117 | // TODO: raise an exception | 117 | // TODO: raise an exception |
118 | die('You are not authorized to delete a link.'); | 118 | die('You are not authorized to delete a link.'); |
119 | } | 119 | } |
120 | $url = $this->links[$offset]['url']; | 120 | $url = $this->_links[$offset]['url']; |
121 | unset($this->urls[$url]); | 121 | unset($this->_urls[$url]); |
122 | unset($this->links[$offset]); | 122 | unset($this->_links[$offset]); |
123 | } | 123 | } |
124 | 124 | ||
125 | /** | 125 | /** |
@@ -127,7 +127,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
127 | */ | 127 | */ |
128 | public function offsetGet($offset) | 128 | public function offsetGet($offset) |
129 | { | 129 | { |
130 | return isset($this->links[$offset]) ? $this->links[$offset] : null; | 130 | return isset($this->_links[$offset]) ? $this->_links[$offset] : null; |
131 | } | 131 | } |
132 | 132 | ||
133 | /** | 133 | /** |
@@ -135,7 +135,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
135 | */ | 135 | */ |
136 | function current() | 136 | function current() |
137 | { | 137 | { |
138 | return $this->links[$this->keys[$this->position]]; | 138 | return $this->_links[$this->_keys[$this->_position]]; |
139 | } | 139 | } |
140 | 140 | ||
141 | /** | 141 | /** |
@@ -143,7 +143,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
143 | */ | 143 | */ |
144 | function key() | 144 | function key() |
145 | { | 145 | { |
146 | return $this->keys[$this->position]; | 146 | return $this->_keys[$this->_position]; |
147 | } | 147 | } |
148 | 148 | ||
149 | /** | 149 | /** |
@@ -151,7 +151,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
151 | */ | 151 | */ |
152 | function next() | 152 | function next() |
153 | { | 153 | { |
154 | ++$this->position; | 154 | ++$this->_position; |
155 | } | 155 | } |
156 | 156 | ||
157 | /** | 157 | /** |
@@ -161,9 +161,9 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
161 | */ | 161 | */ |
162 | function rewind() | 162 | function rewind() |
163 | { | 163 | { |
164 | $this->keys = array_keys($this->links); | 164 | $this->_keys = array_keys($this->_links); |
165 | rsort($this->keys); | 165 | rsort($this->_keys); |
166 | $this->position = 0; | 166 | $this->_position = 0; |
167 | } | 167 | } |
168 | 168 | ||
169 | /** | 169 | /** |
@@ -171,7 +171,7 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
171 | */ | 171 | */ |
172 | function valid() | 172 | function valid() |
173 | { | 173 | { |
174 | return isset($this->keys[$this->position]); | 174 | return isset($this->_keys[$this->_position]); |
175 | } | 175 | } |
176 | 176 | ||
177 | /** | 177 | /** |
@@ -179,14 +179,14 @@ class LinkDB implements Iterator, Countable, ArrayAccess | |||
179 | * | 179 | * |
180 | * If no DB file is found, creates a dummy DB. | 180 | * If no DB file is found, creates a dummy DB. |
181 | */ | 181 | */ |
182 | private function checkDB() | 182 | private function _checkDB() |
183 | { | 183 | { |
184 | if (file_exists($this->datastore)) { | 184 | if (file_exists($this->_datastore)) { |
185 | return; | 185 | return; |
186 | } | 186 | } |
187 | 187 | ||
188 | // Create a dummy database for example | 188 | // Create a dummy database for example |
189 | $this->links = array(); | 189 | $this->_links = array(); |
190 | $link = array( | 190 | $link = array( |
191 | 'title'=>' Shaarli: the personal, minimalist, super-fast, no-database delicious clone', | 191 | 'title'=>' Shaarli: the personal, minimalist, super-fast, no-database delicious clone', |
192 | 'url'=>'https://github.com/shaarli/Shaarli/wiki', | 192 | 'url'=>'https://github.com/shaarli/Shaarli/wiki', |
@@ -199,7 +199,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
199 | 'linkdate'=> date('Ymd_His'), | 199 | 'linkdate'=> date('Ymd_His'), |
200 | 'tags'=>'opensource software' | 200 | 'tags'=>'opensource software' |
201 | ); | 201 | ); |
202 | $this->links[$link['linkdate']] = $link; | 202 | $this->_links[$link['linkdate']] = $link; |
203 | 203 | ||
204 | $link = array( | 204 | $link = array( |
205 | 'title'=>'My secret stuff... - Pastebin.com', | 205 | 'title'=>'My secret stuff... - Pastebin.com', |
@@ -209,60 +209,60 @@ You use the community supported version of the original Shaarli project, by Seba | |||
209 | 'linkdate'=> date('Ymd_His', strtotime('-1 minute')), | 209 | 'linkdate'=> date('Ymd_His', strtotime('-1 minute')), |
210 | 'tags'=>'secretstuff' | 210 | 'tags'=>'secretstuff' |
211 | ); | 211 | ); |
212 | $this->links[$link['linkdate']] = $link; | 212 | $this->_links[$link['linkdate']] = $link; |
213 | 213 | ||
214 | // Write database to disk | 214 | // Write database to disk |
215 | // TODO: raise an exception if the file is not write-able | 215 | // TODO: raise an exception if the file is not write-able |
216 | file_put_contents( | 216 | file_put_contents( |
217 | $this->datastore, | 217 | $this->_datastore, |
218 | self::$phpPrefix.base64_encode(gzdeflate(serialize($this->links))).self::$phpSuffix | 218 | self::$phpPrefix.base64_encode(gzdeflate(serialize($this->_links))).self::$phpSuffix |
219 | ); | 219 | ); |
220 | } | 220 | } |
221 | 221 | ||
222 | /** | 222 | /** |
223 | * Reads database from disk to memory | 223 | * Reads database from disk to memory |
224 | */ | 224 | */ |
225 | private function readdb() | 225 | private function _readDB() |
226 | { | 226 | { |
227 | 227 | ||
228 | // Public links are hidden and user not logged in => nothing to show | 228 | // Public links are hidden and user not logged in => nothing to show |
229 | if ($this->hidePublicLinks && !$this->loggedIn) { | 229 | if ($this->_hidePublicLinks && !$this->_loggedIn) { |
230 | $this->links = array(); | 230 | $this->_links = array(); |
231 | return; | 231 | return; |
232 | } | 232 | } |
233 | 233 | ||
234 | // Read data | 234 | // Read data |
235 | // Note that gzinflate is faster than gzuncompress. | 235 | // Note that gzinflate is faster than gzuncompress. |
236 | // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 | 236 | // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 |
237 | $this->links = array(); | 237 | $this->_links = array(); |
238 | 238 | ||
239 | if (file_exists($this->datastore)) { | 239 | if (file_exists($this->_datastore)) { |
240 | $this->links = unserialize(gzinflate(base64_decode( | 240 | $this->_links = unserialize(gzinflate(base64_decode( |
241 | substr(file_get_contents($this->datastore), | 241 | substr(file_get_contents($this->_datastore), |
242 | strlen(self::$phpPrefix), -strlen(self::$phpSuffix))))); | 242 | strlen(self::$phpPrefix), -strlen(self::$phpSuffix))))); |
243 | } | 243 | } |
244 | 244 | ||
245 | // If user is not logged in, filter private links. | 245 | // If user is not logged in, filter private links. |
246 | if (!$this->loggedIn) { | 246 | if (!$this->_loggedIn) { |
247 | $toremove = array(); | 247 | $toremove = array(); |
248 | foreach ($this->links as $link) { | 248 | foreach ($this->_links as $link) { |
249 | if ($link['private'] != 0) { | 249 | if ($link['private'] != 0) { |
250 | $toremove[] = $link['linkdate']; | 250 | $toremove[] = $link['linkdate']; |
251 | } | 251 | } |
252 | } | 252 | } |
253 | foreach ($toremove as $linkdate) { | 253 | foreach ($toremove as $linkdate) { |
254 | unset($this->links[$linkdate]); | 254 | unset($this->_links[$linkdate]); |
255 | } | 255 | } |
256 | } | 256 | } |
257 | 257 | ||
258 | // Keep the list of the mapping URLs-->linkdate up-to-date. | 258 | // Keep the list of the mapping URLs-->linkdate up-to-date. |
259 | $this->urls = array(); | 259 | $this->_urls = array(); |
260 | foreach ($this->links as $link) { | 260 | foreach ($this->_links as $link) { |
261 | $this->urls[$link['url']] = $link['linkdate']; | 261 | $this->_urls[$link['url']] = $link['linkdate']; |
262 | } | 262 | } |
263 | 263 | ||
264 | // Escape links data | 264 | // Escape links data |
265 | foreach($this->links as &$link) { | 265 | foreach($this->_links as &$link) { |
266 | sanitizeLink($link); | 266 | sanitizeLink($link); |
267 | } | 267 | } |
268 | } | 268 | } |
@@ -272,13 +272,13 @@ You use the community supported version of the original Shaarli project, by Seba | |||
272 | */ | 272 | */ |
273 | public function savedb() | 273 | public function savedb() |
274 | { | 274 | { |
275 | if (!$this->loggedIn) { | 275 | if (!$this->_loggedIn) { |
276 | // TODO: raise an Exception instead | 276 | // TODO: raise an Exception instead |
277 | die('You are not authorized to change the database.'); | 277 | die('You are not authorized to change the database.'); |
278 | } | 278 | } |
279 | file_put_contents( | 279 | file_put_contents( |
280 | $this->datastore, | 280 | $this->_datastore, |
281 | self::$phpPrefix.base64_encode(gzdeflate(serialize($this->links))).self::$phpSuffix | 281 | self::$phpPrefix.base64_encode(gzdeflate(serialize($this->_links))).self::$phpSuffix |
282 | ); | 282 | ); |
283 | invalidateCaches(); | 283 | invalidateCaches(); |
284 | } | 284 | } |
@@ -288,8 +288,8 @@ You use the community supported version of the original Shaarli project, by Seba | |||
288 | */ | 288 | */ |
289 | public function getLinkFromUrl($url) | 289 | public function getLinkFromUrl($url) |
290 | { | 290 | { |
291 | if (isset($this->urls[$url])) { | 291 | if (isset($this->_urls[$url])) { |
292 | return $this->links[$this->urls[$url]]; | 292 | return $this->_links[$this->_urls[$url]]; |
293 | } | 293 | } |
294 | return false; | 294 | return false; |
295 | } | 295 | } |
@@ -316,7 +316,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
316 | $search = mb_convert_case($searchterms, MB_CASE_LOWER, 'UTF-8'); | 316 | $search = mb_convert_case($searchterms, MB_CASE_LOWER, 'UTF-8'); |
317 | $keys = array('title', 'description', 'url', 'tags'); | 317 | $keys = array('title', 'description', 'url', 'tags'); |
318 | 318 | ||
319 | foreach ($this->links as $link) { | 319 | foreach ($this->_links as $link) { |
320 | $found = false; | 320 | $found = false; |
321 | 321 | ||
322 | foreach ($keys as $key) { | 322 | foreach ($keys as $key) { |
@@ -352,7 +352,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
352 | $searchtags = explode(' ', $t); | 352 | $searchtags = explode(' ', $t); |
353 | $filtered = array(); | 353 | $filtered = array(); |
354 | 354 | ||
355 | foreach ($this->links as $l) { | 355 | foreach ($this->_links as $l) { |
356 | $linktags = explode( | 356 | $linktags = explode( |
357 | ' ', | 357 | ' ', |
358 | ($casesensitive ? $l['tags']:mb_convert_case($l['tags'], MB_CASE_LOWER, 'UTF-8')) | 358 | ($casesensitive ? $l['tags']:mb_convert_case($l['tags'], MB_CASE_LOWER, 'UTF-8')) |
@@ -375,9 +375,12 @@ You use the community supported version of the original Shaarli project, by Seba | |||
375 | */ | 375 | */ |
376 | public function filterDay($day) | 376 | public function filterDay($day) |
377 | { | 377 | { |
378 | // TODO: check input format | 378 | if (! checkDateFormat('Ymd', $day)) { |
379 | throw new Exception('Invalid date format'); | ||
380 | } | ||
381 | |||
379 | $filtered = array(); | 382 | $filtered = array(); |
380 | foreach ($this->links as $l) { | 383 | foreach ($this->_links as $l) { |
381 | if (startsWith($l['linkdate'], $day)) { | 384 | if (startsWith($l['linkdate'], $day)) { |
382 | $filtered[$l['linkdate']] = $l; | 385 | $filtered[$l['linkdate']] = $l; |
383 | } | 386 | } |
@@ -392,7 +395,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
392 | public function filterSmallHash($smallHash) | 395 | public function filterSmallHash($smallHash) |
393 | { | 396 | { |
394 | $filtered = array(); | 397 | $filtered = array(); |
395 | foreach ($this->links as $l) { | 398 | foreach ($this->_links as $l) { |
396 | if ($smallHash == smallHash($l['linkdate'])) { | 399 | if ($smallHash == smallHash($l['linkdate'])) { |
397 | // Yes, this is ugly and slow | 400 | // Yes, this is ugly and slow |
398 | $filtered[$l['linkdate']] = $l; | 401 | $filtered[$l['linkdate']] = $l; |
@@ -409,7 +412,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
409 | public function allTags() | 412 | public function allTags() |
410 | { | 413 | { |
411 | $tags = array(); | 414 | $tags = array(); |
412 | foreach ($this->links as $link) { | 415 | foreach ($this->_links as $link) { |
413 | foreach (explode(' ', $link['tags']) as $tag) { | 416 | foreach (explode(' ', $link['tags']) as $tag) { |
414 | if (!empty($tag)) { | 417 | if (!empty($tag)) { |
415 | $tags[$tag] = (empty($tags[$tag]) ? 1 : $tags[$tag] + 1); | 418 | $tags[$tag] = (empty($tags[$tag]) ? 1 : $tags[$tag] + 1); |
@@ -428,7 +431,7 @@ You use the community supported version of the original Shaarli project, by Seba | |||
428 | public function days() | 431 | public function days() |
429 | { | 432 | { |
430 | $linkDays = array(); | 433 | $linkDays = array(); |
431 | foreach (array_keys($this->links) as $day) { | 434 | foreach (array_keys($this->_links) as $day) { |
432 | $linkDays[substr($day, 0, 8)] = 0; | 435 | $linkDays[substr($day, 0, 8)] = 0; |
433 | } | 436 | } |
434 | $linkDays = array_keys($linkDays); | 437 | $linkDays = array_keys($linkDays); |
diff --git a/application/Utils.php b/application/Utils.php index 82220bfc..a1e97b35 100644 --- a/application/Utils.php +++ b/application/Utils.php | |||
@@ -69,4 +69,19 @@ function sanitizeLink(&$link) | |||
69 | $link['description'] = escape($link['description']); | 69 | $link['description'] = escape($link['description']); |
70 | $link['tags'] = escape($link['tags']); | 70 | $link['tags'] = escape($link['tags']); |
71 | } | 71 | } |
72 | |||
73 | /** | ||
74 | * Checks if a string represents a valid date | ||
75 | * | ||
76 | * @param string a string-formatted date | ||
77 | * @param format the expected DateTime format of the string | ||
78 | * @return whether the string is a valid date | ||
79 | * @see http://php.net/manual/en/class.datetime.php | ||
80 | * @see http://php.net/manual/en/datetime.createfromformat.php | ||
81 | */ | ||
82 | function checkDateFormat($format, $string) | ||
83 | { | ||
84 | $date = DateTime::createFromFormat($format, $string); | ||
85 | return $date && $date->format($string) == $string; | ||
86 | } | ||
72 | ?> | 87 | ?> |