char * eval_replace_vars_cb (void *data, const char *text) { struct t_hashtable *pointers, *extra_vars; struct t_eval_regex *eval_regex; struct t_config_option *ptr_option; struct t_gui_buffer *ptr_buffer; char str_value[512], *value, *pos, *pos1, *pos2, *hdata_name, *list_name; char *tmp, *info_name, *hide_char, *hidden_string, *error; const char *prefix, *suffix, *ptr_value, *ptr_arguments, *ptr_string; struct t_hdata *hdata; void *pointer; int i, length_hide_char, length, index, rc, extra_vars_eval; long number; long unsigned int ptr; time_t date; struct tm *date_tmp; pointers = (struct t_hashtable *)(((void **)data)[0]); extra_vars = (struct t_hashtable *)(((void **)data)[1]); extra_vars_eval = *(int *)(((void **)data)[2]); prefix = (const char *)(((void **)data)[3]); suffix = (const char *)(((void **)data)[4]); eval_regex = (struct t_eval_regex *)(((void **)data)[5]); /* 1. variable in hashtable "extra_vars" */ if (extra_vars) { ptr_value = hashtable_get (extra_vars, text); if (ptr_value) { if (extra_vars_eval) { return eval_replace_vars (ptr_value, pointers, extra_vars, extra_vars_eval, prefix, suffix, eval_regex); } else { return strdup (ptr_value); } } } /* * 2. force evaluation of string (recursive call) * --> use with caution: the text must be safe! */ if (strncmp (text, "eval:", 5) == 0) { return eval_replace_vars (text + 5, pointers, extra_vars, extra_vars_eval, prefix, suffix, eval_regex); } /* 3. convert escaped chars */ if (strncmp (text, "esc:", 4) == 0) return string_convert_escaped_chars (text + 4); if ((text[0] == '\\') && text[1] && (text[1] != '\\')) return string_convert_escaped_chars (text); /* 4. hide chars: replace all chars by a given char/string */ if (strncmp (text, "hide:", 5) == 0) { hidden_string = NULL; ptr_string = strchr (text + 5, (text[5] == ',') ? ';' : ','); if (!ptr_string) return strdup (""); hide_char = string_strndup (text + 5, ptr_string - text - 5); if (hide_char) { length_hide_char = strlen (hide_char); length = utf8_strlen (ptr_string + 1); hidden_string = malloc ((length * length_hide_char) + 1); if (hidden_string) { index = 0; for (i = 0; i < length; i++) { memcpy (hidden_string + index, hide_char, length_hide_char); index += length_hide_char; } hidden_string[length * length_hide_char] = '\0'; } free (hide_char); } return (hidden_string) ? hidden_string : strdup (""); } /* 5. regex group captured */ if (strncmp (text, "re:", 3) == 0) { if (eval_regex && eval_regex->result) { if (strcmp (text + 3, "+") == 0) number = eval_regex->last_match; else { number = strtol (text + 3, &error, 10); if (!error || error[0]) number = -1; } if ((number >= 0) && (number <= eval_regex->last_match)) { return string_strndup ( eval_regex->result + eval_regex->match[number].rm_so, eval_regex->match[number].rm_eo - eval_regex->match[number].rm_so); } } return strdup (""); } /* 6. color code */ if (strncmp (text, "color:", 6) == 0) { ptr_value = gui_color_search_config (text + 6); if (ptr_value) return strdup (ptr_value); ptr_value = gui_color_get_custom (text + 6); return strdup ((ptr_value) ? ptr_value : ""); } /* 7. info */ if (strncmp (text, "info:", 5) == 0) { ptr_value = NULL; ptr_arguments = strchr (text + 5, ','); if (ptr_arguments) { info_name = string_strndup (text + 5, ptr_arguments - text - 5); ptr_arguments++; } else info_name = strdup (text + 5); if (info_name) { ptr_value = hook_info_get (NULL, info_name, ptr_arguments); free (info_name); } return strdup ((ptr_value) ? ptr_value : ""); } /* 8. current date/time */ if ((strncmp (text, "date", 4) == 0) && (!text[4] || (text[4] == ':'))) { date = time (NULL); date_tmp = localtime (&date); if (!date_tmp) return strdup (""); rc = (int) strftime (str_value, sizeof (str_value), (text[4] == ':') ? text + 5 : "%F %T", date_tmp); return strdup ((rc > 0) ? str_value : ""); } /* 9. environment variable */ if (strncmp (text, "env:", 4) == 0) { ptr_value = getenv (text + 4); if (ptr_value) return strdup (ptr_value); } /* 10. option: if found, return this value */ if (strncmp (text, "sec.data.", 9) == 0) { ptr_value = hashtable_get (secure_hashtable_data, text + 9); return strdup ((ptr_value) ? ptr_value : ""); } else { config_file_search_with_string (text, NULL, NULL, &ptr_option, NULL); if (ptr_option) { if (!ptr_option->value) return strdup (""); switch (ptr_option->type) { case CONFIG_OPTION_TYPE_BOOLEAN: return strdup (CONFIG_BOOLEAN(ptr_option) ? EVAL_STR_TRUE : EVAL_STR_FALSE); case CONFIG_OPTION_TYPE_INTEGER: if (ptr_option->string_values) return strdup (ptr_option->string_values[CONFIG_INTEGER(ptr_option)]); snprintf (str_value, sizeof (str_value), "%d", CONFIG_INTEGER(ptr_option)); return strdup (str_value); case CONFIG_OPTION_TYPE_STRING: return strdup (CONFIG_STRING(ptr_option)); case CONFIG_OPTION_TYPE_COLOR: return strdup (gui_color_get_name (CONFIG_COLOR(ptr_option))); case CONFIG_NUM_OPTION_TYPES: return strdup (""); } } } /* 11. local variable in buffer */ ptr_buffer = hashtable_get (pointers, "buffer"); if (ptr_buffer) { ptr_value = hashtable_get (ptr_buffer->local_variables, text); if (ptr_value) return strdup (ptr_value); } /* 12. hdata */ value = NULL; hdata_name = NULL; list_name = NULL; pointer = NULL; pos = strchr (text, '.'); if (pos > text) hdata_name = string_strndup (text, pos - text); else hdata_name = strdup (text); if (!hdata_name) goto end; pos1 = strchr (hdata_name, '['); if (pos1 > hdata_name) { pos2 = strchr (pos1 + 1, ']'); if (pos2 > pos1 + 1) { list_name = string_strndup (pos1 + 1, pos2 - pos1 - 1); } tmp = string_strndup (hdata_name, pos1 - hdata_name); if (tmp) { free (hdata_name); hdata_name = tmp; } } hdata = hook_hdata_get (NULL, hdata_name); if (!hdata) goto end; if (list_name) { if (strncmp (list_name, "0x", 2) == 0) { rc = sscanf (list_name, "%lx", &ptr); if ((rc != EOF) && (rc != 0)) { pointer = (void *)ptr; if (!hdata_check_pointer (hdata, NULL, pointer)) goto end; } else goto end; } else pointer = hdata_get_list (hdata, list_name); } if (!pointer) { pointer = hashtable_get (pointers, hdata_name); if (!pointer) goto end; } value = eval_hdata_get_value (hdata, pointer, (pos) ? pos + 1 : NULL); end: if (hdata_name) free (hdata_name); if (list_name) free (list_name); return (value) ? value : strdup (""); }
char * eval_hdata_get_value (struct t_hdata *hdata, void *pointer, const char *path) { char *value, *old_value, *var_name, str_value[128], *pos; const char *ptr_value, *hdata_name; int type; struct t_hashtable *hashtable; value = NULL; var_name = NULL; /* NULL pointer? return empty string */ if (!pointer) return strdup (""); /* no path? just return current pointer as string */ if (!path || !path[0]) { snprintf (str_value, sizeof (str_value), "0x%lx", (long unsigned int)pointer); return strdup (str_value); } /* * look for name of hdata, for example in "window.buffer.full_name", the * hdata name is "window" */ pos = strchr (path, '.'); if (pos > path) var_name = string_strndup (path, pos - path); else var_name = strdup (path); if (!var_name) goto end; /* search type of variable in hdata */ type = hdata_get_var_type (hdata, var_name); if (type < 0) goto end; /* build a string with the value or variable */ switch (type) { case WEECHAT_HDATA_CHAR: snprintf (str_value, sizeof (str_value), "%c", hdata_char (hdata, pointer, var_name)); value = strdup (str_value); break; case WEECHAT_HDATA_INTEGER: snprintf (str_value, sizeof (str_value), "%d", hdata_integer (hdata, pointer, var_name)); value = strdup (str_value); break; case WEECHAT_HDATA_LONG: snprintf (str_value, sizeof (str_value), "%ld", hdata_long (hdata, pointer, var_name)); value = strdup (str_value); break; case WEECHAT_HDATA_STRING: case WEECHAT_HDATA_SHARED_STRING: ptr_value = hdata_string (hdata, pointer, var_name); value = (ptr_value) ? strdup (ptr_value) : NULL; break; case WEECHAT_HDATA_POINTER: pointer = hdata_pointer (hdata, pointer, var_name); snprintf (str_value, sizeof (str_value), "0x%lx", (long unsigned int)pointer); value = strdup (str_value); break; case WEECHAT_HDATA_TIME: snprintf (str_value, sizeof (str_value), "%ld", (long)hdata_time (hdata, pointer, var_name)); value = strdup (str_value); break; case WEECHAT_HDATA_HASHTABLE: pointer = hdata_hashtable (hdata, pointer, var_name); if (pos) { /* * for a hashtable, if there is a "." after name of hdata, * get the value for this key in hashtable */ hashtable = pointer; ptr_value = hashtable_get (hashtable, pos + 1); if (ptr_value) { switch (hashtable->type_values) { case HASHTABLE_INTEGER: snprintf (str_value, sizeof (str_value), "%d", *((int *)ptr_value)); value = strdup (str_value); break; case HASHTABLE_STRING: value = strdup (ptr_value); break; case HASHTABLE_POINTER: case HASHTABLE_BUFFER: snprintf (str_value, sizeof (str_value), "0x%lx", (long unsigned int)ptr_value); value = strdup (str_value); break; case HASHTABLE_TIME: snprintf (str_value, sizeof (str_value), "%ld", (long)(*((time_t *)ptr_value))); value = strdup (str_value); break; case HASHTABLE_NUM_TYPES: break; } } } else { snprintf (str_value, sizeof (str_value), "0x%lx", (long unsigned int)pointer); value = strdup (str_value); } break; } /* * if we are on a pointer and that something else is in path (after "."), * go on with this pointer and remaining path */ if ((type == WEECHAT_HDATA_POINTER) && pos) { hdata_name = hdata_get_var_hdata (hdata, var_name); if (!hdata_name) goto end; hdata = hook_hdata_get (NULL, hdata_name); old_value = value; value = eval_hdata_get_value (hdata, pointer, (pos) ? pos + 1 : NULL); if (old_value) free (old_value); } end: if (var_name) free (var_name); return value; }
char * eval_replace_vars_cb (void *data, const char *text) { struct t_hashtable *pointers, *extra_vars; struct t_config_option *ptr_option; struct t_gui_buffer *ptr_buffer; char str_value[64], *value, *pos, *pos1, *pos2, *hdata_name, *list_name; char *tmp, *info_name, *hide_char, *hidden_string; const char *ptr_value, *ptr_arguments, *ptr_string; struct t_hdata *hdata; void *pointer; int i, length_hide_char, length, index; pointers = (struct t_hashtable *)(((void **)data)[0]); extra_vars = (struct t_hashtable *)(((void **)data)[1]); /* 1. look for var in hashtable "extra_vars" */ if (extra_vars) { ptr_value = hashtable_get (extra_vars, text); if (ptr_value) return strdup (ptr_value); } /* 2. convert escaped chars */ if (strncmp (text, "esc:", 4) == 0) return string_convert_escaped_chars (text + 4); if ((text[0] == '\\') && text[1] && (text[1] != '\\')) return string_convert_escaped_chars (text); /* 3. hide chars: replace all chars by a given char */ if (strncmp (text, "hide:", 5) == 0) { hidden_string = NULL; ptr_string = strchr (text + 5, (text[5] == ',') ? ';' : ','); if (!ptr_string) return strdup (""); hide_char = string_strndup (text + 5, ptr_string - text - 5); if (hide_char) { length_hide_char = strlen (hide_char); length = utf8_strlen (ptr_string + 1); hidden_string = malloc ((length * length_hide_char) + 1); if (hidden_string) { index = 0; for (i = 0; i < length; i++) { memcpy (hidden_string + index, hide_char, length_hide_char); index += length_hide_char; } hidden_string[length * length_hide_char] = '\0'; } free (hide_char); } return (hidden_string) ? hidden_string : strdup (""); } /* 4. look for a color */ if (strncmp (text, "color:", 6) == 0) { ptr_value = gui_color_get_custom (text + 6); return strdup ((ptr_value) ? ptr_value : ""); } /* 5. look for an info */ if (strncmp (text, "info:", 5) == 0) { ptr_value = NULL; ptr_arguments = strchr (text + 5, ','); if (ptr_arguments) { info_name = string_strndup (text + 5, ptr_arguments - text - 5); ptr_arguments++; } else info_name = strdup (text + 5); if (info_name) { ptr_value = hook_info_get (NULL, info_name, ptr_arguments); free (info_name); } return strdup ((ptr_value) ? ptr_value : ""); } /* 6. look for name of option: if found, return this value */ if (strncmp (text, "sec.data.", 9) == 0) { ptr_value = hashtable_get (secure_hashtable_data, text + 9); return strdup ((ptr_value) ? ptr_value : ""); } else { config_file_search_with_string (text, NULL, NULL, &ptr_option, NULL); if (ptr_option) { if (!ptr_option->value) return strdup (""); switch (ptr_option->type) { case CONFIG_OPTION_TYPE_BOOLEAN: return strdup (CONFIG_BOOLEAN(ptr_option) ? EVAL_STR_TRUE : EVAL_STR_FALSE); case CONFIG_OPTION_TYPE_INTEGER: if (ptr_option->string_values) return strdup (ptr_option->string_values[CONFIG_INTEGER(ptr_option)]); snprintf (str_value, sizeof (str_value), "%d", CONFIG_INTEGER(ptr_option)); return strdup (str_value); case CONFIG_OPTION_TYPE_STRING: return strdup (CONFIG_STRING(ptr_option)); case CONFIG_OPTION_TYPE_COLOR: return strdup (gui_color_get_name (CONFIG_COLOR(ptr_option))); case CONFIG_NUM_OPTION_TYPES: return strdup (""); } } } /* 7. look for local variable in buffer */ ptr_buffer = hashtable_get (pointers, "buffer"); if (ptr_buffer) { ptr_value = hashtable_get (ptr_buffer->local_variables, text); if (ptr_value) return strdup (ptr_value); } /* 8. look for hdata */ value = NULL; hdata_name = NULL; list_name = NULL; pointer = NULL; pos = strchr (text, '.'); if (pos > text) hdata_name = string_strndup (text, pos - text); else hdata_name = strdup (text); if (!hdata_name) goto end; pos1 = strchr (hdata_name, '['); if (pos1 > hdata_name) { pos2 = strchr (pos1 + 1, ']'); if (pos2 > pos1 + 1) { list_name = string_strndup (pos1 + 1, pos2 - pos1 - 1); } tmp = string_strndup (hdata_name, pos1 - hdata_name); if (tmp) { free (hdata_name); hdata_name = tmp; } } hdata = hook_hdata_get (NULL, hdata_name); if (!hdata) goto end; if (list_name) pointer = hdata_get_list (hdata, list_name); if (!pointer) { pointer = hashtable_get (pointers, hdata_name); if (!pointer) goto end; } value = eval_hdata_get_value (hdata, pointer, (pos) ? pos + 1 : NULL); end: if (hdata_name) free (hdata_name); if (list_name) free (list_name); return (value) ? value : strdup (""); }