/src/httrack/src/htscore.h
Line | Count | Source |
1 | | /* ------------------------------------------------------------ */ |
2 | | /* |
3 | | HTTrack Website Copier, Offline Browser for Windows and Unix |
4 | | Copyright (C) 1998 Xavier Roche and other contributors |
5 | | |
6 | | SPDX-License-Identifier: GPL-3.0-or-later |
7 | | |
8 | | This program is free software: you can redistribute it and/or modify |
9 | | it under the terms of the GNU General Public License as published by |
10 | | the Free Software Foundation, either version 3 of the License, or |
11 | | (at your option) any later version. |
12 | | |
13 | | This program is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
20 | | |
21 | | Ethical use: we kindly ask that you NOT use this software to harvest email |
22 | | addresses or to collect any other private information about people. Doing so |
23 | | would dishonor our work and waste the many hours we have spent on it. |
24 | | |
25 | | Please visit our Website: http://www.httrack.com |
26 | | */ |
27 | | |
28 | | /* ------------------------------------------------------------ */ |
29 | | /* File: Main file .h */ |
30 | | /* Author: Xavier Roche */ |
31 | | /* ------------------------------------------------------------ */ |
32 | | |
33 | | /* Core engine declarations. Not an installed header, but part of the de-facto |
34 | | API surface: external consumers (e.g. httrack-android) read these structs and |
35 | | constants and call functions declared here. */ |
36 | | #ifndef HTS_CORE_DEFH |
37 | | #define HTS_CORE_DEFH |
38 | | |
39 | | #include "htsglobal.h" |
40 | | |
41 | | /* specific definitions */ |
42 | | #include "htsbase.h" |
43 | | /* Includes and definitions */ |
44 | | #include <limits.h> |
45 | | #include <sys/types.h> |
46 | | #include <sys/stat.h> |
47 | | #ifdef _WIN32 |
48 | | #include <conio.h> |
49 | | #include <direct.h> |
50 | | #else |
51 | | #ifndef _WIN32 |
52 | | #include <unistd.h> |
53 | | #endif |
54 | | #endif |
55 | | /* END specific definitions */ |
56 | | |
57 | | /* Forward definitions */ |
58 | | #ifndef HTS_DEF_FWSTRUCT_lien_url |
59 | | #define HTS_DEF_FWSTRUCT_lien_url |
60 | | typedef struct lien_url lien_url; |
61 | | #endif |
62 | | #ifndef HTS_DEF_FWSTRUCT_lien_back |
63 | | #define HTS_DEF_FWSTRUCT_lien_back |
64 | | typedef struct lien_back lien_back; |
65 | | #endif |
66 | | #ifndef HTS_DEF_FWSTRUCT_struct_back |
67 | | #define HTS_DEF_FWSTRUCT_struct_back |
68 | | typedef struct struct_back struct_back; |
69 | | #endif |
70 | | #ifndef HTS_DEF_FWSTRUCT_cache_back |
71 | | #define HTS_DEF_FWSTRUCT_cache_back |
72 | | typedef struct cache_back cache_back; |
73 | | #endif |
74 | | #ifndef HTS_DEF_FWSTRUCT_hash_struct |
75 | | #define HTS_DEF_FWSTRUCT_hash_struct |
76 | | typedef struct hash_struct hash_struct; |
77 | | #endif |
78 | | #ifndef HTS_DEF_FWSTRUCT_filecreate_params |
79 | | #define HTS_DEF_FWSTRUCT_filecreate_params |
80 | | typedef struct filecreate_params filecreate_params; |
81 | | #endif |
82 | | |
83 | | // Include htslib.h for all types |
84 | | #include "htslib.h" |
85 | | |
86 | | // options |
87 | | #include "htsopt.h" |
88 | | |
89 | | // HTTrack engine sub-headers |
90 | | |
91 | | // main entry point |
92 | | #include "htscoremain.h" |
93 | | |
94 | | // core routines |
95 | | #include "htscore.h" |
96 | | |
97 | | // misc tools for httrack.c |
98 | | #include "htstools.h" |
99 | | |
100 | | // command-line help |
101 | | #include "htshelp.h" |
102 | | |
103 | | // build the on-disk save filename |
104 | | #include "htsname.h" |
105 | | |
106 | | // FTP support |
107 | | #include "htsftp.h" |
108 | | |
109 | | // URL interception |
110 | | #include "htscatchurl.h" |
111 | | |
112 | | // robots.txt handling |
113 | | #include "htsrobots.h" |
114 | | |
115 | | // link-acceptance rules |
116 | | #include "htswizard.h" |
117 | | |
118 | | // regexp/filter routines |
119 | | #include "htsfilters.h" |
120 | | |
121 | | // download backing (the back[] slot ring) |
122 | | #include "htsback.h" |
123 | | |
124 | | // cache handling |
125 | | #include "htscache.h" |
126 | | |
127 | | // hashing |
128 | | #include "htshash.h" |
129 | | #include "coucal.h" |
130 | | |
131 | | #include "htsdefines.h" |
132 | | |
133 | | #include "hts-indextmpl.h" |
134 | | |
135 | | /** A remote URL split into host and path, each a fixed inline buffer |
136 | | (HTS_URLMAXSIZE*2 bytes, NUL-terminated). */ |
137 | | #ifndef HTS_DEF_FWSTRUCT_lien_adrfil |
138 | | #define HTS_DEF_FWSTRUCT_lien_adrfil |
139 | | typedef struct lien_adrfil lien_adrfil; |
140 | | #endif |
141 | | struct lien_adrfil { |
142 | | char adr[HTS_URLMAXSIZE * 2]; /**< host (address) */ |
143 | | char fil[HTS_URLMAXSIZE * 2]; /**< remote file path */ |
144 | | }; |
145 | | |
146 | | /** A remote URL plus the local on-disk path it is saved to. */ |
147 | | #ifndef HTS_DEF_FWSTRUCT_lien_adrfilsave |
148 | | #define HTS_DEF_FWSTRUCT_lien_adrfilsave |
149 | | typedef struct lien_adrfilsave lien_adrfilsave; |
150 | | #endif |
151 | | struct lien_adrfilsave { |
152 | | lien_adrfil af; |
153 | | char save[HTS_URLMAXSIZE * 2]; /**< local save path (with directory) */ |
154 | | }; |
155 | | |
156 | | /** Per-slot connect-fallback bookkeeping (parallel to struct_back.lnk). |
157 | | Tracks which resolved address the slot is currently connecting to so a |
158 | | stuck connect can be retried against the next one. */ |
159 | | typedef struct hts_connect_fallback { |
160 | | int addr_index; /**< candidate being connected (0-based) */ |
161 | | int addr_count; /**< resolved addresses; -1 = not yet probed */ |
162 | | } hts_connect_fallback; |
163 | | |
164 | | /** The download-slot ring: the set of concurrent transfers in flight. |
165 | | Allocated/owned by the engine; consumers (status callbacks, the loop) |
166 | | read it but do not resize or free it. */ |
167 | | #ifndef HTS_DEF_FWSTRUCT_struct_back |
168 | | #define HTS_DEF_FWSTRUCT_struct_back |
169 | | typedef struct struct_back struct_back; |
170 | | #endif |
171 | | struct struct_back { |
172 | | lien_back *lnk; /**< slot array, valid indices [0..count-1] |
173 | | (count+1 entries allocated); a slot is |
174 | | active iff lnk[i].status != STATUS_FREE. |
175 | | See struct lien_back in htsopt.h and the |
176 | | STATUS_* codes in htsbasenet.h. */ |
177 | | int count; /**< number of usable slots (back_max) */ |
178 | | coucal ready; /**< index of slots whose transfer completed */ |
179 | | LLint ready_size_bytes; /**< total bytes buffered in completed slots */ |
180 | | hts_connect_fallback *connect_fallback; /**< per-slot, count+1 entries */ |
181 | | hts_fetch_meta *fetch; /**< per-slot Sec-Fetch-* values, count+1 entries */ |
182 | | hts_boolean bot_challenge_noted; /**< the bot-protection note is already in |
183 | | this mirror's log (#1732) */ |
184 | | TStamp retry_after_until; /**< Retry-After: no new launch before this local |
185 | | ms timestamp; 0 holds nothing */ |
186 | | }; |
187 | | |
188 | | /** Open handle to the mirror cache (the read-from-old / write-to-new state |
189 | | used to resume and to avoid re-fetching unchanged files). Engine-owned. */ |
190 | | #ifndef HTS_DEF_FWSTRUCT_cache_back |
191 | | #define HTS_DEF_FWSTRUCT_cache_back |
192 | | typedef struct cache_back cache_back; |
193 | | #endif |
194 | | struct cache_back { |
195 | | int version; /**< cache-file format version being read */ |
196 | | /* */ |
197 | | int type; |
198 | | int ro; /**< read-only: no new cache is written */ |
199 | | |
200 | | FILE *lst; /**< file list, used for purge */ |
201 | | FILE *txt; /**< human-readable file list (info) */ |
202 | | char lastmodified[256]; |
203 | | // HASH |
204 | | coucal hashtable; |
205 | | // HASH for tests (naming subsystem) |
206 | | coucal cached_tests; |
207 | | /** URLs whose previous entry this run already carried forward (#1421), so a |
208 | | retry of the same link does not store it again. */ |
209 | | coucal kept; |
210 | | /* optional log files */ |
211 | | FILE *log; |
212 | | FILE *errlog; |
213 | | /* read-ahead cursors into the old cache */ |
214 | | int ptr_ant; |
215 | | int ptr_last; |
216 | | /* ZIP-backed cache backend (newer format) */ |
217 | | void *zipInput; |
218 | | void *zipOutput; |
219 | | hts_boolean |
220 | | zipWriteFailed; /**< a cache write failed; stop touching the stream */ |
221 | | int zipWriteFailures; /**< consecutive entry write failures; reset on store */ |
222 | | }; |
223 | | |
224 | | #ifndef HTS_DEF_FWSTRUCT_hash_struct |
225 | | #define HTS_DEF_FWSTRUCT_hash_struct |
226 | | typedef struct hash_struct hash_struct; |
227 | | #endif |
228 | | /** Lookup indexes over the link heap: map save-name / URL back to a link, so a |
229 | | URL seen twice resolves to one entry. The coucal tables index into liens; |
230 | | they do not own the links. */ |
231 | | struct hash_struct { |
232 | | /* points at the engine's link array (opt->liens); not owned */ |
233 | | const lien_url *const*const*liens; |
234 | | /* save-name -> link index (case-insensitive: keys lowercased) */ |
235 | | coucal sav; |
236 | | /* address+path -> link index */ |
237 | | coucal adrfil; |
238 | | /* former address+path -> link index (renamed/moved entries) */ |
239 | | coucal former_adrfil; |
240 | | /* effective urlhack sub-flags: www.==host / // collapse / query-arg sort */ |
241 | | hts_boolean norm_host; |
242 | | hts_boolean norm_slash; |
243 | | hts_boolean norm_query; |
244 | | /* query-strip keys (not owned); set from opt->strip_query at hash_init */ |
245 | | const char *strip_query; |
246 | | /* host-alias rules (not owned); set from opt->host_alias at hash_init */ |
247 | | const char *host_alias; |
248 | | /* scratch: the hash key is a host plus a path, the compare one a path */ |
249 | | char normfil[HTS_URLMAXSIZE * 4]; |
250 | | char normfil2[HTS_URLMAXSIZE * 2]; |
251 | | char catbuff[CATBUFF_SIZE]; |
252 | | }; |
253 | | |
254 | | #ifndef HTS_DEF_FWSTRUCT_filecreate_params |
255 | | #define HTS_DEF_FWSTRUCT_filecreate_params |
256 | | typedef struct filecreate_params filecreate_params; |
257 | | #endif |
258 | | /** Parameters threaded through file-creation callbacks (filenote). */ |
259 | | struct filecreate_params { |
260 | | FILE *lst; /**< open file list to append created paths to */ |
261 | | char path[HTS_URLMAXSIZE * 2]; |
262 | | }; |
263 | | |
264 | | /* Convenience accessors over the link heap; assume `opt` (and where used, |
265 | | `ptr`/`parent_relative`/`module_base`) are in scope. heap(N) is the Nth link; |
266 | | heap_top_index() is the last recorded link's index. */ |
267 | 0 | #define heap(N) (opt->liens[N]) |
268 | | |
269 | 0 | #define heap_top_index() (opt->lien_tot - 1) |
270 | | |
271 | 0 | #define heap_top() (heap(heap_top_index())) |
272 | | |
273 | 0 | #define urladr() (heap(ptr)->adr) |
274 | | |
275 | 0 | #define urlfil() (heap(ptr)->fil) |
276 | | |
277 | 0 | #define savename() (heap(ptr)->sav) |
278 | | |
279 | 0 | #define parenturladr() (heap(heap(ptr)->precedent)->adr) |
280 | | |
281 | 0 | #define parenturlfil() (heap(heap(ptr)->precedent)->fil) |
282 | | |
283 | 0 | #define parentsavename() (heap(heap(ptr)->precedent)->sav) |
284 | | |
285 | | /* A module specifier takes the script's own base even in a .js document. */ |
286 | 0 | #define relative_to_parent() (parent_relative && !module_base) |
287 | | |
288 | 0 | #define relativeurladr() ((!relative_to_parent()) ? urladr() : parenturladr()) |
289 | | |
290 | 0 | #define relativeurlfil() ((!relative_to_parent()) ? urlfil() : parenturlfil()) |
291 | | |
292 | | #define relativesavename() \ |
293 | 0 | ((!relative_to_parent()) ? savename() : parentsavename()) |
294 | | |
295 | | /* Library-internal helpers (engine-only, HTS_INTERNAL_BYTECODE). */ |
296 | | #ifdef HTS_INTERNAL_BYTECODE |
297 | | |
298 | | /* True if a new cache is being written (plain or zip backend). */ |
299 | 0 | HTS_STATIC int cache_writable(cache_back * cache) { |
300 | 0 | return (cache != NULL && cache->zipOutput != NULL); |
301 | 0 | } Unexecuted instantiation: htslib.c:cache_writable Unexecuted instantiation: htsfetch.c:cache_writable Unexecuted instantiation: htswizard.c:cache_writable Unexecuted instantiation: htshash.c:cache_writable Unexecuted instantiation: htstools.c:cache_writable Unexecuted instantiation: htscore.c:cache_writable Unexecuted instantiation: htschanges.c:cache_writable Unexecuted instantiation: htscache.c:cache_writable Unexecuted instantiation: htsback.c:cache_writable Unexecuted instantiation: htsftp.c:cache_writable Unexecuted instantiation: htsname.c:cache_writable Unexecuted instantiation: htscodec.c:cache_writable Unexecuted instantiation: htszlib.c:cache_writable Unexecuted instantiation: htswarc.c:cache_writable Unexecuted instantiation: htsbundle.c:cache_writable Unexecuted instantiation: htsbauth.c:cache_writable Unexecuted instantiation: htspsl.c:cache_writable Unexecuted instantiation: htscoremain.c:cache_writable Unexecuted instantiation: htscatchurl.c:cache_writable Unexecuted instantiation: htsproxy.c:cache_writable Unexecuted instantiation: htsrobots.c:cache_writable Unexecuted instantiation: htssitemap.c:cache_writable Unexecuted instantiation: htsparse.c:cache_writable Unexecuted instantiation: htssinglefile.c:cache_writable Unexecuted instantiation: htsselftest.c:cache_writable Unexecuted instantiation: htsback_selftest.c:cache_writable Unexecuted instantiation: htsselftest_util.c:cache_writable Unexecuted instantiation: htscache_selftest.c:cache_writable Unexecuted instantiation: htscharset_selftest.c:cache_writable Unexecuted instantiation: htscmdline_selftest.c:cache_writable Unexecuted instantiation: htscookie_selftest.c:cache_writable Unexecuted instantiation: htsdns_selftest.c:cache_writable Unexecuted instantiation: htsfetch_selftest.c:cache_writable Unexecuted instantiation: htspsl_selftest.c:cache_writable Unexecuted instantiation: htsbundle_selftest.c:cache_writable Unexecuted instantiation: htsfilters_selftest.c:cache_writable Unexecuted instantiation: htsheader_selftest.c:cache_writable Unexecuted instantiation: htsio_selftest.c:cache_writable Unexecuted instantiation: htslib_selftest.c:cache_writable Unexecuted instantiation: htslines_selftest.c:cache_writable Unexecuted instantiation: htsmime_selftest.c:cache_writable Unexecuted instantiation: htsname_selftest.c:cache_writable Unexecuted instantiation: htsnet_selftest.c:cache_writable Unexecuted instantiation: htsopt_selftest.c:cache_writable Unexecuted instantiation: htsparse_selftest.c:cache_writable Unexecuted instantiation: htstools_selftest.c:cache_writable Unexecuted instantiation: htswarc_selftest.c:cache_writable Unexecuted instantiation: htswizard_selftest.c:cache_writable |
302 | | |
303 | | /* True if an old cache is available to read (plain or zip backend). */ |
304 | 0 | HTS_STATIC int cache_readable(cache_back * cache) { |
305 | 0 | return (cache != NULL && cache->zipInput != NULL); |
306 | 0 | } Unexecuted instantiation: htslib.c:cache_readable Unexecuted instantiation: htsfetch.c:cache_readable Unexecuted instantiation: htswizard.c:cache_readable Unexecuted instantiation: htshash.c:cache_readable Unexecuted instantiation: htstools.c:cache_readable Unexecuted instantiation: htscore.c:cache_readable Unexecuted instantiation: htschanges.c:cache_readable Unexecuted instantiation: htscache.c:cache_readable Unexecuted instantiation: htsback.c:cache_readable Unexecuted instantiation: htsftp.c:cache_readable Unexecuted instantiation: htsname.c:cache_readable Unexecuted instantiation: htscodec.c:cache_readable Unexecuted instantiation: htszlib.c:cache_readable Unexecuted instantiation: htswarc.c:cache_readable Unexecuted instantiation: htsbundle.c:cache_readable Unexecuted instantiation: htsbauth.c:cache_readable Unexecuted instantiation: htspsl.c:cache_readable Unexecuted instantiation: htscoremain.c:cache_readable Unexecuted instantiation: htscatchurl.c:cache_readable Unexecuted instantiation: htsproxy.c:cache_readable Unexecuted instantiation: htsrobots.c:cache_readable Unexecuted instantiation: htssitemap.c:cache_readable Unexecuted instantiation: htsparse.c:cache_readable Unexecuted instantiation: htssinglefile.c:cache_readable Unexecuted instantiation: htsselftest.c:cache_readable Unexecuted instantiation: htsback_selftest.c:cache_readable Unexecuted instantiation: htsselftest_util.c:cache_readable Unexecuted instantiation: htscache_selftest.c:cache_readable Unexecuted instantiation: htscharset_selftest.c:cache_readable Unexecuted instantiation: htscmdline_selftest.c:cache_readable Unexecuted instantiation: htscookie_selftest.c:cache_readable Unexecuted instantiation: htsdns_selftest.c:cache_readable Unexecuted instantiation: htsfetch_selftest.c:cache_readable Unexecuted instantiation: htspsl_selftest.c:cache_readable Unexecuted instantiation: htsbundle_selftest.c:cache_readable Unexecuted instantiation: htsfilters_selftest.c:cache_readable Unexecuted instantiation: htsheader_selftest.c:cache_readable Unexecuted instantiation: htsio_selftest.c:cache_readable Unexecuted instantiation: htslib_selftest.c:cache_readable Unexecuted instantiation: htslines_selftest.c:cache_readable Unexecuted instantiation: htsmime_selftest.c:cache_readable Unexecuted instantiation: htsname_selftest.c:cache_readable Unexecuted instantiation: htsnet_selftest.c:cache_readable Unexecuted instantiation: htsopt_selftest.c:cache_readable Unexecuted instantiation: htsparse_selftest.c:cache_readable Unexecuted instantiation: htstools_selftest.c:cache_readable Unexecuted instantiation: htswarc_selftest.c:cache_readable Unexecuted instantiation: htswizard_selftest.c:cache_readable |
307 | | |
308 | | #endif |
309 | | |
310 | | // Functions |
311 | | |
312 | | /* Library-internal only (engine TUs). */ |
313 | | #ifdef HTS_INTERNAL_BYTECODE |
314 | | |
315 | | char *hts_cancel_file_pop(httrackp * opt); |
316 | | |
317 | | /* Detach the pending hts_addurl() list and give the caller ownership; NULL |
318 | | when none is pending. Free it with hts_addurl_free(). */ |
319 | | char **hts_addurl_take(httrackp *opt); |
320 | | |
321 | | /* Free a list taken with hts_addurl_take(), strings included. */ |
322 | | void hts_addurl_free(char **url); |
323 | | |
324 | | /* Detach the queued rules. Returns NULL if none. The caller frees the list |
325 | | with hts_addurl_free(). */ |
326 | | char **hts_addfilter_take(httrackp *opt); |
327 | | |
328 | | /* Takes the list hts_setfilters() queued, like hts_addfilter_take(). */ |
329 | | char **hts_setfilters_take(httrackp *opt); |
330 | | |
331 | | #endif |
332 | | |
333 | | /* Has the -#L cap left fewer than two free slots? One parser step records |
334 | | robots.txt and then the link itself, so both must still fit. */ |
335 | | hts_boolean hts_maxlinks_no_room(const httrackp *opt); |
336 | | |
337 | | /* Record a link on the heap. All strings are copied (caller keeps ownership). |
338 | | Returns 1 on success, 0 if the link limit (opt->maxlink) is reached. */ |
339 | | int hts_record_link(httrackp * opt, |
340 | | const char *address, const char *file, const char *save, |
341 | | const char *ref_address, const char *ref_file, |
342 | | const char *codebase); |
343 | | |
344 | | /* Index of the most recently recorded link. */ |
345 | | size_t hts_record_link_latest(httrackp *opt); |
346 | | |
347 | | /* Mark link at index lpos as not to be processed (sets pass2 = -1). */ |
348 | | void hts_invalidate_link(httrackp * opt, int lpos); |
349 | | |
350 | | /* Allocates the link heap if absent, and returns HTS_FALSE without memory. */ |
351 | | hts_boolean hts_record_init(httrackp *opt); |
352 | | |
353 | | void hts_record_free(httrackp *opt); |
354 | | |
355 | | /* Load the -%L file at path into *buff, NUL-terminated after its *size bytes, |
356 | | to be freed with freet(). Returns NULL, or why it could not be read, and then |
357 | | *buff is NULL. The reason may be written in errbuf, of HTS_STRERROR_SIZE |
358 | | bytes. */ |
359 | | const char *hts_urllist_load(const char *path, char **buff, size_t *size, |
360 | | char *errbuf); |
361 | | |
362 | | /* The size of the line buffer hts_urllist_next() fills. */ |
363 | | #define HTS_URLLIST_LINE_SIZE (HTS_URLMAXSIZE * 2) |
364 | | |
365 | | typedef enum hts_urllist_status { |
366 | | HTS_URLLIST_END, /* no line is left */ |
367 | | HTS_URLLIST_LINE, /* line holds the next line */ |
368 | | HTS_URLLIST_LONG, /* the line is longer than HTS_URLMAXSIZE bytes */ |
369 | | HTS_URLLIST_NUL /* the line holds a NUL byte */ |
370 | | } hts_urllist_status; |
371 | | |
372 | | /* Read the next -%L line of buff at *pos, and move *pos past it. Returns how |
373 | | the line ended. line holds the head of a LONG or NUL line, which the crawl |
374 | | drops. */ |
375 | | hts_urllist_status hts_urllist_next(const char *buff, size_t size, size_t *pos, |
376 | | char line[HTS_URLLIST_LINE_SIZE]); |
377 | | |
378 | | /* Run the mirror for the given start URL(s) under opt. Top-level engine entry. |
379 | | Returns 1 once the crawl loop ran, 0 or -1 for a bailout. *completed says |
380 | | whether it reached the end: false for a bailout, and for any stop that cut it |
381 | | short, however it arrived (state.stop or exit_xh). */ |
382 | | int httpmirror(char *url1, httrackp *opt, hts_boolean *completed); |
383 | | |
384 | | /* Start the stats clock HTS_STAT.stat_timestart (seconds) and the --max-time |
385 | | clock hts_mirror_elapsed_ms(). */ |
386 | | void hts_mirror_clock_start(void); |
387 | | |
388 | | /* Return the time since hts_mirror_clock_start(), in monotonic ms. */ |
389 | | TStamp hts_mirror_elapsed_ms(void); |
390 | | |
391 | | /* Write len bytes of adr to local path s. url_adr/url_fil (may be NULL) name |
392 | | the source URL for logging/notification. */ |
393 | | int filesave(httrackp * opt, const char *adr, int len, const char *s, |
394 | | const char *url_adr /* = NULL */ , |
395 | | const char *url_fil /* = NULL */ ); |
396 | | |
397 | | char *hts_cancel_file_pop(httrackp * opt); |
398 | | |
399 | | int check_fatal_io_errno(void); |
400 | | |
401 | | int engine_stats(void); |
402 | | |
403 | | void host_ban(httrackp * opt, int ptr, struct_back * sback, const char *host); |
404 | | |
405 | | /* Open local file s for writing (filecreate, truncate) or appending |
406 | | (fileappend), creating parent directories as needed. Return an open FILE* |
407 | | the caller must fclose(), or NULL on failure. */ |
408 | | FILE *filecreate(filenote_strc * strct, const char *s); |
409 | | |
410 | | FILE *fileappend(filenote_strc * strct, const char *s); |
411 | | |
412 | | /* Create an empty file, return 1 on success, 0 on failure. */ |
413 | | int filecreateempty(filenote_strc * strct, const char *filename); |
414 | | |
415 | | int filenote(filenote_strc * strct, const char *s, filecreate_params * params); |
416 | | |
417 | | /* Copy into dest (destsize bytes) the form under which the local path s is |
418 | | listed in new.lst: forward slashes, with the mirror `root` stripped when s |
419 | | sits under it. Also the change report's key, so the two must not drift. */ |
420 | | void hts_savename_listed(const char *root, const char *s, char *dest, |
421 | | size_t destsize); |
422 | | |
423 | | void file_notify(httrackp * opt, const char *adr, const char *fil, |
424 | | const char *save, int create, int modify, int wasupdated); |
425 | | |
426 | | void usercommand(httrackp * opt, int exe, const char *cmd, const char *file, |
427 | | const char *adr, const char *fil); |
428 | | |
429 | | /* usercommand_expand() verdicts; only OK may be run. */ |
430 | 0 | #define USERCOMMAND_EXPAND_OK 1 |
431 | 0 | #define USERCOMMAND_EXPAND_TOOLONG 0 |
432 | 0 | #define USERCOMMAND_EXPAND_REFUSED (-1) |
433 | | /* Rewrite a -V template's $0. On POSIX "file" is ignored: usercommand_exe() |
434 | | passes it to the shell as $1, so the rewrite does not depend on it. */ |
435 | | int usercommand_expand(char *dest, size_t size, const char *cmd, |
436 | | const char *file, const char **why); |
437 | | /* Run a -V template against a save name; returns the shell's exit status, or |
438 | | -1 when the command was not run at all. */ |
439 | | int usercommand_exe(httrackp *opt, const char *cmd, const char *file); |
440 | | #ifndef _WIN32 |
441 | | /* Room for "sh", "-c", the command, the shell's $0, its $1 and the NULL. */ |
442 | | #define USERCOMMAND_ARGV_MAX 6 |
443 | | size_t usercommand_argv(char *argv[USERCOMMAND_ARGV_MAX], const char *command, |
444 | | const char *file); |
445 | | #endif |
446 | | |
447 | | // Finish the makeindex index.html (footer + refresh meta), run usercommand. |
448 | | // Updates *makeindex_done/*makeindex_fp in place; adr/fil are the mode strings. |
449 | | void hts_finish_makeindex(httrackp *opt, int *makeindex_done, |
450 | | FILE **makeindex_fp, int makeindex_links, |
451 | | const char *makeindex_firstlink, |
452 | | const char *template_footer, const char *adr, |
453 | | const char *fil); |
454 | | |
455 | | /* Re-encode 'size' bytes of UCS2 (UTF-16, BMP only) as UTF-8. 'swap' selects |
456 | | little-endian input, 'size' must be even. Returns a NUL-terminated buffer to |
457 | | release with freet(), its length (NUL excluded) in *outsize, or NULL when the |
458 | | result does not fit memory. */ |
459 | | char *hts_ucs2_to_utf8(const unsigned char *src, size_t size, hts_boolean swap, |
460 | | size_t *outsize); |
461 | | |
462 | | // Flush ht_buff[0..ht_len] to save on disk; *fp closed+NULLed on write. |
463 | | // Precondition: ht_len>0. |
464 | | void hts_finish_html_file(httrackp *opt, cache_back *cache, htsblk *r, |
465 | | FILE **fp, const char *ht_buff, size_t ht_len, |
466 | | const char *adr, const char *fil, const char *save); |
467 | | |
468 | | /* Longest suffix a rule builder appends after the path (the wizard's |
469 | | "*[file]"), NUL included; asserted against in htswizard.c. */ |
470 | 0 | #define HTS_FILTER_SUFFIX_MAX 8 |
471 | | |
472 | | /* Per-slot capacity of the filters array; filters_init() strides the slots by |
473 | | it. Holds the longest rule any builder emits, because truncating one changes |
474 | | what it matches. */ |
475 | | #define HTS_FILTER_SLOT_SIZE \ |
476 | 0 | (1 + (HTS_URLMAXSIZE * 2 - 1) + 1 + (HTS_URLMAXSIZE * 2 - 1) + \ |
477 | 0 | HTS_FILTER_SUFFIX_MAX) |
478 | | |
479 | | /* Largest -#F, and the largest filter list that may still grow by |
480 | | HTS_FILTERSINC, because the list's byte size must fit an int. */ |
481 | 0 | #define HTS_FILTERS_MAX (INT_MAX / HTS_FILTER_SLOT_SIZE - HTS_FILTERSINC - 2) |
482 | | |
483 | | int filters_init(char ***ptrfilters, int maxfilter, int filterinc); |
484 | | |
485 | | /* Binds this crawl's filter array to `opt`, and empties the wizard block with |
486 | | it: opt->wizard_filters indexes into that array and outlives no crawl. */ |
487 | | void filters_bind(httrackp *opt, char ***ptrfilters, int *filptr); |
488 | | |
489 | | /* Longest rule a slot holds and the matcher still looks at. */ |
490 | | #define HTS_FILTER_MAXLEN \ |
491 | 0 | (HTS_FILTER_SLOT_SIZE - 1 < STRJOKER_MAXLEN ? HTS_FILTER_SLOT_SIZE - 1 \ |
492 | 0 | : STRJOKER_MAXLEN) |
493 | | |
494 | | /* Stores `pattern` at `pos`, shifting the rules from there up a slot. The one |
495 | | door into the array: a rule past HTS_FILTER_MAXLEN, or one that finds the |
496 | | array full, warns and returns HTS_FALSE, never stored dead (#1270). */ |
497 | | hts_boolean filters_insert(httrackp *opt, int pos, const char *pattern); |
498 | | |
499 | | /* Remove the n rules starting at pos, shifting the rest down. */ |
500 | | void filters_remove(httrackp *opt, int pos, int n); |
501 | | |
502 | | /* Can a filter array of maxfilter rules grow by HTS_FILTERSINC? */ |
503 | | hts_boolean filters_may_grow(int maxfilter); |
504 | | |
505 | | /* Makes room for n more rules. Returns HTS_FALSE, having logged it, only when |
506 | | memory runs out. At the HTS_FILTERS_MAX cap it returns HTS_TRUE and |
507 | | filters_insert() drops what does not fit. */ |
508 | | hts_boolean filters_grow(httrackp *opt, int n); |
509 | | |
510 | | /* Same as filters_grow(), but aborts when memory runs out. */ |
511 | | void filters_make_room(httrackp *opt, int n); |
512 | | |
513 | | /* Returns the fa_strjoker_dual() verdict of the nfil filters on adr+fil, in |
514 | | both forms the wizard tests, and sets *depth when depth is not NULL. */ |
515 | | int filters_match_url(char **filters, int nfil, const char *adr, |
516 | | const char *fil, int *depth); |
517 | | |
518 | | /* Apply the queued list and rules to the user's rules, then drop the queued |
519 | | links after ptr that the change makes them refuse. Crawl thread only, as it |
520 | | alone reads the filters. */ |
521 | | void hts_apply_live_filters(httrackp *opt, struct_back *sback, int ptr); |
522 | | |
523 | | int fspc(httrackp * opt, FILE * fp, const char *type); |
524 | | /* Count one log event into opt's counters that hts_get_stats() publishes, |
525 | | whether or not a log file is open. "panic" counts as an error. */ |
526 | | void fspc_count(httrackp *opt, const char *type); |
527 | | |
528 | | /* Like fil_normalized(), but first drops query keys in STRIP (comma-separated, |
529 | | "*" = all); STRIP NULL/empty behaves exactly like fil_normalized(). */ |
530 | | char *fil_normalized_filtered(const char *source, char *dest, |
531 | | const char *strip); |
532 | | |
533 | | /* As fil_normalized_filtered(), but DO_SLASH/DO_QUERY gate the // collapse and |
534 | | the query-argument sort independently (the urlhack sub-flags). */ |
535 | | char *fil_normalized_filtered_ex(const char *source, char *dest, |
536 | | const char *strip, int do_slash, int do_query); |
537 | | |
538 | | /* For URL ADR/FIL, return (in DEST) the comma keylist to strip from the |
539 | | '\n'-separated "[pattern=]keys" RULES (patterns matched on host/path via |
540 | | strjoker, last wins); NULL if none match. Feeds fil_normalized_filtered(). */ |
541 | | const char *hts_query_strip_keys(const char *rules, const char *adr, |
542 | | const char *fil, char *dest, size_t destsize); |
543 | | |
544 | | /* Is the key ARG[0..KEYLEN) in the comma list STRIP? Tokens are space-trimmed |
545 | | and case-sensitive, and "*" matches any key. */ |
546 | | hts_boolean hts_query_key_stripped(const char *arg, size_t keylen, |
547 | | const char *strip); |
548 | | |
549 | | /* Return the canonical host (length *CANONLEN) of the last RULES entry whose |
550 | | aliases match HOST or FULL ("scheme://host"), or NULL. COLLAPSE_WWW ignores |
551 | | a "www." prefix on both sides. */ |
552 | | const char *hts_host_alias_match(const char *rules, const char *host, |
553 | | const char *full, hts_boolean collapse_www, |
554 | | size_t *canonlen); |
555 | | |
556 | | /* The --host-alias rules of OPT, or NULL when the option was not given. */ |
557 | | const char *hts_host_alias_rules(httrackp *opt); |
558 | | |
559 | | /* ADR with its host replaced by the canonical one, from the '\n'-separated |
560 | | "alias[,alias...]=canonical" RULES (aliases matched with strjoker, last |
561 | | wins). NOWWW matches the host with its www. prefix collapsed, as -%u keys it. |
562 | | Chains are followed to their end, so the result is a fixpoint. Scheme and |
563 | | credentials are kept. NULL when no rule applies, the mapping is a no-op, the |
564 | | rules loop, or the result would not fit DEST. */ |
565 | | const char *hts_host_alias(const char *rules, const char *adr, |
566 | | hts_boolean collapse_www, char *dest, |
567 | | size_t destsize); |
568 | | |
569 | | /* Resolve like hts_host_alias, and set *SETTLED, when SETTLED is not NULL, to |
570 | | whether the chain ended within the hop limit. Exposed for the -#test=spandiff |
571 | | test. */ |
572 | | const char *hts_host_alias_resolve(const char *rules, const char *adr, |
573 | | hts_boolean collapse_www, char *dest, |
574 | | size_t destsize, hts_boolean *settled); |
575 | | |
576 | | /* HTS_TRUE when OPT's url hacks collapse www.host onto host. */ |
577 | | hts_boolean hts_host_alias_collapse_www(httrackp *opt); |
578 | | |
579 | | /* Rewrite AF's host to its --host-alias canonical form, in place, and return |
580 | | it. Idempotent; returns af->adr unchanged when no rule applies. */ |
581 | | const char *hts_host_alias_fold(httrackp *opt, lien_adrfil *af); |
582 | | |
583 | | /* HTS_TRUE if ADRA and ADRB name the same host once RULES are applied. */ |
584 | | hts_boolean hts_host_same_alias(const char *rules, const char *adra, |
585 | | const char *adrb, hts_boolean collapse_www); |
586 | | |
587 | | /* First canonical host in RULES whose chain never ends ("a=b" plus "b=a"), |
588 | | copied into DEST, or NULL if every chain settles. Those hosts are left |
589 | | unaliased, so the engine reports them rather than picking a hop. */ |
590 | | const char *hts_host_alias_looping(const char *rules, hts_boolean collapse_www, |
591 | | char *dest, size_t destsize); |
592 | | |
593 | | /* Read a whole file into a freshly malloc'd, NUL-terminated buffer; the caller |
594 | | owns it and must release it with freet(). Return NULL on missing/unreadable |
595 | | file (readfile_or substitutes defaultdata instead). The byte content is NOT |
596 | | transcoded except readfile_utf8, which expects a UTF-8 path. readfile2 |
597 | | reports the byte size (excluding the NUL) via *size when non-NULL. */ |
598 | | char *readfile(const char *fil); |
599 | | |
600 | | char *readfile2(const char *fil, LLint * size); |
601 | | |
602 | | /* readfile2() refusing a body too large for the int indexes downstream, on the |
603 | | same stat that sizes the read: a caller checking the size itself would leave |
604 | | a window for the file to grow. NULL when it does not fit. "fil" is UTF-8, |
605 | | as a mirror path is. */ |
606 | | char *readfile2_inmem(const char *fil, LLint *size); |
607 | | |
608 | | char *readfile_utf8(const char *fil); |
609 | | |
610 | | char *readfile2_utf8(const char *fil, LLint *size); |
611 | | |
612 | | char *readfile_or(const char *fil, const char *defaultdata); |
613 | | |
614 | | /* Backing (download-slot) scheduler. Operate on the back[] ring (struct_back). |
615 | | Not thread-safe; call from the single crawl loop. */ |
616 | | |
617 | | /* True if a connecting slot should give up on the current address and try the |
618 | | next one: a fallback address remains (addr_index+1 < addr_count) and the |
619 | | candidate has been connecting for at least its deadline, min(timeout, an |
620 | | internal cap). elapsed/timeout in seconds. Exposed for the -#D self-test. */ |
621 | | int back_connect_fallback_due(int addr_index, int addr_count, int elapsed, |
622 | | int timeout); |
623 | | |
624 | | /* How many new sockets may be opened now, honoring maxsoc and the maxconn rate |
625 | | limit (>=0). _strict ignores reserved-slot headroom; the plain form leaves |
626 | | room for naming tests and stops at 0 when the stack is nearly full. */ |
627 | | int back_pluggable_sockets(struct_back * sback, httrackp * opt); |
628 | | |
629 | | int back_pluggable_sockets_strict(struct_back * sback, httrackp * opt); |
630 | | |
631 | | /* One engine-loop tick: refresh the transfer stats and run the loop callback |
632 | | for slot b (-1 = none). HTS_FALSE = the callback requested an abort. */ |
633 | | hts_boolean hts_loop_tick(struct_back *sback, httrackp *opt, int b, int ptr); |
634 | | |
635 | | /* Wait until a test socket can be plugged, pumping transfers, stats and the |
636 | | loop callback; gives up past the -E deadline. HTS_FALSE = callback abort. */ |
637 | | hts_boolean hts_wait_available_socket(struct_back *sback, httrackp *opt, |
638 | | cache_back *cache, int ptr); |
639 | | |
640 | | /* Randomized inter-file pause target in [min_ms,max_ms] (#185), derived from a |
641 | | timestamp seed so it is stable within one gap and rerolls per launch. */ |
642 | | int hts_pause_target_ms(TStamp seed, int min_ms, int max_ms); |
643 | | |
644 | | /* Withhold every new launch for `seconds`, clipped to opt->max_retry_after. |
645 | | A hold already running further out is kept. */ |
646 | | void back_set_retry_after(struct_back *sback, httrackp *opt, int seconds); |
647 | | |
648 | | /* Schedule more links from the heap into free slots. Returns the number queued, |
649 | | or <=0 if none could be added (no free slot / paused / stopped). */ |
650 | | int back_fill(struct_back * sback, httrackp * opt, cache_back * cache, |
651 | | int ptr, int numero_passe); |
652 | | |
653 | | /* Count of links already finished (in background or served from cache). */ |
654 | | int backlinks_done(const struct_back *sback, lien_url **liens, int lien_tot, |
655 | | int ptr); |
656 | | |
657 | | /* Like back_fill, but a no-op (returns -1) when in-memory buffered data already |
658 | | exceeds opt->maxcache. */ |
659 | | int back_fillmax(struct_back * sback, httrackp * opt, cache_back * cache, |
660 | | int ptr, int numero_passe); |
661 | | |
662 | | /* Interactive prompt: continue an interrupted mirror? Returns nonzero to go on. |
663 | | */ |
664 | | int ask_continue(httrackp * opt); |
665 | | |
666 | | /* Number of decimal digits in n. */ |
667 | | int nombre_digit(int n); |
668 | | |
669 | | // Polling |
670 | | #if HTS_POLL |
671 | | int check_flot(T_SOC s); |
672 | | |
673 | | int check_stdin(void); |
674 | | #endif |
675 | | /* Nonzero if the socket has a pending error. */ |
676 | | int check_sockerror(T_SOC s); |
677 | | |
678 | | /* external modules: register a link discovered by a parser plugin. */ |
679 | | int htsAddLink(htsmoduleStruct * str, char *link); |
680 | | |
681 | | /* Worst-case byte expansion HT_ADD_HTMLESCAPED* must reserve per escaper. */ |
682 | 0 | #define HTS_HTMLESCAPE_MAXEXP 5 /* escape_for_html_print: '&'->"&" */ |
683 | 0 | #define HTS_HTMLESCAPE_FULL_MAXEXP 6 /* _full: high byte->"&#xHH;" */ |
684 | | |
685 | | #endif |