1 /* 2 * LibSylph -- E-Mail client library 3 * Copyright (C) 1999-2017 Hiroyuki Yamamoto 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library 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 GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 #ifndef __UTILS_H__ 21 #define __UTILS_H__ 22 23 #ifdef HAVE_CONFIG_H 24 # include "config.h" 25 #endif 26 27 #include <glib.h> 28 #include <stdio.h> 29 #include <string.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 #include <sys/types.h> 33 #include <dirent.h> 34 #include <time.h> 35 #if HAVE_ALLOCA_H 36 # include <alloca.h> 37 #endif 38 39 /* Wrappers for C library function that take pathname arguments. */ 40 #if GLIB_CHECK_VERSION(2, 6, 0) 41 # include <glib/gstdio.h> 42 #else 43 44 #define g_open open 45 #define g_rename rename 46 #define g_mkdir mkdir 47 #define g_stat stat 48 #define g_lstat lstat 49 #define g_unlink unlink 50 #define g_remove remove 51 #define g_rmdir rmdir 52 #define g_fopen fopen 53 #define g_freopen freopen 54 55 #endif /* GLIB_CHECK_VERSION */ 56 57 #if !GLIB_CHECK_VERSION(2, 7, 0) 58 59 #ifdef G_OS_UNIX 60 #define g_chdir chdir 61 #define g_chmod chmod 62 #else 63 gint g_chdir (const gchar *path); 64 gint g_chmod (const gchar *path, 65 gint mode); 66 #endif /* G_OS_UNIX */ 67 68 #endif /* !GLIB_CHECK_VERSION */ 69 70 #ifdef G_OS_UNIX 71 #define syl_link link 72 #else 73 gint syl_link (const gchar *src, 74 const gchar *dest); 75 #endif 76 77 /* The AC_CHECK_SIZEOF() in configure fails for some machines. 78 * we provide some fallback values here */ 79 #if !SIZEOF_UNSIGNED_SHORT 80 #undef SIZEOF_UNSIGNED_SHORT 81 #define SIZEOF_UNSIGNED_SHORT 2 82 #endif 83 #if !SIZEOF_UNSIGNED_INT 84 #undef SIZEOF_UNSIGNED_INT 85 #define SIZEOF_UNSIGNED_INT 4 86 #endif 87 #if !SIZEOF_UNSIGNED_LONG 88 #undef SIZEOF_UNSIGNED_LONG 89 #define SIZEOF_UNSIGNED_LONG 4 90 #endif 91 92 #ifndef HAVE_U32_TYPEDEF 93 #undef u32 /* maybe there is a macro with this name */ 94 typedef guint32 u32; 95 #define HAVE_U32_TYPEDEF 96 #endif 97 98 #if defined(G_OS_WIN32) && !defined(_WIN64) && defined(HAVE_64BIT_TIME_T) 99 /* for backward binary compatibility. Use only in struct definition and 100 pointer arguments. */ 101 typedef gint32 stime_t; 102 #else 103 typedef time_t stime_t; 104 #endif 105 106 #if !GLIB_CHECK_VERSION(2, 26, 0) 107 #if (defined (_MSC_VER) || defined (__MINGW32__)) && !defined(_WIN64) 108 typedef struct _stat32 GStatBuf; 109 #else 110 typedef struct stat GStatBuf; 111 #endif 112 #endif 113 114 #ifndef BIG_ENDIAN_HOST 115 #if (G_BYTE_ORDER == G_BIG_ENDIAN) 116 #define BIG_ENDIAN_HOST 1 117 #endif 118 #endif 119 120 #define CHDIR_RETURN_IF_FAIL(dir) \ 121 { \ 122 if (change_dir(dir) < 0) return; \ 123 } 124 125 #define CHDIR_RETURN_VAL_IF_FAIL(dir, val) \ 126 { \ 127 if (change_dir(dir) < 0) return val; \ 128 } 129 130 #define Xalloca(ptr, size, iffail) \ 131 { \ 132 if ((ptr = alloca(size)) == NULL) { \ 133 g_warning("can't allocate memory\n"); \ 134 iffail; \ 135 } \ 136 } 137 138 #define Xstrdup_a(ptr, str, iffail) \ 139 { \ 140 gchar *__tmp; \ 141 \ 142 if ((__tmp = alloca(strlen(str) + 1)) == NULL) { \ 143 g_warning("can't allocate memory\n"); \ 144 iffail; \ 145 } else \ 146 strcpy(__tmp, str); \ 147 \ 148 ptr = __tmp; \ 149 } 150 151 #define Xstrndup_a(ptr, str, len, iffail) \ 152 { \ 153 gchar *__tmp; \ 154 \ 155 if ((__tmp = alloca(len + 1)) == NULL) { \ 156 g_warning("can't allocate memory\n"); \ 157 iffail; \ 158 } else { \ 159 strncpy(__tmp, str, len); \ 160 __tmp[len] = '\0'; \ 161 } \ 162 \ 163 ptr = __tmp; \ 164 } 165 166 #define Xstrcat_a(ptr, str1, str2, iffail) \ 167 { \ 168 gchar *__tmp; \ 169 gint len1, len2; \ 170 \ 171 len1 = strlen(str1); \ 172 len2 = strlen(str2); \ 173 if ((__tmp = alloca(len1 + len2 + 1)) == NULL) { \ 174 g_warning("can't allocate memory\n"); \ 175 iffail; \ 176 } else { \ 177 memcpy(__tmp, str1, len1); \ 178 memcpy(__tmp + len1, str2, len2 + 1); \ 179 } \ 180 \ 181 ptr = __tmp; \ 182 } 183 184 #define AUTORELEASE_STR(str, iffail) \ 185 { \ 186 gchar *__str; \ 187 Xstrdup_a(__str, str, iffail); \ 188 g_free(str); \ 189 str = __str; \ 190 } 191 192 #define FILE_OP_ERROR(file, func) \ 193 { \ 194 fprintf(stderr, "%s: ", file); \ 195 fflush(stderr); \ 196 perror(func); \ 197 } 198 199 typedef void (*UIUpdateFunc) (void); 200 typedef void (*EventLoopFunc) (void); 201 typedef void (*ProgressFunc) (gint cur, 202 gint total); 203 typedef gchar * (*QueryPasswordFunc) (const gchar *server, 204 const gchar *user); 205 typedef void (*LogFunc) (const gchar *str); 206 typedef void (*LogFlushFunc) (void); 207 208 /* for macro expansion */ 209 #define Str(x) #x 210 #define Xstr(x) Str(x) 211 212 void list_free_strings (GList *list); 213 void slist_free_strings (GSList *list); 214 215 void hash_free_strings (GHashTable *table); 216 void hash_free_value_mem (GHashTable *table); 217 218 gint str_case_equal (gconstpointer v, 219 gconstpointer v2); 220 guint str_case_hash (gconstpointer key); 221 222 void ptr_array_free_strings (GPtrArray *array); 223 224 typedef gboolean (*StrFindFunc) (const gchar *haystack, 225 const gchar *needle); 226 227 gboolean str_find (const gchar *haystack, 228 const gchar *needle); 229 gboolean str_case_find (const gchar *haystack, 230 const gchar *needle); 231 gboolean str_find_equal (const gchar *haystack, 232 const gchar *needle); 233 gboolean str_case_find_equal (const gchar *haystack, 234 const gchar *needle); 235 236 /* number-string conversion */ 237 gint to_number (const gchar *nstr); 238 guint to_unumber (const gchar *nstr); 239 gchar *itos_buf (gchar *nstr, 240 gint n); 241 gchar *itos (gint n); 242 gchar *utos_buf (gchar *nstr, 243 guint n); 244 gchar *to_human_readable_buf (gchar *buf, 245 size_t bufsize, 246 gint64 size); 247 gchar *to_human_readable (gint64 size); 248 249 /* alternative string functions */ 250 gint strcmp2 (const gchar *s1, 251 const gchar *s2); 252 gint path_cmp (const gchar *s1, 253 const gchar *s2); 254 gboolean is_path_parent (const gchar *parent, 255 const gchar *child); 256 257 gchar *strretchomp (gchar *str); 258 gchar *strtailchomp (gchar *str, 259 gchar tail_char); 260 gchar *strcrchomp (gchar *str); 261 262 gchar *strcasestr (const gchar *haystack, 263 const gchar *needle); 264 gpointer my_memmem (gconstpointer haystack, 265 size_t haystacklen, 266 gconstpointer needle, 267 size_t needlelen); 268 269 gchar *strncpy2 (gchar *dest, 270 const gchar *src, 271 size_t n); 272 273 gboolean str_has_suffix_case (const gchar *str, 274 const gchar *suffix); 275 276 gint str_find_format_times (const gchar *haystack, 277 gchar ch); 278 279 gboolean is_next_nonascii (const gchar *s); 280 gint get_next_word_len (const gchar *s); 281 282 /* functions for string parsing */ 283 gint subject_compare (const gchar *s1, 284 const gchar *s2); 285 gint subject_compare_for_sort (const gchar *s1, 286 const gchar *s2); 287 void trim_subject_for_compare (gchar *str); 288 void trim_subject_for_sort (gchar *str); 289 void trim_subject (gchar *str); 290 void eliminate_parenthesis (gchar *str, 291 gchar op, 292 gchar cl); 293 void extract_parenthesis (gchar *str, 294 gchar op, 295 gchar cl); 296 void extract_parenthesis_with_escape (gchar *str, 297 gchar op, 298 gchar cl); 299 300 void extract_parenthesis_with_skip_quote (gchar *str, 301 gchar quote_chr, 302 gchar op, 303 gchar cl); 304 305 void eliminate_quote (gchar *str, 306 gchar quote_chr); 307 void extract_quote (gchar *str, 308 gchar quote_chr); 309 void extract_quote_with_escape (gchar *str, 310 gchar quote_chr); 311 void eliminate_address_comment (gchar *str); 312 gchar *strchr_with_skip_quote (const gchar *str, 313 gint quote_chr, 314 gint c); 315 gchar *strrchr_with_skip_quote (const gchar *str, 316 gint quote_chr, 317 gint c); 318 void extract_address (gchar *str); 319 void extract_list_id_str (gchar *str); 320 321 gchar *extract_addresses (const gchar *str); 322 323 gchar *normalize_address_field (const gchar *str); 324 325 gboolean address_equal (const gchar *addr1, 326 const gchar *addr2); 327 328 GSList *address_list_append_orig (GSList *addr_list, 329 const gchar *str); 330 GSList *address_list_append (GSList *addr_list, 331 const gchar *str); 332 GSList *references_list_prepend (GSList *msgid_list, 333 const gchar *str); 334 GSList *references_list_append (GSList *msgid_list, 335 const gchar *str); 336 GSList *newsgroup_list_append (GSList *group_list, 337 const gchar *str); 338 339 GList *add_history (GList *list, 340 const gchar *str); 341 342 /* modify string */ 343 void remove_return (gchar *str); 344 void remove_space (gchar *str); 345 void unfold_line (gchar *str); 346 void subst_char (gchar *str, 347 gchar orig, 348 gchar subst); 349 void subst_chars (gchar *str, 350 gchar *orig, 351 gchar subst); 352 void subst_null (gchar *str, 353 gint len, 354 gchar subst); 355 void subst_control (gchar *str, 356 gchar subst); 357 void subst_for_filename (gchar *str); 358 359 gchar *get_alt_filename (const gchar *filename, 360 gint count); 361 362 gboolean is_header_line (const gchar *str); 363 gboolean is_ascii_str (const gchar *str); 364 365 gint get_quote_level (const gchar *str); 366 gint check_line_length (const gchar *str, 367 gint max_chars, 368 gint *line); 369 370 gchar *strstr_with_skip_quote (const gchar *haystack, 371 const gchar *needle); 372 gchar *strcasestr_with_skip_quote (const gchar *haystack, 373 const gchar *needle); 374 gchar *strchr_parenthesis_close (const gchar *str, 375 gchar op, 376 gchar cl); 377 378 gchar **strsplit_parenthesis (const gchar *str, 379 gchar op, 380 gchar cl, 381 gint max_tokens); 382 gchar **strsplit_with_quote (const gchar *str, 383 const gchar *delim, 384 gint max_tokens); 385 gchar **strsplit_csv (const gchar *str, 386 gchar delim, 387 gint max_tokens); 388 389 gchar *strconcat_csv (gchar delim, 390 const gchar *field1, 391 ...) G_GNUC_MALLOC G_GNUC_NULL_TERMINATED; 392 393 gchar *get_abbrev_newsgroup_name (const gchar *group, 394 gint len); 395 gchar *trim_string (const gchar *str, 396 gint len); 397 gchar *trim_string_before (const gchar *str, 398 gint len); 399 400 GList *uri_list_extract_filenames (const gchar *uri_list); 401 gboolean is_uri_string (const gchar *str); 402 gchar *get_uri_path (const gchar *uri); 403 gint get_uri_len (const gchar *str); 404 void decode_uri (gchar *decoded_uri, 405 const gchar *encoded_uri); 406 void decode_xdigit_encoded_str (gchar *decoded, 407 const gchar *encoded); 408 gchar *encode_uri (const gchar *filename); 409 gchar *uriencode_for_filename (const gchar *filename); 410 gchar *uriencode_for_mailto (const gchar *mailto); 411 gint scan_mailto_url (const gchar *mailto, 412 gchar **to, 413 gchar **cc, 414 gchar **bcc, 415 gchar **subject, 416 gchar **inreplyto, 417 gchar **body); 418 419 void set_startup_dir (void); 420 void set_rc_dir (const gchar *dir); 421 422 /* return static strings */ 423 const gchar *get_startup_dir (void); 424 const gchar *get_home_dir (void); 425 const gchar *get_document_dir (void); 426 const gchar *get_rc_dir (void); 427 const gchar *get_old_rc_dir (void); 428 const gchar *get_mail_base_dir (void); 429 const gchar *get_news_cache_dir (void); 430 const gchar *get_imap_cache_dir (void); 431 const gchar *get_mime_tmp_dir (void); 432 const gchar *get_template_dir (void); 433 const gchar *get_tmp_dir (void); 434 gchar *get_tmp_file (void); 435 const gchar *get_domain_name (void); 436 437 /* file / directory handling */ 438 off_t get_file_size (const gchar *file); 439 off_t get_file_size_as_crlf (const gchar *file); 440 off_t get_left_file_size (FILE *fp); 441 442 gint get_last_empty_line_size (FILE *fp, 443 off_t size); 444 445 gboolean file_exist (const gchar *file, 446 gboolean allow_fifo); 447 gboolean is_dir_exist (const gchar *dir); 448 gboolean is_file_entry_exist (const gchar *file); 449 gboolean dirent_is_regular_file (struct dirent *d); 450 gboolean dirent_is_directory (struct dirent *d); 451 452 #define is_file_exist(file) file_exist(file, FALSE) 453 #define is_file_or_fifo_exist(file) file_exist(file, TRUE) 454 455 gint change_dir (const gchar *dir); 456 gint make_dir (const gchar *dir); 457 gint make_dir_hier (const gchar *dir); 458 gint remove_all_files (const gchar *dir); 459 gint remove_numbered_files (const gchar *dir, 460 guint first, 461 guint last); 462 gint remove_all_numbered_files (const gchar *dir); 463 gint remove_expired_files (const gchar *dir, 464 guint hours); 465 gint remove_dir_recursive (const gchar *dir); 466 gint rename_force (const gchar *oldpath, 467 const gchar *newpath); 468 gint copy_file (const gchar *src, 469 const gchar *dest, 470 gboolean keep_backup); 471 gint copy_dir (const gchar *src, 472 const gchar *dest); 473 gint move_file (const gchar *src, 474 const gchar *dest, 475 gboolean overwrite); 476 477 gint append_file_part (FILE *fp, 478 off_t offset, 479 size_t length, 480 FILE *dest_fp); 481 gint copy_file_part (FILE *fp, 482 off_t offset, 483 size_t length, 484 const gchar *dest); 485 486 gint copy_file_stream (FILE *fp, 487 FILE *dest_fp); 488 489 gchar *canonicalize_str (const gchar *str); 490 gint canonicalize_file (const gchar *src, 491 const gchar *dest); 492 gint canonicalize_file_replace (const gchar *file); 493 FILE *canonicalize_file_stream (FILE *fp, 494 gint *length); 495 gint uncanonicalize_file (const gchar *src, 496 const gchar *dest); 497 gint uncanonicalize_file_replace(const gchar *file); 498 499 gchar *normalize_newlines (const gchar *str); 500 gchar *strchomp_all (const gchar *str); 501 502 FILE *get_outgoing_rfc2822_file (FILE *fp); 503 gchar *get_outgoing_rfc2822_str (FILE *fp); 504 gchar *generate_mime_boundary (const gchar *prefix); 505 506 gint change_file_mode_rw (FILE *fp, 507 const gchar *file); 508 FILE *my_tmpfile (void); 509 FILE *str_open_as_stream (const gchar *str); 510 gint str_write_to_file (const gchar *str, 511 const gchar *file); 512 gchar *file_read_to_str (const gchar *file); 513 gchar *file_read_stream_to_str (FILE *fp); 514 515 /* process execution */ 516 gint execute_async (gchar *const argv[]); 517 gint execute_sync (gchar *const argv[]); 518 gint execute_command_line (const gchar *cmdline, 519 gboolean async); 520 gint execute_command_line_async_wait 521 (const gchar *cmdline); 522 523 gint execute_open_file (const gchar *file, 524 const gchar *content_type); 525 gint execute_print_file (const gchar *file); 526 gchar *get_command_output (const gchar *cmdline); 527 528 /* open URI with external browser */ 529 gint open_uri (const gchar *uri, 530 const gchar *cmdline); 531 532 /* play sound */ 533 gint play_sound (const gchar *file, 534 gboolean async); 535 536 /* time functions */ 537 stime_t remote_tzoffset_sec (const gchar *zone); 538 stime_t tzoffset_sec (stime_t *now); 539 gchar *tzoffset_buf (gchar *buf, 540 stime_t *now); 541 gchar *tzoffset (stime_t *now); 542 void get_rfc822_date (gchar *buf, 543 gint len); 544 545 size_t my_strftime (gchar *s, 546 size_t max, 547 const gchar *format, 548 const struct tm *tm); 549 550 /* UI hints */ 551 void set_ui_update_func (UIUpdateFunc func); 552 void ui_update (void); 553 554 void set_event_loop_func (EventLoopFunc func); 555 void event_loop_iterate (void); 556 557 void set_progress_func (ProgressFunc func); 558 void progress_show (gint cur, 559 gint total); 560 561 /* user input */ 562 void set_input_query_password_func (QueryPasswordFunc func); 563 564 gchar *input_query_password (const gchar *server, 565 const gchar *user); 566 567 /* logging */ 568 void set_log_file (const gchar *filename); 569 void close_log_file (void); 570 void set_log_verbosity (gboolean verbose); 571 gboolean get_debug_mode (void); 572 void set_debug_mode (gboolean enable); 573 574 void set_log_ui_func (LogFunc print_func, 575 LogFunc message_func, 576 LogFunc warning_func, 577 LogFunc error_func); 578 void set_log_ui_func_full (LogFunc print_func, 579 LogFunc message_func, 580 LogFunc warning_func, 581 LogFunc error_func, 582 LogFlushFunc flush_func); 583 584 void set_log_show_status_func (LogFunc status_func); 585 586 void debug_print (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 587 void status_print (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 588 589 void log_write (const gchar *str, 590 const gchar *prefix); 591 592 void log_print (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 593 void log_message (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 594 void log_warning (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 595 void log_error (const gchar *format, ...) G_GNUC_PRINTF(1, 2); 596 597 void log_flush (void); 598 599 #endif /* __UTILS_H__ */ 600