comparison libpurple/plugins/log_reader.c @ 17979:c8d2e131cc37

QIP logger was implemented
author Michael Shkutkov <mshkutkov@soc.pidgin.im>
date Wed, 13 Jun 2007 12:26:17 +0000
parents 21773944db4b
children b5e9a814b711
comparison
equal deleted inserted replaced
17978:fa4b70c5ea9d 17979:c8d2e131cc37
1722 g_free(data->path); 1722 g_free(data->path);
1723 g_free(data->their_nickname); 1723 g_free(data->their_nickname);
1724 1724
1725 } 1725 }
1726 1726
1727 /*****************************************************************************
1728 * QIP Logger *
1729 *****************************************************************************/
1730
1731 /* The QIP logger doesn't write logs, only reads them. This is to include
1732 * QIP logs in the log viewer transparently.
1733 */
1734 #define QIP_LOG_DELIMITER "--------------------------------------"
1735 #define QIP_LOG_IN_MESSAGE (QIP_LOG_DELIMITER "<-")
1736 #define QIP_LOG_OUT_MESSAGE (QIP_LOG_DELIMITER ">-")
1737 #define QIP_LOG_IN_MESSAGE_ESC (QIP_LOG_DELIMITER "&lt;-")
1738 #define QIP_LOG_OUT_MESSAGE_ESC (QIP_LOG_DELIMITER "&gt;-")
1739
1740 #define DEBUG_MESSAGE(var, sign, value, title) if(var sign value) \
1741 purple_debug(PURPLE_DEBUG_ERROR, title, \
1742 #var " " #sign " " #value "\n");
1743
1744 static PurpleLogLogger *qip_logger;
1745 static void qip_logger_finalize(PurpleLog *log);
1746
1747 struct qip_logger_data {
1748
1749 char *path; /* FIXME: Change this to use PurpleStringref like log.c:old_logger_list */
1750 int offset;
1751 int length;
1752 };
1753
1754 static GList *qip_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account)
1755 {
1756 GList *list = NULL;
1757 const char *logdir;
1758 PurplePlugin *plugin;
1759 PurplePluginProtocolInfo *prpl_info;
1760 const char *buddy_name;
1761 char *username;
1762 char *filename;
1763 char *path;
1764 GError *error = NULL;
1765 gchar *contents = NULL;
1766 gsize length;
1767 gchar *c;
1768
1769 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1770 "start\n");
1771
1772 g_return_val_if_fail(sn != NULL, list);
1773 g_return_val_if_fail(account != NULL, list);
1774
1775 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1776 "arguments not NULL\n");
1777
1778 /* QIP is ICQ messenger. Should we add prpl-aim? */
1779 if (strcmp(account->protocol_id, "prpl-icq"))
1780 return list;
1781
1782 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1783 "protocol is 'prpl-icq'\n");
1784
1785 logdir = purple_prefs_get_string("/plugins/core/log_reader/qip/log_directory");
1786
1787 /* By clearing the log directory path, this logger can be (effectively) disabled. */
1788 if (!*logdir)
1789 return list;
1790
1791 plugin = purple_find_prpl(purple_account_get_protocol_id(account));
1792 if (!plugin)
1793 return NULL;
1794
1795 prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
1796 if (!prpl_info->list_icon)
1797 return NULL;
1798
1799 buddy_name = g_strdup(purple_normalize(account, sn));
1800 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1801 "buddy_name %s\n", buddy_name);
1802
1803 username = g_strdup(purple_normalize(account, account->username));
1804 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1805 "username %s\n", username);
1806
1807 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1808 "sn %s\n", sn);
1809
1810 filename = g_strdup_printf("%s.txt", buddy_name);
1811 path = g_build_filename(
1812 logdir, username, "History", filename, NULL);
1813 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1814 "Reading %s\n", path);
1815 if (!g_file_get_contents(path, &contents, &length, &error))
1816 if (error)
1817 g_error_free(error);
1818
1819 if (contents) {
1820 struct qip_logger_data *data = NULL;
1821
1822 purple_debug(PURPLE_DEBUG_INFO, "QIP logger list",
1823 "File %s is found\n", filename);
1824 c = contents;
1825 if (purple_str_has_prefix(c, QIP_LOG_IN_MESSAGE) ||
1826 purple_str_has_prefix(c, QIP_LOG_OUT_MESSAGE)) {
1827
1828 /* find next line */
1829 while(*c && *c != '\n') {
1830 c++;
1831 }
1832
1833 if (*c) {
1834 char *timestamp = c;
1835
1836 while (*timestamp && (*timestamp !='('))
1837 timestamp++;
1838
1839 if (*timestamp == '(') {
1840 struct tm tm;
1841
1842 timestamp++;
1843
1844 /* Parse the time, day, month and year */
1845 if (sscanf(timestamp, "%u:%u:%u %u/%u/%u",
1846 &tm.tm_hour, &tm.tm_min, &tm.tm_sec,
1847 &tm.tm_mday, &tm.tm_mon, &tm.tm_year) != 6) {
1848 purple_debug(PURPLE_DEBUG_ERROR, "QIP logger list",
1849 "Parsing timestamp error\n");
1850 } else {
1851 PurpleLog *log;
1852
1853
1854 /* cos month of year in [0,11] */
1855 tm.tm_mon -= 1;
1856 /* cos years since 1900 */
1857 tm.tm_year -= 1900;
1858
1859 purple_debug(PURPLE_DEBUG_INFO,
1860 "QIP logger list",
1861 "Parsing timestamp: %u/%u/%u %u:%u:%u\n",
1862 tm.tm_year, tm.tm_mon, tm.tm_mday,
1863 tm.tm_hour, tm.tm_min, tm.tm_sec);
1864
1865 /* Let the C library deal with
1866 * daylight savings time.
1867 */
1868 tm.tm_isdst = -1;
1869
1870 data = g_new0(
1871 struct qip_logger_data, 1);
1872 data->path = g_strdup(path);
1873 data->offset = 0;
1874 data->length = strlen(contents);
1875
1876 /* XXX: Look into this later... Should we pass in a struct tm? */
1877 log = purple_log_new(PURPLE_LOG_IM,
1878 sn, account, NULL, mktime(&tm), NULL);
1879
1880 log->logger = qip_logger;
1881 log->logger_data = data;
1882
1883 list = g_list_append(list, log);
1884 }
1885 }
1886 }
1887 }
1888
1889 g_free(contents);
1890 }
1891
1892 g_free(username);
1893 g_free(path);
1894 g_free(filename);
1895
1896 return list;
1897 }
1898
1899 static char * qip_logger_read (PurpleLog *log, PurpleLogReadFlags *flags)
1900 {
1901 struct qip_logger_data *data;
1902 char *read;
1903 FILE *file;
1904 PurpleBuddy *buddy;
1905 char *escaped;
1906 GString *formatted;
1907 char *c;
1908 const char *line;
1909
1910 purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
1911 "start\n");
1912
1913 DEBUG_MESSAGE(log, ==, NULL, "QIP logger read");
1914 g_return_val_if_fail(log != NULL, g_strdup(""));
1915
1916 data = log->logger_data;
1917
1918 DEBUG_MESSAGE(data->path, ==, NULL, "QIP logger read");
1919 g_return_val_if_fail(data->path != NULL, g_strdup(""));
1920
1921 DEBUG_MESSAGE(data->length, <=, 0, "QIP logger read");
1922 g_return_val_if_fail(data->length > 0, g_strdup(""));
1923
1924
1925 purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
1926 "Reading %s\n", data->path);
1927
1928 read = g_malloc(data->length + 2);
1929
1930 file = g_fopen(data->path, "rb");
1931 fseek(file, data->offset, SEEK_SET);
1932 fread(read, data->length, 1, file);
1933 fclose(file);
1934
1935 if (read[data->length-1] == '\n') {
1936 read[data->length] = '\0';
1937 } else {
1938 read[data->length] = '\n';
1939 read[data->length+1] = '\0';
1940 }
1941
1942 /* Load miscellaneous data. */
1943 buddy = purple_find_buddy(log->account, log->name);
1944
1945 escaped = g_markup_escape_text(read, -1);
1946 g_free(read);
1947 read = escaped;
1948
1949 /* Apply formatting... */
1950 formatted = g_string_sized_new(strlen(read));
1951 c = read;
1952 line = read;
1953
1954 while (*c)
1955 {
1956 gboolean is_in_message = FALSE;
1957
1958 if (purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC) ||
1959 purple_str_has_prefix(line, QIP_LOG_OUT_MESSAGE_ESC)) {
1960 const char *buddy_name;
1961 is_in_message = purple_str_has_prefix(line, QIP_LOG_IN_MESSAGE_ESC);
1962
1963 purple_debug(PURPLE_DEBUG_INFO, "QIP loggger read",
1964 "%s message\n", (is_in_message) ? "incoming" : "Outgoing");
1965
1966 /* find next line */
1967 while(*c && *c!= '\n')
1968 c++;
1969 /* XXX: Do we need buddy_name when we have buddy->alias? */
1970 buddy_name = c;
1971
1972 /* we hope that nickname hasn't '(' symbol */
1973 while (*c && *c != '(')
1974 c++;
1975
1976 if (*c == '(') {
1977 const char *timestamp = c;
1978 int hour;
1979 int min;
1980 int sec;
1981
1982 timestamp++;
1983
1984 /* Parse the time, day, month and year */
1985 if (sscanf(timestamp, "%u:%u:%u",
1986 &hour, &min, &sec) != 3)
1987 purple_debug(PURPLE_DEBUG_ERROR, "QIP logger read",
1988 "Parsing timestamp error\n");
1989 else {
1990 g_string_append(formatted, "<font size=\"2\">");
1991 g_string_append_printf(formatted,
1992 "(%u:%02u:%02u) %cM ", hour % 12,
1993 min, sec, (hour >= 12) ? 'P': 'A');
1994 g_string_append(formatted, "</font> ");
1995
1996 if (is_in_message) {
1997 if (buddy_name != NULL && buddy->alias) {
1998 g_string_append_printf(formatted,
1999 "<span style=\"color: #A82F2F;\">"
2000 "<b>%s</b></span>: ", buddy->alias);
2001 }
2002 } else {
2003 const char *acct_name;
2004 acct_name = purple_account_get_alias(log->account);
2005 if (!acct_name)
2006 acct_name = purple_account_get_username(log->account);
2007
2008 g_string_append_printf(formatted,
2009 "<span style=\"color: #16569E;\">"
2010 "<b>%s</b></span>: ", acct_name);
2011 }
2012
2013 /* find next line */
2014 while(c && *c != '\n')
2015 c++;
2016
2017 line = ++c;
2018
2019 if ((c = strstr(c, "\n")))
2020 *c = '\0';
2021
2022 purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
2023 "writing message: \"%s\"\n", line);
2024
2025 g_string_append(formatted, line);
2026 line = ++c;
2027 g_string_append_c(formatted, '\n');
2028 }
2029 }
2030 } else {
2031 if ((c = strchr(c, '\n')))
2032 *c = '\0';
2033
2034 if (line[0] != '\n' && line[0] != '\r') {
2035 purple_debug(PURPLE_DEBUG_INFO, "QIP logger read",
2036 "line is not delimiter \"%s\"\n", line);
2037
2038 g_string_append(formatted, line);
2039 g_string_append_c(formatted, '\n');
2040 }
2041 line = ++c;
2042 }
2043 }
2044 g_free(read);
2045 /* XXX: TODO: Avoid this g_strchomp() */
2046 return g_strchomp(g_string_free(formatted, FALSE));
2047 }
2048
2049 static int qip_logger_size (PurpleLog *log)
2050 {
2051 struct qip_logger_data *data;
2052 char *text;
2053 size_t size;
2054
2055 g_return_val_if_fail(log != NULL, 0);
2056
2057 data = log->logger_data;
2058
2059 if (purple_prefs_get_bool("/plugins/core/log_reader/fast_sizes")) {
2060 return data ? data->length : 0;
2061 }
2062
2063 text = qip_logger_read(log, NULL);
2064 size = strlen(text);
2065 g_free(text);
2066
2067 return size;
2068 }
2069
2070 static void qip_logger_finalize(PurpleLog *log)
2071 {
2072 struct qip_logger_data *data;
2073
2074 g_return_if_fail(log != NULL);
2075
2076 data = log->logger_data;
2077
2078 g_free(data->path);
2079 }
1727 2080
1728 /***************************************************************************** 2081 /*****************************************************************************
1729 * Plugin Code * 2082 * Plugin Code *
1730 *****************************************************************************/ 2083 *****************************************************************************/
1731 2084
1968 g_free(folder); 2321 g_free(folder);
1969 } else /* !folder */ 2322 } else /* !folder */
1970 path = g_strdup(""); 2323 path = g_strdup("");
1971 #endif 2324 #endif
1972 2325
1973 purple_prefs_add_string("/plugins/core/log_reader/trillian/log_directory", path);
1974 g_free(path);
1975
1976 #ifdef _WIN32 2326 #ifdef _WIN32
1977 } /* !found */ 2327 } /* !found */
1978 #endif 2328 #endif
2329
2330 /* Add QIP log directory preference. */
2331 purple_prefs_add_none("/plugins/core/log_reader/qip");
2332
2333 #ifdef _WIN32
2334 /* Calculate default Messenger Plus! log directory. */
2335 folder = wpurple_get_special_folder(CSIDL_PROGRAM_FILES);
2336 if (folder) {
2337 #endif
2338 path = g_build_filename(
2339 #ifdef _WIN32
2340 folder,
2341 #else
2342 PURPLE_LOG_READER_WINDOWS_MOUNT_POINT, "Program Files",
2343 #endif
2344 "QIP", "Users", NULL);
2345 #ifdef _WIN32
2346 g_free(folder);
2347 } else /* !folder */
2348 path = g_strdup("");
2349 #endif
2350
2351 purple_debug(PURPLE_DEBUG_INFO, "QIP log reader", "QIP log directory %s\n", path);
2352
2353 purple_prefs_add_string("/plugins/core/log_reader/qip/log_directory", path);
2354 g_free(path);
1979 } 2355 }
1980 2356
1981 static gboolean 2357 static gboolean
1982 plugin_load(PurplePlugin *plugin) 2358 plugin_load(PurplePlugin *plugin)
1983 { 2359 {
2017 messenger_plus_logger_finalize, 2393 messenger_plus_logger_finalize,
2018 messenger_plus_logger_list, 2394 messenger_plus_logger_list,
2019 messenger_plus_logger_read, 2395 messenger_plus_logger_read,
2020 messenger_plus_logger_size); 2396 messenger_plus_logger_size);
2021 purple_log_logger_add(messenger_plus_logger); 2397 purple_log_logger_add(messenger_plus_logger);
2022 #endif 2398
2023 2399 #endif
2400
2401 /* The names of IM clients are marked for translation at the request of
2402 translators who wanted to transliterate them. Many translators
2403 choose to leave them alone. Choose what's best for your language. */
2404 qip_logger = purple_log_logger_new("qip", _("QIP"), 6,
2405 NULL,
2406 NULL,
2407 qip_logger_finalize,
2408 qip_logger_list,
2409 qip_logger_read,
2410 qip_logger_size);
2411 purple_log_logger_add(qip_logger);
2412
2024 /* The names of IM clients are marked for translation at the request of 2413 /* The names of IM clients are marked for translation at the request of
2025 translators who wanted to transliterate them. Many translators 2414 translators who wanted to transliterate them. Many translators
2026 choose to leave them alone. Choose what's best for your language. */ 2415 choose to leave them alone. Choose what's best for your language. */
2027 msn_logger = purple_log_logger_new("msn", _("MSN Messenger"), 6, 2416 msn_logger = purple_log_logger_new("msn", _("MSN Messenger"), 6,
2028 NULL, 2417 NULL,
2058 purple_log_logger_remove(fire_logger); 2447 purple_log_logger_remove(fire_logger);
2059 purple_log_logger_remove(messenger_plus_logger); 2448 purple_log_logger_remove(messenger_plus_logger);
2060 #endif 2449 #endif
2061 purple_log_logger_remove(msn_logger); 2450 purple_log_logger_remove(msn_logger);
2062 purple_log_logger_remove(trillian_logger); 2451 purple_log_logger_remove(trillian_logger);
2452 purple_log_logger_remove(qip_logger);
2063 2453
2064 return TRUE; 2454 return TRUE;
2065 } 2455 }
2066 2456
2067 static PurplePluginPrefFrame * 2457 static PurplePluginPrefFrame *
2105 2495
2106 ppref = purple_plugin_pref_new_with_name_and_label( 2496 ppref = purple_plugin_pref_new_with_name_and_label(
2107 "/plugins/core/log_reader/messenger_plus/log_directory", _("Messenger Plus!")); 2497 "/plugins/core/log_reader/messenger_plus/log_directory", _("Messenger Plus!"));
2108 purple_plugin_pref_frame_add(frame, ppref); 2498 purple_plugin_pref_frame_add(frame, ppref);
2109 #endif 2499 #endif
2500
2501 ppref = purple_plugin_pref_new_with_name_and_label(
2502 "/plugins/core/log_reader/qip/log_directory", _("QIP"));
2503 purple_plugin_pref_frame_add(frame, ppref);
2504 purple_debug(PURPLE_DEBUG_INFO, "QIP log reader", "QIP creating directory\n");
2110 2505
2111 ppref = purple_plugin_pref_new_with_name_and_label( 2506 ppref = purple_plugin_pref_new_with_name_and_label(
2112 "/plugins/core/log_reader/msn/log_directory", _("MSN Messenger")); 2507 "/plugins/core/log_reader/msn/log_directory", _("MSN Messenger"));
2113 purple_plugin_pref_frame_add(frame, ppref); 2508 purple_plugin_pref_frame_add(frame, ppref);
2114 2509