#ifdef __cplusplus
extern "C" {
#endif
#ifndef DONE_LIB_H
#define DONE_LIB_H 1
#include <stdio.h>

#ifdef WIN32
#if (_MSC_VER > 1900)
#include <stdint.h>
#else
#include "mystdint.h"
#endif
#endif


#include <time.h>
#ifdef WIN32
#include <direct.h>
#include <sys/timeb.h>
#else
#include <sys/time.h>
#include <unistd.h>
#include <dirent.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>

#include "defines.h"

// chrisp added recently, hope this doesn't cause any compile errors.
#	ifndef FALSE
#		define FALSE 0
#	endif
#	ifndef TRUE
#		define TRUE !FALSE
#	endif

#ifdef WIN32
#	include <conio.h>
#	define getch  _getch
#	define getche _getche
#else
#	define getch()	do_getch(FALSE)
#	define getche()	do_getch(TRUE)
#endif


#include "pair.h"
#include "isofix.h"
#include "lib_spawn.h"
char *lib_read_file_string(char *fname, char *data, int sz);
char *lib_nospaces(char *s, char *tmp);
int ziconv_total(void);
unsigned long fixed_atol(char *s);
int dnsx_smooth(void);
void myssl_set_fix_domain(int (*fn)(char *s));
int lib_from_two(char *from);
int lib_file_copy_size(char *src, char *dst, char *reason, int sz, char *prefix);
int lib_remove(char *fname);
int lib_filetype(char *fname, char *ext);
char charmatch(char c);
int disk_usage(char *path, double *used, double *total);
int  lib_file_age(char *fname);
void set_in_crash(int x);

void stack_ok(char *whence);
#define lib_exists(aaa) lib_exists_real(aaa,__FILE__,__LINE__)
int lib_exists_real(char *fname, char *src, int line);
int lib_is_domain(char *email1, char *dom2);
int lib_split_comma_match_wild(char *wild_list, char *text);
size_t GetStackUsage();
char *lib_trim_dot(char *txt);
int lib_elapsed(time_t was);
int lib_year_at(time_t x);
char *lib_dash_date(time_t t, char *bf);
char *lib_daymon_time(char *tstr);
int fast_store(int useit);
char *stack_whence(void);
void my_setseed(unsigned int u, unsigned int v);
int myrand(void);


#include "fasttime.h"

#ifdef ISOSX
char *strupr(char *s);
char *strlwr(char *s);
#endif



int lib_identical(char *file1, char *file2);
void lib_touch(char *fname);
char *lib_url_encode2(char *tmp, char *url);
int match_wild_imap(char *wild,char *text, char **found);
#define bit_new(a) bit_new_real(a,__FILE__,__LINE__)
char *lib_trimmore(char *email, char *tmp);
int lib_lastchar(char *s, char c);
int lib_strlen(const char *s);
int lib_symlink(char *fname, char *symlink);
char *lib_get_word(char *out, char *xcmd, int want);
char *strncat_safe(char *dst, char *src, int len, int dstlen);
char *strncpy_safe(char *dst, char *src, int len, int dstlen);
char *lib_get_word_strip(char *out, char *xcmd, int want);
int lib_str_hash_old(char *s, int max);
#ifndef HAVE_BIGINT
#define HAVE_BIGINT
#ifdef WIN32
typedef __int64 bigint;
typedef unsigned __int64 ubigint;
#else
typedef int64_t bigint;
typedef unsigned long long ubigint;
#endif
#endif
bigint lib_freespace_big(char *s);
int lib_freespace_mb(char *s);

int lib_split_and_match_wild_long(char *wild_list, char *text);
// Must include debug.h to redefine 'FILE' as early as possible. 
char *lib_etrim(char *email, char *tmp);
char *lib_mailto_encode(char *tmp, char *input); // strip quotes as outlook seems to be confused by them.
int lib_max_handle(void);
char *lib_url_encode3(char *tmp, char *url, int len);
int lib_ncpy_debug_write(void);
char *ncpy2(char *dst, char *src, int len, int bflen);
time_t str_to_time(char *n);
char *time_to_str(time_t x, char *tmp);

char *read_line(char *bf, int bfsz, int hide);
char *lib_clean_angle(char *fname, char *tmp);
int is_localhost(char *s);
int dfopen_hist_info(IHANDLE handle, int isopen, int logonly, char *filename, int line, char *info);
char *lib_etrimlow(char *email, char *tmp);
char *strfind(char *string,char delim,char **next);
char *lib_date_short(char *tmp, time_t t);
int lib_file_move(char *src, char *dst, char *reason);
char *lib_date_path(char *tmp, time_t t);
char *nullok(char *s);
int lib_create_file2(char *fname, char *body);
int lib_saferep(char *in, char *wild, char *tpl, char *result);
char *lib_date_simple3(char *tmp, time_t t);
int wildrep(char *in, char *wild, char *tpl, char *result);
char *timezone_name(char *bf, int bfsz);
char *timezone_name_short(char *bf, int bfsz);
int lib_same_domain(char *email1, char *email2);
char *lib_bar_decode(char *s, char *tmp, int bfsz);
char *lib_bar_encode(char *s, char *tmp, int bfsz);
char *lib_bar_clean(char *s, char *tmp, int bfsz);
double time_double(void);
int lib_add_slashif(char *s);
char *lib_dayofweek(void);
char *strstrnc_modify(char *s1, char *s2);
char *lib_clean_fname(char *in);
char *lib_clean_fname2(char *in);
int lib_str_set(char **a, char *s);
int ncpy_file(char *bf, char *fname, int len);

char *lib_remove_char(char *mask, char r, char *out);


int lib_freespace_debug(char *s, int *r_sc, int *r_bs, int *r_fc);
int system_dir(char *bf, int bfsz);
char *buildtime(char *bf, int bfsz);
int lib_get_port(int port, char *setting);
char *lib_trim_slash(char *txt);
int lib_count_slash(char *txt);
int lib_contains_slash(char *txt);
char *lib_strip_crlf(char *s);
int lib_strip_crlf_x(char *s);
char *lib_strip_crlf_atend(char *s);
char *lib_trim_end(char *s);
char *lib_trim_crlf(char *bf);
void lib_close_on_exec(int fd);
char *lib_truncate(char *s, int n);
char *ex_decode_spaces(char *pass, char *in);
unsigned int lib_thread_cpu(void);
time_t lib_ctime(char *fname);
int lib_strip_html(char *in, char *out, int bfsz);
char *lib_strip_text(char *in, char *txt, char *out, int bfsz);
char *lib_webdav_date_at(char *bf, time_t t);
char *lib_cleanup_dotslash(char *xfilename); // remove /a/b/./c
int lib_set_timezone(double x);
int lib_iswhite(char c);
int lib_simple_wash(char *s);
char *strclr(char *s);
char *lib_trim_eol(char *bf);
int lib_write_file_string(char *fname, char *data);

/* QSORT compare fns ... */
int qsort_strcmp(const void *arg1, const void *arg2);
int qsort_strcmpnc(const void *arg1, const void *arg2);
int qsort_int(const void *arg1, const void *arg2);
void qreverse(void *list, size_t count, size_t size);
void lib_set_imsg(int (*fn)(const char *, ...));
int lib_sprintf( char *buffer, int bfsize, char *format, ... );
char *lib_first_email(char *str2, char *buf);
int lib_minutes(void);
char *lib_encode_utf8(unsigned int code, char *result);
int lib_remove_enable(void);
int lib_yday(void);
char *lib_remove_before(char *in, char *tostrip);
char *lib_web_encode_js(char *out,char *in,int outbfsz);

int lib_split_email(char *email, char *user, char *dom);
int lib_isnt351(void);
int nlib_rule_from(char *from);
int lib_set_isdst(void);
char *file_strdup(char *s);
time_t lib_parsedate_dayonly(char *rec);
char *lib_strip(char *s, char *tostrip);
char *lib_remove_string(char *s, char *tostrip);
char *lib_first_emailorgroup(char *str2, char *buf);
void header_split(char *line, char *header, char *value);

int token_quoted_good(char *s, char *p[], char *end, char *sep, int tmax);
int token_quoted_better(char *s, char *p[], char *sep, int tmax);
char *lib_unquote(char *s, char *tmp);
char *lib_unsquote(char *s, char *tmp);
int lib_copy_open(FILE *fin, FILE *fout, char *reason);
int lib_match_anyof(char *list, char *thing);
char *lib_crlf_to_spaces(char *tmp);
char *lib_web_encode_8bit(char *tmp, char *input, int bfsz);
char *lib_imap_time(char *tmp, time_t t);
char *lib_cleanup_slash(char *xfilename);
int lib_timezone_nodaylight(void);
unsigned int lib_xtoi(char *s);
extern unsigned char char2byte_array[256];
#define char2byte(s) (char2byte_array[(s)[0]] * 16 + char2byte_array[(s)[1]])
char *strstrnc_old(char *s1, char *s2);
int strstr_test(char *a1, char *a2);
void lib_set_cidr(int (*fn)(char *address, char *cidr)) ;

char *lib_url_enable(char *xin, char *tmp);
char *lib_percent(char *s, double f);
char *lib_perseck(char *s, double f);
char* lib_ftoa_nob(char *s, double f);
char* lib_itoa_nob(char *s, int i);

char *lib_quote_slash(char *in, char *tmp);
void *safe_memmove_real(void *dst, const void *src, int bytes, void *start, int bfsz, char *file, int line);
#define safe_memmove(a,b,c,d,e) safe_memmove_real(a,b,c,d,e,__FILE__,__LINE__)

int about_process(char *infile, char *outfile);

char *lib_web_xss(char *tmp, char *input);

char *lib_encode_quote(char *tmp, char *input, int bfsz);
char *lib_encode_quoteonly(char *tmp, char *input, int bfsz);
char *lib_decode_quoteonly(char *bf, char *s, int bfsz);
char *lib_decode_exclamation(char *bf, char *s, int bfsz);
char *lib_decode_percent(char *bf, char *s, int bfsz);
char *lib_decode_percent_clean(char *bf, char *s, int bfsz);

char *lib_trim_dquote(char *tmp, char *input, int bfsz);
char *lib_trim_squote(char *tmp, char *input, int bfsz);
int lib_esc_encoded(char *s);
int lib_append_file(FILE *fout, char *xname);
char *lib_ip_fname(char *ip, char *tmp);
char *lib_date_simple(char *tmp, time_t t);
time_t lib_date_xml(char *dte);

char *lib_cleanup_dotdot(char *xfilename2); // remove /a/b/./c and change a/b/../d to a/d
int lib_match_email(char *em1, char *em2);
void *safe_memcpy_real(void *dst, const void *src, int bytes, void *start, int bfsz, char *file, int line);
#define safe_memcpy(dst,src,len,start,total) safe_memcpy_real(dst,src,len,start,total,__FILE__,__LINE__)
int lib_file_size_r(char *fname, char *src, int line);
#define lib_file_size(a) lib_file_size_r(a,__FILE__,__LINE__)
int lib_stat_x(char *fname, int *sz, time_t *time_write, int *isdir, char *src, int line);
#define lib_stat(a,b,c,d) lib_stat_x(a,b,c,d,__FILE__,__LINE__)
int lib_timezone(void);
char *lib_bytes_string_simple(int bytes, char *ret, int bfsz);
char *lib_bytes_string_basic(int bytes, char *ret, int bfsz, int multiplier);
int lib_str_hash_nc(char *s, int max, int width);
unsigned long lib_file_size_unsigned(char *fname);
int lib_compare_base(char *dom1, char *dom2);
time_t lib_date_dashed(char *xdte);
char *lib_escape_square(char *subj, char *tmp);
char *lib_short_time(char *tmp, time_t t);
char *lib_log_date(time_t t, char *bf);
char *lib_slash_encode(char *str, char *tmp);
int int_time(time_t *x);

typedef struct CHTML {FILE *f; char bf[BFSZ]; int len;} Chtml;
int chtml_read(Chtml *h, char *out, int bfsz);
int chtml_free(Chtml **ph);
Chtml *chtml_open(char *fname);

char *lib_double_string(double bytes, char *ret, int bfsz);
char *lib_double_string_real(double bytes, char comma, char *ret, int bfsz);
char *lib_single_slash(char *in, char *out);
char *lib_timezone_string(char *zone);
char * lib_class_c(char *in, char *out);
unsigned long lib_file_osize_unsigned(FILE *f);
int lib_delete_tree(char *path, char *reason, double *tot, int age, int *nskip);
int lib_url_split2(char *url, char *protocol, char *host, char *port, char *rest);

int lib_mkdir_x(char *s, int mode, char *src, int line);
int lib_create_dir_x(char *s, int mode, int(*cb)(void *, char *), void *p, char *src, int line);
int lib_create_missing_x(char *s, int mode, int(*cb)(void *,char *), void *p, char *src, int line);
#define lib_mkdir(a,b) lib_mkdir_x(a,b,__FILE__,__LINE__)
#define lib_create_dir(a,b) lib_create_dir_x(a,b,NULL,NULL,__FILE__,__LINE__)
#define lib_create_dir_ex(a,b,c,d) lib_create_dir_x(a,b,c,d,__FILE__,__LINE__)
#define lib_create_missing(a,b) lib_create_missing_x(a,b,NULL,NULL,__FILE__,__LINE__)
#define lib_create_missing_ex(a,b,c,d) lib_create_missing_x(a,b,c,d,__FILE__,__LINE__)
char *lib_get_rest2(char *out, char *cmd, int n); // Ignore double spaces...
void lib_copy_upto_quoted(char **src, char *c, char *dst, int bfsz) ;

//void *safe_memmove(void *dst, const void *src, int bytes, void *start, int bfsz, char *src, char *line);
char *system_error(int ecode, char *bf, int bfsz);

#ifndef issep
#	define issep(x) (x=='/'||x=='\\')
#endif
#ifndef iseol
#	define iseol(x) (x == '\r' || x == '\n' || x == '\0')
#endif
#ifndef fixsep
	char *fixsep(char *path, int bfsz);
#endif

int sisascii(int c);
int sisspace(int c);

int lib_get_host_port(char *host,char *dflt, int port, char *setting);
int remove_rename(char *oldf, char *newf, char *error, int bfsz);
void assign(char **to, char *value);
char *strtrm(char *bf);
int lib_undotstuff(char *fname);

int lib_set_startstop_file(char *s);
char *lib_startstop_logfile(void);
int lib_fix_mode(char *s, int mode, int lastn);
int path_compare(char *path1, char *path2);
int path_ncompare(char *path1, char *path2, int n);

char *make_path(char *path, char *file, char *result, int bfsz);
char *make_full_path(char *file, char *result, int bfsz);
char *strip_ext(char *file);
char *comma_number(char *number, int bfsz);
char *lib_spaces(int n, char *tmp);

int lib_abort_do2(int (*fn)(char *src, int line));
char *lib_to_unix_slash(char *txt);
unsigned long hex_to_ulong(char * text);
char *lib_persec(char *s, double f);

int rfc_raw_email(char *email, char *raw, int bfsz);
char *lib_fix_email(char *str2, char *tmp);
int lib_tz_set(void);
int lib_timezone_fix(void);

#ifdef WIN32
#	define SEP '\\'
#	ifndef _S_IFDIR
#		define _S_IFDIR 0040000
#	endif
#	ifndef S_ISDIR
#		define S_ISDIR(x) ((_S_IFDIR & x)>0)
#	endif
#else
#	define SEP '/'
#endif
int nulloki(int *i);
char *lib_nntp_escape(char *s, char *tmp);
int lib_msec_now(void);
void lib_set_emsg(int (*fn)(const char *, ...));
char *lib_from_time(char *tmp);
int lib_month(void);
int lib_year(void);
char *lib_get_word(char *out, char *cmd, int want);
time_t lib_gmt_to_local(time_t x);
time_t lib_local_to_gmt(time_t x);
char *std_slash(char *in, char *out);
void if_free(void **a);
char *lib_strdate(char *bf);
int match_wild_ipnum(char *iprange, char *ipnum);
int match_wild_or_ip(char *wild, char *text);
int match_wild(char *wildcard,char *text);
int match_wildnc(char *wildcard,char *text);
int match_wildnc_at(char *wild,char *text, char **found);

int split_email(char *email, char *fullname, char *address, int bfsz);
int match_email(char *match,char *email);
int match_email_real(char *match,char *email,int exact);
int match_emailnc(char *match,char *email);
int match_emailnc_real(char *match,char *email,int exact);

int strip_subj(char *subj, char *result, int bfsz);
int match_subjnc(char *match, char *subj);
int match_subjnc_real(char *match, char *subj, int exact);

/* Dynamic buffers that increase in size when you need to add more to it:*/
#define DBUF_INC 1000
typedef struct DBUF {char *d; int size;int len;int inc;} DBuf;
DBuf *dbuf_new(void);
DBuf *dbuf_new_size(int inc);
void dbuf_free(DBuf *d);
void dbuf_addl(DBuf *d,char *bf, int len);
void dbuf_add(DBuf *d, char *bf);
void dbuf_addf(DBuf *d,char *fmt,...);
void dbuf_addc(DBuf *d, char c);
char *dbuf_bf(DBuf *d);

int lib_split_and_match_wild(char *wild_list, char *text);
int lib_match_groups(char *xwild, char *xgrp2, int *isat);
char *ncpy_nullok(char *dst, char *src, int len);
char *lib_nullok(char *s);

#ifndef GOT_WORDLIST
typedef struct WORDLIST {char *word; struct WORDLIST *next;} Wordlist ;
#define GOT_WORDLIST 1
#endif
int lib_gmt_offset_at_broken(time_t t);
int lib_gmt_offset_at(time_t t);
time_t web_date_get(char *dte);
time_t web_date_get_correct(char *dte);
time_t web_date_gmt(char *dte);
int word_sort(Wordlist **pp);
int fclose_nfs(FILE *f);
char *lib_fts_encode(char *tmp, char *input,int bfsz);
char *lib_fts_decode(char *tmp, char *input,int bfsz);
//void b_free(void *p);
//void *b_realloc(void *was, int sz);
int word_add_end(Wordlist **w, char *name);

int lib_path_split2(char *in, char *path, char *fname);
int lib_fullpath(char *in);
int lib_path_trailing(char *in, char *dir);
int word_delete(Wordlist **ww, char *exact);
char *lib_path_pfromend(char *path, int parts);
char *lib_get_rest(char *out, char *cmd, int n);
void lib_copy_upto(char **src, char c, char *dst, int bfsz);
void lib_copy_upto_any(char **src, char *c, char *dst, int bfsz);
void lib_skip_any(char **src, char *c);
void lib_copy_upto_str(char **src, char *c, char *dst, int bfsz);
int lib_freespace(char *strx);
int lib_url_split_host(char *url, char *host, char *fname);
int lib_freespace2(char *strx);
typedef struct XBITMAP {char *mask; int sz;} Bitmap;
char *lib_unescape(char *s, char *bf, int tmpsz);
Bitmap *bit_new_real(int sz, char *src, int line);
void stack_ok(char *where);
void stack_init(char *whence, int stacksz);
void bit_clear(Bitmap *b);
int bit_set(Bitmap *b, int x, int v);
int bit_isset(Bitmap *b, int x);
int bit_free(Bitmap *b);
double nice_atof(char *s);
char *nice_speed(int d, char *tmp);

int lib_file_copy_mkdir(char *src, char *dst, char *reason, int makedir);
int image_too_big(int x, int y);
int image_too_bigfile(char *fname, int big_jpg);
Wordlist *word_folders(char *path);
int lib_month_find(char *s);
int nice_atoi_mb(char *s);
enum {STS_YEARS,STS_MONTHS,STS_WEEKS,STS_DAYS,STS_HOURS,STS_MINS,STS_SECS};
int string_to_secs_type(char *s);
int string_to_secs(char *s);
int stack_tot(void);
int stack_tot_usage(void);

int lib_abort_do(int (*fn)(void));
char *lib_trim_spaces(char *s, char *tmp);
char *lib_trim_spaces2(char *s, char *tmp);
int lib_trim_spaces_end(char *s);
int lib_fopen_mutex(int x);
int lib_has_upper(char *s);
FILE *lib_fopen_create(char *fname, char *mode, int fmod);
int lib_file_copy(char *src, char *dst, char *reason);
int lib_file_count_lines(char *file, int *lines);
int lib_parts_subject(char *subject, char *subj, char *fname, int *parti, int *partmax);
#define lib_copy_file lib_file_copy
int lib_file_copy_contains(char *src, char *dst, char *contains, char *reason, char *cause);

int lib_file_read(char *file, char **data, int *size, int max);
int lib_file_write(char *fname, char *txt);
int nice_atoi(char *s);
char* lib_itoa(char *s, int i);
char* lib_ftoa(char *s, double f);
char *nice_num(int d, char *tmp);
char *lib_mail_timezone(char *s);
char *lib_mail_timezone_get(struct tm *x, char *zone, int bfsz);
int lib_fix_daylight(struct tm *t,int *x);
char *lib_hex_to_bin(char *hex, unsigned char *bin, int *outlen) ;
char *lib_bin_to_hex(char *bin, int binlen, char *out, int outlen);
void lib_abort_real(char *src, int line);
#define lib_abort() lib_abort_real(__FILE__,__LINE__)
int bit_info_r2(Bitmap *b, int *x, int *y, int *z);

int lib_file_osizeh_x(int handle, char *src, int line);
int lib_file_osize_x(FILE *f, char *src, int line);
#define lib_file_osizeh(a) lib_file_osizeh_x(a,__FILE__,__LINE__)
#define lib_file_osize(a) lib_file_osize_x(a,__FILE__,__LINE__)

char *lib_web_encode(char *tmp, char *xinput, int bfsz);
int word_copy_real(Wordlist **dst, Wordlist *src, char *file, int line);
int lib_min(int a, int b);
//int mfilter_set_extra(Wordlist *w);
int word_add_nodup_real(Wordlist **w, char *name, char *src, int line);
char *ncpy_fast(char *dst, char *src, int len);

#define word_add_nodup(a,b) word_add_nodup_real(a,b,__FILE__,__LINE__)
#define word_add(a,b) word_add_real(a,b,__FILE__,__LINE__,FALSE)
#define word_add_atend(a,b) word_add_real(a,b,__FILE__,__LINE__,TRUE)
#define word_copy(a,b) word_copy_real(a,b,__FILE__,__LINE__)


Wordlist *word_loadfile(char *file);
int word_savefile(Wordlist *lines, char *file);

#define word_reverse(a) word_reverse_real(a,__FILE__,__LINE__)

void word_reverse_real(Wordlist **list, char *file, int line);
int word_tok(Wordlist **list, char *string, char *toks);
int word_free(Wordlist **w);
int luhn_check_number(char *number);
char *os_slash(char *in, char *out);
char *lib_addsep(char *s, char *tmp);
char *strstrnc(char *s1, char *s2);
int lib_match_list_trim_dtrue(char *xwild, char *xgrp2);
int lib_match_list_trim_dfalse(char *xwild, char *xgrp2);
int imap_token_split(char *s, char *p[], char *sep, int tmax);
char *lib_fix_email2(char *str2);

//int word_add_real(Wordlist **w, char *name);
int word_add_real(Wordlist **w, char *name, char *file, int line, int atend);

int word_add_at(Wordlist **w, Wordlist *at, char *name, int replace);

int word_remove_real(Wordlist **ww, char *s, int (*fn)(char *, char *));
#define word_remove(a,b) word_remove_real(a,b,strcmp)
#define word_removenc(a,b) word_remove_real(a,b,strcmpnc)
int time_diff(time_t then);

int word_find(Wordlist *w, char *s);
int word_findnc(Wordlist *w, char *s);
char *lib_bin_to_hex(char *bin, int binlen, char *out, int outlen);
char *lib_getcwd(char *tmp);
int start_shell(char *path);

int start_shell(char *path);
char *unix_slash(char *in, char *out);
int tree_base(char *bf, char *base, char *wild);
int token_quote(char *s, char *p[], int tmax);
char *strip_eol(char *s);
char *lib_emsg_time(char *tstr);
char *lib_emsg_time2(char *tstr);
int lib_split_email_name(char *name_and_email, char *email_bf, char *name_bf, int bfsz);
int lib_wash_file(char *given, char *out);
int lib_emsg_time_setfull(int x);

int lib_isnt(void);
int lib_iswindows(void);
char *lib_cdrive(void);

#define HWORDHASH 5000
typedef struct WENTRY {char *word; struct WENTRY *next;} Wentry; 
typedef struct {
	Wentry *table[HWORDHASH];
} Hwordlist;
int hword_pop(Hwordlist *x, int *at, char *word);

int hword_find(Hwordlist *x, char *word);
int hword_add(Hwordlist *x, char *word);
int hword_free(Hwordlist **xx);
int hword_new(Hwordlist **x);



int lib_detach_prog(char *cmd, char *etext);
int lib_detach(void) ;
int lib_stat_isdir(char *fname);
char *lib_guess_content(char *fname);
char *lib_guess_suffix(char *fname);

//#define lib_msleep(a) lib_msleep_real(a,__FILE__,__LINE__)
//void lib_msleep_real(int x, char *file, int line);
void lib_msleep(int x);
char *lib_pad_right(char *src, int width, char *tmp);
char *lib_strdup(char **dst, char *src);
char *int_to_str(int x, char *tmp);
char *ncat(char *dst, char *src, int len);
char *ncat_sep(char *dst, char *sep, char *src, int len);
char *strclean(char *src, char *txt, int len);
char *lib_url_encode(char *tmp, char *url);
char *lib_capitalize(char *word, char *tmp);
char *lib_capitalize_all(char *word, char *tmp);

char *lib_url_decode(char *bf, char *s);
int token_split2(char *s, char *p[], char *sep, int tmax);


char *lib_token_encode_quoted(char **names, char **values, int n, int ignore_empty_values, char *bf, int bfsz);
int lib_token_split_quoted(char *s, char **names, char **values, int max_pairs);
int lib_token_split_quoted_keep(char *s, char **names, char **values, int max_pairs);
char *lib_token_find(char *name,char *names[], char *values[],int size);

char *lib_web_date2(time_t t, char *bf);
char *lib_date_basic(time_t t_msg, char *bf,int offset, char *date_format, char *time_format);
time_t lib_mtime_open(FILE *f);
char *lib_time(char *bf,time_t t);
int cvt_crlf_lf(char *bf, int r);
int cvt_lf_crlf(char *bf, int r,  char *tmp);
int lib_fix_crlf(char *bf, int r,  char *tmp);
int lib_isdir(char *fname);
char *hms(char *tmp, time_t t);
char *lib_hourmin(char *tmp);

char *lib_file_name_only(char *full_path_and_name);
char *lib_dir_name_only(char *full_path_and_name, char *bf, int bfsz);
char *lib_get_extension(char *fname);

char *mystrtok(char *start, char *toks, char **upto);
int token_split(char *s, char *p[], char *sep, int tmax);
int quoted_token_split(char *s, char *p[], char *sep, int tmax);
int quoted_token_split_rm_quot(char *s, char *p[], char *sep, int tmax);
int quoted_token_split2_rm_quot(char *s, char *p[], char *sep, int tmax);
char *lib_month_name(int idx_between_0_and_11);
char *lib_month_name_full(int idx_between_0_and_11);
char *lib_weekday_name(int idx_between_0_Sunday_and_6_Saturday);
char *lib_hour_name(int hour_between_0_and_24, char *bf);
char *lib_24hour_name(int hour_between_0_and_24, char *bf);
char *lib_minute_name(int minute_between_0_and_59, char *bf);

extern char *interval_english[14];
enum { I_SEC, I_SECS, I_MIN, I_MINS, I_HR, I_HRS, I_DAY, I_DAYS, I_WK, I_WKS, I_MON, I_MONS, I_YR, I_YRS };
char *lib_time_interval(int minutes, char *bf, int display_exact);
char *lib_time_interval_ex(int seconds, char *bf, int display_exact, char *strings[]);

char *lib_not_null(char *txt);

char *lib_file_date(char *bf,time_t t);
int lib_var_replace(char *line, char *out, int outlen, char *var, char *val);
time_t lib_mtime(char *fname);
void lib_set_mtime(char *fname, time_t t);
int lib_url_split_more(char *url, char *host, char *path, char *fname);

char *lib_ftp_time(time_t t);
int lib_url_split(char *url, char *protocol, char *host, char *xdir, char *fname);
int lib_path_split(char *in, char *path, char *fname);
int lib_encrypt(char *bf, int len, char *key);
int lib_decrypt(char *bf, int len, char *key);
/*char *str_encode(char *s);*/
char *lib_crypt(char *key, char *salt);
char *lib_strip_quotes(char *s, char *tmp);
char *ncpy_realok(char *dst, char *src, int len, char *fname, int line);
char *ncpy_debug(char *dst, char *src, int len, char *fname, int line);
char *ncpy_real(char *dst, char *src, int len, char *fname, int line, int size);
// chrisp changed from debug to real, because debug function is unstable if src is not null terminated...
#define ncpy(a,b,c) ncpy_real(a,b,c,__FILE__,__LINE__,sizeof(a))
#define ncpy_ok(a,b,c) ncpy_realok(a,b,c,__FILE__,__LINE__)
int ncpy_idle(void);
int lib_ncpy_debug_start(int x);
int lib_ncpy_debug_flush(void);
void stack_print(void);
char *lib_file_only(char *fname, char *tmp);
char * strprint(char *line, char *tmp);

char *mystrlwr(char *s);
char *mystrupr(char *s);
typedef struct {char *start; char *savedp; char saved; char *upto; int len; char *lastret; int debug; } Strlines;
char *str_lines_next_any(Strlines *v, int *goteol, int *ended_with_cr, char *tmp);
void str_lines_start(Strlines *v, char *s, int len);
char *str_lines_next_eol(Strlines *v, int *goteol);
char *str_lines_next(Strlines *v);
void str_lines_end(Strlines *v);
int strncmp_strlen(char *txt, char *start); /* same as strncmp(txt,start,lib_strlen(txt)) */
int strnicmp_strlen(char *txt, char *start);  /* same as strnicmp(txt,start,lib_strlen(txt)) */
int lib_tail_file(char *inname, char *outname, int want, int append);
int strcmpnc_slashfirst(char *s1, char *s2);


#ifndef WIN32
#	ifndef stricmp
#		define stricmp strcmpnc
#		define strnicmp strncmpnc
#	endif
#endif

#ifndef __cplusplus
/*
false and true are defined as part of the C++ language specification.
And redefining false in this case, can cause some code to fail to compile.
*/
#ifndef false
#	define false 0
#endif
#ifndef true
#	define true (!false)
#endif
#endif

int str_vappend(char **s, char *add);
int lib_file_size_true(char *fname);
int lib_token_comma(char *s, char *p[], int tmax);
int lib_match_list(char *xxxwild, char *xxgrp2);
char *lib_mygetenv(char *s);
char *lib_web_date(char *bf);
char *lib_web_date_at(char *bf, time_t t);
int lib_mkdir_all(char *s, int mode);
int lib_create_file(char *fname);
int lib_create_path(char *s, int mode);
char *lib_short_date_local(time_t t, char *bf);

time_t lib_date_get(char *dte) ;
int lib_str_hash(char *s, int max);
int lib_int_hash(int key, int max);
int lib_is_file(char *fname);
int lib_is_symlink(char *fname);
int lib_is_dir(char *fname);
int lib_chdir(char *s);
int lib_chmod(char *fname, int mde);
int lib_chown(char *fname, int uid, int gid);
char *lib_cr_encode(char *s, char *tmp, int bfsz);
char *lib_cr_decode(char *s, char *tmp, int bfsz);
char *lib_cr_decode2(char *s, char *tmp, int bfsz);
int lib_spawnv_wait(char *xcmd, char *arg[], char *reason);
char *str_lines_rest(Strlines *v, int *x);



#define LIB_BFSZ 1000
typedef struct XWILD_DATA {
	int dev,inode;
	int isdir;
	int islink;
	int isnorm;
	int issub;
	int size;
	int mode;
	int nlinks;
	int gid,uid;
	char symlink[LIB_BFSZ];
	char name[LIB_BFSZ];
	time_t time_create,time_access,time_write;
	struct XWILD_DATA *next;
} WILD_DATA;
typedef struct VVWUILD_DATA {
	WILD_DATA norm;
	char name[LIB_BFSZ];
	struct XWILD_DATA *next;
} VWILD_DATA;


#ifdef WIN32
typedef struct {intptr_t h; int fast; WILD_DATA *list;WILD_DATA *cur;} WILD_HANDLE;
#else
typedef struct {DIR *h; char *path; char *wild; int fast; WILD_DATA *list; WILD_DATA *cur; } WILD_HANDLE;
#endif

typedef struct XSWILD_HANDLE {WILD_HANDLE *wh; WILD_DATA *sorted; WILD_DATA *cur;} SWILD_HANDLE;

int wild_end_r(WILD_HANDLE **hh);
int wild_end_safe(WILD_HANDLE **hh);
int wild_first_r(WILD_HANDLE **hh, char *xwild, WILD_DATA *data, char *src, int line);
int wild_first_time(WILD_HANDLE **hh, char *xwild, WILD_DATA *data, char *src, int line);
int wild_next_r(WILD_HANDLE *h, WILD_DATA *data, char *src, int line);
char *lib_short_date(time_t t, char *bf);

int wild_next_safe(WILD_HANDLE *h, WILD_DATA *data, char *src, int line);
int wild_first_safe(WILD_HANDLE **hh, char *wild, WILD_DATA *data, char *src, int line);

// chrisp testing...
//#define BADFINDFILE 1

#ifdef BADFINDFILE
#define wild_first(aa,bb,cc) wild_first_safe(aa,bb,cc,__FILE__,__LINE__)
#define wild_next(aa,bb) wild_next_safe(aa,bb,__FILE__,__LINE__)
#define wild_end(aa) wild_end_safe(aa)
#else
#define wild_first(aa,bb,cc) wild_first_time(aa,bb,cc,__FILE__,__LINE__)
#define wild_next(aa,bb) wild_next_r(aa,bb,__FILE__,__LINE__)
#define wild_end(aa) wild_end_r(aa)
#endif

int wild_skip(WILD_DATA *data);
int wild_count(int n);

// Identical but these functiosn SORT the directory, unix doesn't!!!
int swild_end(SWILD_HANDLE **hh);
int swild_next(SWILD_HANDLE *h, WILD_DATA *data);
int swild_first(SWILD_HANDLE **hh, char *wild, WILD_DATA *data);

int safei(int i, int max, char *tag);


/*
Example usage of wild_*() functions to scan a directory:
void print_out_dir_list(char *dir){
	WILD_HANDLE *h;
	WILD_DATA mydata;
	int more;
	more = wild_first(&h, dir, &mydata);
	while(more){
		printf("found (%s)\n", mydata.name);
		more = wild_next(h, &mydata);
	}
	wild_end(&h);
}


//chrisp version... 

	WILD_HANDLE *h;
	WILD_DATA mydata;
	int more;
	for (more = wild_first(&h, path, &mydata);more;more = wild_next(h, &mydata)){
		if (strstr(mydata.name,".swm")==NULL) continue;

	}
	wild_end(&h);
	return TRUE;

*/
int wild_count(int n);
int lib_used_tree(char *path, double *total, int *ntot);
char *nice_double(double d, char *tmp);
int lib_used_ntree(char *path, double *total, int *nfiles);
int lib_tree_count(char *path, char *fname, int *nfiles);
char *last_strstr(const char *haystack, const char *needle);
char *strstrnc_fast(char *s1, char *s2);
char *strstr_fast(char *s1, char *s2);
char *strstrf(const char *s1, const char *s2); // fast version of strstr...
int lib_delete_dir(char *path, char *reason, double *deleted);
int lib_month_find(char *s);
int lib_tzone_find(char *s);
int lib_get_zone(char *rec); /* return time zone offset in seconds, GMT = 0 */
int lib_get_hour(char *rec, int *hour, int *min, int *sec);

time_t  lib_parsedate(char *rec);
char *lib_shorter_date(time_t t, char *bf);

int user_test_ssha(char *hash, char *pass);
int user_create_ssha(char *pass, char *result);
int user_migrate_password(char *passhash, char *dom);

int vwild_first(WILD_HANDLE **hh, char *wild, VWILD_DATA *data);
int vwild_next(WILD_HANDLE *h, VWILD_DATA *data, char *src, int line);
int vwild_end(WILD_HANDLE **hh);
int lib_del_isok(char *src);
int remove_unquoted_chars(char *s, char *remove);

int lib_email_hasheader(char *fname);
//#define lib_email_getheaders(fname) lib_email_getheaders_real(fname,__FILE__,__LINE__)
Pair *lib_email_getheaders_real(char *fname, char *file, int line);

char *lib_first_single(char *txt, char c);
int sisdigit(int c);
int sisalnum(int c);
int sisalpha(int c);
int sisupper(int c);
int sislower(int c);
int sisprint(int c);


int lib_starts_with_nc(char *txt, char *start);
int lib_starts_with(char *txt, char *start);
int lib_ends_with(char *txt, char *end);
int lib_ends_with_nc(char *txt, char *end);
char *lib_strchr_2nd(char *str, char c);

char *nstrcat(char *existing_text, char *text_to_append, int existing_text_bfsz);
char *lib_to_forward_slash(char *txt);
char *lib_to_back_slash(char *txt);
char *lib_to_file_system_slash(char *txt);
char *lib_trim_dots(char *txt, int n, char *bf, int bfsz);
int lib_file_names_equal(char *f1, char *f2);
int lib_file_compare(char *fn1, char *fn2);
int lib_text_file_compare(char *fn1, char *fn2);
int lib_read_next_line(FILE *f, char *bf, int bfsz);

int feof_checked(FILE *x);

// testing remove next 4 lines
/*#ifdef feof
#undef feof
#endif
#define feof feof_checked
*/



char *lib_make_password(char *tmp, int len);



#define clock NEVER_USE_CLOCK


#ifndef WIN32
char *strlwr(char *s);
#endif
char *win_slash(char *in, char *out);

typedef struct TREE_HANDLE {int recursive; int (*access_check)(void *link, char *s); void *p1; WILD_DATA *wd; WILD_DATA *cur;} Tree_Handle;

int tree_scan(Tree_Handle *tree, WILD_DATA **th, char *base, char *wild, char *p[], int upto, int np, int issub);
int tree_first(Tree_Handle **th, char *wild, int rec, int (*access_check)(void *x, char *s), void *p1, WILD_DATA *data);


int tree_end(Tree_Handle **hh);
int tree_next(Tree_Handle *h, WILD_DATA *data);
int tree_tot_subdir(WILD_DATA *h, char *path);
int tree_reset(Tree_Handle *h, WILD_DATA *data);
int lib_istrue(char *s);
int wild_dump(void);
#define addstuff(x) char *x=st->x

#ifdef unix
int GetTickCount(void);
int GetTickCount64(void);
#endif
char *unix_mode_show(int mode, int isdir, int islink, char *tmp);

#endif

int lib_isip(char *s);
int lib_isquoted(char *s);
char *lib_logtime(char *tstr);
char *lib_logtime2(char *tstr);
char *lib_mail_time(char *tmp, time_t t);
char *lib_nice_display_format_time(char *tmp, time_t t);
char *lib_nice_display_format_datetime(char *tmp, time_t t);
char *lib_nice_display_format_date(char *tmp, time_t t);
char *lib_nice_display_format_datetime2(char *tmp, time_t t, int day_first);
char *lib_nice_display_format_datetime_gmt(char *tmp, time_t t);
char *lib_nice_daterange_compact(char *tmp, time_t t, time_t t2);
char *lib_nice_display_format_gmtime(char *tmp, time_t t);
char *lib_nice_display_format_gmdate(char *tmp, time_t t);
char *lib_notify_date(time_t t_raw, char *bf, int offset);

char lib_make_hex_digit(int f);
int lib_hex_digit(int c);
char *lib_replace(char *in, char *out, int outbfsz, char *from, char *to);
int lib_replace_in_file(char *fname, char *src, char *dst);

char *str_lines_next_crlf(Strlines *v, int *goteol);
FILE* spawnfopen(const char *filename, const char *mode) ;
char *lib_strip_angle(char *email, char *tmp);
char *lib_strip_square(char *email, char *tmp);

int spawnfclose_x(FILE *f, char *src, int line);
#define spawnfclose(a) spawnfclose_x(a,__FILE__,__LINE__)

int setup_nat(char *hostip, int lclport, int remport, char *proto);
int wild_split(char *in, char *path, char *wild);

char *lib_bytes_string(int bytes, char *ret, int bfsz);
char *lib_bytes_string_real(int bytes, char comma, char *ret, int bfsz);
char *lib_bytes_string2(int bytes, char *ret, int bfsz);
char *lib_bytes_string2_real(int bytes, char comma, char *ret, int bfsz);
int lib_bytes_parse(char *s);
int lib_time_interval_parse(char *s);
int lib_contains_dot_dot(char *fname);
int lib_count_dot_dot(char *fname);
int lib_count_chr(char *txt, int ch);
int wild_stats_report(void);

int bit_info_r(Bitmap *b, int *x, int *y);
void lib_assert_failed(char *file, int line);
#define lib_assert(x) if (!(x)) lib_assert_failed(__FILE__,__LINE__)

char *lib_comma(int num, char *ret, int bfsz);
char *lib_comma_real(int num, char comma, char *ret, int bfsz);
char *str_lines_next_bin(Strlines *v, int *len);
char *lib_get_quote(char *s, char *bf);
char *strchr_last(char *txt, char c);
char *strchr_slast(char *txt, char c);
int lib_ncrc32_noalign(char *xin,int len);

int lib_hour(void);
int lib_mday(void);
char *lib_trim_qspaces(char *s, char *tmp);
int lib_ncrc32(char *xin,int len);
int tree_simple(Tree_Handle **th, char *wild, void *p1, WILD_DATA *data);
int spawnfcloseh(FILE *f);
int word_count(Wordlist *w);
char * word_geti(Wordlist *w, int i);

int istrue(char *string);
int isfalse(char *string);
int lib_remove_with_retry(char *f);
int lib_rename_with_retry(char *src, char *dst);
int lib_clear_file(char *fname);
int bit_isset_r(Bitmap *b, int x);
int bit_set_r(Bitmap *b, int x, int v);
int bit_copy(Bitmap *b, char *data, int bits);
int bit_info(Bitmap *b, int *x, int *y);
int word_print(char *info, Wordlist *w);
int strcmpnc_test(char *a1, char *a2);
int word_del(Wordlist **ww, char *contains);
int lib_split_name(char *s, char *first, char *last);
int lib_split_comma_match_wild(char *wild_list, char *text);

int lib_space_before(char *bf, char *s);

#define wild_first_good(aa,bb,cc) wild_first_safe(aa,bb,cc,__FILE__,__LINE__)
#define wild_next_good(aa,bb) wild_next_safe(aa,bb,__FILE__,__LINE__)
#define wild_end_good(aa) wild_end_safe(aa)


int strcmpnc_old(char *s1, char *s2) ;
// chrisp removed these and breaks some function behaviour and no measurable speed diff? 
#ifdef HAS_STRNCASE
#define strcmpnc strcasecmp
#define strncmpnc strncasecmp
#else
#ifdef WIN32
#define strcmpnc _stricmp
#define strncmpnc _strnicmp
#else
int strcmpnc(char *s1, char *s2) ;
int strncmpnc(const char *s1, const char *s2, size_t n);
#define NEED_STRCMPNC TRUE
#endif
#endif

#ifdef __BORLANDC__
#define strcmpnc strcmpnc_old
#define strncmpnc strncmpnc
#endif


char *lib_remove_trailing_path_sep(char *fname);
#define strip_trail_sep lib_remove_trailing_path_sep

#ifdef WIN32
#define LIB_TEXT_EOLN "\r\n"
#define LIB_PATH_SEP_STRING "\\"
#define LIB_PATH_SEP_CHAR '\\'
#else
#define LIB_TEXT_EOLN "\n"
#define LIB_PATH_SEP_STRING "/"
#define LIB_PATH_SEP_CHAR '/'
#endif

#ifndef NO_HCOUNT
	int hcount_init(void);
	int hcount_open_real(int n, char *filename, int line);
	int hcount_close_real(int n, char *filename, int line);
	int hcount_report(void);
	int hcount_log(int n, char *filename, int line, char *reason);
#	define hcount_open(n) hcount_open_real(n,__FILE__,__LINE__)
#	define hcount_close(n) hcount_close_real(n,__FILE__,__LINE__)
#else
#	define hcount_open(n)
#	define hcount_close(n)
#endif

#ifdef NEED_SETENV
	int setenv(const char *label, const char *value, int overwrite);
#endif
#ifdef NEED_UNSETENV
	void unsetenv(const char *label);
#endif

int lib_good_sms(char *sms);
#ifdef __cplusplus
}

#endif

#ifndef IGNORE_SAFE_LIB
#include "safelib.h"
#endif

