comparison src/util.c @ 6982:083d1e4a9c78

[gaim-migrate @ 7538] This is Mr. Holland's Opus. And by Mr. Holland I mean Robot101. He rewrote the coreish IM image support so that the binary data gets ripped out in the prpl and put in an imgstore instead of just being passed in the same huge as char string as the actual message. This is good because it's prpl agnostic, or something. It also means we don't have a silly length of "-1" with pretty much every send or receive IM function. It should be crash free, bug free, and memleak free, but additional testing is always a good thing. If you like good stuff then you'll love this patch. But don't take my word for it--ba dun dunt! committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 27 Sep 2003 19:17:21 +0000
parents dd0eecfbe413
children 9d038cc7e825
comparison
equal deleted inserted replaced
6981:abd3c684da31 6982:083d1e4a9c78
938 g_strfreev(split); 938 g_strfreev(split);
939 939
940 return ret; 940 return ret;
941 } 941 }
942 942
943 const char *gaim_strcasestr(const char *haystack, const char *needle) {
944 size_t hlen, nlen;
945 const char *tmp, *ret;
946
947 g_return_val_if_fail(haystack != NULL, NULL);
948 g_return_val_if_fail(needle != NULL, NULL);
949
950 hlen = strlen(haystack);
951 nlen = strlen(needle);
952 tmp = haystack,
953 ret = NULL;
954
955 g_return_val_if_fail(hlen > 0, NULL);
956 g_return_val_if_fail(nlen > 0, NULL);
957
958 while (*tmp && !ret) {
959 if (!g_ascii_strncasecmp(needle, tmp, nlen))
960 ret = tmp;
961 else
962 tmp++;
963 }
964
965 return ret;
966 }
967
943 char *gaim_get_size_string(size_t size) 968 char *gaim_get_size_string(size_t size)
944 { 969 {
945 static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; 970 static const char *size_str[4] = { "bytes", "KB", "MB", "GB" };
946 float size_mag; 971 float size_mag;
947 int size_index = 0; 972 int size_index = 0;
961 } 986 }
962 987
963 return g_strdup_printf("%.2f %s", size_mag, size_str[size_index]); 988 return g_strdup_printf("%.2f %s", size_mag, size_str[size_index]);
964 } 989 }
965 } 990 }
991
992 gboolean gaim_markup_find_tag(const char *needle, const char *haystack, const char **start, const char **end, GData **attributes) {
993 GData *attribs;
994 const char *cur = haystack;
995 char *name = NULL;
996 gboolean found = FALSE;
997 gboolean in_tag = FALSE;
998 gboolean in_attr = FALSE;
999 gboolean in_quotes = FALSE;
1000 size_t needlelen = strlen(needle);
1001
1002 g_datalist_init(&attribs);
1003
1004 while (*cur && !found) {
1005 if (in_tag) {
1006 if (in_quotes) {
1007 const char *close = cur;
1008
1009 while (*close && *close != '"')
1010 close++;
1011
1012 /* if we got the close quote, store the value and carry on from *
1013 * after it. if we ran to the end of the string, point to the NULL *
1014 * and we're outta here */
1015 if (*close) {
1016 /* only store a value if we have an attribute name */
1017 if (name) {
1018 size_t len = close - cur;
1019 char *val = g_strndup(cur, len);
1020
1021 g_datalist_set_data_full(&attribs, name, val, g_free);
1022 g_free(name);
1023 name = NULL;
1024 }
1025
1026 in_quotes = FALSE;
1027 cur = close + 1;
1028 } else {
1029 cur = close;
1030 }
1031 } else if (in_attr) {
1032 const char *close = cur;
1033
1034 while (*close && *close != '>' && *close != '"' && *close != ' ' && *close != '=')
1035 close++;
1036
1037 /* if we got the equals, store the name of the attribute. if we got
1038 * the quote, save the attribute and go straight to quote mode.
1039 * otherwise the tag closed or we reached the end of the string,
1040 * so we can get outta here */
1041 switch (*close) {
1042 case '"':
1043 in_quotes = TRUE;
1044 case '=':
1045 {
1046 size_t len = close - cur;
1047
1048 /* don't store a blank attribute name */
1049 if (len) {
1050 if (name)
1051 g_free(name);
1052 name = g_ascii_strdown(cur, len);
1053 }
1054
1055 in_attr = FALSE;
1056 cur = close + 1;
1057 break;
1058 }
1059 case ' ':
1060 case '>':
1061 in_attr = FALSE;
1062 default:
1063 cur = close;
1064 break;
1065 }
1066 } else {
1067 switch (*cur) {
1068 case ' ':
1069 /* swallow extra spaces inside tag */
1070 while (*cur && *cur == ' ') cur++;
1071 in_attr = TRUE;
1072 break;
1073 case '>':
1074 found = TRUE;
1075 *end = cur;
1076 break;
1077 case '"':
1078 in_quotes = TRUE;
1079 default:
1080 cur++;
1081 break;
1082 }
1083 }
1084 } else {
1085 /* if we hit a < followed by the name of our tag... */
1086 if (*cur == '<' && !g_ascii_strncasecmp(cur + 1, needle, needlelen)) {
1087 *start = cur;
1088 cur = cur + needlelen + 1;
1089
1090 /* if we're pointing at a space or a >, we found the right tag. if *
1091 * we're not, we've found a longer tag, so we need to skip to the *
1092 * >, but not being distracted by >s inside quotes. */
1093 if (*cur == ' ' || *cur == '>') {
1094 in_tag = TRUE;
1095 } else {
1096 while (*cur && *cur != '"' && *cur != '>') {
1097 if (*cur == '"') {
1098 cur++;
1099 while (*cur && *cur != '"')
1100 cur++;
1101 } else {
1102 cur++;
1103 }
1104 }
1105 }
1106 } else {
1107 cur++;
1108 }
1109 }
1110 }
1111
1112 /* clean up any attribute name from a premature termination */
1113 if (name)
1114 g_free(name);
1115
1116 if (found) {
1117 *attributes = attribs;
1118 } else {
1119 *start = NULL;
1120 *end = NULL;
1121 *attributes = NULL;
1122 }
1123
1124 return found;
1125 }