]>
Commit | Line | Data |
---|---|---|
1 | <?php | |
2 | /** | |
3 | * poche, a read it later open source system | |
4 | * | |
5 | * @category poche | |
6 | * @author Nicolas LÅ“uillet <support@inthepoche.com> | |
7 | * @copyright 2013 | |
8 | * @license http://www.wtfpl.net/ see COPYING file | |
9 | */ | |
10 | ||
11 | function encode_string($string) | |
12 | { | |
13 | return sha1($string . SALT); | |
14 | } | |
15 | ||
16 | function get_external_file($url) | |
17 | { | |
18 | $timeout = 15; | |
19 | $useragent = "Mozilla/5.0 (Windows NT 5.1; rv:18.0) Gecko/20100101 Firefox/18.0"; | |
20 | ||
21 | if (in_array ('curl', get_loaded_extensions())) { | |
22 | # Fetch feed from URL | |
23 | $curl = curl_init(); | |
24 | curl_setopt($curl, CURLOPT_URL, $url); | |
25 | curl_setopt($curl, CURLOPT_TIMEOUT, $timeout); | |
26 | curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); | |
27 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); | |
28 | curl_setopt($curl, CURLOPT_HEADER, false); | |
29 | ||
30 | # for ssl, do not verified certificate | |
31 | curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); | |
32 | curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE ); | |
33 | ||
34 | # FeedBurner requires a proper USER-AGENT... | |
35 | curl_setopt($curl, CURL_HTTP_VERSION_1_1, true); | |
36 | curl_setopt($curl, CURLOPT_ENCODING, "gzip, deflate"); | |
37 | curl_setopt($curl, CURLOPT_USERAGENT, $useragent); | |
38 | ||
39 | $data = curl_exec($curl); | |
40 | $httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE); | |
41 | $httpcodeOK = isset($httpcode) and ($httpcode == 200 or $httpcode == 301); | |
42 | curl_close($curl); | |
43 | } else { | |
44 | # create http context and add timeout and user-agent | |
45 | $context = stream_context_create( | |
46 | array( | |
47 | 'http' => array( | |
48 | 'timeout' => $timeout, | |
49 | 'header' => "User-Agent: " . $useragent, | |
50 | 'follow_location' => true | |
51 | ), | |
52 | 'ssl' => array( | |
53 | 'verify_peer' => false, | |
54 | 'allow_self_signed' => true | |
55 | ) | |
56 | ) | |
57 | ); | |
58 | ||
59 | # only download page lesser than 4MB | |
60 | $data = @file_get_contents($url, false, $context, -1, 4000000); | |
61 | ||
62 | if (isset($http_response_header) and isset($http_response_header[0])) { | |
63 | $httpcodeOK = isset($http_response_header) and isset($http_response_header[0]) and ((strpos($http_response_header[0], '200 OK') !== FALSE) or (strpos($http_response_header[0], '301 Moved Permanently') !== FALSE)); | |
64 | } | |
65 | } | |
66 | ||
67 | # if response is not empty and response is OK | |
68 | if (isset($data) and isset($httpcodeOK) and $httpcodeOK) { | |
69 | ||
70 | # take charset of page and get it | |
71 | preg_match('#<meta .*charset=.*>#Usi', $data, $meta); | |
72 | ||
73 | # if meta tag is found | |
74 | if (!empty($meta[0])) { | |
75 | preg_match('#charset="?(.*)"#si', $meta[0], $encoding); | |
76 | # if charset is found set it otherwise, set it to utf-8 | |
77 | $html_charset = (!empty($encoding[1])) ? strtolower($encoding[1]) : 'utf-8'; | |
78 | } else { | |
79 | $html_charset = 'utf-8'; | |
80 | $encoding[1] = ''; | |
81 | } | |
82 | ||
83 | # replace charset of url to charset of page | |
84 | $data = str_replace('charset=' . $encoding[1], 'charset=' . $html_charset, $data); | |
85 | ||
86 | return $data; | |
87 | } | |
88 | else { | |
89 | return FALSE; | |
90 | } | |
91 | } | |
92 | ||
93 | function fetch_url_content($url) | |
94 | { | |
95 | $url = base64_decode($url); | |
96 | if (pocheTools::isUrl($url)) { | |
97 | $url = pocheTools::cleanURL($url); | |
98 | $html = Encoding::toUTF8(get_external_file($url)); | |
99 | ||
100 | # if get_external_file if not able to retrieve HTTPS content, try the same URL with HTTP protocol | |
101 | if (!preg_match('!^https?://!i', $url) && (!isset($html) || strlen($html) <= 0)) { | |
102 | $url = 'http://' . $url; | |
103 | $html = Encoding::toUTF8(get_external_file($url)); | |
104 | } | |
105 | ||
106 | if (function_exists('tidy_parse_string')) { | |
107 | $tidy = tidy_parse_string($html, array(), 'UTF8'); | |
108 | $tidy->cleanRepair(); | |
109 | $html = $tidy->value; | |
110 | } | |
111 | ||
112 | $parameters = array(); | |
113 | if (isset($html) and strlen($html) > 0) | |
114 | { | |
115 | $readability = new Readability($html, $url); | |
116 | $readability->convertLinksToFootnotes = CONVERT_LINKS_FOOTNOTES; | |
117 | $readability->revertForcedParagraphElements = REVERT_FORCED_PARAGRAPH_ELEMENTS; | |
118 | ||
119 | if($readability->init()) | |
120 | { | |
121 | $content = $readability->articleContent->innerHTML; | |
122 | $parameters['title'] = $readability->articleTitle->innerHTML; | |
123 | $parameters['content'] = $content; | |
124 | ||
125 | return $parameters; | |
126 | } | |
127 | } | |
128 | } | |
129 | else { | |
130 | #$msg->add('e', _('error during url preparation : the link is not valid')); | |
131 | pocheTools::logm($url . ' is not a valid url'); | |
132 | } | |
133 | ||
134 | return FALSE; | |
135 | } | |
136 | ||
137 | function display_view($view, $id = 0, $full_head = 'yes') | |
138 | { | |
139 | global $tpl, $store; | |
140 | ||
141 | switch ($view) | |
142 | { | |
143 | case 'install': | |
144 | pocheTools::logm('install mode'); | |
145 | break; | |
146 | case 'import'; | |
147 | pocheTools::logm('import mode'); | |
148 | break; | |
149 | case 'export': | |
150 | $entries = $store->retrieveAll(); | |
151 | $tpl->assign('export', pocheTools::renderJson($entries)); | |
152 | $tpl->draw('export'); | |
153 | pocheTools::logm('export view'); | |
154 | break; | |
155 | case 'config': | |
156 | $tpl->assign('load_all_js', 0); | |
157 | $tpl->draw('head'); | |
158 | $tpl->draw('home'); | |
159 | $tpl->draw('config'); | |
160 | $tpl->draw('js'); | |
161 | $tpl->draw('footer'); | |
162 | pocheTools::logm('config view'); | |
163 | break; | |
164 | case 'view': | |
165 | $entry = $store->retrieveOneById($id); | |
166 | if ($entry != NULL) { | |
167 | pocheTools::logm('view link #' . $id); | |
168 | $tpl->assign('id', $entry['id']); | |
169 | $tpl->assign('url', $entry['url']); | |
170 | $tpl->assign('title', $entry['title']); | |
171 | $content = $entry['content']; | |
172 | if (function_exists('tidy_parse_string')) { | |
173 | $tidy = tidy_parse_string($content, array('indent'=>true, 'show-body-only' => true), 'UTF8'); | |
174 | $tidy->cleanRepair(); | |
175 | $content = $tidy->value; | |
176 | } | |
177 | $tpl->assign('content', $content); | |
178 | $tpl->assign('is_fav', $entry['is_fav']); | |
179 | $tpl->assign('is_read', $entry['is_read']); | |
180 | $tpl->assign('load_all_js', 0); | |
181 | $tpl->draw('view'); | |
182 | } | |
183 | else { | |
184 | pocheTools::logm('error in view call : entry is NULL'); | |
185 | } | |
186 | break; | |
187 | default: # home view | |
188 | $entries = $store->getEntriesByView($view); | |
189 | $tpl->assign('entries', $entries); | |
190 | ||
191 | if ($full_head == 'yes') { | |
192 | $tpl->assign('load_all_js', 1); | |
193 | $tpl->draw('head'); | |
194 | $tpl->draw('home'); | |
195 | } | |
196 | ||
197 | $tpl->draw('entries'); | |
198 | if ($full_head == 'yes') { | |
199 | $tpl->draw('js'); | |
200 | $tpl->draw('footer'); | |
201 | } | |
202 | break; | |
203 | } | |
204 | } | |
205 | ||
206 | /** | |
207 | * Call action (mark as fav, archive, delete, etc.) | |
208 | */ | |
209 | function action_to_do($action, $url, $id = 0) | |
210 | { | |
211 | global $store; | |
212 | ||
213 | switch ($action) | |
214 | { | |
215 | case 'add': | |
216 | if($parametres_url = fetch_url_content($url)) { | |
217 | if ($store->add($url, $parametres_url['title'], $parametres_url['content'])) { | |
218 | pocheTools::logm('add link ' . $url); | |
219 | $last_id = $store->getLastId(); | |
220 | if (DOWNLOAD_PICTURES) { | |
221 | $content = filtre_picture($parametres_url['content'], $url, $last_id); | |
222 | } | |
223 | #$msg->add('s', _('the link has been added successfully')); | |
224 | } | |
225 | else { | |
226 | #$msg->add('e', _('error during insertion : the link wasn\'t added')); | |
227 | pocheTools::logm('error during insertion : the link wasn\'t added'); | |
228 | } | |
229 | } | |
230 | else { | |
231 | #$msg->add('e', _('error during url preparation : the link wasn\'t added')); | |
232 | pocheTools::logm('error during content fetch'); | |
233 | } | |
234 | break; | |
235 | case 'delete': | |
236 | if ($store->deleteById($id)) { | |
237 | if (DOWNLOAD_PICTURES) { | |
238 | remove_directory(ABS_PATH . $id); | |
239 | } | |
240 | #$msg->add('s', _('the link has been deleted successfully')); | |
241 | pocheTools::logm('delete link #' . $id); | |
242 | } | |
243 | else { | |
244 | #$msg->add('e', _('the link wasn\'t deleted')); | |
245 | pocheTools::logm('error : can\'t delete link #' . $id); | |
246 | } | |
247 | break; | |
248 | case 'toggle_fav' : | |
249 | $store->favoriteById($id); | |
250 | pocheTools::logm('mark as favorite link #' . $id); | |
251 | break; | |
252 | case 'toggle_archive' : | |
253 | $store->archiveById($id); | |
254 | pocheTools::logm('archive link #' . $id); | |
255 | break; | |
256 | default: | |
257 | break; | |
258 | } | |
259 | } |