utils.h (13687B)
1 /* 2 * Claws Mail -- a GTK based, lightweight, and fast e-mail client 3 * Copyright (C) 1999-2024 The Claws Mail Team and Hiroyuki Yamamoto 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 * The code of the g_utf8_substring function below is owned by 19 * Matthias Clasen <matthiasc@src.gnome.org>/<mclasen@redhat.com> 20 * and is got from GLIB 2.30 21 */ 22 23 #ifndef __UTILS_H__ 24 #define __UTILS_H__ 25 26 #include <glib.h> 27 #include <glib-object.h> 28 #include <stdio.h> 29 #include <string.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <sys/types.h> 33 #include <time.h> 34 #if HAVE_ALLOCA_H 35 # include <alloca.h> 36 #endif 37 #include <wchar.h> 38 39 /* Handling Base64 content in procmime and prefs_customheader */ 40 #define B64_LINE_SIZE 57 41 42 /* Wrappers for C library function that take pathname arguments. */ 43 # include <glib/gstdio.h> 44 45 /* why is this sometimes undefined !? */ 46 #ifndef G_MAXOFFSET 47 typedef gint64 goffset; 48 #define G_MINOFFSET G_MININT64 49 #define G_MAXOFFSET G_MAXINT64 50 #endif 51 52 #ifndef BIG_ENDIAN_HOST 53 #if (G_BYTE_ORDER == G_BIG_ENDIAN) 54 #define BIG_ENDIAN_HOST 1 55 #endif 56 #endif 57 58 #define CHDIR_RETURN_IF_FAIL(dir) \ 59 { \ 60 if (change_dir(dir) < 0) return; \ 61 } 62 63 #define CHDIR_RETURN_VAL_IF_FAIL(dir, val) \ 64 { \ 65 if (change_dir(dir) < 0) return val; \ 66 } 67 68 #define CHDIR_EXEC_CODE_RETURN_VAL_IF_FAIL(dir, val, code) \ 69 { \ 70 if (change_dir(dir) < 0) { \ 71 code \ 72 return val; \ 73 } \ 74 } 75 76 #define MAX_ALLOCA_MEM_SIZE 102400 77 78 #define Xalloca(ptr, size, iffail) \ 79 { \ 80 size_t __size = size; \ 81 \ 82 if (__size > MAX_ALLOCA_MEM_SIZE) { \ 83 g_warning("%" G_GSIZE_FORMAT " bytes exceeds max alloca size '%d'", __size, MAX_ALLOCA_MEM_SIZE); \ 84 iffail; \ 85 } \ 86 if ((ptr = alloca(__size)) == NULL) { \ 87 g_warning("can't allocate memory"); \ 88 iffail; \ 89 } \ 90 } 91 92 #define Xstrdup_a(ptr, str, iffail) \ 93 { \ 94 gchar *__tmp; \ 95 size_t __size = strlen(str); \ 96 \ 97 if (__size > MAX_ALLOCA_MEM_SIZE) { \ 98 g_warning("%" G_GSIZE_FORMAT " bytes exceeds max alloca size '%d'", __size, MAX_ALLOCA_MEM_SIZE); \ 99 iffail; \ 100 } \ 101 if ((__tmp = alloca(__size + 1)) == NULL) { \ 102 g_warning("can't allocate memory"); \ 103 iffail; \ 104 } else \ 105 strcpy(__tmp, str); \ 106 \ 107 ptr = __tmp; \ 108 } 109 110 #define Xstrndup_a(ptr, str, len, iffail) \ 111 { \ 112 gchar *__tmp; \ 113 size_t __size = len; \ 114 \ 115 if (__size > MAX_ALLOCA_MEM_SIZE) { \ 116 g_warning("%" G_GSIZE_FORMAT "bytes exceeds max alloca size '%d'", __size, MAX_ALLOCA_MEM_SIZE); \ 117 iffail; \ 118 } \ 119 if ((__tmp = alloca(__size + 1)) == NULL) { \ 120 g_warning("can't allocate memory"); \ 121 iffail; \ 122 } else { \ 123 memcpy(__tmp, str, __size); \ 124 __tmp[__size] = '\0'; \ 125 } \ 126 \ 127 ptr = __tmp; \ 128 } 129 130 #define Xstrcat_a(ptr, str1, str2, iffail) \ 131 { \ 132 gchar *__tmp; \ 133 size_t len1, len2; \ 134 \ 135 len1 = strlen(str1); \ 136 len2 = strlen(str2); \ 137 if (len1 + len2 > MAX_ALLOCA_MEM_SIZE) { \ 138 g_warning("%" G_GSIZE_FORMAT " bytes exceeds max alloca size '%d'", len1 + len2, MAX_ALLOCA_MEM_SIZE); \ 139 iffail; \ 140 } \ 141 if ((__tmp = alloca(len1 + len2 + 1)) == NULL) { \ 142 g_warning("can't allocate memory"); \ 143 iffail; \ 144 } else { \ 145 memcpy(__tmp, str1, len1); \ 146 memcpy(__tmp + len1, str2, len2 + 1); \ 147 } \ 148 \ 149 ptr = __tmp; \ 150 } 151 152 #define AUTORELEASE_STR(str, iffail) \ 153 { \ 154 gchar *__str; \ 155 Xstrdup_a(__str, str, iffail); \ 156 g_free(str); \ 157 str = __str; \ 158 } 159 160 #define FILE_OP_ERROR(file, func) \ 161 { \ 162 g_printerr("%s: ", file); \ 163 fflush(stderr); \ 164 perror(func); \ 165 } 166 167 #define IS_ASCII(c) (((guchar) c) <= 0177 ? 1 : 0) 168 169 #define cm_return_val_if_fail(expr,val) G_STMT_START { \ 170 if (!(expr)) { \ 171 g_print("%s:%d Condition %s failed\n", __FILE__, __LINE__, #expr);\ 172 return val; \ 173 } \ 174 } G_STMT_END 175 176 #define cm_return_if_fail(expr) G_STMT_START { \ 177 if (!(expr)) { \ 178 g_print("%s:%d Condition %s failed\n", __FILE__, __LINE__, #expr);\ 179 return; \ 180 } \ 181 } G_STMT_END 182 183 #ifndef MIN 184 #define MIN(a, b) ((a) < (b) ? (a) : (b)) 185 #endif 186 #ifndef MAX 187 #define MAX(a, b) ((a) > (b) ? (a) : (b)) 188 #endif 189 190 #ifdef __cplusplus 191 extern "C" { 192 #endif 193 194 typedef gpointer (*GNodeMapFunc) (gpointer nodedata, gpointer data); 195 196 /* debug functions */ 197 void debug_set_mode (gboolean mode); 198 gboolean debug_get_mode (void); 199 200 #ifdef HAVE_VA_OPT 201 #define debug_print(format, ...) debug_print_real(__FILE__, __LINE__, format __VA_OPT__(,) __VA_ARGS__) 202 #else 203 #define debug_print \ 204 debug_print_real("%s:%d:", debug_srcname(__FILE__), __LINE__), \ 205 debug_print_real 206 #endif 207 208 /* for macro expansion */ 209 #define Str(x) #x 210 #define Xstr(x) Str(x) 211 212 /* String utilities. */ 213 214 void list_free_strings_full (GList *list); 215 void slist_free_strings_full (GSList *list); 216 217 void hash_free_strings (GHashTable *table); 218 219 gint str_case_equal (gconstpointer v, 220 gconstpointer v2); 221 guint str_case_hash (gconstpointer key); 222 223 /* number-string conversion */ 224 gchar *itos_buf (gchar *nstr, 225 gint n); 226 gchar *itos (gint n); 227 gchar *to_human_readable (goffset size); 228 229 /* alternative string functions */ 230 gint path_cmp (const gchar *s1, 231 const gchar *s2); 232 gchar *strretchomp (gchar *str); 233 gchar *strtailchomp (gchar *str, 234 gchar tail_char); 235 gchar *strcrchomp (gchar *str); 236 gchar *strcrlftrunc (gchar *str); 237 #ifndef HAVE_STRCASESTR 238 gchar *strcasestr (const gchar *haystack, 239 const gchar *needle); 240 #endif /* HAVE_STRCASESTR */ 241 gchar *strncasestr (const gchar *haystack, 242 gint haystack_len, 243 const gchar *needle); 244 gpointer my_memmem (gconstpointer haystack, 245 size_t haystacklen, 246 gconstpointer needle, 247 size_t needlelen); 248 gchar *strncpy2 (gchar *dest, 249 const gchar *src, 250 size_t n); 251 252 gboolean is_next_nonascii (const gchar *s); 253 gint get_next_word_len (const gchar *s); 254 255 /* functions for string parsing */ 256 gint subject_compare (const gchar *s1, 257 const gchar *s2); 258 gint subject_compare_for_sort (const gchar *s1, 259 const gchar *s2); 260 void trim_subject (gchar *str); 261 void eliminate_parenthesis (gchar *str, 262 gchar op, 263 gchar cl); 264 void extract_parenthesis (gchar *str, 265 gchar op, 266 gchar cl); 267 268 void extract_quote (gchar *str, 269 gchar quote_chr); 270 gchar *escape_internal_quotes (gchar *str, 271 gchar quote_chr); 272 void eliminate_address_comment (gchar *str); 273 gchar *strchr_with_skip_quote (const gchar *str, 274 gint quote_chr, 275 gint c); 276 void extract_address (gchar *str); 277 void extract_list_id_str (gchar *str); 278 279 GSList *address_list_append (GSList *addr_list, 280 const gchar *str); 281 GSList *address_list_append_with_comments(GSList *addr_list, 282 const gchar *str); 283 GSList *references_list_prepend (GSList *msgid_list, 284 const gchar *str); 285 GSList *references_list_append (GSList *msgid_list, 286 const gchar *str); 287 288 GList *add_history (GList *list, 289 const gchar *str); 290 291 void remove_return (gchar *str); 292 void remove_space (gchar *str); 293 void unfold_line (gchar *str); 294 void subst_char (gchar *str, 295 gchar orig, 296 gchar subst); 297 void subst_chars (gchar *str, 298 gchar *orig, 299 gchar subst); 300 void subst_for_filename (gchar *str); 301 void subst_for_shellsafe_filename (gchar *str); 302 gboolean is_ascii_str (const gchar *str); 303 gint check_line_length (const gchar *str, 304 gint max_chars, 305 gint *line); 306 307 gchar **strsplit_with_quote (const gchar *str, 308 const gchar *delim, 309 gint max_tokens); 310 311 gchar *trim_string (const gchar *str, 312 gint len); 313 314 GList *uri_list_extract_filenames (const gchar *uri_list); 315 gboolean is_uri_string (const gchar *str); 316 gchar *get_uri_path (const gchar *uri); 317 gint get_uri_len (const gchar *str); 318 void decode_uri (gchar *decoded_uri, 319 const gchar *encoded_uri); 320 void decode_uri_with_plus (gchar *decoded_uri, 321 const gchar *encoded_uri, 322 gboolean with_plus); 323 gint scan_mailto_url (const gchar *mailto, 324 gchar **from, 325 gchar **to, 326 gchar **cc, 327 gchar **bcc, 328 gchar **subject, 329 gchar **body, 330 gchar ***attach, 331 gchar **inreplyto); 332 333 /* return static strings */ 334 const gchar *get_home_dir (void); 335 const gchar *get_rc_dir (void); 336 void set_rc_dir (const gchar *dir); 337 gboolean rc_dir_is_alt (void); 338 const gchar *get_mail_base_dir (void); 339 const gchar *get_imap_cache_dir (void); 340 const gchar *get_mime_tmp_dir (void); 341 const gchar *get_template_dir (void); 342 const gchar *get_tmp_dir (void); 343 const gchar *get_locale_dir (void); 344 gchar *get_tmp_file (void); 345 const gchar *get_domain_name (void); 346 gboolean is_numeric_host_address (const gchar *hostaddress); 347 const gchar *get_desktop_file(void); 348 349 /* file / directory handling */ 350 off_t get_file_size (const gchar *file); 351 time_t get_file_mtime (const gchar *file); 352 353 gboolean file_exist (const gchar *file, 354 gboolean allow_fifo); 355 gboolean is_relative_filename (const gchar *file); 356 gboolean is_dir_exist (const gchar *dir); 357 gboolean is_file_entry_exist (const gchar *file); 358 gboolean is_file_entry_regular(const gchar *file); 359 360 #define is_file_exist(file) file_exist(file, FALSE) 361 #define is_file_or_fifo_exist(file) file_exist(file, TRUE) 362 363 gint change_dir (const gchar *dir); 364 gint make_dir_hier (const gchar *dir); 365 gint remove_all_files (const gchar *dir); 366 gint remove_numbered_files (const gchar *dir, 367 guint first, 368 guint last); 369 gint remove_numbered_files_not_in_list(const gchar *dir, 370 GSList *numberlist); 371 gint remove_all_numbered_files (const gchar *dir); 372 gint remove_dir_recursive (const gchar *dir); 373 gchar *canonicalize_str (const gchar *str); 374 gchar *normalize_newlines (const gchar *str); 375 376 gchar *get_outgoing_rfc2822_str (FILE *fp); 377 378 char *fgets_crlf(char *buf, int size, FILE *stream); 379 380 /* process execution */ 381 gint execute_command_line (const gchar *cmdline, 382 gboolean async, 383 const gchar *working_directory); 384 gchar *get_command_output (const gchar *cmdline); 385 FILE *get_command_output_stream (const gchar *cmdline); 386 387 /* open URI with external browser */ 388 gint open_uri(const gchar *uri, const gchar *cmdline); 389 /* open file with text editor */ 390 gint open_txt_editor(const gchar *filepath, const gchar *cmdline); 391 392 /* time functions */ 393 time_t remote_tzoffset_sec (const gchar *zone); 394 time_t tzoffset_sec (time_t *now); 395 gchar *tzoffset (time_t *now); 396 void get_rfc822_date (gchar *buf, 397 gint len); 398 void get_rfc822_date_hide_tz (gchar *buf, 399 gint len); 400 401 size_t fast_strftime (gchar *buf, 402 gint buflen, 403 const gchar *format, 404 struct tm *lt); 405 406 /* debugging */ 407 #ifdef HAVE_VA_OPT 408 void debug_print_real (const char *file, int line, const gchar *format, ...) G_GNUC_PRINTF(3, 4); 409 #else 410 void debug_print_real (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 411 #endif 412 const char * debug_srcname (const char *file); 413 414 /* subject threading */ 415 void * subject_table_lookup(GHashTable *subject_table, gchar * subject); 416 void subject_table_insert(GHashTable *subject_table, gchar * subject, 417 void * data); 418 void subject_table_remove(GHashTable *subject_table, gchar * subject); 419 void utils_free_regex(void); 420 gint subject_get_prefix_length (const gchar *subject); 421 422 /* quoting recognition */ 423 const gchar * line_has_quote_char (const gchar *str); 424 425 gint g_int_compare (gconstpointer a, gconstpointer b); 426 427 gchar *generate_mime_boundary (const gchar *prefix); 428 429 gint quote_cmd_argument(gchar * result, guint size, 430 const gchar * path); 431 GNode *g_node_map(GNode *node, GNodeMapFunc func, gpointer data); 432 433 gboolean get_hex_value(guchar *out, gchar c1, gchar c2); 434 void get_hex_str(gchar *out, guchar ch); 435 436 /* auto pointer for containers that support GType system */ 437 438 #define G_TYPE_AUTO_POINTER g_auto_pointer_register() 439 typedef struct AutoPointer GAuto; 440 GType g_auto_pointer_register (void); 441 GAuto *g_auto_pointer_new (gpointer pointer); 442 GAuto *g_auto_pointer_new_with_free (gpointer p, 443 GFreeFunc free); 444 gpointer g_auto_pointer_get_ptr (GAuto *auto_ptr); 445 GAuto *g_auto_pointer_copy (GAuto *auto_ptr); 446 void g_auto_pointer_free (GAuto *auto_ptr); 447 gboolean get_uri_part (const gchar *start, 448 const gchar *scanpos, 449 const gchar **bp, 450 const gchar **ep, 451 gboolean hdr); 452 gchar *make_uri_string (const gchar *bp, 453 const gchar *ep); 454 gboolean get_email_part (const gchar *start, 455 const gchar *scanpos, 456 const gchar **bp, 457 const gchar **ep, 458 gboolean hdr); 459 gchar *make_email_string(const gchar *bp, 460 const gchar *ep); 461 gchar *make_http_string (const gchar *bp, 462 const gchar *ep); 463 464 gchar *mailcap_get_command_for_type(const gchar *type, 465 const gchar *file_to_open); 466 void mailcap_update_default (const gchar *type, 467 const gchar *command); 468 469 gboolean file_is_email(const gchar *filename); 470 gboolean sc_g_list_bigger(GList *list, gint max); 471 gboolean sc_g_slist_bigger(GSList *list, gint max); 472 473 int cm_canonicalize_filename(const gchar *filename, gchar **canonical_name); 474 475 guchar *g_base64_decode_zero(const gchar *text, gsize *out_len); 476 477 gboolean get_random_bytes(void *buf, size_t count); 478 479 #ifdef __cplusplus 480 } 481 #endif 482 483 gboolean get_serverportfp_from_filename(const gchar *str, gchar **server, gchar **port, gchar **fp); 484 485 #endif /* __UTILS_H__ */