summaryrefslogtreecommitdiff
path: root/plugins/NewsAggregstor/Src
diff options
context:
space:
mode:
authorVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
committerVadim Dashevskiy <watcherhd@gmail.com>2012-05-15 10:38:20 +0000
commit48540940b6c28bb4378abfeb500ec45a625b37b6 (patch)
tree2ef294c0763e802f91d868bdef4229b6868527de /plugins/NewsAggregstor/Src
parent5c350913f011e119127baeb32a6aedeb4f0d33bc (diff)
initial commit
git-svn-id: http://svn.miranda-ng.org/main/trunk@2 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/NewsAggregstor/Src')
-rw-r--r--plugins/NewsAggregstor/Src/Common.h162
-rw-r--r--plugins/NewsAggregstor/Src/Entities.cpp381
-rw-r--r--plugins/NewsAggregstor/Src/Icons.cpp79
-rw-r--r--plugins/NewsAggregstor/Src/Menus.cpp78
-rw-r--r--plugins/NewsAggregstor/Src/NewsAggregator.cpp140
-rw-r--r--plugins/NewsAggregstor/Src/Options.cpp627
-rw-r--r--plugins/NewsAggregstor/Src/Services.cpp232
-rw-r--r--plugins/NewsAggregstor/Src/Update.cpp147
-rw-r--r--plugins/NewsAggregstor/Src/Utils.cpp1389
9 files changed, 3235 insertions, 0 deletions
diff --git a/plugins/NewsAggregstor/Src/Common.h b/plugins/NewsAggregstor/Src/Common.h
new file mode 100644
index 0000000000..789ddcffea
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Common.h
@@ -0,0 +1,162 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#define MIRANDA_VER 0x0A00
+
+// Windows Header Files:
+#include <windows.h>
+#include <commctrl.h>
+#include <time.h>
+#include <fcntl.h>
+#include <io.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys\stat.h>
+
+#include <boost/regex.hpp>
+
+// Miranda header files
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_langpack.h>
+#include <m_options.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_system.h>
+#include <m_popup.h>
+#include <m_hotkeys.h>
+#include <m_netlib.h>
+#include <m_icolib.h>
+#include <win2k.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_xml.h>
+#include <m_avatars.h>
+
+#include <m_folders.h>
+#include <m_popup.h>
+
+#include "..\version.h"
+#include "..\resource.h"
+
+#define MODULE "NewsAggr"
+#define TAGSHELP "#<title># - The title of the item.\r\n#<description># - The item synopsis.\r\n#<link># - The URL of the item.\r\n#<author># - Email address of the author of the item.\r\n#<comments># - URL of a page for comments relating to the item.\r\n#<guid># - A string that uniquely identifies the item.\r\n#<category># - Specify one or more categories that the item belongs to."
+#define TAGSDEFAULT "#<title>#\r\n#<link>#\r\n#<description>#"
+#define DEFAULT_AVATARS_FOLDER "NewsAggregator"
+extern HINSTANCE hInst;
+extern HWND hAddFeedDlg;
+extern HWND hChangeFeedDlg;
+extern UINT_PTR timerId;
+// check if Feeds is currently updating
+extern BOOL ThreadRunning;
+extern BOOL UpdateListFlag;
+extern TCHAR tszRoot[MAX_PATH];
+struct ItemInfo
+{
+ HWND hwndList;
+ HANDLE hContact;
+ int SelNumber;
+ TCHAR nick[MAX_PATH];
+ TCHAR url[MAX_PATH];
+};
+
+//============ STRUCT USED TO MAKE AN UPDATE LIST ============
+
+struct NEWSCONTACTLIST {
+ HANDLE hContact;
+ struct NEWSCONTACTLIST *next;
+};
+
+typedef struct NEWSCONTACTLIST UPDATELIST;
+
+extern UPDATELIST *UpdateListHead;
+extern UPDATELIST *UpdateListTail;
+
+void UpdateListAdd(HANDLE hContact);
+void UpdateThreadProc(LPVOID hWnd);
+void DestroyUpdateList(void);
+
+extern HANDLE hUpdateMutex;
+
+int NewsAggrInit(WPARAM wParam,LPARAM lParam);
+INT OptInit(WPARAM wParam, LPARAM lParam);
+int NewsAggrPreShutdown(WPARAM wParam,LPARAM lParam);
+VOID NetlibInit();
+VOID NetlibUnInit();
+VOID InitMenu();
+VOID InitIcons();
+HICON LoadIconEx(const char* name, BOOL big);
+HANDLE GetIconHandle(const char* name);
+INT_PTR NewsAggrGetName(WPARAM wParam, LPARAM lParam);
+INT_PTR NewsAggrGetCaps(WPARAM wp,LPARAM lp);
+INT_PTR NewsAggrSetStatus(WPARAM wp,LPARAM /*lp*/);
+INT_PTR NewsAggrGetStatus(WPARAM/* wp*/,LPARAM/* lp*/);
+INT_PTR NewsAggrLoadIcon(WPARAM wParam,LPARAM lParam);
+INT_PTR NewsAggrGetInfo(WPARAM wParam,LPARAM lParam);
+INT_PTR NewsAggrGetAvatarInfo(WPARAM wParam,LPARAM lParam);
+
+INT_PTR CheckAllFeeds(WPARAM wParam,LPARAM lParam);
+INT_PTR AddFeed(WPARAM wParam,LPARAM lParam);
+INT_PTR ChangeFeed(WPARAM wParam,LPARAM lParam);
+INT_PTR ImportFeeds(WPARAM wParam,LPARAM lParam);
+INT_PTR ExportFeeds(WPARAM wParam,LPARAM lParam);
+INT_PTR CheckFeed(WPARAM wParam,LPARAM lParam);
+INT_PTR CALLBACK DlgProcAddFeedOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcChangeFeedOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcChangeFeedMenu(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+VOID CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+VOID CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
+
+BOOL IsMyContact(HANDLE hContact);
+VOID GetNewsData(TCHAR *szUrl, char** szData, HANDLE hContact, HWND hwndDlg);
+VOID CreateList (HWND hwndList);
+VOID UpdateList (HWND hwndList);
+VOID DeleteAllItems(HWND hwndList);
+time_t __stdcall DateToUnixTime(TCHAR *stamp, BOOL FeedType);
+VOID CheckCurrentFeed (HANDLE hContact);
+TCHAR* CheckFeed(TCHAR* tszURL, HWND hwndDlg);
+size_t decode_html_entities_utf8(char *dest, const char *src);
+
+// =============== NewsAggr SERVICES ================
+// Check all Feeds info
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_CHECKALLFEEDS "NEWSAGGR/CheckAllFeeds"
+
+// Add new Feed channel
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_ADDFEED "NEWSAGGR/AddNewsFeed"
+
+// Add new Feed channel
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_CHANGEFEED "NEWSAGGR/ChangeNewsFeed"
+
+// Import Feed chanels from file
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_IMPORTFEEDS "NEWSAGGR/ImportFeeds"
+
+// Export Feed chanels to file
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_EXPORTFEEDS "NEWSAGGR/ExportFeeds"
+
+// Check Feed info
+// WPARAM = LPARAM = NULL
+#define MS_NEWSAGGR_CHECKFEED "NEWSAGGR/CheckFeed" \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Entities.cpp b/plugins/NewsAggregstor/Src/Entities.cpp
new file mode 100644
index 0000000000..7d6daf4a94
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Entities.cpp
@@ -0,0 +1,381 @@
+#include "common.h"
+
+#define UNICODE_MAX 0x10FFFFul
+
+static const char *named_entities[][2] =
+{
+ { "AElig;", "Æ" },
+ { "Aacute;", "Á" },
+ { "Acirc;", "Â" },
+ { "Agrave;", "À" },
+ { "Alpha;", "Α" },
+ { "Aring;", "Å" },
+ { "Atilde;", "Ã" },
+ { "Auml;", "Ä" },
+ { "Beta;", "Β" },
+ { "Ccedil;", "Ç" },
+ { "Chi;", "Χ" },
+ { "Dagger;", "‡" },
+ { "Delta;", "Δ" },
+ { "ETH;", "Ð" },
+ { "Eacute;", "É" },
+ { "Ecirc;", "Ê" },
+ { "Egrave;", "È" },
+ { "Epsilon;", "Ε" },
+ { "Eta;", "Η" },
+ { "Euml;", "Ë" },
+ { "Gamma;", "Γ" },
+ { "Iacute;", "Í" },
+ { "Icirc;", "Î" },
+ { "Igrave;", "Ì" },
+ { "Iota;", "Ι" },
+ { "Iuml;", "Ï" },
+ { "Kappa;", "Κ" },
+ { "Lambda;", "Λ" },
+ { "Mu;", "Μ" },
+ { "Ntilde;", "Ñ" },
+ { "Nu;", "Ν" },
+ { "OElig;", "Œ" },
+ { "Oacute;", "Ó" },
+ { "Ocirc;", "Ô" },
+ { "Ograve;", "Ò" },
+ { "Omega;", "Ω" },
+ { "Omicron;", "Ο" },
+ { "Oslash;", "Ø" },
+ { "Otilde;", "Õ" },
+ { "Ouml;", "Ö" },
+ { "Phi;", "Φ" },
+ { "Pi;", "Π" },
+ { "Prime;", "″" },
+ { "Psi;", "Ψ" },
+ { "Rho;", "Ρ" },
+ { "Scaron;", "Š" },
+ { "Sigma;", "Σ" },
+ { "THORN;", "Þ" },
+ { "Tau;", "Τ" },
+ { "Theta;", "Θ" },
+ { "Uacute;", "Ú" },
+ { "Ucirc;", "Û" },
+ { "Ugrave;", "Ù" },
+ { "Upsilon;", "Υ" },
+ { "Uuml;", "Ü" },
+ { "Xi;", "Ξ" },
+ { "Yacute;", "Ý" },
+ { "Yuml;", "Ÿ" },
+ { "Zeta;", "Ζ" },
+ { "aacute;", "á" },
+ { "acirc;", "â" },
+ { "acute;", "´" },
+ { "aelig;", "æ" },
+ { "agrave;", "à" },
+ { "alefsym;", "ℵ" },
+ { "alpha;", "α" },
+ { "amp;", "&" },
+ { "and;", "∧" },
+ { "ang;", "∠" },
+ { "apos;", "'" },
+ { "aring;", "å" },
+ { "asymp;", "≈" },
+ { "atilde;", "ã" },
+ { "auml;", "ä" },
+ { "bdquo;", "„" },
+ { "beta;", "β" },
+ { "brvbar;", "¦" },
+ { "bull;", "•" },
+ { "cap;", "∩" },
+ { "ccedil;", "ç" },
+ { "cedil;", "¸" },
+ { "cent;", "¢" },
+ { "chi;", "χ" },
+ { "circ;", "ˆ" },
+ { "clubs;", "♣" },
+ { "cong;", "≅" },
+ { "copy;", "©" },
+ { "crarr;", "↵" },
+ { "cup;", "∪" },
+ { "curren;", "¤" },
+ { "dArr;", "⇓" },
+ { "dagger;", "†" },
+ { "darr;", "↓" },
+ { "deg;", "°" },
+ { "delta;", "δ" },
+ { "diams;", "♦" },
+ { "divide;", "÷" },
+ { "eacute;", "é" },
+ { "ecirc;", "ê" },
+ { "egrave;", "è" },
+ { "empty;", "∅" },
+ { "emsp;", " " },
+ { "ensp;", " " },
+ { "epsilon;", "ε" },
+ { "equiv;", "≡" },
+ { "eta;", "η" },
+ { "eth;", "ð" },
+ { "euml;", "ë" },
+ { "euro;", "€" },
+ { "exist;", "∃" },
+ { "fnof;", "ƒ" },
+ { "forall;", "∀" },
+ { "frac12;", "½" },
+ { "frac14;", "¼" },
+ { "frac34;", "¾" },
+ { "frasl;", "⁄" },
+ { "gamma;", "γ" },
+ { "ge;", "≥" },
+ { "gt;", ">" },
+ { "hArr;", "⇔" },
+ { "harr;", "↔" },
+ { "hearts;", "♥" },
+ { "hellip;", "…" },
+ { "iacute;", "í" },
+ { "icirc;", "î" },
+ { "iexcl;", "¡" },
+ { "igrave;", "ì" },
+ { "image;", "ℑ" },
+ { "infin;", "∞" },
+ { "int;", "∫" },
+ { "iota;", "ι" },
+ { "iquest;", "¿" },
+ { "isin;", "∈" },
+ { "iuml;", "ï" },
+ { "kappa;", "κ" },
+ { "lArr;", "⇐" },
+ { "lambda;", "λ" },
+ { "lang;", "〈" },
+ { "laquo;", "«" },
+ { "larr;", "←" },
+ { "lceil;", "⌈" },
+ { "ldquo;", "“" },
+ { "le;", "≤" },
+ { "lfloor;", "⌊" },
+ { "lowast;", "∗" },
+ { "loz;", "◊" },
+ { "lrm;", "\xE2\x80\x8E" },
+ { "lsaquo;", "‹" },
+ { "lsquo;", "‘" },
+ { "lt;", "<" },
+ { "macr;", "¯" },
+ { "mdash;", "—" },
+ { "micro;", "µ" },
+ { "middot;", "·" },
+ { "minus;", "−" },
+ { "mu;", "μ" },
+ { "nabla;", "∇" },
+ { "nbsp;", " " },
+ { "ndash;", "–" },
+ { "ne;", "≠" },
+ { "ni;", "∋" },
+ { "not;", "¬" },
+ { "notin;", "∉" },
+ { "nsub;", "⊄" },
+ { "ntilde;", "ñ" },
+ { "nu;", "ν" },
+ { "oacute;", "ó" },
+ { "ocirc;", "ô" },
+ { "oelig;", "œ" },
+ { "ograve;", "ò" },
+ { "oline;", "‾" },
+ { "omega;", "ω" },
+ { "omicron;", "ο" },
+ { "oplus;", "⊕" },
+ { "or;", "∨" },
+ { "ordf;", "ª" },
+ { "ordm;", "º" },
+ { "oslash;", "ø" },
+ { "otilde;", "õ" },
+ { "otimes;", "⊗" },
+ { "ouml;", "ö" },
+ { "para;", "¶" },
+ { "part;", "∂" },
+ { "permil;", "‰" },
+ { "perp;", "⊥" },
+ { "phi;", "φ" },
+ { "pi;", "π" },
+ { "piv;", "ϖ" },
+ { "plusmn;", "±" },
+ { "pound;", "£" },
+ { "prime;", "′" },
+ { "prod;", "∏" },
+ { "prop;", "∝" },
+ { "psi;", "ψ" },
+ { "quot;", "\"" },
+ { "rArr;", "⇒" },
+ { "radic;", "√" },
+ { "rang;", "〉" },
+ { "raquo;", "»" },
+ { "rarr;", "→" },
+ { "rceil;", "⌉" },
+ { "rdquo;", "”" },
+ { "real;", "ℜ" },
+ { "reg;", "®" },
+ { "rfloor;", "⌋" },
+ { "rho;", "ρ" },
+ { "rlm;", "\xE2\x80\x8F" },
+ { "rsaquo;", "›" },
+ { "rsquo;", "’" },
+ { "sbquo;", "‚" },
+ { "scaron;", "š" },
+ { "sdot;", "⋅" },
+ { "sect;", "§" },
+ { "shy;", "\xC2\xAD" },
+ { "sigma;", "σ" },
+ { "sigmaf;", "ς" },
+ { "sim;", "∼" },
+ { "spades;", "♠" },
+ { "sub;", "⊂" },
+ { "sube;", "⊆" },
+ { "sum;", "∑" },
+ { "sup;", "⊃" },
+ { "sup1;", "¹" },
+ { "sup2;", "²" },
+ { "sup3;", "³" },
+ { "supe;", "⊇" },
+ { "szlig;", "ß" },
+ { "tau;", "τ" },
+ { "there4;", "∴" },
+ { "theta;", "θ" },
+ { "thetasym;", "ϑ" },
+ { "thinsp;", " " },
+ { "thorn;", "þ" },
+ { "tilde;", "˜" },
+ { "times;", "×" },
+ { "trade;", "™" },
+ { "uArr;", "⇑" },
+ { "uacute;", "ú" },
+ { "uarr;", "↑" },
+ { "ucirc;", "û" },
+ { "ugrave;", "ù" },
+ { "uml;", "¨" },
+ { "upsih;", "ϒ" },
+ { "upsilon;", "υ" },
+ { "uuml;", "ü" },
+ { "weierp;", "℘" },
+ { "xi;", "ξ" },
+ { "yacute;", "ý" },
+ { "yen;", "¥" },
+ { "yuml;", "ÿ" },
+ { "zeta;", "ζ" },
+ { "zwj;", "\xE2\x80\x8D" },
+ { "zwnj;", "\xE2\x80\x8C" }
+};
+
+static int cmp(const void *key, const void *element)
+{
+ return strncmp((const char *)key, *(const char **)element,
+ strlen(*(const char **)element));
+}
+
+static const char *get_named_entity(const char *name)
+{
+ const char **entity = (const char **)bsearch(name, named_entities, sizeof(named_entities) / sizeof(*named_entities),
+ sizeof(*named_entities), cmp);
+
+ return entity ? entity[1] : NULL;
+}
+
+static size_t putc_utf8(unsigned long cp, char *buffer)
+{
+ unsigned char *bytes = (unsigned char *)buffer;
+
+ if(cp <= 0x007Ful)
+ {
+ bytes[0] = (unsigned char)cp;
+ return 1;
+ }
+
+ if(cp <= 0x07FFul)
+ {
+ bytes[1] = (unsigned char)((2u << 6) | (cp & 0x3Fu));
+ bytes[0] = (unsigned char)((6u << 5) | (cp >> 6));
+ return 2;
+ }
+
+ if(cp <= 0xFFFFul)
+ {
+ bytes[2] = (unsigned char)(( 2u << 6) | ( cp & 0x3Fu));
+ bytes[1] = (unsigned char)(( 2u << 6) | ((cp >> 6) & 0x3Fu));
+ bytes[0] = (unsigned char)((14u << 4) | (cp >> 12));
+ return 3;
+ }
+
+ if(cp <= 0x10FFFFul)
+ {
+ bytes[3] = (unsigned char)(( 2u << 6) | ( cp & 0x3Fu));
+ bytes[2] = (unsigned char)(( 2u << 6) | ((cp >> 6) & 0x3Fu));
+ bytes[1] = (unsigned char)(( 2u << 6) | ((cp >> 12) & 0x3Fu));
+ bytes[0] = (unsigned char)((30u << 3) | (cp >> 18));
+ return 4;
+ }
+
+ return 0;
+}
+
+static BOOL parse_entity(const char *current, char **to, const char **from)
+{
+ const char *end = strchr(current, ';');
+ if(!end) return 0;
+
+ if(current[1] == '#')
+ {
+ char *tail = NULL;
+ errno = 0;
+
+ BOOL hex = current[2] == 'x' || current[2] == 'X';
+
+ unsigned long cp = strtoul(
+ current + (hex ? 3 : 2), &tail, hex ? 16 : 10);
+
+ if(tail == end && !errno && cp <= UNICODE_MAX)
+ {
+ *to += putc_utf8(cp, *to);
+ *from = end + 1;
+
+ return 1;
+ }
+ }
+ else
+ {
+ const char *entity = get_named_entity(&current[1]);
+ if(entity)
+ {
+ size_t len = strlen(entity);
+ memcpy(*to, entity, len);
+
+ *to += len;
+ *from = end + 1;
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+size_t decode_html_entities_utf8(char *dest, const char *src)
+{
+ if(!src) src = dest;
+
+ char *to = dest;
+ const char *from = src;
+
+ const char *current;
+ while(current = strchr(from, '&'))
+ {
+ memcpy(to, from, (size_t)(current - from));
+ to += current - from;
+
+ if(parse_entity(current, &to, &from))
+ continue;
+
+ from = current;
+ *to++ = *from++;
+ }
+
+ size_t remaining = strlen(from);
+
+ memcpy(to, from, remaining);
+ to += remaining;
+
+ *to = 0;
+ return (size_t)(to - dest);
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Icons.cpp b/plugins/NewsAggregstor/Src/Icons.cpp
new file mode 100644
index 0000000000..a0c08f7825
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Icons.cpp
@@ -0,0 +1,79 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+struct _tag_iconList
+{
+ TCHAR* szDescr;
+ char* szName;
+ int defIconID;
+ HANDLE hIconLibItem;
+}
+
+static iconList[] =
+{
+ { _T("Protocol icon"), "main", IDI_ICON },
+ { _T("Check All Feeds"), "checkall", IDI_CHECKALL },
+ { _T("Add Feed"), "addfeed", IDI_ADDFEED },
+ { _T("Import Feeds"), "importfeeds", IDI_IMPORTFEEDS },
+ { _T("Export Feeds"), "exportfeeds", IDI_EXPORTFEEDS },
+ { _T("Check Feed"), "checkfeed", IDI_CHECKALL },
+};
+
+VOID InitIcons()
+{
+ TCHAR szFile[MAX_PATH];
+ char szSettingName[100];
+ SKINICONDESC sid = {0};
+ unsigned i;
+
+ GetModuleFileName(hInst, szFile, MAX_PATH);
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszDefaultFile = szFile;
+ sid.pszName = szSettingName;
+ sid.ptszSection = _T("News Aggregator");
+
+ for (i = 0; i < SIZEOF(iconList); i++)
+ {
+ mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", MODULE, iconList[i].szName);
+
+ sid.ptszDescription = iconList[i].szDescr;
+ sid.iDefaultIndex = -iconList[i].defIconID;
+ iconList[i].hIconLibItem = ( HANDLE )CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+}
+
+HICON LoadIconEx(const char* name, BOOL big)
+{
+ char szSettingName[100];
+ mir_snprintf(szSettingName, SIZEOF(szSettingName), "%s_%s", MODULE, name);
+ return (HICON)CallService(MS_SKIN2_GETICON, big, (LPARAM)szSettingName);
+}
+
+HANDLE GetIconHandle(const char* name)
+{
+ unsigned i;
+ for (i=0; i < SIZEOF(iconList); i++)
+ if (strcmp(iconList[i].szName, name) == 0)
+ return iconList[i].hIconLibItem;
+ return NULL;
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Menus.cpp b/plugins/NewsAggregstor/Src/Menus.cpp
new file mode 100644
index 0000000000..9228a4c198
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Menus.cpp
@@ -0,0 +1,78 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+HANDLE hService2[6];
+
+VOID InitMenu()
+{
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.pszContactOwner = MODULE;
+ mi.flags = CMIF_TCHAR|CMIF_ICONFROMICOLIB|CMIF_NOTOFFLINE;
+
+ // adding main menu items
+ mi.ptszPopupName = _T("News Aggregator");
+ mi.popupPosition = 500099000;
+
+ mi.position=10100001;
+ mi.icolibItem = GetIconHandle("main");
+ mi.ptszName = _T("Check All Feeds");
+ mi.pszService = MS_NEWSAGGR_CHECKALLFEEDS;
+ hService2[0] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ mi.position=10100002;
+ mi.icolibItem = GetIconHandle("addfeed");
+ mi.ptszName = _T("Add Feed");
+ mi.pszService = MS_NEWSAGGR_ADDFEED;
+ hService2[1] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ mi.position=10100003;
+ mi.icolibItem = GetIconHandle("importfeeds");
+ mi.ptszName = _T("Import Feeds");
+ mi.pszService = MS_NEWSAGGR_IMPORTFEEDS;
+ hService2[2] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ mi.position=10100004;
+ mi.icolibItem = GetIconHandle("exportfeeds");
+ mi.ptszName = _T("Export Feeds");
+ mi.pszService = MS_NEWSAGGR_EXPORTFEEDS;
+ hService2[3] = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ // adding contact menu items
+ mi.position=-0x7FFFFFFA;
+ mi.icolibItem = GetIconHandle("checkfeed");
+ mi.ptszName = _T("Check feed");
+ mi.pszService = MS_NEWSAGGR_CHECKFEED;
+ hService2[4] = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ // adding contact menu items
+ mi.position=-0x7FFFFFFA;
+ //mi.icolibItem = GetIconHandle("checkfeed");
+ mi.ptszName = _T("Change feed");
+ mi.pszService = MS_NEWSAGGR_CHANGEFEED;
+ hService2[5] = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
+
+ ZeroMemory(&mi, sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ICON;
+ mi.icolibItem = GetIconHandle("checkall");
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hService2[0], (LPARAM)&mi);
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/NewsAggregator.cpp b/plugins/NewsAggregstor/Src/NewsAggregator.cpp
new file mode 100644
index 0000000000..3bbead8745
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/NewsAggregator.cpp
@@ -0,0 +1,140 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "Common.h"
+
+HINSTANCE hInst = NULL;
+PLUGINLINK *pluginLink;
+int hLangpack;
+struct MM_INTERFACE mmi;
+HANDLE hOptHook = NULL, hLoadHook = NULL, hOnPreShutdown = NULL, hPrebuildMenuHook = NULL, hPackUpdaterFolder = NULL;
+HANDLE hProtoService[7];
+HWND hAddFeedDlg;
+HWND hChangeFeedDlg;
+XML_API xi = {0};
+struct UTF8_INTERFACE utfi;
+TCHAR tszRoot[MAX_PATH] = {0};
+HANDLE hUpdateMutex;
+#define NUM_SERVICES 6
+HANDLE hService[NUM_SERVICES];
+
+PLUGININFOEX pluginInfoEx = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ 0,
+ // {56CC3F29-CCBF-4546-A8BA-9856248A412A}
+ {0x56cc3f29, 0xccbf, 0x4546, {0xa8, 0xba, 0x98, 0x56, 0x24, 0x8a, 0x41, 0x2a}}
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ if(mirandaVersion < 0x0900)
+ {
+ MessageBox(NULL, TranslateT("News Aggregator plugin requires Miranda IM 0.9.0.0 or later"), TranslateT("Fatal error"), MB_OK);
+ return NULL;
+ }
+ return &pluginInfoEx;
+}
+
+static const MUUID interfaces[] = {{0x29517be5, 0x779a, 0x48e5, {0x89, 0x50, 0xcb, 0x4d, 0xe1, 0xd4, 0x31, 0x72}}, MIID_LAST};
+
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+extern "C" __declspec(dllexport) int Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+ mir_getLP(&pluginInfoEx);
+ mir_getMMI(&mmi);
+ mir_getXI(&xi);
+ mir_getUTFI(&utfi);
+
+ if (ServiceExists(MS_FOLDERS_REGISTER_PATH))
+ {
+ hPackUpdaterFolder = FoldersRegisterCustomPathT("News Aggregator", "Avatars", MIRANDA_USERDATAT _T("\\Avatars\\")_T(DEFAULT_AVATARS_FOLDER));
+ FoldersGetCustomPathT(hPackUpdaterFolder, tszRoot, MAX_PATH, _T(""));
+ }
+ else
+ {
+ TCHAR* tszFolder = Utils_ReplaceVarsT(_T("%miranda_userdata%\\"_T(DEFAULT_AVATARS_FOLDER)));
+ lstrcpyn(tszRoot, tszFolder, SIZEOF(tszRoot));
+ mir_free(tszFolder);
+ }
+
+ // Add options hook
+ hOptHook = HookEvent(ME_OPT_INITIALISE, OptInit);
+ hLoadHook = HookEvent(ME_SYSTEM_MODULESLOADED, NewsAggrInit);
+ hOnPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, NewsAggrPreShutdown);
+
+ hUpdateMutex = CreateMutex(NULL, FALSE, NULL);
+
+ // register weather protocol
+ PROTOCOLDESCRIPTOR pd = {0};
+ pd.cbSize = PROTOCOLDESCRIPTOR_V3_SIZE;
+ pd.szName = MODULE;
+ pd.type = PROTOTYPE_PROTOCOL;
+ CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd);
+
+ hProtoService[0] = CreateProtoServiceFunction(MODULE, PS_GETNAME, NewsAggrGetName);
+ hProtoService[1] = CreateProtoServiceFunction(MODULE, PS_GETCAPS, NewsAggrGetCaps);
+ hProtoService[2] = CreateProtoServiceFunction(MODULE, PS_SETSTATUS, NewsAggrSetStatus);
+ hProtoService[3] = CreateProtoServiceFunction(MODULE, PS_GETSTATUS, NewsAggrGetStatus);
+ hProtoService[4] = CreateProtoServiceFunction(MODULE, PS_LOADICON, NewsAggrLoadIcon);
+ hProtoService[5] = CreateProtoServiceFunction(MODULE, PSS_GETINFO, NewsAggrGetInfo);
+ hProtoService[6] = CreateProtoServiceFunction(MODULE, PS_GETAVATARINFO, NewsAggrGetAvatarInfo);
+
+ hService[0] = CreateServiceFunction(MS_NEWSAGGR_CHECKALLFEEDS, CheckAllFeeds);
+ hService[1] = CreateServiceFunction(MS_NEWSAGGR_ADDFEED, AddFeed);
+ hService[2] = CreateServiceFunction(MS_NEWSAGGR_IMPORTFEEDS, ImportFeeds);
+ hService[3] = CreateServiceFunction(MS_NEWSAGGR_EXPORTFEEDS, ExportFeeds);
+ hService[4] = CreateServiceFunction(MS_NEWSAGGR_CHECKFEED, CheckFeed);
+ hService[5] = CreateServiceFunction(MS_NEWSAGGR_CHANGEFEED, ChangeFeed);
+
+ return 0;
+}
+
+extern "C" __declspec(dllexport) int Unload(void)
+{
+ for (int i = 0;i<NUM_SERVICES;i++)
+ DestroyServiceFunction(hService[i]);
+
+ UnhookEvent(hOptHook);
+ UnhookEvent(hLoadHook);
+ UnhookEvent(hOnPreShutdown);
+
+ DestroyUpdateList();
+ CloseHandle(hUpdateMutex);
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Options.cpp b/plugins/NewsAggregstor/Src/Options.cpp
new file mode 100644
index 0000000000..ae9f5b5739
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Options.cpp
@@ -0,0 +1,627 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+INT_PTR CALLBACK DlgProcAddFeedOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
+ SetWindowText(hwndDlg, TranslateT("Add Feed"));
+ SetDlgItemText(hwndDlg, IDC_FEEDURL, _T("http://"));
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, _T(TAGSDEFAULT));
+ SendDlgItemMessage(hwndDlg, IDC_CHECKTIME, EM_LIMITTEXT, 3, 0);
+ SetDlgItemInt(hwndDlg, IDC_CHECKTIME, 60, TRUE);
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE_SPIN, UDM_SETRANGE32, 0, 999);
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ TCHAR str[MAX_PATH];
+ if (!GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed name"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str)) || lstrcmp(str, _T("http://")) == 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false) < 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter checking interval"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter message format"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else
+ {
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)MODULE);
+ GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Nick", str);
+ HWND hwndList = (HWND)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "URL", str);
+ DBWriteContactSettingByte(hContact, MODULE, "CheckState", 1);
+ DBWriteContactSettingDword(hContact, MODULE, "UpdateTime", GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false));
+ GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "MsgFormat", str);
+ DBWriteContactSettingWord(hContact, MODULE, "Status", CallProtoService(MODULE, PS_GETSTATUS, 0, 0));
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ DBWriteContactSettingByte(hContact, MODULE, "UseAuth", 1);
+ GetDlgItemText(hwndDlg, IDC_LOGIN, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Login", str);
+ GetDlgItemText(hwndDlg, IDC_PASSWORD, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Password", str);
+ }
+ DeleteAllItems(hwndList);
+ UpdateList(hwndList);
+ }
+ }
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_USEAUTH:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE);
+ }
+ }
+ break;
+
+ case IDC_TAGHELP:
+ MessageBox(hwndDlg, TranslateT(TAGSHELP), TranslateT("Feed Tag Help"), MB_OK);
+ break;
+
+ case IDC_RESET:
+ if (MessageBox(hwndDlg, TranslateT("Are you sure?"), TranslateT("Tags Mask Reset"), MB_YESNO | MB_ICONWARNING) == IDYES)
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, _T(TAGSDEFAULT));
+ break;
+
+ case IDC_DISCOVERY:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), FALSE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Wait..."));
+ TCHAR tszURL[MAX_PATH] = {0}, *tszTitle = NULL;
+ if (GetDlgItemText(hwndDlg, IDC_FEEDURL, tszURL, SIZEOF(tszURL)) || lstrcmp(tszURL, _T("http://")) != 0)
+ tszTitle = CheckFeed(tszURL, hwndDlg);
+ else
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ SetDlgItemText(hwndDlg, IDC_FEEDTITLE, tszTitle);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), TRUE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Check Feed"));
+ }
+ break;
+ }
+ break;
+ }
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK DlgProcChangeFeedOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ ItemInfo &SelItem = *(ItemInfo*)lParam;
+ ItemInfo *nSelItem = new ItemInfo(SelItem);
+ SetWindowText(hwndDlg, TranslateT("Change Feed"));
+ SendDlgItemMessage(hwndDlg, IDC_CHECKTIME, EM_LIMITTEXT, 3, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TIMEOUT_VALUE_SPIN, UDM_SETRANGE32, 0, 999);
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if (IsMyContact(hContact))
+ {
+ DBVARIANT dbNick = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "Nick", &dbNick))
+ break;
+ else if (lstrcmp(dbNick.ptszVal, SelItem.nick) == 0)
+ {
+ DBFreeVariant(&dbNick);
+ DBVARIANT dbURL = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "URL", &dbURL))
+ break;
+ else if (lstrcmp(dbURL.ptszVal, SelItem.url) == 0)
+ {
+ DBFreeVariant(&dbURL);
+ nSelItem->hContact = hContact;
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG)nSelItem);
+ SetDlgItemText(hwndDlg, IDC_FEEDURL, SelItem.url);
+ SetDlgItemText(hwndDlg, IDC_FEEDTITLE, SelItem.nick);
+ SetDlgItemInt(hwndDlg, IDC_CHECKTIME, DBGetContactSettingDword(hContact, MODULE, "UpdateTime", 60), TRUE);
+ DBVARIANT dbMsg = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "MsgFormat", &dbMsg))
+ {
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, dbMsg.ptszVal);
+ DBFreeVariant(&dbMsg);
+ }
+ if (DBGetContactSettingByte(hContact, MODULE, "UseAuth", 0))
+ {
+ CheckDlgButton(hwndDlg, IDC_USEAUTH, BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE);
+ DBVARIANT dbLogin = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Login", &dbLogin))
+ {
+ SetDlgItemText(hwndDlg, IDC_LOGIN, dbLogin.ptszVal);
+ DBFreeVariant(&dbLogin);
+ }
+ DBVARIANT dbPass = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Password", &dbPass))
+ {
+ SetDlgItemText(hwndDlg, IDC_PASSWORD, dbPass.ptszVal);
+ DBFreeVariant(&dbPass);
+ }
+ }
+ break;
+ }
+ DBFreeVariant(&dbURL);
+ }
+ DBFreeVariant(&dbNick);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ ItemInfo *SelItem = (ItemInfo*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ TCHAR str[MAX_PATH];
+ if (!GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed name"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str)) || lstrcmp(str, _T("http://")) == 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false) < 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter checking interval"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter message format"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else
+ {
+ GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str));
+ DBWriteContactSettingTString(SelItem->hContact, MODULE, "URL", str);
+ GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str));
+ DBWriteContactSettingTString(SelItem->hContact, MODULE, "Nick", str);
+ DBWriteContactSettingDword(SelItem->hContact, MODULE, "UpdateTime", GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false));
+ GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str));
+ DBWriteContactSettingTString(SelItem->hContact, MODULE, "MsgFormat", str);
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ DBWriteContactSettingByte(SelItem->hContact, MODULE, "UseAuth", 1);
+ GetDlgItemText(hwndDlg, IDC_LOGIN, str, SIZEOF(str));
+ DBWriteContactSettingTString(SelItem->hContact, MODULE, "Login", str);
+ GetDlgItemText(hwndDlg, IDC_PASSWORD, str, SIZEOF(str));
+ DBWriteContactSettingTString(SelItem->hContact, MODULE, "Password", str);
+ }
+ DeleteAllItems(SelItem->hwndList);
+ UpdateList(SelItem->hwndList);
+ }
+ }
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_USEAUTH:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE);
+ }
+ break;
+ }
+
+ case IDC_TAGHELP:
+ MessageBox(hwndDlg, TranslateT(TAGSHELP), TranslateT("Feed Tag Help"), MB_OK);
+ break;
+
+ case IDC_RESET:
+ if (MessageBox(hwndDlg, TranslateT("Are you sure?"), TranslateT("Tags Mask Reset"), MB_YESNO | MB_ICONWARNING) == IDYES)
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, _T(TAGSDEFAULT));
+ break;
+
+ case IDC_DISCOVERY:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), FALSE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Wait..."));
+ TCHAR tszURL[MAX_PATH] = {0}, *tszTitle = NULL;
+ if (GetDlgItemText(hwndDlg, IDC_FEEDURL, tszURL, SIZEOF(tszURL)) || lstrcmp(tszURL, _T("http://")) != 0)
+ tszTitle = CheckFeed(tszURL, hwndDlg);
+ else
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ SetDlgItemText(hwndDlg, IDC_FEEDTITLE, tszTitle);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), TRUE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Check Feed"));
+ }
+ break;
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ ItemInfo *SelItem = (ItemInfo*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ delete SelItem;
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK DlgProcChangeFeedMenu(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowText(hwndDlg, TranslateT("Change Feed"));
+ SendDlgItemMessage(hwndDlg, IDC_CHECKTIME, UDM_SETRANGE32, 0, 999);
+
+ HANDLE hContact = (HANDLE)lParam;
+ DBVARIANT dbNick = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Nick", &dbNick))
+ {
+ SetDlgItemText(hwndDlg, IDC_FEEDTITLE, dbNick.ptszVal);
+ DBFreeVariant(&dbNick);
+ DBVARIANT dbURL = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "URL", &dbURL))
+ {
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG)lParam);
+ SetDlgItemText(hwndDlg, IDC_FEEDURL, dbURL.ptszVal);
+ DBFreeVariant(&dbURL);
+ SetDlgItemInt(hwndDlg, IDC_CHECKTIME, DBGetContactSettingDword(hContact, MODULE, "UpdateTime", 60), TRUE);
+ DBVARIANT dbMsg = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "MsgFormat", &dbMsg))
+ {
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, dbMsg.ptszVal);
+ DBFreeVariant(&dbMsg);
+ }
+ if (DBGetContactSettingByte(hContact, MODULE, "UseAuth", 0))
+ {
+ CheckDlgButton(hwndDlg, IDC_USEAUTH, BST_CHECKED);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE);
+ DBVARIANT dbLogin = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Login", &dbLogin))
+ {
+ SetDlgItemText(hwndDlg, IDC_LOGIN, dbLogin.ptszVal);
+ DBFreeVariant(&dbLogin);
+ }
+ DBVARIANT dbPass = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Password", &dbPass))
+ {
+ SetDlgItemText(hwndDlg, IDC_PASSWORD, dbPass.ptszVal);
+ DBFreeVariant(&dbPass);
+ }
+ }
+ break;
+ }
+ }
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ HANDLE hContact = (HANDLE)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ TCHAR str[MAX_PATH];
+ if (!GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed name"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str)) || lstrcmp(str, _T("http://")) == 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false) < 0)
+ {
+ MessageBox(hwndDlg, TranslateT("Enter checking interval"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else if (!GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str)))
+ {
+ MessageBox(hwndDlg, TranslateT("Enter message format"), TranslateT("Error"), MB_OK);
+ break;
+ }
+ else
+ {
+ GetDlgItemText(hwndDlg, IDC_FEEDURL, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "URL", str);
+ GetDlgItemText(hwndDlg, IDC_FEEDTITLE, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Nick", str);
+ DBWriteContactSettingDword(hContact, MODULE, "UpdateTime", GetDlgItemInt(hwndDlg, IDC_CHECKTIME, false, false));
+ GetDlgItemText(hwndDlg, IDC_TAGSEDIT, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "MsgFormat", str);
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ DBWriteContactSettingByte(hContact, MODULE, "UseAuth", 1);
+ GetDlgItemText(hwndDlg, IDC_LOGIN, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Login", str);
+ GetDlgItemText(hwndDlg, IDC_PASSWORD, str, SIZEOF(str));
+ DBWriteContactSettingTString(hContact, MODULE, "Password", str);
+ }
+ }
+ }
+
+ case IDCANCEL:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case IDC_USEAUTH:
+ {
+ if (IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), TRUE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_LOGIN), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE);
+ }
+ break;
+ }
+
+ case IDC_TAGHELP:
+ MessageBox(hwndDlg, TranslateT(TAGSHELP), TranslateT("Feed Tag Help"), MB_OK);
+ break;
+
+ case IDC_RESET:
+ if (MessageBox(hwndDlg, TranslateT("Are you sure?"), TranslateT("Tags Mask Reset"), MB_YESNO | MB_ICONWARNING) == IDYES)
+ SetDlgItemText(hwndDlg, IDC_TAGSEDIT, _T(TAGSDEFAULT));
+ break;
+
+ case IDC_DISCOVERY:
+ {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), FALSE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Wait..."));
+ TCHAR tszURL[MAX_PATH] = {0}, *tszTitle = NULL;
+ if (GetDlgItemText(hwndDlg, IDC_FEEDURL, tszURL, SIZEOF(tszURL)) || lstrcmp(tszURL, _T("http://")) != 0)
+ tszTitle = CheckFeed(tszURL, hwndDlg);
+ else
+ MessageBox(hwndDlg, TranslateT("Enter Feed URL"), TranslateT("Error"), MB_OK);
+ SetDlgItemText(hwndDlg, IDC_FEEDTITLE, tszTitle);
+ EnableWindow(GetDlgItem(hwndDlg, IDC_DISCOVERY), TRUE);
+ SetDlgItemText(hwndDlg, IDC_DISCOVERY, TranslateT("Check Feed"));
+ }
+ break;
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+
+ return FALSE;
+}
+
+INT_PTR CALLBACK UpdateNotifyOptsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ HWND hwndList = GetDlgItem(hwndDlg, IDC_FEEDLIST);
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, 0);
+ CreateList(hwndList);
+ UpdateList(hwndList);
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_ADD:
+ {
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDFEED), hwndDlg, DlgProcAddFeedOpts, (LPARAM)hwndList);
+ }
+ return FALSE;
+ case IDC_CHANGE:
+ {
+ ItemInfo SelItem = {0};
+ int sel = ListView_GetSelectionMark(hwndList);
+ ListView_GetItemText(hwndList, sel, 0, SelItem.nick, MAX_PATH);
+ ListView_GetItemText(hwndList, sel, 1, SelItem.url, MAX_PATH);
+ SelItem.hwndList = hwndList;
+ SelItem.SelNumber = sel;
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDFEED), hwndDlg, DlgProcChangeFeedOpts, (LPARAM)&SelItem);
+ }
+ return FALSE;
+ case IDC_REMOVE:
+ {
+ if (MessageBox(hwndDlg, TranslateT("Are you sure?"), TranslateT("Contact deleting"), MB_YESNO | MB_ICONWARNING) == IDYES)
+ {
+ TCHAR nick[MAX_PATH], url[MAX_PATH];
+ int sel = ListView_GetSelectionMark(hwndList);
+ ListView_GetItemText(hwndList, sel, 0, nick, MAX_PATH);
+ ListView_GetItemText(hwndList, sel, 1, url, MAX_PATH);
+
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ DBVARIANT dbNick = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "Nick", &dbNick))
+ break;
+ else if (lstrcmp(dbNick.ptszVal, nick) == 0)
+ {
+ DBFreeVariant(&dbNick);
+ DBVARIANT dbURL = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "URL", &dbURL))
+ break;
+ else if (lstrcmp(dbURL.ptszVal, url) == 0)
+ {
+ DBFreeVariant(&dbURL);
+ CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0);
+ ListView_DeleteItem(hwndList, sel);
+ break;
+ }
+ DBFreeVariant(&dbURL);
+ }
+ DBFreeVariant(&dbNick);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ }
+ return FALSE;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ NMHDR *hdr = (NMHDR *)lParam;
+ switch (hdr->code)
+ {
+ case PSN_APPLY:
+ {
+ HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ int i = 0;
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ DBWriteContactSettingByte(hContact, MODULE, "CheckState", ListView_GetCheckState(hwndList, i));
+ i += 1;
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ break;
+ }
+
+ case NM_DBLCLK:
+ {
+ ItemInfo SelItem = {0};
+ int sel = ListView_GetHotItem(hwndList);
+ if (sel != -1)
+ {
+ ListView_GetItemText(hwndList, sel, 0, SelItem.nick, MAX_PATH);
+ ListView_GetItemText(hwndList, sel, 1, SelItem.url, MAX_PATH);
+ SelItem.hwndList = hwndList;
+ SelItem.SelNumber = sel;
+ CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDFEED), hwndDlg, DlgProcChangeFeedOpts, (LPARAM)&SelItem);
+ }
+ break;
+ }
+
+ case LVN_ITEMCHANGED:
+ {
+ NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam;
+ if(((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) && !UpdateListFlag)
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ }
+ break;
+ }
+ }
+ }
+ }//end* switch (msg)
+ return FALSE;
+}
+
+INT OptInit(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInst;
+ odp.flags = ODPF_TCHAR | ODPF_BOLDGROUPS;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS);
+ odp.ptszGroup = _T("Network");
+ odp.ptszTitle = _T("News Aggregator");
+ odp.pfnDlgProc = UpdateNotifyOptsProc;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Services.cpp b/plugins/NewsAggregstor/Src/Services.cpp
new file mode 100644
index 0000000000..42fbc2e0b0
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Services.cpp
@@ -0,0 +1,232 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+int g_nStatus = ID_STATUS_OFFLINE;
+UINT_PTR timerId = 0;
+
+void SetContactStatus(HANDLE hContact,int nNewStatus)
+{
+ if(DBGetContactSettingWord(hContact,MODULE,"Status",ID_STATUS_OFFLINE) != nNewStatus)
+ DBWriteContactSettingWord(hContact,MODULE,"Status",nNewStatus);
+}
+
+static void __cdecl WorkingThread(void* param)
+{
+ int nStatus = (int)param;
+// UpdateAll(FALSE, FALSE);
+ HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ SetContactStatus(hContact, nStatus);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+}
+
+int NewsAggrInit(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ SetContactStatus(hContact, ID_STATUS_OFFLINE);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ NetlibInit();
+ InitIcons();
+ InitMenu();
+
+ // timer for the first update
+ timerId = SetTimer(NULL, 0, 5000, timerProc2); // first update is 5 sec after load
+
+ return 0;
+}
+
+int NewsAggrPreShutdown(WPARAM wParam,LPARAM lParam)
+{
+ if (hAddFeedDlg)
+ {
+ SendMessage(hAddFeedDlg, WM_CLOSE, 0, 0);
+ }
+ if (hChangeFeedDlg)
+ {
+ SendMessage(hChangeFeedDlg, WM_CLOSE, 0, 0);
+ }
+ mir_forkthread(WorkingThread, (void*)ID_STATUS_OFFLINE);
+ KillTimer(NULL, timerId);
+ NetlibUnInit();
+
+ return 0;
+}
+
+INT_PTR NewsAggrGetName(WPARAM wParam, LPARAM lParam)
+{
+ if(lParam)
+ {
+ lstrcpynA((char*)lParam, MODULE, wParam);
+ return 0;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+INT_PTR NewsAggrGetCaps(WPARAM wp,LPARAM lp)
+{
+ switch(wp)
+ {
+ case PFLAGNUM_1:
+ return PF1_IM | PF1_PEER2PEER;
+ case PFLAGNUM_3:
+ case PFLAGNUM_2:
+ return PF2_ONLINE;
+ case PFLAGNUM_4:
+ return PF4_AVATARS;
+ case PFLAG_UNIQUEIDTEXT:
+ return (INT_PTR) "News Feed";
+ case PFLAG_UNIQUEIDSETTING:
+ return (INT_PTR) "URL";
+ default:
+ return 0;
+ }
+}
+
+INT_PTR NewsAggrSetStatus(WPARAM wp,LPARAM /*lp*/)
+{
+ int nStatus = wp;
+ if((ID_STATUS_ONLINE == nStatus) || (ID_STATUS_OFFLINE == nStatus))
+ {
+ int nOldStatus = g_nStatus;
+ if(nStatus != g_nStatus)
+ {
+ g_nStatus = nStatus;
+ mir_forkthread(WorkingThread, (void*)g_nStatus);
+ ProtoBroadcastAck(MODULE, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)nOldStatus, g_nStatus);
+ }
+
+ }
+
+ return 0;
+}
+
+INT_PTR NewsAggrGetStatus(WPARAM/* wp*/,LPARAM/* lp*/)
+{
+ return g_nStatus;
+}
+
+INT_PTR NewsAggrLoadIcon(WPARAM wParam,LPARAM lParam)
+{
+ return (LOWORD(wParam) == PLI_PROTOCOL) ? (INT_PTR)CopyIcon(LoadIconEx("main", FALSE)) : 0;
+}
+
+static void __cdecl AckThreadProc(HANDLE param)
+{
+ Sleep(100);
+ ProtoBroadcastAck(MODULE, param, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, 0);
+}
+
+INT_PTR NewsAggrGetInfo(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *ccs = (CCSDATA *) lParam;
+ mir_forkthread(AckThreadProc, ccs->hContact);
+ return 0;
+}
+
+INT_PTR CheckAllFeeds(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact= (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ UpdateListAdd(hContact);
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ if (!ThreadRunning)
+ mir_forkthread(UpdateThreadProc, NULL);
+
+
+ return 0;
+}
+
+INT_PTR AddFeed(WPARAM wParam,LPARAM lParam)
+{
+ hAddFeedDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_ADDFEED), NULL, DlgProcAddFeedOpts);
+ ShowWindow(hAddFeedDlg, SW_SHOW);
+ return 0;
+}
+
+INT_PTR ChangeFeed(WPARAM wParam,LPARAM lParam)
+{
+ hChangeFeedDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ADDFEED), NULL, DlgProcChangeFeedMenu, (LPARAM)wParam);
+ ShowWindow(hChangeFeedDlg, SW_SHOW);
+ return 0;
+}
+
+INT_PTR ImportFeeds(WPARAM wParam,LPARAM lParam)
+{
+ return 0;
+}
+
+INT_PTR ExportFeeds(WPARAM wParam,LPARAM lParam)
+{
+ return 0;
+}
+
+INT_PTR CheckFeed(WPARAM wParam,LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE)wParam;
+ if(IsMyContact(hContact))
+ UpdateListAdd(hContact);
+ if (!ThreadRunning)
+ mir_forkthread(UpdateThreadProc, NULL);
+ return 0;
+}
+
+INT_PTR NewsAggrGetAvatarInfo(WPARAM wParam,LPARAM lParam)
+{
+ PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*) lParam;
+
+ if(!IsMyContact(pai->hContact))
+ return GAIR_NOAVATAR;
+
+ // if GAIF_FORCE is set, we are updating the feed
+ // otherwise, cached avatar is used
+ if (wParam & GAIF_FORCE)
+ UpdateListAdd(pai->hContact);
+ //CheckCurrentFeed(pai->hContact);
+ if (!ThreadRunning)
+ mir_forkthread(UpdateThreadProc, NULL);
+
+ DBVARIANT dbv = {0};
+ if(DBGetContactSettingTString(pai->hContact,MODULE,"ImageURL",&dbv))
+ {
+ return GAIR_NOAVATAR;
+ }
+ DBFreeVariant(&dbv);
+ return GAIR_WAITFOR;
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Update.cpp b/plugins/NewsAggregstor/Src/Update.cpp
new file mode 100644
index 0000000000..f2f5ecf92a
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Update.cpp
@@ -0,0 +1,147 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+// check if Feed is currently updating
+BOOL ThreadRunning;
+UPDATELIST *UpdateListHead = NULL;
+UPDATELIST *UpdateListTail = NULL;
+
+// main auto-update timer
+VOID CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ // only run if it is not current updating and the auto update option is enabled
+ if (!ThreadRunning && !Miranda_Terminated())
+ {
+ BOOL HaveUpdates = FALSE;
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if(IsMyContact(hContact))
+ {
+ if (DBGetContactSettingDword(hContact, MODULE, "UpdateTime", 60))
+ {
+ double diff = difftime(time(NULL), DBGetContactSettingDword(hContact, MODULE, "LastCheck", 0));
+ if (diff >= DBGetContactSettingDword(hContact, MODULE, "UpdateTime", 60) * 60)
+ {
+ UpdateListAdd(hContact);
+ HaveUpdates = TRUE;
+ }
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ if (!ThreadRunning && HaveUpdates)
+ mir_forkthread(UpdateThreadProc, NULL);
+ }
+}
+
+// temporary timer for first run
+// when this is run, it kill the old startup timer and create the permenant one above
+VOID CALLBACK timerProc2(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ KillTimer(NULL, timerId);
+ ThreadRunning = FALSE;
+
+ if (!Miranda_Terminated())
+ {
+ CheckAllFeeds(0,0);
+ timerId = SetTimer(NULL, 0, 30000, (TIMERPROC)timerProc);
+ }
+}
+
+void UpdateListAdd(HANDLE hContact)
+{
+ UPDATELIST *newItem;
+
+ newItem = (UPDATELIST*)mir_alloc(sizeof(UPDATELIST));
+ newItem->hContact = hContact;
+ newItem->next = NULL;
+
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ if (UpdateListTail == NULL) UpdateListHead = newItem;
+ else UpdateListTail->next = newItem;
+ UpdateListTail = newItem;
+
+ ReleaseMutex(hUpdateMutex);
+}
+
+HANDLE UpdateGetFirst()
+{
+ HANDLE hContact = NULL;
+
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ if (UpdateListHead != NULL)
+ {
+ UPDATELIST* Item = UpdateListHead;
+
+ hContact = Item->hContact;
+ UpdateListHead = Item->next;
+ mir_free(Item);
+
+ if (UpdateListHead == NULL) UpdateListTail = NULL;
+ }
+
+ ReleaseMutex(hUpdateMutex);
+
+ return hContact;
+}
+
+void DestroyUpdateList(void)
+{
+ UPDATELIST *temp;
+
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+
+ temp = UpdateListHead;
+
+ // free the list one by one
+ while (temp != NULL)
+ {
+ UpdateListHead = temp->next;
+ mir_free(temp);
+ temp = UpdateListHead;
+ }
+ // make sure the entire list is clear
+ UpdateListTail = NULL;
+
+ ReleaseMutex(hUpdateMutex);
+}
+
+void UpdateThreadProc(LPVOID hWnd)
+{
+ WaitForSingleObject(hUpdateMutex, INFINITE);
+ if (ThreadRunning)
+ {
+ ReleaseMutex(hUpdateMutex);
+ return;
+ }
+ ThreadRunning = TRUE; // prevent 2 instance of this thread running
+ ReleaseMutex(hUpdateMutex);
+
+ // update weather by getting the first station from the queue until the queue is empty
+ while (UpdateListHead != NULL && !Miranda_Terminated())
+ CheckCurrentFeed(UpdateGetFirst());
+
+ // exit the update thread
+ ThreadRunning = FALSE;
+} \ No newline at end of file
diff --git a/plugins/NewsAggregstor/Src/Utils.cpp b/plugins/NewsAggregstor/Src/Utils.cpp
new file mode 100644
index 0000000000..c474fa56e4
--- /dev/null
+++ b/plugins/NewsAggregstor/Src/Utils.cpp
@@ -0,0 +1,1389 @@
+/*
+Copyright (C) 2012 Mataes
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "common.h"
+
+HANDLE hNetlibUser = NULL, hNetlibHttp;
+BOOL UpdateListFlag = FALSE;
+
+BOOL IsMyContact(HANDLE hContact)
+{
+ const char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ return szProto != NULL && strcmp(MODULE, szProto) == 0;
+}
+
+VOID NetlibInit()
+{
+ NETLIBUSER nlu = {0};
+ nlu.cbSize = sizeof(nlu);
+ nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_HTTPCONNS | NUF_TCHAR; // | NUF_HTTPGATEWAY;
+ nlu.ptszDescriptiveName = TranslateT("NewsAggr HTTP connection");
+ nlu.szSettingsModule = MODULE;
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
+}
+
+VOID NetlibUnInit()
+{
+ Netlib_CloseHandle(hNetlibUser);
+ hNetlibUser = NULL;
+}
+
+static void arrayToHex(BYTE* data, size_t datasz, char* res)
+{
+ char* resptr = res;
+ for (unsigned i=0; i<datasz ; i++)
+ {
+ const BYTE ch = data[i];
+
+ const char ch0 = (char)(ch >> 4);
+ *resptr++ = (char)((ch0 <= 9) ? ('0' + ch0) : (('a' - 10) + ch0));
+
+ const char ch1 = (char)(ch & 0xF);
+ *resptr++ = (char)((ch1 <= 9) ? ('0' + ch1) : (('a' - 10) + ch1));
+ }
+ *resptr = '\0';
+}
+
+int GetImageFormat(const TCHAR* ext)
+{
+ if(lstrcmp(ext,_T(".jpg")) || lstrcmp(ext,_T(".jpeg")))
+ {
+ return PA_FORMAT_JPEG;
+ }
+ else if(lstrcmp(ext,_T(".png")))
+ {
+ return PA_FORMAT_PNG;
+ }
+ else if(lstrcmp(ext,_T(".gif")))
+ {
+ return PA_FORMAT_GIF;
+ }
+ else if(lstrcmp(ext,_T(".ico")))
+ {
+ return PA_FORMAT_ICON;
+ }
+ else if(lstrcmp(ext,_T(".bmp")))
+ {
+ return PA_FORMAT_BMP;
+ }
+ else if(lstrcmp(ext,_T(".swf")))
+ {
+ return PA_FORMAT_SWF;
+ }
+ else if(lstrcmp(ext,_T(".xml")))
+ {
+ return PA_FORMAT_XML;
+ }
+ else if(lstrcmp(ext,_T(".jpg")) || lstrcmp(ext,_T(".jpeg")))
+ {
+ return PA_FORMAT_JPEG;
+ }
+ else
+ {
+ return PA_FORMAT_UNKNOWN;
+ }
+}
+void CreateAuthString(char* auth, HANDLE hContact, HWND hwndDlg)
+{
+ char *user = NULL, *pass = NULL;
+ TCHAR *tlogin = NULL, *tpass = NULL, buf[MAX_PATH] = {0};
+ if (hContact && DBGetContactSettingByte(hContact, MODULE, "UseAuth", 0))
+ {
+ DBVARIANT dbLogin = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Login", &dbLogin))
+ {
+ tlogin = (TCHAR*)mir_alloc(_tcslen(dbLogin.ptszVal)*sizeof(TCHAR));
+ memcpy(tlogin, dbLogin.ptszVal, _tcslen(dbLogin.ptszVal)*sizeof(TCHAR));
+ tlogin[_tcslen(dbLogin.ptszVal)] = 0;
+ DBFreeVariant(&dbLogin);
+ }
+ DBVARIANT dbPass = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Password", &dbPass))
+ {
+ tpass = (TCHAR*)mir_alloc(_tcslen(dbPass.ptszVal)*sizeof(TCHAR));
+ memcpy(tpass, dbPass.ptszVal, _tcslen(dbPass.ptszVal)*sizeof(TCHAR));
+ tpass[_tcslen(dbPass.ptszVal)] = 0;
+ DBFreeVariant(&dbPass);
+ }
+ }
+ else if (hwndDlg && IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ GetDlgItemText(hwndDlg, IDC_LOGIN, buf, SIZEOF(buf));
+ tlogin = buf;
+ GetDlgItemText(hwndDlg, IDC_PASSWORD, buf, SIZEOF(buf));
+ tpass = buf;
+ }
+ user = mir_t2a(tlogin);
+ pass = mir_t2a(tpass);
+
+ char str[MAX_PATH];
+ int len = mir_snprintf(str, SIZEOF(str), "%s:%s", user, pass);
+ mir_free(user);
+ mir_free(pass);
+
+ strcpy(auth, "Basic ");
+ NETLIBBASE64 nlb = { auth+6, 250, (PBYTE)str, len };
+ CallService(MS_NETLIB_BASE64ENCODE, 0, LPARAM(&nlb));
+}
+
+VOID GetNewsData(TCHAR *tszUrl, char** szData, HANDLE hContact, HWND hwndDlg)
+{
+ char* szRedirUrl = NULL;
+ NETLIBHTTPREQUEST nlhr = {0};
+ NETLIBHTTPHEADER headers[5];
+
+ // initialize the netlib request
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_NODUMP | NLHRF_HTTP11;
+ char *szUrl = mir_t2a(tszUrl);
+ nlhr.szUrl = szUrl;
+ nlhr.nlc = hNetlibHttp;
+
+ // change the header so the plugin is pretended to be IE 6 + WinXP
+ nlhr.headers = headers;
+ nlhr.headers[0].szName = "User-Agent";
+ nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
+ nlhr.headers[1].szName = "Cache-Control";
+ nlhr.headers[1].szValue = "no-cache";
+ nlhr.headers[2].szName = "Pragma";
+ nlhr.headers[2].szValue = "no-cache";
+ nlhr.headers[3].szName = "Connection";
+ nlhr.headers[3].szValue = "close";
+ if (DBGetContactSettingByte(hContact, MODULE, "UseAuth", 0) || IsDlgButtonChecked(hwndDlg, IDC_USEAUTH))
+ {
+ nlhr.headersCount = 5;
+ nlhr.headers[4].szName = "Authorization";
+
+ char auth[256];
+ CreateAuthString(auth, hContact, hwndDlg);
+ nlhr.headers[4].szValue = auth;
+ }
+ else
+ nlhr.headersCount = 4;
+
+ // download the page
+ NETLIBHTTPREQUEST *nlhrReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser, (LPARAM)&nlhr);
+ if (nlhrReply)
+ {
+ // if the recieved code is 200 OK
+ switch(nlhrReply->resultCode)
+ {
+ case 200:
+ {
+ if (nlhrReply->dataLength)
+ {
+ // allocate memory and save the retrieved data
+ *szData = (char *)mir_alloc(nlhrReply->dataLength + 2);
+ memcpy(*szData, nlhrReply->pData, nlhrReply->dataLength);
+ (*szData)[nlhrReply->dataLength] = 0;
+ }
+ break;
+ }
+
+ case 401:
+ {
+ //ShowMessage(0, TranslateT("Cannot upload VersionInfo. Incorrect username or password"));
+ break;
+ }
+
+ case 301:
+ case 302:
+ case 307:
+ // get the url for the new location and save it to szInfo
+ // look for the reply header "Location"
+ for (int i=0; i<nlhrReply->headersCount; i++)
+ {
+ if (!strcmp(nlhrReply->headers[i].szName, "Location"))
+ {
+ size_t rlen = 0;
+ if (nlhrReply->headers[i].szValue[0] == '/')
+ {
+ const char* szPath;
+ const char* szPref = strstr(szUrl, "://");
+ szPref = szPref ? szPref + 3 : szUrl;
+ szPath = strchr(szPref, '/');
+ rlen = szPath != NULL ? szPath - szUrl : strlen(szUrl);
+ }
+
+ szRedirUrl = (char*)mir_realloc(szRedirUrl,
+ rlen + strlen(nlhrReply->headers[i].szValue)*3 + 1);
+
+ strncpy(szRedirUrl, szUrl, rlen);
+ strcpy(szRedirUrl+rlen, nlhrReply->headers[i].szValue);
+
+ nlhr.szUrl = szRedirUrl;
+ break;
+ }
+ }
+ break;
+
+ default:
+ //ShowMessage(0, TranslateT("Cannot upload VersionInfo. Unknown error"));
+ break;
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)nlhrReply);
+ }
+ mir_free(szUrl);
+}
+
+VOID CreateList (HWND hwndList)
+{
+ SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
+
+ LVCOLUMN lvc = {0};
+ // Initialize the LVCOLUMN structure.
+ // The mask specifies that the format, width, text, and
+ // subitem members of the structure are valid.
+ lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+ lvc.fmt = LVCFMT_LEFT;
+
+ lvc.iSubItem = 0;
+ lvc.pszText = TranslateT("Feed");
+ lvc.cx = 160; // width of column in pixels
+ ListView_InsertColumn(hwndList, 0, &lvc);
+
+ lvc.iSubItem = 1;
+ lvc.pszText = TranslateT("URL");
+ lvc.cx = 280; // width of column in pixels
+ ListView_InsertColumn(hwndList, 1, &lvc);
+}
+
+VOID UpdateList (HWND hwndList)
+{
+ LVITEM lvI = {0};
+
+ // Some code to create the list-view control.
+ // Initialize LVITEM members that are common to all
+ // items.
+ HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ int i = 0;
+ while (hContact != NULL)
+ {
+ if (IsMyContact(hContact))
+ {
+ UpdateListFlag = TRUE;
+ lvI.mask = LVIF_TEXT;
+ lvI.iSubItem = 0;
+ DBVARIANT dbNick = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "Nick", &dbNick))
+ {
+ lvI.pszText = dbNick.ptszVal;
+ lvI.iItem = i;
+ ListView_InsertItem(hwndList, &lvI);
+ lvI.iSubItem = 1;
+ DBVARIANT dbURL = {0};
+ if (!DBGetContactSettingTString(hContact, MODULE, "URL", &dbURL))
+ {
+ lvI.pszText = dbURL.ptszVal;
+ ListView_SetItem(hwndList, &lvI);
+ i += 1;
+ ListView_SetCheckState(hwndList, lvI.iItem, DBGetContactSettingByte(hContact, MODULE, "CheckState", 1));
+ DBFreeVariant(&dbURL);
+ }
+ DBFreeVariant(&dbNick);
+ }
+ }
+ hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
+ }
+ UpdateListFlag = FALSE;
+}
+
+VOID DeleteAllItems(HWND hwndList)
+{
+ ListView_DeleteAllItems(hwndList);
+}
+
+time_t __stdcall DateToUnixTime(TCHAR* stamp, BOOL FeedType)
+{
+ struct tm timestamp;
+ TCHAR date[9];
+ int i, y;
+ time_t t;
+
+ if ( stamp == NULL ) return ( time_t ) 0;
+
+ TCHAR *p = stamp;
+
+ if (FeedType)
+ {
+ // skip '-' chars
+ int si = 0, sj = 0;
+ while (1) {
+ if ( p[si] == _T('-') )
+ si++;
+ else
+ if ( !( p[sj++] = p[si++] ))
+ break;
+ };
+ }
+ else
+ {
+ TCHAR weekday[4], monthstr[4], timezonesign[2];
+ INT day, month, year, hour, min, sec, timezoneh, timezonem;
+ _stscanf( p, _T("%3s, %d %3s %d %d:%d:%d %1s%02d%02d"), &weekday, &day, &monthstr, &year, &hour, &min, &sec, &timezonesign, &timezoneh, &timezonem);
+ if (lstrcmpi(monthstr, _T("Jan")) ==0)
+ month = 1;
+ if (lstrcmpi(monthstr, _T("Feb")) ==0)
+ month = 2;
+ if (lstrcmpi(monthstr, _T("Mar")) ==0)
+ month = 3;
+ if (lstrcmpi(monthstr, _T("Apr")) ==0)
+ month = 4;
+ if (lstrcmpi(monthstr, _T("May")) ==0)
+ month = 5;
+ if (lstrcmpi(monthstr, _T("Jun")) ==0)
+ month = 6;
+ if (lstrcmpi(monthstr, _T("Jul")) ==0)
+ month = 7;
+ if (lstrcmpi(monthstr, _T("Aug")) ==0)
+ month = 8;
+ if (lstrcmpi(monthstr, _T("Sep")) ==0)
+ month = 9;
+ if (lstrcmpi(monthstr, _T("Oct")) ==0)
+ month = 10;
+ if (lstrcmpi(monthstr, _T("Nov")) ==0)
+ month = 11;
+ if (lstrcmpi(monthstr, _T("Dec")) ==0)
+ month = 12;
+ if (lstrcmp(timezonesign, _T("+")) ==0)
+ mir_sntprintf(p, 4+2+2+1+2+1+2+1+2+1, _T("%04d%02d%02dT%02d:%02d:%02d"), year, month, day, hour-timezoneh, min-timezonem, sec);
+ else if (lstrcmp(timezonesign, _T("-")) ==0)
+ mir_sntprintf(p, 4+2+2+1+2+1+2+1+2+1, _T("%04d%02d%02dT%02d:%02d:%02d"), year, month, day, hour+timezoneh, min+timezonem, sec);
+ else
+ mir_sntprintf(p, 4+2+2+1+2+1+2+1+2+1, _T("%04d%02d%02dT%02d:%02d:%02d"), year, month, day, hour, min, sec);
+ }
+ // Get the date part
+ for ( i=0; *p!='\0' && i<8 && isdigit( *p ); p++,i++ )
+ date[i] = *p;
+
+ // Parse year
+ if ( i == 6 ) {
+ // 2-digit year ( 1970-2069 )
+ y = ( date[0]-'0' )*10 + ( date[1]-'0' );
+ if ( y < 70 ) y += 100;
+ }
+ else if ( i == 8 ) {
+ // 4-digit year
+ y = ( date[0]-'0' )*1000 + ( date[1]-'0' )*100 + ( date[2]-'0' )*10 + date[3]-'0';
+ y -= 1900;
+ }
+ else
+ return ( time_t ) 0;
+ timestamp.tm_year = y;
+ // Parse month
+ timestamp.tm_mon = ( date[i-4]-'0' )*10 + date[i-3]-'0' - 1;
+ // Parse date
+ timestamp.tm_mday = ( date[i-2]-'0' )*10 + date[i-1]-'0';
+
+ // Skip any date/time delimiter
+ for ( ; *p!='\0' && !isdigit( *p ); p++ );
+
+ // Parse time
+ if ( _stscanf( p, _T("%d:%d:%d"), &timestamp.tm_hour, &timestamp.tm_min, &timestamp.tm_sec ) != 3 )
+ return ( time_t ) 0;
+
+ timestamp.tm_isdst = 0; // DST is already present in _timezone below
+ t = mktime( &timestamp );
+
+ _tzset();
+ t -= _timezone;
+
+ if ( t >= 0 )
+ return t;
+ else
+ return ( time_t ) 0;
+}
+
+TCHAR* StrReplace (TCHAR* Search, TCHAR* Replace, TCHAR* Resource)
+{
+ int i = 0;
+ int SearchLen = (int)_tcslen(Search);
+ TCHAR* Work = mir_tstrdup(Replace);
+ int ReplaceLen = (int)_tcslen(Work);
+
+ TCHAR* Pointer = _tcsstr(Resource, Search);
+
+ while (Pointer != NULL)
+ {
+ int PointerLen = (int)_tcslen(Pointer);
+ int ResourceLen = (int)_tcslen(Resource);
+
+ TCHAR* NewText = (TCHAR*)mir_calloc((ResourceLen - SearchLen + ReplaceLen + 1)*sizeof(TCHAR));
+
+ _tcsncpy(NewText, Resource, ResourceLen - PointerLen);
+ _tcscat(NewText, Work);
+ _tcscat(NewText, Pointer + SearchLen);
+
+ Resource = (TCHAR*)mir_alloc((ResourceLen - SearchLen + ReplaceLen + 1)*sizeof(TCHAR));
+
+ for (i = 0; i < (ResourceLen - SearchLen + ReplaceLen); i++)
+ Resource[i] = NewText[i];
+ Resource[i] = 0;
+ mir_free(NewText);
+
+ Pointer = _tcsstr(Resource + (ResourceLen - PointerLen + ReplaceLen), Search);
+ }
+ mir_free(Work);
+
+ return Resource;
+}
+
+BOOL DownloadFile(LPCTSTR tszURL, LPCTSTR tszLocal)
+{
+ HANDLE hFile = NULL;
+ DWORD dwBytes;
+
+ NETLIBHTTPREQUEST nlhr = {0};
+ nlhr.cbSize = sizeof(nlhr);
+ nlhr.requestType = REQUEST_GET;
+ nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11;
+ char* szUrl = mir_t2a(tszURL);
+ nlhr.szUrl = szUrl;
+ nlhr.headersCount = 4;
+ nlhr.headers=(NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount);
+ nlhr.headers[0].szName = "User-Agent";
+ nlhr.headers[0].szValue = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)";
+ nlhr.headers[1].szName = "Connection";
+ nlhr.headers[1].szValue = "close";
+ nlhr.headers[2].szName = "Cache-Control";
+ nlhr.headers[2].szValue = "no-cache";
+ nlhr.headers[3].szName = "Pragma";
+ nlhr.headers[3].szValue = "no-cache";
+
+ bool ret = false;
+ NETLIBHTTPREQUEST *pReply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hNetlibUser,(LPARAM)&nlhr);
+
+ if(pReply)
+ {
+ if((200 == pReply->resultCode) && (pReply->dataLength > 0))
+ {
+ char *date = NULL, *size = NULL;
+ for (int i = 0; i < pReply->headersCount; i++)
+ {
+ if (lstrcmpiA(pReply->headers[i].szName, "Last-Modified") == 0)
+ {
+ date = pReply->headers[i].szValue;
+ continue;
+ }
+ if (lstrcmpiA(pReply->headers[i].szName, "Content-Length") == 0)
+ {
+ size = pReply->headers[i].szValue;
+ continue;
+ }
+ }
+ if (date != NULL && size != NULL)
+ {
+ TCHAR *tdate = mir_a2t(date);
+ TCHAR *tsize = mir_a2t(size);
+ int fh;
+ struct _stat buf;
+
+ fh = _topen(tszLocal, _O_RDONLY);
+ if (fh != -1)
+ {
+ _fstat(fh, &buf);
+ time_t modtime = DateToUnixTime(tdate, 0);
+ time_t filemodtime = mktime(localtime(&buf.st_atime));
+ if (modtime > filemodtime && buf.st_size != _ttoi(tsize))
+ {
+ hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, NULL);
+ ret = true;
+ }
+ _close(fh);
+ }
+ else
+ {
+ hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, NULL);
+ ret = true;
+ }
+ mir_free(tdate);
+ mir_free(tsize);
+ }
+ else
+ {
+ hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, NULL);
+ ret = true;
+ }
+ }
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,(LPARAM)pReply);
+ }
+
+ mir_free(szUrl);
+ mir_free(nlhr.headers);
+
+ if (hFile)
+ CloseHandle(hFile);
+
+ return ret;
+}
+
+size_t PathToRelative(const TCHAR *pSrc, TCHAR *pOut)
+{ return CallService( MS_UTILS_PATHTORELATIVET, (WPARAM)pSrc, (LPARAM)pOut );
+}
+
+TCHAR* CheckFeed(TCHAR* tszURL, HWND hwndDlg)
+{
+ char *szData = NULL;
+ DBVARIANT dbVar = {0};
+ if (CallProtoService(MODULE, PS_GETSTATUS, 0, 0) != ID_STATUS_OFFLINE)
+ {
+ GetNewsData(tszURL, &szData, NULL, hwndDlg);
+ if (szData)
+ {
+ TCHAR *tszData = mir_a2t(szData);
+ int bytesParsed = 0;
+ HXML hXml = xi.parseString(tszData, &bytesParsed, NULL);
+ BOOL UtfEncode = FALSE;
+ TCHAR *newtszData = mir_utf8decodeT(szData);
+ if (newtszData)
+ {
+ UtfEncode = TRUE;
+ mir_free(newtszData);
+ }
+ mir_free(tszData);
+ mir_free(szData);
+ if(hXml != NULL)
+ {
+ int childcount = 0;
+ HXML node = xi.getChild(hXml, childcount);
+ while(node)
+ {
+ if (lstrcmpi(xi.getName(node), _T("rss")) == 0 || lstrcmpi(xi.getName(node), _T("rdf")) == 0)
+ {
+ HXML chan = xi.getChild(node, 0);
+ for (int j = 0; j < xi.getChildCount(chan); j++)
+ {
+ HXML child = xi.getChild(chan, j);
+ if (lstrcmpi(xi.getName(child), _T("title")) == 0)
+ {
+ TCHAR mes[MAX_PATH];
+ mir_sntprintf(mes, SIZEOF(mes), TranslateT("%s\nis a valid feed's address."), tszURL);
+ MessageBox(NULL, mes, TranslateT("New Aggregator"), MB_OK|MB_ICONINFORMATION);
+ TCHAR *tszTitle = (TCHAR*)xi.getText(child);
+ if (UtfEncode)
+ {
+ char* szstring = mir_t2a(tszTitle);
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ tszTitle = (TCHAR*)mir_alloc(sizeof(TCHAR)*lstrlen(tszstring)+1);
+ _tcscpy(tszTitle, tszstring);
+ mir_free(tszstring);
+ mir_free(szstring);
+ }
+ return tszTitle;
+ }
+ }
+ }
+ else if (lstrcmpi(xi.getName(node), _T("feed")) == 0)
+ {
+ for (int j = 0; j < xi.getChildCount(node); j++)
+ {
+ HXML child = xi.getChild(node, j);
+ if (lstrcmpi(xi.getName(child), _T("title")) == 0)
+ {
+ TCHAR mes[MAX_PATH];
+ mir_sntprintf(mes, SIZEOF(mes), TranslateT("%s\nis a valid feed's address."), tszURL);
+ MessageBox(NULL, mes, TranslateT("New Aggregator"), MB_OK|MB_ICONINFORMATION);
+ TCHAR *tszTitle = (TCHAR*)xi.getText(child);
+ if (UtfEncode)
+ {
+ char* szstring = mir_t2a(tszTitle);
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ tszTitle = (TCHAR*)mir_alloc(sizeof(TCHAR)*lstrlen(tszstring)+1);
+ _tcscpy(tszTitle, tszstring);
+ mir_free(tszstring);
+ mir_free(szstring);
+ }
+ return tszTitle;
+ }
+ }
+ }
+ childcount +=1;
+ node = xi.getChild(hXml, childcount);
+ }
+ }
+ xi.destroyNode(hXml);
+ }
+ else
+ {
+ TCHAR mes[MAX_PATH];
+ mir_sntprintf(mes, SIZEOF(mes), TranslateT("%s\nis a not valid feed's address."), tszURL);
+ MessageBox(NULL, mes, TranslateT("New Aggregator"), MB_OK|MB_ICONERROR);
+ }
+ }
+ return NULL;
+}
+
+VOID CheckCurrentFeed(HANDLE hContact)
+{
+ char *szData = NULL;
+ DBVARIANT dbURL = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "URL", &dbURL))
+ return;
+ else if ((DBGetContactSettingWord(hContact, MODULE, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) && DBGetContactSettingByte(hContact, MODULE, "CheckState", 1) != 0)
+ {
+ GetNewsData(dbURL.ptszVal, &szData, hContact, NULL);
+ DBFreeVariant(&dbURL);
+ if (szData)
+ {
+ TCHAR *tszData = mir_a2t(szData);
+ int bytesParsed = 0;
+ HXML hXml = xi.parseString(tszData, &bytesParsed, NULL);
+ BOOL UtfEncode = FALSE;
+ TCHAR *newtszData = mir_utf8decodeT(szData);
+ if (newtszData)
+ {
+ UtfEncode = TRUE;
+ mir_free(newtszData);
+ }
+ mir_free(tszData);
+ mir_free(szData);
+ if(hXml != NULL)
+ {
+ int childcount = 0;
+ HXML node = xi.getChild(hXml, childcount);
+ while(node)
+ {
+ if (lstrcmpi(xi.getName(node), _T("rss")) == 0 || lstrcmpi(xi.getName(node), _T("rdf")) == 0)
+ {
+ if (lstrcmpi(xi.getName(node), _T("rss")) == 0)
+ {
+ for (int i = 0; i < xi.getAttrCount(node); i++)
+ {
+ if (lstrcmpi(xi.getAttrName(node, i), _T("version")) == 0)
+ {
+ TCHAR ver[MAX_PATH];
+ mir_sntprintf(ver, SIZEOF(ver), _T("RSS %s"), xi.getAttrValue(node, xi.getAttrName(node, i)));
+ DBWriteContactSettingTString(hContact, MODULE, "MirVer", ver);
+ break;
+ }
+ }
+ }
+ else if (lstrcmpi(xi.getName(node), _T("rdf")) == 0)
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "MirVer", _T("RSS 1.0"));
+ }
+
+ HXML chan = xi.getChild(node, 0);
+ for (int j = 0; j < xi.getChildCount(chan); j++)
+ {
+ HXML child = xi.getChild(chan, j);
+ if (lstrcmpi(xi.getName(child), _T("title")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "FirstName", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "FirstName", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("link")) == 0)
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "Homepage", xi.getText(child));
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("description")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "About", tszstring);
+ DBWriteContactSettingTString(hContact, "CList", "StatusMsg", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "About", tszstring);
+ DBWriteContactSettingTString(hContact, "CList", "StatusMsg", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("language")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Language1", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Language1", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("managingEditor")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "e-mail", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "e-mail", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("category")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Interest0Text", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Interest0Text", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("image")) == 0)
+ {
+ for (int x = 0; x < xi.getChildCount(child); x++)
+ {
+ HXML imageval = xi.getChild(child, x);
+ if (lstrcmpi(xi.getName(imageval), _T("url")) == 0)
+ {
+ LPCTSTR url = xi.getText(imageval);
+ DBWriteContactSettingTString(hContact, MODULE, "ImageURL", url);
+
+ PROTO_AVATAR_INFORMATIONT pai = {NULL};
+ pai.cbSize = sizeof(pai);
+ pai.hContact = hContact;
+ DBVARIANT dbVar = {0};
+
+ if(!DBGetContactSettingTString(hContact, MODULE, "Nick", &dbVar))
+ {
+ TCHAR *ext = _tcsrchr((TCHAR*)url, _T('.')) + 1;
+ pai.format = GetImageFormat(ext);
+
+ TCHAR *filename = dbVar.ptszVal;
+ mir_sntprintf(pai.filename, SIZEOF(pai.filename), _T("%s\\%s.%s"), tszRoot, filename, ext);
+ if (DownloadFile(url, pai.filename))
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "ImagePath", pai.filename);
+ ProtoBroadcastAck(MODULE, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE) &pai, NULL);
+ }
+ else
+ ProtoBroadcastAck(MODULE, hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE) &pai, NULL);
+ DBFreeVariant(&dbVar);
+ break;
+ }
+ }
+ else
+ {
+ DBDeleteContactSetting(hContact, MODULE, "ImageURL");
+ DBDeleteContactSetting(hContact, MODULE, "ImagePath");
+ }
+ }
+ }
+ if (lstrcmpi(xi.getName(child), _T("lastBuildDate")) == 0 && xi.getText(child))
+ {
+ TCHAR *lastupdtime = (TCHAR*)xi.getText(child);
+ time_t stamp = DateToUnixTime(lastupdtime, 0);
+ double deltaupd = difftime(time(NULL), stamp);
+ double deltacheck = difftime(time(NULL), DBGetContactSettingDword(hContact, MODULE, "LastCheck", 0));
+ if (deltaupd - deltacheck >= 0)
+ {
+ DBWriteContactSettingDword(hContact, MODULE, "LastCheck", time(NULL));
+ xi.destroyNode(hXml);
+ return;
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("item")) == 0)
+ {
+ TCHAR *title = NULL, *link = NULL, *datetime = NULL, *descr = NULL, *author = NULL, *comments = NULL, *guid = NULL, *category = NULL;
+ for (int z = 0; z < xi.getChildCount(child); z++)
+ {
+ HXML itemval = xi.getChild(child, z);
+ if (lstrcmpi(xi.getName(itemval), _T("title")) == 0)
+ {
+ title = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("link")) == 0)
+ {
+ link = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("pubDate")) == 0)
+ {
+ datetime = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("dc:date")) == 0)
+ {
+ datetime = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("description")) == 0)
+ {
+ descr = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("author")) == 0)
+ {
+ author = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("comments")) == 0)
+ {
+ comments = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("guid")) == 0)
+ {
+ guid = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("category")) == 0)
+ {
+ category = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ }
+ TCHAR* message;
+ DBVARIANT dbMsg = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "MsgFormat", &dbMsg))
+ message = _T(TAGSDEFAULT);
+ else
+ {
+ message = (TCHAR*)mir_alloc(_tcslen(dbMsg.ptszVal)*sizeof(TCHAR));
+ memcpy(message, dbMsg.ptszVal, _tcslen(dbMsg.ptszVal)*sizeof(TCHAR));
+ message[_tcslen(dbMsg.ptszVal)] = 0;
+ DBFreeVariant(&dbMsg);
+ }
+ if (lstrcmp(title, NULL) == 0)
+ message = StrReplace(_T("#<title>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<title>#"), title, message);
+ if (lstrcmp(link, NULL) == 0)
+ message = StrReplace(_T("#<link>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<link>#"), link, message);
+ if (lstrcmp(descr, NULL) == 0)
+ message = StrReplace(_T("#<description>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<description>#"), descr, message);
+ if (lstrcmp(author, NULL) == 0)
+ message = StrReplace(_T("#<author>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<author>#"), author, message);
+ if (lstrcmp(comments, NULL) == 0)
+ message = StrReplace(_T("#<comments>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<comments>#"), comments, message);
+ if (lstrcmp(guid, NULL) == 0)
+ message = StrReplace(_T("#<guid>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<guid>#"), guid, message);
+ if (lstrcmp(category, NULL) == 0)
+ message = StrReplace(_T("#<category>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<category>#"), category, message);
+
+ message = StrReplace(_T("<br>"), _T("\n"), message);
+ message = StrReplace(_T("<br/>"), _T("\n"), message);
+ message = StrReplace(_T("<br />"), _T("\n"), message);
+
+ char* pszUtf;
+ if (!UtfEncode)
+ pszUtf = mir_utf8encodeT(message);
+ else
+ pszUtf = mir_t2a(message);
+ decode_html_entities_utf8(pszUtf, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(pszUtf);
+ strcpy(pszUtf, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ xRegEx = "^\\s+";
+ xStr = pszUtf;
+ strcpy(pszUtf, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+
+ time_t stamp;
+ if (lstrcmpi(datetime, NULL) ==0)
+ stamp = time(NULL);
+ else
+ stamp = DateToUnixTime(datetime, 0);
+
+ DBEVENTINFO olddbei = { 0 };
+ HANDLE hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0);
+ BOOL MesExist = FALSE;
+ while(hDbEvent)
+ {
+ ZeroMemory(&olddbei, sizeof(olddbei));
+ olddbei.cbSize = sizeof(olddbei);
+ olddbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
+ olddbei.pBlob = (PBYTE)mir_alloc(olddbei.cbBlob);
+ CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&olddbei);
+ if (olddbei.cbBlob == lstrlenA(pszUtf) + 1 && lstrcmpA((char*)olddbei.pBlob, pszUtf) == 0)
+ MesExist = TRUE;
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0);
+ mir_free(olddbei.pBlob);
+ }
+
+ if (!MesExist)
+ {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_UTF;
+ dbei.szModule = MODULE;
+ dbei.timestamp = stamp;
+ dbei.cbBlob = lstrlenA(pszUtf) + 1;
+ dbei.pBlob = (PBYTE)pszUtf;
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ }
+ mir_free(pszUtf);
+ mir_free(message);
+ }
+ }
+ }
+ else if (lstrcmpi(xi.getName(node), _T("feed")) == 0)
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "MirVer", _T("Atom 3"));
+ for (int j = 0; j < xi.getChildCount(node); j++)
+ {
+ HXML child = xi.getChild(node, j);
+ if (lstrcmpi(xi.getName(child), _T("title")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "FirstName", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "FirstName", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("link")) == 0)
+ {
+ for (int x = 0; x < xi.getAttrCount(child); x++)
+ {
+ if (lstrcmpi(xi.getAttrName(child, x), _T("rel")) == 0)
+ {
+ if (lstrcmpi(xi.getAttrValue(child, xi.getAttrName(child, x)), _T("self")) == 0)
+ break;
+ }
+ if (lstrcmpi(xi.getAttrName(child, x), _T("href")) == 0)
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "Homepage", xi.getAttrValue(child, xi.getAttrName(child, x)));
+ }
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("subtitle")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "About", tszstring);
+ DBWriteContactSettingTString(hContact, "CList", "StatusMsg", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "About", tszstring);
+ DBWriteContactSettingTString(hContact, "CList", "StatusMsg", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("language")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Language1", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Language1", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("author")) == 0)
+ {
+ for (int x = 0; x < xi.getChildCount(child); x++)
+ {
+ HXML authorval = xi.getChild(child, x);
+ if (lstrcmpi(xi.getName(authorval), _T("name")) == 0)
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "e-mail", xi.getText(authorval));
+ break;
+ }
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("category")) == 0 && xi.getText(child))
+ {
+ char* szstring = mir_t2a(xi.getText(child));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ if (UtfEncode)
+ {
+ TCHAR* tszstring = mir_utf8decodeT(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Interest0Text", tszstring);
+ mir_free(tszstring);
+ }
+ else
+ {
+ TCHAR* tszstring = mir_a2t(szstring);
+ DBWriteContactSettingTString(hContact, MODULE, "Interest0Text", tszstring);
+ mir_free(tszstring);
+ }
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("icon")) == 0)
+ {
+ for (int x = 0; x < xi.getChildCount(child); x++)
+ {
+ HXML imageval = xi.getChild(child, x);
+ if (lstrcmpi(xi.getName(imageval), _T("url")) == 0)
+ {
+ LPCTSTR url = xi.getText(imageval);
+ DBWriteContactSettingTString(hContact, MODULE, "ImageURL", url);
+
+ PROTO_AVATAR_INFORMATIONT pai = {NULL};
+ pai.cbSize = sizeof(pai);
+ pai.hContact = hContact;
+ DBVARIANT dbVar = {0};
+
+ if(!DBGetContactSettingTString(hContact, MODULE, "Nick", &dbVar))
+ {
+ TCHAR *ext = _tcsrchr((TCHAR*)url, _T('.')) + 1;
+ pai.format = GetImageFormat(ext);
+
+ TCHAR *filename = dbVar.ptszVal;
+ mir_sntprintf(pai.filename, SIZEOF(pai.filename), _T("%s\\%s.%s"), tszRoot, filename, ext);
+ if (DownloadFile(url, pai.filename))
+ {
+ DBWriteContactSettingTString(hContact, MODULE, "ImagePath", pai.filename);
+ ProtoBroadcastAck(MODULE, hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE) &pai, NULL);
+ }
+ else
+ ProtoBroadcastAck(MODULE, hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, (HANDLE) &pai, NULL);
+ DBFreeVariant(&dbVar);
+ break;
+ }
+ }
+ else
+ {
+ DBDeleteContactSetting(hContact, MODULE, "ImageURL");
+ DBDeleteContactSetting(hContact, MODULE, "ImagePath");
+ }
+ }
+ }
+ if (lstrcmpi(xi.getName(child), _T("updated")) == 0 && xi.getText(child))
+ {
+ TCHAR *lastupdtime = (TCHAR*)xi.getText(child);
+ time_t stamp = DateToUnixTime(lastupdtime, 0);
+ double deltaupd = difftime(time(NULL), stamp);
+ double deltacheck = difftime(time(NULL), DBGetContactSettingDword(hContact, MODULE, "LastCheck", 0));
+ if (deltaupd - deltacheck >= 0)
+ {
+ DBWriteContactSettingDword(hContact, MODULE, "LastCheck", time(NULL));
+ xi.destroyNode(hXml);
+ return;
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(child), _T("entry")) == 0)
+ {
+ TCHAR *title = NULL, *link = NULL, *datetime = NULL, *descr = NULL, *author = NULL, *comments = NULL, *guid = NULL, *category = NULL;
+ for (int z = 0; z < xi.getChildCount(child); z++)
+ {
+ HXML itemval = xi.getChild(child, z);
+ if (lstrcmpi(xi.getName(itemval), _T("title")) == 0 && xi.getText(itemval))
+ {
+ char* szstring = mir_t2a(xi.getText(itemval));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ title = mir_a2t(szstring);
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("link")) == 0)
+ {
+ for (int x = 0; x < xi.getAttrCount(itemval); x++)
+ {
+ if (lstrcmpi(xi.getAttrName(itemval, x), _T("href")) == 0)
+ {
+ link = (TCHAR*)xi.getAttrValue(itemval, xi.getAttrName(itemval, x));
+ break;
+ }
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("updated")) == 0)
+ {
+ datetime = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if ((lstrcmpi(xi.getName(itemval), _T("summary")) == 0 || lstrcmpi(xi.getName(itemval), _T("content")) == 0) && xi.getText(itemval))
+ {
+ char* szstring = mir_t2a(xi.getText(itemval));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ descr = mir_a2t(szstring);
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("author")) == 0)
+ {
+ for (int x = 0; x < xi.getChildCount(itemval); x++)
+ {
+ HXML authorval = xi.getChild(itemval, x);
+ if (lstrcmpi(xi.getName(authorval), _T("name")) == 0 && xi.getText(authorval))
+ {
+ char* szstring = mir_t2a(xi.getText(authorval));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ author = mir_a2t(szstring);
+ mir_free(szstring);
+ break;
+ }
+ }
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("comments")) == 0 && xi.getText(itemval))
+ {
+ char* szstring = mir_t2a(xi.getText(itemval));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ comments = mir_a2t(szstring);
+ mir_free(szstring);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("id")) == 0)
+ {
+ guid = (TCHAR*)xi.getText(itemval);
+ continue;
+ }
+ if (lstrcmpi(xi.getName(itemval), _T("category")) == 0)
+ {
+ for (int x = 0; x < xi.getAttrCount(itemval); x++)
+ {
+ if (lstrcmpi(xi.getAttrName(itemval, x), _T("term")) == 0 && xi.getText(itemval))
+ {
+ char* szstring = mir_t2a(xi.getAttrValue(itemval, xi.getAttrName(itemval, x)));
+ decode_html_entities_utf8(szstring, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(szstring);
+ strcpy(szstring, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ category = mir_a2t(szstring);
+ mir_free(szstring);
+ break;
+ }
+ }
+ continue;
+ }
+ }
+ TCHAR* message;
+ DBVARIANT dbMsg = {0};
+ if (DBGetContactSettingTString(hContact, MODULE, "MsgFormat", &dbMsg))
+ message = _T(TAGSDEFAULT);
+ else
+ {
+ message = (TCHAR*)mir_alloc(_tcslen(dbMsg.ptszVal)*sizeof(TCHAR));
+ memcpy(message, dbMsg.ptszVal, _tcslen(dbMsg.ptszVal)*sizeof(TCHAR));
+ message[_tcslen(dbMsg.ptszVal)] = 0;
+ DBFreeVariant(&dbMsg);
+ }
+ if (lstrcmp(title, NULL) == 0)
+ message = StrReplace(_T("#<title>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<title>#"), title, message);
+ if (lstrcmp(link, NULL) == 0)
+ message = StrReplace(_T("#<link>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<link>#"), link, message);
+ if (lstrcmp(descr, NULL) == 0)
+ message = StrReplace(_T("#<description>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<description>#"), descr, message);
+ if (lstrcmp(author, NULL) == 0)
+ message = StrReplace(_T("#<author>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<author>#"), author, message);
+ if (lstrcmp(comments, NULL) == 0)
+ message = StrReplace(_T("#<comments>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<comments>#"), comments, message);
+ if (lstrcmp(guid, NULL) == 0)
+ message = StrReplace(_T("#<guid>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<guid>#"), guid, message);
+ if (lstrcmp(category, NULL) == 0)
+ message = StrReplace(_T("#<category>#"), TranslateT("empty"), message);
+ else
+ message = StrReplace(_T("#<category>#"), category, message);
+
+ message = StrReplace(_T("<br>"), _T("\n"), message);
+ message = StrReplace(_T("<br/>"), _T("\n"), message);
+ message = StrReplace(_T("<br />"), _T("\n"), message);
+
+ char* pszUtf;
+ if (!UtfEncode)
+ pszUtf = mir_utf8encodeT(message);
+ else
+ pszUtf = mir_t2a(message);
+ decode_html_entities_utf8(pszUtf, 0);
+ boost::regex xRegEx("<(.|\n)*?>");
+ std::string xStr(pszUtf);
+ strcpy(pszUtf, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+ xRegEx = "^\\s+";
+ xStr = pszUtf;
+ strcpy(pszUtf, boost::regex_replace(xStr, xRegEx, "", boost::match_default | boost::format_perl).c_str());
+
+ time_t stamp;
+ if (lstrcmpi(datetime, NULL) ==0)
+ stamp = time(NULL);
+ else
+ stamp = DateToUnixTime(datetime, 1);
+
+ DBEVENTINFO olddbei = { 0 };
+ HANDLE hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0);
+ BOOL MesExist = FALSE;
+ while(hDbEvent)
+ {
+ ZeroMemory(&olddbei, sizeof(olddbei));
+ olddbei.cbSize = sizeof(olddbei);
+ olddbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0);
+ olddbei.pBlob = (PBYTE)malloc(olddbei.cbBlob);
+ CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&olddbei);
+ if (olddbei.cbBlob == lstrlenA(pszUtf) + 1 && lstrcmpA((char*)olddbei.pBlob, pszUtf) == 0)
+ MesExist = TRUE;
+ hDbEvent = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDbEvent, 0);
+ }
+
+ if (!MesExist)
+ {
+ DBEVENTINFO dbei = {0};
+ dbei.cbSize = sizeof(dbei);
+ dbei.eventType = EVENTTYPE_MESSAGE;
+ dbei.flags = DBEF_UTF;
+ dbei.szModule = MODULE;
+ dbei.timestamp = stamp;
+ dbei.cbBlob = lstrlenA(pszUtf) + 1;
+ dbei.pBlob = (PBYTE)pszUtf;
+ CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&dbei);
+ }
+ mir_free(pszUtf);
+ }
+ }
+ }
+ childcount +=1;
+ node = xi.getChild(hXml, childcount);
+ }
+ xi.destroyNode(hXml);
+ }
+ }
+ DBWriteContactSettingDword(hContact, MODULE, "LastCheck", time(NULL));
+ }
+} \ No newline at end of file