Coverage Report

Created: 2026-09-04 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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 <sys/types.h>
45
#include <sys/stat.h>
46
#ifdef _WIN32
47
#include <conio.h>
48
#include <direct.h>
49
#else
50
#ifndef _WIN32
51
#include <unistd.h>
52
#endif
53
#endif
54
/* END specific definitions */
55
56
/* Forward definitions */
57
#ifndef HTS_DEF_FWSTRUCT_lien_url
58
#define HTS_DEF_FWSTRUCT_lien_url
59
typedef struct lien_url lien_url;
60
#endif
61
#ifndef HTS_DEF_FWSTRUCT_lien_back
62
#define HTS_DEF_FWSTRUCT_lien_back
63
typedef struct lien_back lien_back;
64
#endif
65
#ifndef HTS_DEF_FWSTRUCT_struct_back
66
#define HTS_DEF_FWSTRUCT_struct_back
67
typedef struct struct_back struct_back;
68
#endif
69
#ifndef HTS_DEF_FWSTRUCT_cache_back
70
#define HTS_DEF_FWSTRUCT_cache_back
71
typedef struct cache_back cache_back;
72
#endif
73
#ifndef HTS_DEF_FWSTRUCT_hash_struct
74
#define HTS_DEF_FWSTRUCT_hash_struct
75
typedef struct hash_struct hash_struct;
76
#endif
77
#ifndef HTS_DEF_FWSTRUCT_filecreate_params
78
#define HTS_DEF_FWSTRUCT_filecreate_params
79
typedef struct filecreate_params filecreate_params;
80
#endif
81
82
// Include htslib.h for all types
83
#include "htslib.h"
84
85
// options
86
#include "htsopt.h"
87
88
// HTTrack engine sub-headers
89
90
// main entry point
91
#include "htscoremain.h"
92
93
// core routines
94
#include "htscore.h"
95
96
// misc tools for httrack.c
97
#include "htstools.h"
98
99
// command-line help
100
#include "htshelp.h"
101
102
// build the on-disk save filename
103
#include "htsname.h"
104
105
// FTP support
106
#include "htsftp.h"
107
108
// URL interception
109
#include "htscatchurl.h"
110
111
// robots.txt handling
112
#include "htsrobots.h"
113
114
// link-acceptance rules
115
#include "htswizard.h"
116
117
// regexp/filter routines
118
#include "htsfilters.h"
119
120
// download backing (the back[] slot ring)
121
#include "htsback.h"
122
123
// cache handling
124
#include "htscache.h"
125
126
// hashing
127
#include "htshash.h"
128
#include "coucal.h"
129
130
#include "htsdefines.h"
131
132
#include "hts-indextmpl.h"
133
134
/** A remote URL split into host and path, each a fixed inline buffer
135
    (HTS_URLMAXSIZE*2 bytes, NUL-terminated). */
136
#ifndef HTS_DEF_FWSTRUCT_lien_adrfil
137
#define HTS_DEF_FWSTRUCT_lien_adrfil
138
typedef struct lien_adrfil lien_adrfil;
139
#endif
140
struct lien_adrfil {
141
  char adr[HTS_URLMAXSIZE * 2]; /**< host (address) */
142
  char fil[HTS_URLMAXSIZE * 2]; /**< remote file path */
143
};
144
145
/** A remote URL plus the local on-disk path it is saved to. */
146
#ifndef HTS_DEF_FWSTRUCT_lien_adrfilsave
147
#define HTS_DEF_FWSTRUCT_lien_adrfilsave
148
typedef struct lien_adrfilsave lien_adrfilsave;
149
#endif
150
struct lien_adrfilsave {
151
  lien_adrfil af;
152
  char save[HTS_URLMAXSIZE * 2]; /**< local save path (with directory) */
153
};
154
155
/** Per-slot connect-fallback bookkeeping (parallel to struct_back.lnk).
156
    Tracks which resolved address the slot is currently connecting to so a
157
    stuck connect can be retried against the next one. */
158
typedef struct hts_connect_fallback {
159
  int addr_index;       /**< candidate being connected (0-based) */
160
  int addr_count;       /**< resolved addresses; -1 = not yet probed */
161
  TStamp connect_start; /**< when the current candidate's connect began */
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
};
182
183
/** Open handle to the mirror cache (the read-from-old / write-to-new state
184
    used to resume and to avoid re-fetching unchanged files). Engine-owned. */
185
#ifndef HTS_DEF_FWSTRUCT_cache_back
186
#define HTS_DEF_FWSTRUCT_cache_back
187
typedef struct cache_back cache_back;
188
#endif
189
struct cache_back {
190
  int version; /**< cache-file format version being read */
191
  /* */
192
  int type;
193
  int ro;                   /**< read-only: no new cache is written */
194
195
  FILE *lst;                /**< file list, used for purge */
196
  FILE *txt;                /**< human-readable file list (info) */
197
  char lastmodified[256];
198
  // HASH
199
  coucal hashtable;
200
  // HASH for tests (naming subsystem)
201
  coucal cached_tests;
202
  /** URLs whose previous entry this run already carried forward (#1421), so a
203
      retry of the same link does not store it again. */
204
  coucal kept;
205
  /* optional log files */
206
  FILE *log;
207
  FILE *errlog;
208
  /* read-ahead cursors into the old cache */
209
  int ptr_ant;
210
  int ptr_last;
211
  /* ZIP-backed cache backend (newer format) */
212
  void *zipInput;
213
  void *zipOutput;
214
  hts_boolean
215
      zipWriteFailed; /**< a cache write failed; stop touching the stream */
216
  int zipWriteFailures; /**< consecutive entry write failures; reset on store */
217
};
218
219
#ifndef HTS_DEF_FWSTRUCT_hash_struct
220
#define HTS_DEF_FWSTRUCT_hash_struct
221
typedef struct hash_struct hash_struct;
222
#endif
223
/** Lookup indexes over the link heap: map save-name / URL back to a link, so a
224
    URL seen twice resolves to one entry. The coucal tables index into liens;
225
    they do not own the links. */
226
struct hash_struct {
227
  /* points at the engine's link array (opt->liens); not owned */
228
  const lien_url *const*const*liens;
229
  /* save-name -> link index (case-insensitive: keys lowercased) */
230
  coucal sav;
231
  /* address+path -> link index */
232
  coucal adrfil;
233
  /* former address+path -> link index (renamed/moved entries) */
234
  coucal former_adrfil;
235
  /* effective urlhack sub-flags: www.==host / // collapse / query-arg sort */
236
  hts_boolean norm_host;
237
  hts_boolean norm_slash;
238
  hts_boolean norm_query;
239
  /* query-strip keys (not owned); set from opt->strip_query at hash_init */
240
  const char *strip_query;
241
  /* host-alias rules (not owned); set from opt->host_alias at hash_init */
242
  const char *host_alias;
243
  /* scratch: the hash key is a host plus a path, the compare one a path */
244
  char normfil[HTS_URLMAXSIZE * 4];
245
  char normfil2[HTS_URLMAXSIZE * 2];
246
  char catbuff[CATBUFF_SIZE];
247
};
248
249
#ifndef HTS_DEF_FWSTRUCT_filecreate_params
250
#define HTS_DEF_FWSTRUCT_filecreate_params
251
typedef struct filecreate_params filecreate_params;
252
#endif
253
/** Parameters threaded through file-creation callbacks (filenote). */
254
struct filecreate_params {
255
  FILE *lst; /**< open file list to append created paths to */
256
  char path[HTS_URLMAXSIZE * 2];
257
};
258
259
/* Convenience accessors over the link heap; assume `opt` (and where used,
260
   `ptr`/`parent_relative`) are in scope. heap(N) is the Nth link;
261
   heap_top_index() is the last recorded link's index. */
262
0
#define heap(N)            (opt->liens[N])
263
264
0
#define heap_top_index()   (opt->lien_tot - 1)
265
266
0
#define heap_top()         (heap(heap_top_index()))
267
268
0
#define urladr()           (heap(ptr)->adr)
269
270
0
#define urlfil()           (heap(ptr)->fil)
271
272
0
#define savename()         (heap(ptr)->sav)
273
274
0
#define parenturladr()     (heap(heap(ptr)->precedent)->adr)
275
276
0
#define parenturlfil()     (heap(heap(ptr)->precedent)->fil)
277
278
0
#define parentsavename()   (heap(heap(ptr)->precedent)->sav)
279
280
0
#define relativeurladr()   ((!parent_relative)?urladr():parenturladr())
281
282
0
#define relativeurlfil()   ((!parent_relative)?urlfil():parenturlfil())
283
284
0
#define relativesavename() ((!parent_relative)?savename():parentsavename())
285
286
/* Library-internal helpers (engine-only, HTS_INTERNAL_BYTECODE). */
287
#ifdef HTS_INTERNAL_BYTECODE
288
289
/* True if a new cache is being written (plain or zip backend). */
290
0
HTS_STATIC int cache_writable(cache_back * cache) {
291
0
  return (cache != NULL && cache->zipOutput != NULL);
292
0
}
Unexecuted instantiation: fuzz-url.c:cache_writable
Unexecuted instantiation: htslib.c:cache_writable
Unexecuted instantiation: htscore.c:cache_writable
Unexecuted instantiation: htshash.c:cache_writable
Unexecuted instantiation: htscache.c:cache_writable
Unexecuted instantiation: htsback.c:cache_writable
Unexecuted instantiation: htsftp.c:cache_writable
Unexecuted instantiation: htsparse.c:cache_writable
Unexecuted instantiation: htsname.c:cache_writable
Unexecuted instantiation: htsrobots.c:cache_writable
Unexecuted instantiation: htstools.c:cache_writable
Unexecuted instantiation: htswizard.c:cache_writable
Unexecuted instantiation: htsbauth.c:cache_writable
Unexecuted instantiation: htscodec.c:cache_writable
Unexecuted instantiation: htswarc.c:cache_writable
Unexecuted instantiation: htschanges.c:cache_writable
Unexecuted instantiation: htssinglefile.c:cache_writable
Unexecuted instantiation: htssitemap.c:cache_writable
Unexecuted instantiation: htsproxy.c:cache_writable
Unexecuted instantiation: htszlib.c:cache_writable
293
294
/* True if an old cache is available to read (plain or zip backend). */
295
0
HTS_STATIC int cache_readable(cache_back * cache) {
296
0
  return (cache != NULL && cache->zipInput != NULL);
297
0
}
Unexecuted instantiation: fuzz-url.c:cache_readable
Unexecuted instantiation: htslib.c:cache_readable
Unexecuted instantiation: htscore.c:cache_readable
Unexecuted instantiation: htshash.c:cache_readable
Unexecuted instantiation: htscache.c:cache_readable
Unexecuted instantiation: htsback.c:cache_readable
Unexecuted instantiation: htsftp.c:cache_readable
Unexecuted instantiation: htsparse.c:cache_readable
Unexecuted instantiation: htsname.c:cache_readable
Unexecuted instantiation: htsrobots.c:cache_readable
Unexecuted instantiation: htstools.c:cache_readable
Unexecuted instantiation: htswizard.c:cache_readable
Unexecuted instantiation: htsbauth.c:cache_readable
Unexecuted instantiation: htscodec.c:cache_readable
Unexecuted instantiation: htswarc.c:cache_readable
Unexecuted instantiation: htschanges.c:cache_readable
Unexecuted instantiation: htssinglefile.c:cache_readable
Unexecuted instantiation: htssitemap.c:cache_readable
Unexecuted instantiation: htsproxy.c:cache_readable
Unexecuted instantiation: htszlib.c:cache_readable
298
299
#endif
300
301
// Functions
302
303
/* Library-internal only (engine TUs). */
304
#ifdef HTS_INTERNAL_BYTECODE
305
306
char *hts_cancel_file_pop(httrackp * opt);
307
308
/* Detach the pending hts_addurl() list and give the caller ownership; NULL
309
   when none is pending. Free it with hts_addurl_free(). */
310
char **hts_addurl_take(httrackp *opt);
311
312
/* Free a list taken with hts_addurl_take(), strings included. */
313
void hts_addurl_free(char **url);
314
315
#endif
316
317
/* Record a link on the heap. All strings are copied (caller keeps ownership).
318
   Returns 1 on success, 0 if the link limit (opt->maxlink) is reached. */
319
int hts_record_link(httrackp * opt,
320
                    const char *address, const char *file, const char *save,
321
                    const char *ref_address, const char *ref_file,
322
                    const char *codebase);
323
324
/* Index of the most recently recorded link. */
325
size_t hts_record_link_latest(httrackp *opt);
326
327
/* Mark link at index lpos as not to be processed (sets pass2 = -1). */
328
void hts_invalidate_link(httrackp * opt, int lpos);
329
330
/* Reset / free the engine's link heap. */
331
void hts_record_init(httrackp *opt);
332
333
void hts_record_free(httrackp *opt);
334
335
/* Run the mirror for the given start URL(s) under opt. Top-level engine entry.
336
   Returns 1 once the crawl loop ran, 0 or -1 for a bailout. *completed says
337
   whether it reached the end: false for a bailout, and for any stop that cut it
338
   short, however it arrived (state.stop or exit_xh). */
339
int httpmirror(char *url1, httrackp *opt, hts_boolean *completed);
340
341
/* Write len bytes of adr to local path s. url_adr/url_fil (may be NULL) name
342
   the source URL for logging/notification. */
343
int filesave(httrackp * opt, const char *adr, int len, const char *s,
344
             const char *url_adr /* = NULL */ ,
345
             const char *url_fil /* = NULL */ );
346
347
char *hts_cancel_file_pop(httrackp * opt);
348
349
int check_fatal_io_errno(void);
350
351
int engine_stats(void);
352
353
void host_ban(httrackp * opt, int ptr, struct_back * sback, const char *host);
354
355
/* Open local file s for writing (filecreate, truncate) or appending
356
   (fileappend), creating parent directories as needed. Return an open FILE*
357
   the caller must fclose(), or NULL on failure. */
358
FILE *filecreate(filenote_strc * strct, const char *s);
359
360
FILE *fileappend(filenote_strc * strct, const char *s);
361
362
/* Create an empty file, return 1 on success, 0 on failure. */
363
int filecreateempty(filenote_strc * strct, const char *filename);
364
365
int filenote(filenote_strc * strct, const char *s, filecreate_params * params);
366
367
/* Copy into dest (destsize bytes) the form under which the local path s is
368
   listed in new.lst: forward slashes, with the mirror `root` stripped when s
369
   sits under it. Also the change report's key, so the two must not drift. */
370
void hts_savename_listed(const char *root, const char *s, char *dest,
371
                         size_t destsize);
372
373
/* Copy the whitespace-delimited token at *ptr into dest (destsize bytes, NUL
374
   included) and advance *ptr past it and the whitespace after it. HTS_FALSE
375
   when the token was longer, dest then holding what fit. A caller reading a
376
   filter must refuse it: a cut pattern authorizes something else. */
377
hts_boolean hts_scan_token(char **ptr, char *dest, size_t destsize);
378
379
void file_notify(httrackp * opt, const char *adr, const char *fil,
380
                 const char *save, int create, int modify, int wasupdated);
381
382
void usercommand(httrackp * opt, int exe, const char *cmd, const char *file,
383
                 const char *adr, const char *fil);
384
385
void usercommand_exe(const char *cmd, const char *file);
386
387
// Finish the makeindex index.html (footer + refresh meta), run usercommand.
388
// Updates *makeindex_done/*makeindex_fp in place; adr/fil are the mode strings.
389
void hts_finish_makeindex(httrackp *opt, int *makeindex_done,
390
                          FILE **makeindex_fp, int makeindex_links,
391
                          const char *makeindex_firstlink,
392
                          const char *template_footer, const char *adr,
393
                          const char *fil);
394
395
// Flush ht_buff[0..ht_len] to save on disk; *fp closed+NULLed on write.
396
// Precondition: ht_len>0.
397
void hts_finish_html_file(httrackp *opt, cache_back *cache, htsblk *r,
398
                          FILE **fp, const char *ht_buff, size_t ht_len,
399
                          const char *adr, const char *fil, const char *save);
400
401
/* Longest suffix a rule builder appends after the path (the wizard's
402
   "*[file]"), NUL included; asserted against in htswizard.c. */
403
0
#define HTS_FILTER_SUFFIX_MAX 8
404
405
/* Per-slot capacity of the filters array; filters_init() strides the slots by
406
   it. Holds the longest rule any builder emits, because truncating one changes
407
   what it matches. */
408
#define HTS_FILTER_SLOT_SIZE                                                   \
409
0
  (1 + (HTS_URLMAXSIZE * 2 - 1) + 1 + (HTS_URLMAXSIZE * 2 - 1) +               \
410
0
   HTS_FILTER_SUFFIX_MAX)
411
412
int filters_init(char ***ptrfilters, int maxfilter, int filterinc);
413
414
/* Binds this crawl's filter array to `opt`, and empties the wizard block with
415
   it: opt->wizard_filters indexes into that array and outlives no crawl. */
416
void filters_bind(httrackp *opt, char ***ptrfilters, int *filptr);
417
418
/* Longest rule a slot holds and the matcher still looks at. */
419
#define HTS_FILTER_MAXLEN                                                      \
420
0
  (HTS_FILTER_SLOT_SIZE - 1 < STRJOKER_MAXLEN ? HTS_FILTER_SLOT_SIZE - 1       \
421
0
                                              : STRJOKER_MAXLEN)
422
423
/* Stores `pattern` at `pos`, shifting the rules from there up a slot; the
424
   caller has ensured there is room. The one door into the array: a rule past
425
   HTS_FILTER_MAXLEN warns and returns HTS_FALSE, never stored dead (#1270). */
426
hts_boolean filters_insert(httrackp *opt, int pos, const char *pattern);
427
428
int fspc(httrackp * opt, FILE * fp, const char *type);
429
430
char *next_token(char *p, int flag);
431
432
/* Like fil_normalized(), but first drops query keys in STRIP (comma-separated,
433
   "*" = all); STRIP NULL/empty behaves exactly like fil_normalized(). */
434
char *fil_normalized_filtered(const char *source, char *dest,
435
                              const char *strip);
436
437
/* As fil_normalized_filtered(), but DO_SLASH/DO_QUERY gate the // collapse and
438
   the query-argument sort independently (the urlhack sub-flags). */
439
char *fil_normalized_filtered_ex(const char *source, char *dest,
440
                                 const char *strip, int do_slash, int do_query);
441
442
/* For URL ADR/FIL, return (in DEST) the comma keylist to strip from the
443
   '\n'-separated "[pattern=]keys" RULES (patterns matched on host/path via
444
   strjoker, last wins); NULL if none match. Feeds fil_normalized_filtered(). */
445
const char *hts_query_strip_keys(const char *rules, const char *adr,
446
                                 const char *fil, char *dest, size_t destsize);
447
448
/* The --host-alias rules of OPT, or NULL when the option was not given. */
449
const char *hts_host_alias_rules(httrackp *opt);
450
451
/* ADR with its host replaced by the canonical one, from the '\n'-separated
452
   "alias[,alias...]=canonical" RULES (aliases matched with strjoker, last
453
   wins). NOWWW matches the host with its www. prefix collapsed, as -%u keys it.
454
   Chains are followed to their end, so the result is a fixpoint. Scheme and
455
   credentials are kept. NULL when no rule applies, the mapping is a no-op, the
456
   rules loop, or the result would not fit DEST. */
457
const char *hts_host_alias(const char *rules, const char *adr,
458
                           hts_boolean collapse_www, char *dest,
459
                           size_t destsize);
460
461
/* HTS_TRUE when OPT's url hacks collapse www.host onto host. */
462
hts_boolean hts_host_alias_collapse_www(httrackp *opt);
463
464
/* Rewrite AF's host to its --host-alias canonical form, in place, and return
465
   it. Idempotent; returns af->adr unchanged when no rule applies. */
466
const char *hts_host_alias_fold(httrackp *opt, lien_adrfil *af);
467
468
/* HTS_TRUE if ADRA and ADRB name the same host once RULES are applied. */
469
hts_boolean hts_host_same_alias(const char *rules, const char *adra,
470
                                const char *adrb, hts_boolean collapse_www);
471
472
/* First canonical host in RULES whose chain never ends ("a=b" plus "b=a"),
473
   copied into DEST, or NULL if every chain settles. Those hosts are left
474
   unaliased, so the engine reports them rather than picking a hop. */
475
const char *hts_host_alias_looping(const char *rules, hts_boolean collapse_www,
476
                                   char *dest, size_t destsize);
477
478
/* Read a whole file into a freshly malloc'd, NUL-terminated buffer; the caller
479
   owns it and must release it with freet(). Return NULL on missing/unreadable
480
   file (readfile_or substitutes defaultdata instead). The byte content is NOT
481
   transcoded except readfile_utf8, which expects a UTF-8 path. readfile2
482
   reports the byte size (excluding the NUL) via *size when non-NULL. */
483
char *readfile(const char *fil);
484
485
char *readfile2(const char *fil, LLint * size);
486
487
/* readfile2() refusing a body too large for the int indexes downstream, on the
488
   same stat that sizes the read: a caller checking the size itself would leave
489
   a window for the file to grow. NULL when it does not fit. */
490
char *readfile2_inmem(const char *fil, LLint *size);
491
492
char *readfile_utf8(const char *fil);
493
494
char *readfile2_utf8(const char *fil, LLint *size);
495
496
char *readfile_or(const char *fil, const char *defaultdata);
497
498
/* Backing (download-slot) scheduler. Operate on the back[] ring (struct_back).
499
   Not thread-safe; call from the single crawl loop. */
500
501
/* True if a connecting slot should give up on the current address and try the
502
   next one: a fallback address remains (addr_index+1 < addr_count) and the
503
   candidate has been connecting for at least its deadline, min(timeout, an
504
   internal cap). elapsed/timeout in seconds. Exposed for the -#D self-test. */
505
int back_connect_fallback_due(int addr_index, int addr_count, int elapsed,
506
                              int timeout);
507
508
/* How many new sockets may be opened now, honoring maxsoc and the maxconn rate
509
   limit (>=0). _strict ignores reserved-slot headroom; the plain form leaves
510
   room for naming tests and stops at 0 when the stack is nearly full. */
511
int back_pluggable_sockets(struct_back * sback, httrackp * opt);
512
513
int back_pluggable_sockets_strict(struct_back * sback, httrackp * opt);
514
515
/* One engine-loop tick: refresh the transfer stats and run the loop callback
516
   for slot b (-1 = none). HTS_FALSE = the callback requested an abort. */
517
hts_boolean hts_loop_tick(struct_back *sback, httrackp *opt, int b, int ptr);
518
519
/* Wait until a test socket can be plugged, pumping transfers, stats and the
520
   loop callback; gives up past the -E deadline. HTS_FALSE = callback abort. */
521
hts_boolean hts_wait_available_socket(struct_back *sback, httrackp *opt,
522
                                      cache_back *cache, int ptr);
523
524
/* Randomized inter-file pause target in [min_ms,max_ms] (#185), derived from a
525
   timestamp seed so it is stable within one gap and rerolls per launch. */
526
int hts_pause_target_ms(TStamp seed, int min_ms, int max_ms);
527
528
/* Schedule more links from the heap into free slots. Returns the number queued,
529
   or <=0 if none could be added (no free slot / paused / stopped). */
530
int back_fill(struct_back * sback, httrackp * opt, cache_back * cache,
531
              int ptr, int numero_passe);
532
533
/* Count of links already finished (in background or served from cache). */
534
int backlinks_done(const struct_back *sback, lien_url **liens, int lien_tot,
535
                   int ptr);
536
537
/* Like back_fill, but a no-op (returns -1) when in-memory buffered data already
538
   exceeds opt->maxcache. */
539
int back_fillmax(struct_back * sback, httrackp * opt, cache_back * cache,
540
                 int ptr, int numero_passe);
541
542
/* Interactive prompt: continue an interrupted mirror? Returns nonzero to go on.
543
 */
544
int ask_continue(httrackp * opt);
545
546
/* Number of decimal digits in n. */
547
int nombre_digit(int n);
548
549
// Polling
550
#if HTS_POLL
551
int check_flot(T_SOC s);
552
553
int check_stdin(void);
554
#endif
555
/* Nonzero if the socket has a pending error. */
556
int check_sockerror(T_SOC s);
557
558
/* external modules: register a link discovered by a parser plugin. */
559
int htsAddLink(htsmoduleStruct * str, char *link);
560
561
/* Worst-case byte expansion HT_ADD_HTMLESCAPED* must reserve per escaper. */
562
0
#define HTS_HTMLESCAPE_MAXEXP 5      /* escape_for_html_print: '&'->"&amp;" */
563
0
#define HTS_HTMLESCAPE_FULL_MAXEXP 6 /* _full: high byte->"&#xHH;" */
564
565
#endif