Mercurial > pidgin.yaz
comparison libpurple/plugins/log_reader.c @ 20921:b2b16843851b
A patch from QuLogic to eliminate some duplication in the aMSN code, also
from QuLogic. Fixes #3497 (again).
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sat, 13 Oct 2007 21:55:41 +0000 |
parents | 54d232b52607 |
children | d0fdf2f95277 |
comparison
equal
deleted
inserted
replaced
20920:ef44eb0859fe | 20921:b2b16843851b |
---|---|
2093 | 2093 |
2094 #define AMSN_LOG_CONV_START "|\"LRED[Conversation started on " | 2094 #define AMSN_LOG_CONV_START "|\"LRED[Conversation started on " |
2095 #define AMSN_LOG_CONV_END "|\"LRED[You have closed the window on " | 2095 #define AMSN_LOG_CONV_END "|\"LRED[You have closed the window on " |
2096 #define AMSN_LOG_CONV_EXTRA "01 Aug 2001 00:00:00]" | 2096 #define AMSN_LOG_CONV_EXTRA "01 Aug 2001 00:00:00]" |
2097 | 2097 |
2098 /* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ | 2098 static GList *amsn_logger_parse_file(char *filename, const char *sn, PurpleAccount *account) |
2099 /* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ | |
2100 static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) | |
2101 { | 2099 { |
2102 GList *list = NULL; | 2100 GList *list = NULL; |
2103 struct amsn_logger_data *data; | |
2104 const char *logdir; | |
2105 char *username; | |
2106 char *log_path; | |
2107 char *buddy_log; | |
2108 char *filename; | |
2109 GDir *dir; | |
2110 const char *name; | |
2111 GError *error; | 2101 GError *error; |
2112 char *contents; | 2102 char *contents; |
2103 struct amsn_logger_data *data; | |
2113 PurpleLog *log; | 2104 PurpleLog *log; |
2114 GList *files = NULL; | 2105 |
2115 GList *f; | 2106 purple_debug_info("aMSN logger", "Reading %s\n", filename); |
2116 | 2107 error = NULL; |
2117 logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); | 2108 if (!g_file_get_contents(filename, &contents, NULL, &error)) { |
2118 | 2109 purple_debug_error("aMSN logger", |
2119 /* By clearing the log directory path, this logger can be (effectively) disabled. */ | 2110 "Couldn't read file %s: %s \n", filename, |
2120 if (!logdir || !*logdir) | 2111 (error && error->message) ? |
2121 return NULL; | 2112 error->message : "Unknown error"); |
2122 | 2113 if (error) |
2123 /* aMSN only works with MSN/WLM */ | 2114 g_error_free(error); |
2124 if (strcmp(account->protocol_id, "prpl-msn")) | 2115 } else { |
2125 return NULL; | 2116 char *c = contents; |
2126 | 2117 gboolean found_start = FALSE; |
2127 username = g_strdup(purple_normalize(account, account->username)); | 2118 char *start_log = c; |
2128 buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); | 2119 int offset = 0; |
2129 log_path = g_build_filename(logdir, username, "logs", NULL); | 2120 struct tm tm; |
2130 | 2121 while (c && *c) { |
2131 /* First check in the top-level */ | 2122 if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { |
2132 filename = g_build_filename(log_path, buddy_log, NULL); | 2123 char month[4]; |
2133 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | 2124 if (sscanf(c + strlen(AMSN_LOG_CONV_START), |
2134 files = g_list_prepend(files, filename); | 2125 "%u %3s %u %u:%u:%u", |
2135 else | 2126 &tm.tm_mday, (char*)&month, &tm.tm_year, |
2136 g_free(filename); | 2127 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { |
2137 | |
2138 /* Check in previous months */ | |
2139 dir = g_dir_open(log_path, 0, NULL); | |
2140 if (dir) { | |
2141 while ((name = g_dir_read_name(dir)) != NULL) { | |
2142 filename = g_build_filename(log_path, name, buddy_log, NULL); | |
2143 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2144 files = g_list_prepend(files, filename); | |
2145 else | |
2146 g_free(filename); | |
2147 } | |
2148 g_dir_close(dir); | |
2149 } | |
2150 | |
2151 g_free(log_path); | |
2152 | |
2153 /* New versions use 'friendlier' directory names */ | |
2154 purple_util_chrreplace(username, '@', '_'); | |
2155 purple_util_chrreplace(username, '.', '_'); | |
2156 | |
2157 log_path = g_build_filename(logdir, username, "logs", NULL); | |
2158 | |
2159 /* First check in the top-level */ | |
2160 filename = g_build_filename(log_path, buddy_log, NULL); | |
2161 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2162 files = g_list_prepend(files, filename); | |
2163 else | |
2164 g_free(filename); | |
2165 | |
2166 /* Check in previous months */ | |
2167 dir = g_dir_open(log_path, 0, NULL); | |
2168 if (dir) { | |
2169 while ((name = g_dir_read_name(dir)) != NULL) { | |
2170 filename = g_build_filename(log_path, name, buddy_log, NULL); | |
2171 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2172 files = g_list_prepend(files, filename); | |
2173 else | |
2174 g_free(filename); | |
2175 } | |
2176 g_dir_close(dir); | |
2177 } | |
2178 | |
2179 g_free(log_path); | |
2180 g_free(username); | |
2181 g_free(buddy_log); | |
2182 | |
2183 /* Loop through files looking for logs */ | |
2184 for(f = g_list_first(files); f; f = g_list_next(f)) { | |
2185 filename = f->data; | |
2186 purple_debug_info("aMSN logger", "Reading %s\n", filename); | |
2187 error = NULL; | |
2188 if (!g_file_get_contents(filename, &contents, NULL, &error)) { | |
2189 purple_debug_error("aMSN logger", | |
2190 "Couldn't read file %s: %s \n", filename, | |
2191 (error && error->message) ? | |
2192 error->message : "Unknown error"); | |
2193 if (error) | |
2194 g_error_free(error); | |
2195 } else { | |
2196 char *c = contents; | |
2197 gboolean found_start = FALSE; | |
2198 char *start_log = c; | |
2199 int offset = 0; | |
2200 struct tm tm; | |
2201 while (c && *c) { | |
2202 if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { | |
2203 char month[4]; | |
2204 if (sscanf(c + strlen(AMSN_LOG_CONV_START), | |
2205 "%u %3s %u %u:%u:%u", | |
2206 &tm.tm_mday, (char*)&month, &tm.tm_year, | |
2207 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { | |
2208 found_start = FALSE; | |
2209 purple_debug_error("aMSN logger", | |
2210 "Error parsing start date for %s\n", | |
2211 filename); | |
2212 } else { | |
2213 tm.tm_year -= 1900; | |
2214 | |
2215 /* Let the C library deal with | |
2216 * daylight savings time. | |
2217 */ | |
2218 tm.tm_isdst = -1; | |
2219 tm.tm_mon = get_month(month); | |
2220 | |
2221 found_start = TRUE; | |
2222 offset = c - contents; | |
2223 start_log = c; | |
2224 } | |
2225 } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { | |
2226 data = g_new0(struct amsn_logger_data, 1); | |
2227 data->path = g_strdup(filename); | |
2228 data->offset = offset; | |
2229 data->length = c - start_log | |
2230 + strlen(AMSN_LOG_CONV_END) | |
2231 + strlen(AMSN_LOG_CONV_EXTRA); | |
2232 log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); | |
2233 log->logger = amsn_logger; | |
2234 log->logger_data = data; | |
2235 list = g_list_prepend(list, log); | |
2236 found_start = FALSE; | 2128 found_start = FALSE; |
2237 | 2129 purple_debug_error("aMSN logger", |
2238 purple_debug_info("aMSN logger", | 2130 "Error parsing start date for %s\n", |
2239 "Found log for %s:" | 2131 filename); |
2240 " path = (%s)," | 2132 } else { |
2241 " offset = (%d)," | 2133 tm.tm_year -= 1900; |
2242 " length = (%d)\n", | 2134 |
2243 sn, data->path, data->offset, data->length); | 2135 /* Let the C library deal with |
2136 * daylight savings time. | |
2137 */ | |
2138 tm.tm_isdst = -1; | |
2139 tm.tm_mon = get_month(month); | |
2140 | |
2141 found_start = TRUE; | |
2142 offset = c - contents; | |
2143 start_log = c; | |
2244 } | 2144 } |
2245 c = strstr(c, "\n"); | 2145 } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { |
2246 c++; | |
2247 } | |
2248 | |
2249 /* I've seen the file end without the AMSN_LOG_CONV_END bit */ | |
2250 if (found_start) { | |
2251 data = g_new0(struct amsn_logger_data, 1); | 2146 data = g_new0(struct amsn_logger_data, 1); |
2252 data->path = g_strdup(filename); | 2147 data->path = g_strdup(filename); |
2253 data->offset = offset; | 2148 data->offset = offset; |
2254 data->length = c - start_log | 2149 data->length = c - start_log |
2255 + strlen(AMSN_LOG_CONV_END) | 2150 + strlen(AMSN_LOG_CONV_END) |
2265 " path = (%s)," | 2160 " path = (%s)," |
2266 " offset = (%d)," | 2161 " offset = (%d)," |
2267 " length = (%d)\n", | 2162 " length = (%d)\n", |
2268 sn, data->path, data->offset, data->length); | 2163 sn, data->path, data->offset, data->length); |
2269 } | 2164 } |
2270 g_free(contents); | 2165 c = strstr(c, "\n"); |
2271 } | 2166 c++; |
2167 } | |
2168 | |
2169 /* I've seen the file end without the AMSN_LOG_CONV_END bit */ | |
2170 if (found_start) { | |
2171 data = g_new0(struct amsn_logger_data, 1); | |
2172 data->path = g_strdup(filename); | |
2173 data->offset = offset; | |
2174 data->length = c - start_log | |
2175 + strlen(AMSN_LOG_CONV_END) | |
2176 + strlen(AMSN_LOG_CONV_EXTRA); | |
2177 log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); | |
2178 log->logger = amsn_logger; | |
2179 log->logger_data = data; | |
2180 list = g_list_prepend(list, log); | |
2181 found_start = FALSE; | |
2182 | |
2183 purple_debug_info("aMSN logger", | |
2184 "Found log for %s:" | |
2185 " path = (%s)," | |
2186 " offset = (%d)," | |
2187 " length = (%d)\n", | |
2188 sn, data->path, data->offset, data->length); | |
2189 } | |
2190 g_free(contents); | |
2191 } | |
2192 | |
2193 return list; | |
2194 } | |
2195 | |
2196 /* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ | |
2197 /* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ | |
2198 static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) | |
2199 { | |
2200 GList *list = NULL; | |
2201 const char *logdir; | |
2202 char *username; | |
2203 char *log_path; | |
2204 char *buddy_log; | |
2205 char *filename; | |
2206 GDir *dir; | |
2207 const char *name; | |
2208 | |
2209 logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); | |
2210 | |
2211 /* By clearing the log directory path, this logger can be (effectively) disabled. */ | |
2212 if (!logdir || !*logdir) | |
2213 return NULL; | |
2214 | |
2215 /* aMSN only works with MSN/WLM */ | |
2216 if (strcmp(account->protocol_id, "prpl-msn")) | |
2217 return NULL; | |
2218 | |
2219 username = g_strdup(purple_normalize(account, account->username)); | |
2220 buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); | |
2221 log_path = g_build_filename(logdir, username, "logs", NULL); | |
2222 | |
2223 /* First check in the top-level */ | |
2224 filename = g_build_filename(log_path, buddy_log, NULL); | |
2225 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2226 list = amsn_logger_parse_file(filename, sn, account); | |
2227 else | |
2272 g_free(filename); | 2228 g_free(filename); |
2273 } | 2229 |
2274 | 2230 /* Check in previous months */ |
2275 g_list_free(files); | 2231 dir = g_dir_open(log_path, 0, NULL); |
2232 if (dir) { | |
2233 while ((name = g_dir_read_name(dir)) != NULL) { | |
2234 filename = g_build_filename(log_path, name, buddy_log, NULL); | |
2235 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2236 list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); | |
2237 g_free(filename); | |
2238 } | |
2239 g_dir_close(dir); | |
2240 } | |
2241 | |
2242 g_free(log_path); | |
2243 | |
2244 /* New versions use 'friendlier' directory names */ | |
2245 purple_util_chrreplace(username, '@', '_'); | |
2246 purple_util_chrreplace(username, '.', '_'); | |
2247 | |
2248 log_path = g_build_filename(logdir, username, "logs", NULL); | |
2249 | |
2250 /* First check in the top-level */ | |
2251 filename = g_build_filename(log_path, buddy_log, NULL); | |
2252 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2253 list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); | |
2254 g_free(filename); | |
2255 | |
2256 /* Check in previous months */ | |
2257 dir = g_dir_open(log_path, 0, NULL); | |
2258 if (dir) { | |
2259 while ((name = g_dir_read_name(dir)) != NULL) { | |
2260 filename = g_build_filename(log_path, name, buddy_log, NULL); | |
2261 if (g_file_test(filename, G_FILE_TEST_EXISTS)) | |
2262 list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); | |
2263 g_free(filename); | |
2264 } | |
2265 g_dir_close(dir); | |
2266 } | |
2267 | |
2268 g_free(log_path); | |
2269 g_free(username); | |
2270 g_free(buddy_log); | |
2276 | 2271 |
2277 return list; | 2272 return list; |
2278 } | 2273 } |
2279 | 2274 |
2280 /* Really it's |"L, but the string's been escaped */ | 2275 /* Really it's |"L, but the string's been escaped */ |