Codebase list kopanocore / 42c6766
New upstream version 8.1.0 Carsten Schoenert 7 years ago
397 changed file(s) with 2294 addition(s) and 5963 deletion(s). Raw diff Collapse all Expand all
6161
6262 # /common/
6363 /common/config.h*
64 /common/cov-scope
6465 /common/ecversion.h
6566 /common/include/kopano/ecversion.h
6667 /common/include/kopano/zconfig.h
8182 # /installer/linux/
8283 /installer/linux/ldap.openldap.cfg
8384 /installer/linux/ldap.active-directory.cfg
85 /installer/linux/ldapms.openldap.cfg
86 /installer/linux/ldapms.active-directory.cfg
8487
8588 # /installer/userscripts/
8689 /installer/userscripts/creategroup
9093 /installer/userscripts/createcompany
9194 /installer/userscripts/deletecompany
9295
93 # /php-webclient-ajax/
94 /php-webclient-ajax/debug.txt
95 /php-webclient-ajax/errors.txt
96 /php-webclient-ajax/debug_xml
97 /php-webclient-ajax/tmp
98 /php-webclient-ajax/config.php
99
100 ## /provider/ECProps/
101 #/provider/ECProps/Debug
102 #
103 ## /provider/client/
104 #/provider/client/Debug
105 #/provider/client/Release
106 #
107 ## /provider/plugins/
108 #/provider/plugins/plugintest
109 #
110 # /provider/server/
111 /provider/server/kopano-server
96 /provider/kopano-server
11297
11398 # /provider/soap/
11499 /provider/soap/*res.xml
151136 /swig/python/RecurrenceState.py
152137 /swig/python/RecurrenceState_wrap.cxx
153138 /swig/python/kopano/build/
139 /swig/python/zarafa/build/
154140
155141 # Ignore Python compiled files
156142 *.pyc
0 A quick overview of the Kopano code structure
1 =============================================
2
3 Overview
4 ========
5
6 The codebase has a lot of libraries, components and for example scripts.
7 Each top level directory is listed below with a clear description of what it does.
8
9
10 autoconf - helpers for autoconf: php, boost and swig
11 caldav - Ical server implementation which uses kopano-server as backend
12 common - commonly used libraries for everything except server/client. There are three different "common" utils: util, ssl and mapi.
13 doc - Kopano documentation and manpages
14 ECtools - ECtools consists of a lot of seperate tools which use the MAPI library.
15 gateway - POP3/IMAP gateway for Kopano
16 inetmapi - VMIME to MAPI and MAPI to VMIME library (should be called libinetmapi)
17 libfreebusy - Freebusy library from windows and from Linux
18 libicalmapi - Ical to MAPI and MAPI to Ical library
19 mapi4linux - Source compatbile Windows MAPI library
20 php-ext - PHP-MAPI module
21 php7-ext - PHP-MAPI module (PHP 7)
22 po - Translations
23 provider - Directory where the kopano-server and client is located
24 spooler - Kopano-dagent/spooler
25 swig - Python bindings for MAPI
26 tools - Collection of PHP and Python tools
27 libsync - Shared library that is used by the synchronisation agent in Windows for offline synchronisation
28
29 MAPI Properties
30 ===============
31
32 All initial MAPI properties can be found in mapi4linux/include/mapi.h, later added property definitions are found in common/mapiext.h.
33 Kopano defined properties (all properties which start with PR_EC_*) can be found in common/ECTags.h.
34
35 Provider
36 ========
37
38 Provider consists of a few directories:
39 client - Generates mapi client exposes MAPI interface. (Providers GAB, all your stores, private and delegate)
40 libserver - Splitted for historical reasons from server
41 server - the kopano-server
42 common - soap ulitlities for provider / client (ECSearchClient <-> Server and Indexer)
43 contacts - addressbookprovier, displays one or multiple addressbooks in for example webapp as contacts.
44 plugins - Userplugins: ldap, ad, db and unix.
0 A quick overview of the Kopano Core database structure
1 =======================================================
2
3 Overview
4 ========
5
6 The Datbase has the following tables:
7 +--------------------+
8 | Tables_in_kopano |
9 +--------------------+
10 | abchanges |
11 | acl |
12 | changes |
13 | clientupdatestatus |
14 | deferredupdate |
15 | hierarchy |
16 | indexedproperties |
17 | lob |
18 | mvproperties |
19 | names |
20 | object |
21 | objectmvproperty |
22 | objectproperty |
23 | objectrelation |
24 | outgoingqueue |
25 | properties |
26 | receivefolder |
27 | searchresults |
28 | settings |
29 | singleinstances |
30 | stores |
31 | syncedmessages |
32 | syncs |
33 | tproperties |
34 | users |
35 | versions |
36 +--------------------+
37
38 abchanges
39 =========
40
41 Has a journal of all GAB changes -> every change (add/delete/modify) is in this
42 table.
43
44 acl
45 ===
46
47 List of all acls - each record is an ACE (access control entry) userx has
48 permissiony on folderz (With a pair record for rights for grant and deny, but
49 deny was never implemented in the Kopano server) Columns:
50
51 * id:
52 * hierarchy_id:
53 * type: 2=grant,1=deny
54 * rights: bitmask of the rights (owner, etc.) - same in mapi defined permissions
55
56 changes
57 =======
58
59 Has a journal of all mailbox changes -> messages in folders added, deleted,
60 modified - exposed via ICA.
61
62 clientupdatestatus
63 ==================
64
65 Has a list of all the reported statuses of client updates
66
67 deferredupdate
68 ==============
69
70 Is a per-folder list of changes to tproperties that haven't been written to
71 tproperties yet (for performance reasons)
72
73 hierarchy
74 =========
75
76 Is the parent-child relationship table for the mailbox (IPM_SUBTREE_ROOT -> ...)
77
78 Columns
79 * id:
80 * parent:
81 * type: 1=mailbox, 3=folder, 5=message, 6=recipient, 7=attachment
82 * flags: folders:0=root folder,1=normal folder,2=search folder;
83 messages:0=normal message, 64=associative message, 1024=deleted
84 * owner:
85
86 indexedproperties
87 =================
88
89 Mapping between from certain properties to their hierarchyid example:
90 PR_ENTRY_ID abcdef match to hierarchy.id 12345
91
92 lob
93 ===
94
95 Attachments chunked into 256K blocks (only in mysql-stored format)
96
97 Names
98 =====
99
100 Nothing but named properties mapping to property id's - property ids are
101 subtracted by 0x8500
102
103 outgoingqueue
104 =============
105
106 Two things: 1. queue that outlook polls for messages that it wants to send, 2.
107 queue of spooler, of messages that it wants to send
108
109 Columns:
110 * flags: if even then outlook queue, if odd spooler queue
111 * properties - the list of properties for each hierarchy.id - each value is put
112 into its corresponding column type (binary, double, etc.)
113 * mvproperties - looks exactly the same, but it also has orderid, so there can
114 * be multiple records for the same property for the same hierarchy.id (done for
115 performance reasons)
116
117 receivefolder
118 =============
119 It points at which folder is your actual receivefolder in your hierarchy
120
121 searchresults
122 =============
123
124 When you do a search all of the results are saved and updated forever until you
125 delete the search folder settings - random server-wide settings
126
127 singleinstances
128 ===============
129
130 Record of attachment-deduplication (single instance store)
131
132 stores
133 ======
134
135 links stores to users (hierarchy.id to users.id)
136
137 syncedmessages
138 ==============
139
140 Is used in restricted ICS (when we can't use the journal) - sync only the last 4
141 weeks is an example. This represents the messages that have been sent to a
142 mobile. only for z-push
143
144 syncs
145 =====
146
147 A list of all folders that are being tracked for ICS - we do not really use it,
148 we only write to it (investigation, maybe?)
149
150 tproperties
151 ===========
152
153 The list of properties for each hierarchy.id - each value is put into its
154 corresponding column type (binary, double, etc.) *BUT* It only contains the
155 properties that can be seen in tables therefore excludes attachments and
156 recipients everything is truncated to 255 bytes or characters.
157
158 users
159 ======
160
161 Users table with the relation column (externid)
162
163 Versions
164 ========
165
166 List of all zarafa versions ever installed on the system
167
168 =============================
169 Tables specific for DB plugin
170 =============================
171
172 object - everything normally in ldap
173 objectmvproperty - everything normally in ldap
174 objectproperty - everything normally in ldap
175 objectrelation - everything normally in ldap
2020 libkcarchiver.ldd libkcarchivercore.ldd \
2121 kopano-archiver.ldx kopano-cfgchecker.ldx \
2222 kopano-monitor.ldx kopano-passwd.ldx kopano-stats.ldx
23 CLEANFILES = ${noinst_DATA}
2324
2425
2526 kopano_admin_SOURCES = \
3738 archiver/main.cpp
3839 kopano_archiver_CPPFLAGS = \
3940 ${AM_CPPFLAGS} -I${top_srcdir}/provider/client \
40 -I${top_srcdir}/provider/include -I${top_srcdir}/provider/soap \
41 -I${top_srcdir}/provider/include \
4142 -I${top_builddir}/provider/soap -I${top_srcdir}/ECtools/archiver \
4243 ${GSOAP_CFLAGS} ${MYSQL_INCLUDES}
4344 kopano_archiver_LDADD = \
196197 EXTRA_libkcarchivercore_la_DEPENDENCIES = \
197198 ${top_builddir}/default.sym
198199
199 mapitime_SOURCES = mapitime.cpp hx-time.c
200 mapitime_SOURCES = mapitime.cpp
200201 mapitime_LDADD = -lrt ${top_builddir}/mapi4linux/src/libmapi.la \
201202 ${top_builddir}/common/libkcmapi.la \
202203 ${top_builddir}/common/libkcutil.la
4646 #include <kopano/mapiext.h>
4747 #include <kopano/Util.h>
4848 #include <kopano/ECRestriction.h>
49 #include <kopano/ECABEntryID.h>
5049 #include <kopano/charset/convert.h>
5150 #include "ConsoleTable.h"
5251 #include <kopano/mapi_ptr.h>
328327 cout << endl;
329328 cout << "Global options: [-h|--host path]" << endl;
330329 ct.Resize(4,2);
330 ct.AddColumn(0, "--config file"); ct.AddColumn(1, "Use a configuration file");
331331 ct.AddColumn(0, "-h path"); ct.AddColumn(1, "Connect through <path>, e.g. file:///var/run/socket");
332332 ct.AddColumn(0, "--node name"); ct.AddColumn(1, "Execute the command on cluster node <name>");
333 ct.AddColumn(0, "--utf8"); ct.AddColumn(1, "Force the current locale to UTF-8");
333334 ct.AddColumn(0, "-v"); ct.AddColumn(1, "Increase verbosity. A maximum of 7 is possible where 1=fatal errors only, 6=debug and 7=everything.");
334335 ct.AddColumn(0, "--verbosity x"); ct.AddColumn(1, "Set verbosity to value 'x': 0...7 (0 = disable)");
335336 ct.AddColumn(0, "-V"); ct.AddColumn(1, "Print version info.");
845846 if (lpECUser->lpszServername != NULL && *reinterpret_cast<LPSTR>(lpECUser->lpszServername) != '\0')
846847 cout << "Home server:\t\t" << (LPSTR)lpECUser->lpszServername << endl;
847848
848 adm_oof_status(lpProps);
849
850849 if (lpProps) {
851850 time_t logon = 0, logoff = 0;
852851 char d[64];
853852
853 adm_oof_status(lpProps);
854854 if(lpProps[0].ulPropTag == PR_LAST_LOGON_TIME)
855855 FileTimeToUnixTime(lpProps[0].Value.ft, &logon);
856856 if(lpProps[1].ulPropTag == PR_LAST_LOGOFF_TIME)
22902290 {
22912291 bool operator()(const string &t1, const string &t2) const
22922292 {
2293 return stricmp((char*)t1.c_str(), (char*)t2.c_str()) < 0;
2293 return strcasecmp((char*)t1.c_str(), (char*)t2.c_str()) < 0;
22942294 }
22952295 };
22962296
24332433 unsigned int loglevel = EC_LOGLEVEL_NONE;
24342434
24352435 ECLogger *lpLogger = NULL;
2436
2437 InputValidator validateInput;
2438
24392436 const configsetting_t lpDefaults[] = {
24402437 { "server_socket", "default:" },
24412438 { "sslkey_file", "" },
24452442 ECConfig *lpsConfig = ECConfig::Create(lpDefaults);
24462443 bool bExplicitConfig = false;
24472444 ConsoleTable ct(0,0);
2448
2449 #ifdef LINUX
24502445 const char *szConfig = ECConfig::GetDefaultPath("admin.cfg");
2451 #else
2452 char *szConfig = "admin.cfg";
2453 #endif
2454
24552446
24562447 // Set locale to system variables
24572448 setlocale(LC_MESSAGES, "");
24652456
24662457 int c;
24672458 while (1) {
2459 InputValidator validateInput;
24682460 c = getopt_long(argc, argv, "VlLsc:u:d:U:Pp:f:e:a:h:g:G:b:B:i:I:n:v", long_options, NULL);
24692461 if (c == -1)
24702462 break;
25902582 break;
25912583 // Make values from Mb to bytes which the server wants
25922584 case OPT_USER_QUOTA_HARD:
2593 quotahard = _atoi64(optarg) *1024*1024;
2585 quotahard = atoll(optarg) *1024*1024;
25942586 break;
25952587 case OPT_USER_QUOTA_SOFT:
2596 quotasoft = _atoi64(optarg) *1024*1024;
2588 quotasoft = atoll(optarg) *1024*1024;
25972589 break;
25982590 case OPT_USER_QUOTA_WARN:
2599 quotawarn = _atoi64(optarg) *1024*1024;
2591 quotawarn = atoll(optarg) *1024*1024;
26002592 break;
26012593 case OPT_USER_QUOTA_OVERRIDE:
26022594 quota = parse_yesno(optarg);
26032595 break;
26042596 case OPT_USER_DEFAULT_QUOTA_HARD:
2605 ud_quotahard = _atoi64(optarg) * 1024 * 1024;
2597 ud_quotahard = atoll(optarg) * 1024 * 1024;
26062598 break;
26072599 case OPT_USER_DEFAULT_QUOTA_SOFT:
2608 ud_quotasoft = _atoi64(optarg) * 1024 * 1024;
2600 ud_quotasoft = atoll(optarg) * 1024 * 1024;
26092601 break;
26102602 case OPT_USER_DEFAULT_QUOTA_WARN:
2611 ud_quotawarn = _atoi64(optarg) * 1024 * 1024;
2603 ud_quotawarn = atoll(optarg) * 1024 * 1024;
26122604 break;
26132605 case OPT_USER_DEFAULT_QUOTA_OVERRIDE:
26142606 ud_quota = parse_yesno(optarg);
27792771 cerr << "Username (-u) cannot be empty" << endl;
27802772 return 1;
27812773 }
2782 if (username && stricmp(username, "SYSTEM")==0) {
2774 if (username && strcasecmp(username, "SYSTEM")==0) {
27832775 cerr << "Username (-u) cannot be SYSTEM" << endl;
27842776 return 1;
27852777 }
30633055 cout << "force a resync of all offline profiles for all users? [y/N]: ";
30643056
30653057 cin >> response;
3066 if (response.empty() || stricmp(response.c_str(), "n") == 0 || stricmp(response.c_str(), "no") == 0)
3058 if (response.empty() || strcasecmp(response.c_str(), "n") == 0 || strcasecmp(response.c_str(), "no") == 0)
30673059 return 0;
3068 if (stricmp(response.c_str(), "y") != 0 && stricmp(response.c_str(), "yes") != 0) {
3060 if (strcasecmp(response.c_str(), "y") != 0 && strcasecmp(response.c_str(), "yes") != 0) {
30693061 cout << "Invalid response." << endl;
30703062 return 1;
30713063 }
32213213 break;
32223214
32233215 case MODE_DETAILS:
3224 if (detailstype == NULL || stricmp(detailstype, "user") == 0)
3216 if (detailstype == NULL || strcasecmp(detailstype, "user") == 0)
32253217 ulClass = ACTIVE_USER;
3226 else if (stricmp(detailstype, "group") == 0)
3218 else if (strcasecmp(detailstype, "group") == 0)
32273219 ulClass = DISTLIST_GROUP;
3228 else if (stricmp(detailstype, "company") == 0)
3220 else if (strcasecmp(detailstype, "company") == 0)
32293221 ulClass = CONTAINER_COMPANY;
3230 else if (stricmp(detailstype, "archive") != 0) {
3222 else if (strcasecmp(detailstype, "archive") != 0) {
32313223 hr = MAPI_E_INVALID_TYPE;
32323224 cerr << "Unknown userobject type \"" << detailstype << "\"" << endl;
32333225 goto exit;
32343226 }
32353227
3236 if (detailstype && stricmp(detailstype, "archive") == 0)
3228 if (detailstype && strcasecmp(detailstype, "archive") == 0)
32373229 hr = print_archive_details(lpSession, lpECMsgStore, username);
32383230 else
32393231 hr = print_details(lpSession, lpECMsgStore, ulClass, username);
42954287 break;
42964288 case MODE_LIST_SENDAS:
42974289
4298 if (detailstype == NULL || stricmp(detailstype, "user") == 0) {
4290 if (detailstype == NULL || strcasecmp(detailstype, "user") == 0) {
42994291 hr = lpServiceAdmin->ResolveUserName((LPTSTR)username, 0, &cbUserId, &lpUserId);
43004292 detailstype = "user";
4301 } else if (stricmp(detailstype, "group") == 0) {
4293 } else if (strcasecmp(detailstype, "group") == 0) {
43024294 hr = lpServiceAdmin->ResolveGroupName((LPTSTR)username, 0, &cbUserId, &lpUserId);
43034295 } else {
43044296 hr = MAPI_E_INVALID_TYPE;
5353 * if the settings aren't safe.
5454 * @param[out] lpptrArchiver
5555 * Pointer to a ArchivePtr that will be assigned the address of the returned object.
56 *
57 * @return HRESULT
5856 */
5957 HRESULT ArchiveControlImpl::Create(ArchiverSessionPtr ptrSession, ECConfig *lpConfig, ECLogger *lpLogger, bool bForceCleanup, ArchiveControlPtr *lpptrArchiveControl)
6058 {
7876 }
7977
8078 /**
81 * Constructor
82 *
8379 * @param[in] lpSession
8480 * Pointer to the Session.
8581 * @param[in] lpConfig
8884 * Pointer to an ECLogger object that's used for logging.
8985 * @param[in] bForceCleanup Force a cleanup operation to continue, even
9086 * if the settings aren't safe.
91 *
92 * @return HRESULT
9387 */
9488 ArchiveControlImpl::ArchiveControlImpl(ArchiverSessionPtr ptrSession, ECConfig *lpConfig, ECLogger *lpLogger, bool bForceCleanup)
9589 : m_ptrSession(ptrSession)
110104 , m_bForceCleanup(bForceCleanup)
111105 { }
112106
113 /**
114 * Destructor
115 */
116107 ArchiveControlImpl::~ArchiveControlImpl()
117108 {
118109 m_lpLogger->Release();
143134 return MAPI_E_INVALID_PARAMETER;
144135 }
145136
146 if (stricmp(lpszCleanupAction, "delete") == 0)
137 if (strcasecmp(lpszCleanupAction, "delete") == 0)
147138 m_cleanupAction = caDelete;
148 else if (stricmp(lpszCleanupAction, "store") == 0)
139 else if (strcasecmp(lpszCleanupAction, "store") == 0)
149140 m_cleanupAction = caStore;
150 else if (stricmp(lpszCleanupAction, "none") == 0)
141 else if (strcasecmp(lpszCleanupAction, "none") == 0)
151142 m_cleanupAction = caNone;
152143 else {
153144 m_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unknown cleanup_action specified in config: '%s'", lpszCleanupAction);
166157 * @param[in] bLocalOnly
167158 * If set to true only messsages for users that have their store on the local server
168159 * will be archived.
169 *
170 * @return HRESULT
171160 */
172161 eResult ArchiveControlImpl::ArchiveAll(bool bLocalOnly, bool bAutoAttach, unsigned int ulFlags)
173162 {
209198 *
210199 * @param[in] strUser
211200 * The username for which to archive the messages.
212 *
213 * @return HRESULT
214201 */
215202 eResult ArchiveControlImpl::Archive(const tstring &strUser, bool bAutoAttach, unsigned int ulFlags)
216203 {
266253 * @param[in] bLocalOnly
267254 * If set to true only messsages for users that have their store on the local server
268255 * will be archived.
269 *
270 * @return HRESULT
271256 */
272257 eResult ArchiveControlImpl::CleanupAll(bool bLocalOnly)
273258 {
289274 *
290275 * @param[in] strUser
291276 * The username for which to archive the messages.
292 *
293 * @return HRESULT
294277 */
295278 eResult ArchiveControlImpl::Cleanup(const tstring &strUser)
296279 {
304287
305288 return MAPIErrorToArchiveError(hr);
306289 }
307
308290
309291 /**
310292 * Process all users.
340322 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Failed to process user '" TSTRING_PRINTF "'. (hr=0x%08x)", iUser->c_str(), hrTmp);
341323 bHaveErrors = true;
342324 } else if (hrTmp == MAPI_W_PARTIAL_COMPLETION) {
343 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Errors occured while processing user '" TSTRING_PRINTF "'.", iUser->c_str());
325 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Errors occurred while processing user '" TSTRING_PRINTF "'.", iUser->c_str());
344326 bHaveErrors = true;
345327 }
346328 }
559541 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Done archiving messages");
560542 }
561543
562
563544 if (ptrDeleteOp) {
564545 // First delete all messages that are elegible for deletion, so we don't unneccesary stub them first
565546 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Deleting old messages");
575556 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Done deleting messages");
576557 }
577558
578
579559 if (ptrStubOp) {
580560 // Now stub the remaing messages (if they're old enough)
581561 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Stubbing messages");
711691 * @param[in] bProcessUnread
712692 * If set to true, unread messages will also be processed. Otherwise unread message
713693 * will be left untouched.
714 *
715 * @return HRESULT
716694 */
717695 HRESULT ArchiveControlImpl::ProcessFolder(MAPIFolderPtr &ptrFolder, ArchiveOperationPtr ptrArchiveOperation)
718696 {
5252 * Pointer to an ECLogger object to which message will be logged.
5353 * @param[out] lpptrArchiveManager
5454 * Pointer to an ArchiveManagePtr that will be assigned the address of the returned object.
55 *
56 * @return HRESULT
5755 */
5856 HRESULT ArchiveManageImpl::Create(ArchiverSessionPtr ptrSession, ECConfig *lpConfig, const TCHAR *lpszUser, ECLogger *lpLogger, ArchiveManagePtr *lpptrArchiveManage)
5957 {
9189 }
9290
9391 /**
94 * Constructor
95 *
9692 * @param[in] ptrSession
9793 * Pointer to a Session object.
9894 * @param[in] lpConfig
120116 }
121117 }
122118
123 /**
124 * Destructor
125 */
126119 ArchiveManageImpl::~ArchiveManageImpl()
127120 {
128121 m_lpLogger->Release();
156149 * the user is used as the root foldername.
157150 * @param[in] ulFlags
158151 * @ref flags specifying the options used for attaching the archive.
159 * @return HRESULT
160152 *
161153 * @section flags Flags
162154 * @li \b ATT_USE_IPM_SUBTREE Use the IPM subtree of the archive store as the root of the archive.
379371 * in the archive store, the exact folder need to be specified.
380372 * If the archive root was placed in the IPM subtree of the archive store, this parameter
381373 * must be set to NULL.
382 *
383 * @return HRESULT
384374 */
385375 eResult ArchiveManageImpl::DetachFrom(const char *lpszArchiveServer, const TCHAR *lpszArchive, const TCHAR *lpszFolder)
386376 {
506496 *
507497 * @param[in] ulArchive
508498 * The index of the archive in the list of archives.
509 *
510 * @return HRESULT
511499 */
512500 eResult ArchiveManageImpl::DetachFrom(unsigned int ulArchive)
513501 {
559547 *
560548 * @param[in] ostr
561549 * The std::ostream to which the list will be outputted.
562 *
563 * @return HRESULT
564550 */
565551 eResult ArchiveManageImpl::ListArchives(std::ostream &ostr)
566552 {
681667 }
682668 }
683669
684
685670 hrTmp = ptrArchiveStore->OpenEntry(iArchive->sItemEntryId.size(), iArchive->sItemEntryId, &ptrArchiveFolder.iid, fMapiDeferredErrors, &ulType, &ptrArchiveFolder);
686671 if (hrTmp != hrSuccess) {
687672 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Failed to open folder (hr=%s)", stringify(hrTmp, true).c_str());
101101
102102 for (unsigned j = 0; bComplete && j < IDX_MAX; ++j) {
103103 if (PROP_TYPE(ptrRows[i].lpProps[j].ulPropTag) == PT_ERROR) {
104 m_lpLogger->Log(EC_LOGLEVEL_WARNING, "Got uncomplete row, row %u, column %u contains error 0x%08x", i, j, ptrRows[i].lpProps[j].Value.err);
104 m_lpLogger->Log(EC_LOGLEVEL_WARNING, "Got incomplete row, row %u, column %u contains error 0x%08x", i, j, ptrRows[i].lpProps[j].Value.err);
105105 bComplete = false;
106106 }
107107 }
139139
140140 }
141141
142
143142 /**
144143 * Create an ArchiveStateCollector instance.
145144 * @param[in] ArchiverSessionPtr The archive session
161160 }
162161
163162 /**
164 * Constructor
165163 * @param[in] ArchiverSessionPtr The archive session
166164 * @param[in] lpLogger The logger.
167165 */
3838 const SObjectEntry &m_objEntry;
3939 };
4040
41
4241 /**
4342 * Compare two SObjectEntry instances.
4443 * This method uses CompareEntryIDs to do the comparison.
6261 const SObjectEntry &m_objEntry;
6362 };
6463
65
6664 /**
6765 * Compare a store entryid with the store entryid from an SObjectEntry instance.
6866 * This method uses CompareEntryIDs to do the comparison.
9391
9492 } // namespace Predicates
9593
96
9794 /**
9895 * Create an ArchiveStateUpdater instance.
9996 * @param[in] ptrSession The archiver session.
118115 }
119116
120117 /**
121 * Constructor
122118 * @param[in] ptrSession The archiver session.
123119 * @param[in] lpLogger The logger.
124120 * @param[in] mapArchiveInfo The map containing the users that have and/or
3838 * @param[out] lppSession
3939 * Pointer to a Session pointer that will be assigned the address of the returned
4040 * ArchiverSession object.
41 * @return HRESULT
4241 */
4342 HRESULT ArchiverSession::Create(ECConfig *lpConfig, ECLogger *lpLogger, ArchiverSessionPtr *lpptrSession)
4443 {
7069 * @param[out] lppSession
7170 * Pointer to a Session pointer that will be assigned the address of the returned
7271 * Session object.
73 *
74 * @return HRESULT
7572 */
7673 HRESULT ArchiverSession::Create(const MAPISessionPtr &ptrSession, ECLogger *lpLogger, ArchiverSessionPtr *lpptrSession)
7774 {
9188 * @param[out] lppSession
9289 * Pointer to a ArchiverSession pointer that will be assigned the address of the returned
9390 * ArchiverSession object.
94 *
95 * @return HRESULT
9691 */
9792 HRESULT ArchiverSession::Create(const MAPISessionPtr &ptrSession, ECConfig *lpConfig, ECLogger *lpLogger, ArchiverSessionPtr *lpptrSession)
9893 {
126121 return hr;
127122 }
128123
129 /**
130 * Destructor
131 */
132124 ArchiverSession::~ArchiverSession()
133125 {
134126 m_lpLogger->Release();
135127 }
136128
137 /**
138 * Constructor
139 */
140129 ArchiverSession::ArchiverSession(ECLogger *lpLogger): m_lpLogger(lpLogger)
141130 {
142131 m_lpLogger->AddRef();
148137 * @param[in] lpConfig
149138 * The configuration used for creating the ArchiverSession. The values extracted from the
150139 * configuration are server_path, sslkey_file and sslkey_path.
151 *
152 * @return HRESULT
153140 */
154141 HRESULT ArchiverSession::Init(ECConfig *lpConfig)
155142 {
168155 * @param[in]
169156 * lpszSslPass
170157 * The password for the certificate.
171
172 * @return HRESULT
173158 */
174159 HRESULT ArchiverSession::Init(const char *lpszServerPath, const char *lpszSslPath, const char *lpszSslPass)
175160 {
214199 * @param[in] ptrSession
215200 * MAPISessionPtr that points to the MAPISession to contruct this
216201 * ArchiverSession object for.
217 *
218 * @return HRESULT
219202 */
220203 HRESULT ArchiverSession::Init(const MAPISessionPtr &ptrSession, const char *lpszSslPath, const char *lpszSslPass)
221204 {
244227 * @param[out] lppMsgStore
245228 * Pointer to a IMsgStore pointer that will be assigned the
246229 * address of the returned message store.
247 *
248 * @return HRESULT
249230 */
250231 HRESULT ArchiverSession::OpenStoreByName(const tstring &strUser, LPMDB *lppMsgStore)
251232 {
287268 * @param[out] lppMsgStore
288269 * Pointer to a IMsgStore pointer that will be assigned the
289270 * address of the returned message store.
290 *
291 * @return HRESULT
292271 */
293272 HRESULT ArchiverSession::OpenStore(const entryid_t &sEntryId, ULONG ulFlags, LPMDB *lppMsgStore)
294273 {
331310 * @param[out] lppMsgStore
332311 * Pointer to a IMsgStore pointer that will be assigned the
333312 * address of the returned message store.
334 *
335 * @return HRESULT
336313 */
337314 HRESULT ArchiverSession::OpenStore(const entryid_t &sEntryId, LPMDB *lppMsgStore)
338315 {
347324 * @param[out] lppMsgStore
348325 * Pointer to a IMsgStore pointer that will be assigned the
349326 * address of the returned message store.
350 *
351 * @return HRESULT
352327 */
353328 HRESULT ArchiverSession::OpenReadOnlyStore(const entryid_t &sEntryId, LPMDB *lppMsgStore)
354329 {
372347 * Pointer to a boolean that will be set to true if the user is ACL capable.
373348 * This argument can be set to NULL if the active/non-active
374349 * information is not required.
375 *
376 * @return HRESULT
377350 */
378351 HRESULT ArchiverSession::GetUserInfo(const tstring &strUser, abentryid_t *lpsEntryId, tstring *lpstrFullname, bool *lpbAclCapable)
379352 {
488461 * @param[out] lppAbContainer
489462 * Pointer to a IABContainer pointer that will be assigned the
490463 * address of the returned addressbook container.
491 *
492 * @return HRESULT
493464 */
494465 HRESULT ArchiverSession::GetGAL(LPABCONT *lppAbContainer)
495466 {
556527 * @param[out] lpbResult
557528 * Pointer to a boolean that will be set to true if the two stores
558529 * reference the same store.
559 *
560 * @return HRESULT
561530 */
562531 HRESULT ArchiverSession::CompareStoreIds(LPMDB lpUserStore, LPMDB lpArchiveStore, bool *lpbResult)
563532 {
593562 * @param[out] lpbResult
594563 * Pointer to a boolean that will be set to true if the two ids
595564 * reference the same store.
596 *
597 * @return HRESULT
598565 */
599566 HRESULT ArchiverSession::CompareStoreIds(const entryid_t &sEntryId1, const entryid_t &sEntryId2, bool *lpbResult)
600567 {
608575 return hr;
609576
610577 *lpbResult = (ulResult == TRUE);
611 return hrSuccess;
612 }
613
614 /**
615 * Check if the server specified by strServername is the server we're currently connected with.
616 *
617 * @param[in] strServername
618 * The name of the server to check.
619 * @param[out] lpbResult
620 * Pointer to a boolean that will be set to true if the server is the
621 * same server we're currently connected with.
622 *
623 * @return HRESULT
624 */
625 HRESULT ArchiverSession::ServerIsLocal(const std::string &strServername, bool *lpbResult)
626 {
627 HRESULT hr;
628 char *lpszServername = NULL;
629 ECSVRNAMELIST sSvrNameList = {0};
630 ECServiceAdminPtr ptrServiceAdmin;
631 ECServerListPtr ptrServerList;
632
633 hr = m_ptrAdminStore->QueryInterface(ptrServiceAdmin.iid, &ptrServiceAdmin);
634 if (hr != hrSuccess)
635 return hr;
636
637 lpszServername = (char*)strServername.c_str();
638
639 sSvrNameList.cServers = 1;
640 sSvrNameList.lpszaServer = (LPTSTR*)&lpszServername;
641
642 hr = ptrServiceAdmin->GetServerDetails(&sSvrNameList, EC_SERVERDETAIL_NO_NAME, &ptrServerList); // No MAPI_UNICODE
643 if (hr != hrSuccess)
644 return hr;
645
646 *lpbResult = (ptrServerList->lpsaServer[0].ulFlags & EC_SDFLAG_IS_PEER) == EC_SDFLAG_IS_PEER;
647578 return hrSuccess;
648579 }
649580
668599 lpptrSession->reset(lpSession);
669600 return hr;
670601 }
671
672602
673603 HRESULT ArchiverSession::OpenMAPIProp(ULONG cbEntryID, LPENTRYID lpEntryID, LPMAPIPROP *lppProp)
674604 {
4747 HRESULT GetGAL(LPABCONT *lppAbContainer);
4848 HRESULT CompareStoreIds(LPMDB lpUserStore, LPMDB lpArchiveStore, bool *lpbResult);
4949 HRESULT CompareStoreIds(const entryid_t &sEntryId1, const entryid_t &sEntryId2, bool *lpbResult);
50 HRESULT ServerIsLocal(const std::string &strServername, bool *lpbResult);
5150
5251 HRESULT CreateRemote(const char *lpszServerPath, ECLogger *lpLogger, ArchiverSessionPtr *lpptrSession);
5352
111111 return strEscaped;
112112 }
113113
114
115114 ScopedUserLogging::ScopedUserLogging(ECArchiverLogger *lpLogger, const tstring &strUser)
116115 : m_lpLogger(lpLogger)
117116 , m_strPrevUser(lpLogger->SetUser(strUser))
122121 m_lpLogger->SetUser(m_strPrevUser);
123122 }
124123
125
126124 ScopedFolderLogging::ScopedFolderLogging(ECArchiverLogger *lpLogger, const tstring &strFolder)
127125 : m_lpLogger(lpLogger)
128126 , m_strPrevFolder(lpLogger->SetFolder(strFolder))
3030 #define CbNewROWLIST(_centries) \
3131 (offsetof(ROWLIST,aEntries) + (_centries)*sizeof(ROWENTRY))
3232 #endif
33
3433
3534 /**
3635 * Create an ArchiveHelper object based on a message store and a folder name.
4544 * implies that the archive is remote (other server/cluster).
4645 * @param[out] lpptrArchiveHelper
4746 * Pointer to a ArchiveHelperPtr that assigned the address of the returned ArchiveHelper.
48 *
49 * @return HRESULT
5047 */
5148 HRESULT ArchiveHelper::Create(LPMDB lpArchiveStore, const tstring &strFolder, const char *lpszServerPath, ArchiveHelperPtr *lpptrArchiveHelper)
5249 {
7976 * implies that the archive is remote (other server/cluster).
8077 * @param[out] lpptrArchiveHelper
8178 * Pointer to a ArchiveHelperPtr that assigned the address of the returned ArchiveHelper.
82 *
83 * @return HRESULT
8479 */
8580 HRESULT ArchiveHelper::Create(LPMDB lpArchiveStore, LPMAPIFOLDER lpArchiveFolder, const char *lpszServerPath, ArchiveHelperPtr *lpptrArchiveHelper)
8681 {
141136 return hrSuccess;
142137 }
143138
144 /**
145 * Constructor
146 */
147139 ArchiveHelper::ArchiveHelper(LPMDB lpArchiveStore, const tstring &strFolder, const std::string &strServerPath)
148140 : m_ptrArchiveStore(lpArchiveStore, true)
149141 , m_strFolder(strFolder)
150142 , m_strServerPath(strServerPath)
151143 { }
152144
153 /**
154 * Constructor
155 */
156145 ArchiveHelper::ArchiveHelper(LPMDB lpArchiveStore, LPMAPIFOLDER lpArchiveFolder, const std::string &strServerPath)
157146 : m_ptrArchiveStore(lpArchiveStore, true)
158147 , m_ptrArchiveFolder(lpArchiveFolder, true)
161150
162151 /**
163152 * Initialize an ArchiveHelper object.
164 * @return HRESULT
165153 */
166154 HRESULT ArchiveHelper::Init()
167155 {
183171 * @param[out] lpsUserEntryId
184172 * Pointer to a entryid_t that will be populated with the entryid of the user
185173 * who's store is attached to this archive.
186 *
187 * @return HRESULT
188174 */
189175 HRESULT ArchiveHelper::GetAttachedUser(abentryid_t *lpsUserEntryId)
190176 {
209195 * @param[in] sUserEntryId
210196 * The entryid of the user who's store is attached to this
211197 * archive.
212 *
213 * @return HRESULT
214198 */
215199 HRESULT ArchiveHelper::SetAttachedUser(const abentryid_t &sUserEntryId)
216200 {
236220 * @param[out] lpSObjectEntry
237221 * Pointer to a SObjectEntry structure that will be populated with the unique
238222 * reference to this archive.
239 *
240 * @return HRESULT
241223 */
242224 HRESULT ArchiveHelper::GetArchiveEntry(bool bCreate, SObjectEntry *lpsObjectEntry)
243225 {
341323 *
342324 * @param[in] aType
343325 * The ArchiveType type of this archive.
344 *
345 * @return HRESULT
346326 */
347327 HRESULT ArchiveHelper::SetArchiveType(ArchiveType archType, AttachType attachType)
348328 {
374354 * The entryid of the user for who permissions are being set.
375355 * @param[in] bWriteable.
376356 * If set to true, the archive will be writable by the user.
377 *
378 * @return HRESULT
379357 */
380358 HRESULT ArchiveHelper::SetPermissions(const abentryid_t &sUserEntryId, bool bWritable)
381359 {
467445 * The Session pointer that's used to open folders with.
468446 * @param[out] lppDestinationFolder
469447 * Pointer to a MAPIFolder pointer that's assigned the address of the returned folder.
470 *
471 * @return HRESULT
472448 */
473449 HRESULT ArchiveHelper::GetArchiveFolderFor(MAPIFolderPtr &ptrSourceFolder, ArchiverSessionPtr ptrSession, LPMAPIFOLDER *lppDestinationFolder)
474450 {
663639 * @param[out] lppArchiveFolder
664640 * Pointer to the MAPIFolder pointer that will be assigned the address of the
665641 * returned folder.
666 *
667 * @return HRESULT
668642 */
669643 HRESULT ArchiveHelper::GetArchiveFolder(bool bCreate, LPMAPIFOLDER *lppArchiveFolder)
670644 {
695669 * Pointer to the MAPIFolder to check.
696670 * @param[out] lpbResult
697671 * True if the folder is the same as would be returned by GetArchiveFolder.
698 *
699 * @return HRESULT
700672 */
701673 HRESULT ArchiveHelper::IsArchiveFolder(LPMAPIFOLDER lpFolder, bool *lpbResult)
702674 {
3939 * @param[out] lppptrMAPIPropHelper
4040 * Pointer to a MAPIPropHelperPtr that will be assigned the returned
4141 * MAPIPropHelper object.
42 *
43 * @return HRESULT
4442 */
4543 HRESULT MAPIPropHelper::Create(MAPIPropPtr ptrMapiProp, MAPIPropHelperPtr *lpptrMAPIPropHelper)
4644 {
6159 return hrSuccess;
6260 }
6361
64 /**
65 * Constructor
66 */
6762 MAPIPropHelper::MAPIPropHelper(MAPIPropPtr ptrMapiProp)
6863 : m_ptrMapiProp(ptrMapiProp)
6964 { }
132127 return ptrMessageProps[IDX_HIERARCHYID].Value.err;
133128 hr = hrSuccess;
134129
135
136130 // Determine stubbed / dirty state.
137131 if (PROP_TYPE(ptrMessageProps[IDX_STUBBED].ulPropTag) != PT_ERROR && ptrMessageProps[IDX_STUBBED].Value.b == TRUE)
138132 ulState |= MessageState::msStubbed;
144138 if ((ulState & MessageState::msStubbed) == 0)
145139 ulState |= MessageState::msDirty;
146140 }
147
148141
149142 // Determine copy / move state.
150143 if (PROP_TYPE(ptrMessageProps[IDX_ORIGINAL_SOURCEKEY].ulPropTag) == PT_ERROR) {
255248 *
256249 * @param[in] bIgnoreSourceKey
257250 * Don't try to detect a copy/move and return an empty list in that case.
258 *
259 * @return HRESULT
260251 */
261252 HRESULT MAPIPropHelper::GetArchiveList(ObjectEntryList *lplstArchives, bool bIgnoreSourceKey)
262253 {
342333 * The list of archive references that should be stored in the object.
343334 * @param[in] bExplicitCommit
344335 * If set to true, the changes are committed before this function returns.
345 *
346 * @return HRESULT
347336 */
348337 HRESULT MAPIPropHelper::SetArchiveList(const ObjectEntryList &lstArchives, bool bExplicitCommit)
349338 {
417406 * The id of the referenced object.
418407 * @param[in] bExplicitCommit
419408 * If set to true, the changes are committed before this function returns.
420 *
421 * @return HRESULT
422409 */
423410 HRESULT MAPIPropHelper::SetReference(const SObjectEntry &sEntry, bool bExplicitCommit)
424411 {
443430 return hr;
444431 }
445432
446
447433 HRESULT MAPIPropHelper::ClearReference(bool bExplicitCommit)
448434 {
449435 HRESULT hr;
458444
459445 return hr;
460446 }
461
462447
463448 HRESULT MAPIPropHelper::GetReference(SObjectEntry *lpEntry)
464449 {
484469 lpEntry->sItemEntryId.assign(ptrMessageProps[IDX_REF_ITEM_ENTRYID].Value.bin);
485470 return hr;
486471 }
487
488472
489473 HRESULT MAPIPropHelper::ReferencePrevious(const SObjectEntry &sEntry)
490474 {
536520 * return true if the message class is not updated properly. However, this is done in the caller
537521 * of this function, which has no notion of the set of named properies that are needed to remove this
538522 * property.
539 *
540 * @return HRESULT.
541523 */
542524 HRESULT MAPIPropHelper::RemoveStub()
543525 {
551533 return m_ptrMapiProp->DeleteProps((LPSPropTagArray)&sptaDirtyProps, NULL);
552534 }
553535
554
555536 /**
556537 * Detach an object from its archived version.
557538 * This does not cause the reference in the archived version to be removed.
558 *
559 * @return HRESULT
560539 */
561540 HRESULT MAPIPropHelper::DetachFromArchives()
562541 {
572551 * @param[in] lppFolder
573552 * Pointer to a IMAPIFolder pointer that will be assigned the address
574553 * of the returned folder.
575 *
576 * @return HRESULT
577554 */
578555 HRESULT MAPIPropHelper::GetParentFolder(ArchiverSessionPtr ptrSession, LPMAPIFOLDER *lppFolder)
579556 {
602579
603580 return ptrFolder->QueryInterface(IID_IMAPIFolder,
604581 reinterpret_cast<LPVOID *>(lppFolder));
605 }
606
607 /**
608 * Get the list of properties needed to be able to determine if the message from which
609 * the properties are obtained is stubbed and if so to get a list of archived versions.
610 *
611 * @param[in] ptrMapiProp An IMAPIProp that lives on the same server as the the
612 * message from which the properties will be obtained. This
613 * is needed to properly resolve the named properties.
614 * @param[in] lpExtra Optional pointer to a PropTagArray containing additional
615 * properties that will also be placed in the resulting
616 * PropTagArray. This is for convenience when building a list
617 * of properties where not only the archive properties are
618 * required.
619 * @param[out] lppProps The resulting PropTagArray.
620 */
621 HRESULT MAPIPropHelper::GetArchiverProps(MAPIPropPtr ptrMapiProp, LPSPropTagArray lpExtra, LPSPropTagArray *lppProps)
622 {
623 HRESULT hr = hrSuccess;
624
625 SizedSPropTagArray(2, sptaFixedProps) = {2, {PR_MESSAGE_CLASS, PR_SOURCE_KEY}};
626
627 PROPMAP_START
628 PROPMAP_NAMED_ID(STUBBED, PT_BOOLEAN, PSETID_Archive, dispidStubbed)
629 PROPMAP_NAMED_ID(ARCHIVE_STORE_ENTRYIDS, PT_MV_BINARY, PSETID_Archive, dispidStoreEntryIds)
630 PROPMAP_NAMED_ID(ARCHIVE_ITEM_ENTRYIDS, PT_MV_BINARY, PSETID_Archive, dispidItemEntryIds)
631 PROPMAP_NAMED_ID(ORIGINAL_SOURCEKEY, PT_BINARY, PSETID_Archive, dispidOrigSourceKey)
632 PROPMAP_INIT(ptrMapiProp)
633
634 hr = MAPIAllocateBuffer(CbNewSPropTagArray(sptaFixedProps.cValues + 4 + (lpExtra ? lpExtra->cValues : 0)), (LPVOID*)lppProps);
635 if (hr != hrSuccess)
636 goto exit;
637
638 for (ULONG i = 0; i < sptaFixedProps.cValues; ++i)
639 (*lppProps)->aulPropTag[i] = sptaFixedProps.aulPropTag[i];
640
641 (*lppProps)->cValues = sptaFixedProps.cValues;
642 (*lppProps)->aulPropTag[(*lppProps)->cValues++] = PROP_STUBBED;
643 (*lppProps)->aulPropTag[(*lppProps)->cValues++] = PROP_ARCHIVE_STORE_ENTRYIDS;
644 (*lppProps)->aulPropTag[(*lppProps)->cValues++] = PROP_ARCHIVE_ITEM_ENTRYIDS;
645 (*lppProps)->aulPropTag[(*lppProps)->cValues++] = PROP_ORIGINAL_SOURCEKEY;
646
647 for (ULONG i = 0; lpExtra && i < lpExtra->cValues; ++i)
648 (*lppProps)->aulPropTag[(*lppProps)->cValues++] = lpExtra->aulPropTag[i];
649
650 exit:
651 return hr;
652 }
653
654 /**
655 * Check if a message is stubbed.
656 * This is accomplished by checking if the named property {72e98ebc-57d2-4ab5-b0aad50a7b531cb9}/stubbed is set to true or false.
657 * If that property is absent the PR_MESSAGE_CLASS is compared to "IPM.Zarafa.Stub". If that matches the message is
658 * considered stubbed as well.
659 *
660 * @param[in] ptrMapiProp An IMAPIProp that lives on the same server as the the
661 * message from which the properties were obtained. This
662 * is needed to properly resolve the named properties.
663 * @param[in] lpProps The list of properties to use to determine if the message
664 * from which they were obtained is stubbed.
665 * @param[in] cbProps The amount of properties in lpProps.
666 * @param[out] lpbResult Pointer to a boolean that will be set to true if the
667 * message is stubbed, and false otherwise.
668 *
669 * @return HRESULT
670 */
671 HRESULT MAPIPropHelper::IsStubbed(MAPIPropPtr ptrMapiProp, LPSPropValue lpProps, ULONG cbProps, bool *lpbResult)
672 {
673 HRESULT hr = hrSuccess;
674 LPSPropValue lpPropStubbed = NULL;
675 LPSPropValue lpPropMessageClass = NULL;
676
677 PROPMAP_START
678 PROPMAP_NAMED_ID(STUBBED, PT_BOOLEAN, PSETID_Archive, dispidStubbed)
679 PROPMAP_INIT(ptrMapiProp)
680
681 lpPropStubbed = PpropFindProp(lpProps, cbProps, PROP_STUBBED);
682
683 if (!lpPropStubbed) {
684 // PROP_STUBBED doesn't exist, check the message class to be sure
685 lpPropMessageClass = PpropFindProp(lpProps, cbProps, PR_MESSAGE_CLASS);
686 if (lpPropMessageClass)
687 *lpbResult = (_tcsicmp(lpPropMessageClass->Value.LPSZ, _T("IPM.Zarafa.Stub")) == 0);
688 else
689 *lpbResult = false;
690 } else
691 *lpbResult = (lpPropStubbed->Value.b != 0);
692
693 exit:
694 return hr;
695582 }
696583
697584 /**
708595 * for the message from which they were obtained.
709596 * @param[in] cbProps The amount of properties in lpProps.
710597 * @param[out] lplstArchives Pointer to a list that will be populated with the archive references.
711 *
712 * @return HRESULT
713598 */
714599 HRESULT MAPIPropHelper::GetArchiveList(MAPIPropPtr ptrMapiProp, LPSPropValue lpProps, ULONG cbProps, ObjectEntryList *lplstArchives)
715600 {
5656 HRESULT SetClean();
5757 HRESULT DetachFromArchives();
5858 virtual HRESULT GetParentFolder(ArchiverSessionPtr ptrSession, LPMAPIFOLDER *lppFolder);
59
60 static HRESULT GetArchiverProps(MAPIPropPtr ptrMapiProp, LPSPropTagArray lpExtra, LPSPropTagArray *lppProps);
61 static HRESULT IsStubbed(MAPIPropPtr ptrMapiProp, LPSPropValue lpProps, ULONG cbProps, bool *lpbResult);
6259 static HRESULT GetArchiveList(MAPIPropPtr ptrMapiProp, LPSPropValue lpProps, ULONG cbProps, ObjectEntryList *lplstArchives);
6360
6461 protected:
5656 * @param[out] lpptrStoreHelper
5757 * Pointer to a StoreHelperPtr that will be assigned the address
5858 * of the new StoreHelper object.
59 *
60 * @return HRESULT
6159 */
6260 HRESULT StoreHelper::Create(MsgStorePtr &ptrMsgStore, StoreHelperPtr *lpptrStoreHelper)
6361 {
7775 *lpptrStoreHelper = std::move(ptrStoreHelper);
7876 return hrSuccess;
7977 }
80
8178
8279 /**
8380 * Constructor.
122119 * @param[out] lppFolder
123120 * Pointer to a IMapiFolder pointer that will be assigned the address
124121 * of the returned folderd.
125 *
126 * @return HRESULT
127122 */
128123 HRESULT StoreHelper::GetFolder(const tstring &strFolder, bool bCreate, LPMAPIFOLDER *lppFolder)
129124 {
145140 /**
146141 * Create or reinitialize the searchfolders used by the archiver. The search folders
147142 * need to be updated whenever the set of attached archives for a store change.
148 *
149 * @return HRESULT
150143 */
151144 HRESULT StoreHelper::UpdateSearchFolders()
152145 {
206199 * @param[out] lppFolder
207200 * Pointer to an IMAPIFolder pointer that will be assigned the
208201 * address of the returned folder.
209 *
210 * @return HRESULT
211202 */
212203 HRESULT StoreHelper::GetIpmSubtree(LPMAPIFOLDER *lppFolder)
213204 {
246237 * address of the searcholder containing the messages that are eligible
247238 * for stubbing. These are basically all non-stubbed, archived messages that
248239 * are not flagged to be never stubbed.
249 *
250 * @return HRESULT
251240 */
252241 HRESULT StoreHelper::GetSearchFolders(LPMAPIFOLDER *lppSearchArchiveFolder, LPMAPIFOLDER *lppSearchDeleteFolder, LPMAPIFOLDER *lppSearchStubFolder)
253242 {
365354 * @param[out] lppFolder
366355 * Pointer to an IMAPIFolder pointer that will be assigned the
367356 * address of the returned folder.
368 *
369 * @return HRESULT
370357 */
371358 HRESULT StoreHelper::GetSubFolder(MAPIFolderPtr &ptrFolder, const tstring &strFolder, bool bCreate, LPMAPIFOLDER *lppFolder)
372359 {
552539 return hr;
553540 ptrEntryList->lpbin[0].cb = ptrPropEntryId->Value.bin.cb;
554541 ptrEntryList->lpbin[0].lpb = ptrPropEntryId->Value.bin.lpb;
555
556542
557543 sPropStubbed.ulPropTag = PROP_STUBBED; sPropStubbed.Value.b = 1;
558544
637623 ptrEntryList->lpbin[0].cb = ptrPropEntryId->Value.bin.cb;
638624 ptrEntryList->lpbin[0].lpb = ptrPropEntryId->Value.bin.lpb;
639625
640
641626 // Create/Update the search folder that tracks all archived message that are not flagged to be never deleted or never stubbed
642627 resDeleteFolder.append(
643628 *lpresClassCheck +
702687 return hr;
703688 ptrEntryList->lpbin[0].cb = ptrPropEntryId->Value.bin.cb;
704689 ptrEntryList->lpbin[0].lpb = ptrPropEntryId->Value.bin.lpb;
705
706690
707691 sPropStubbed.ulPropTag = PROP_STUBBED;
708692 sPropStubbed.Value.b = 1;
8989 { }
9090
9191 /**
92 * Copy constructor.
93 *
9492 * @param[in] other
9593 * The entryid to copy.
9694 */
320318 { }
321319
322320 /**
323 * Copy constructor.
324 *
325321 * @param[in] other
326322 * The entryid to copy.
327323 */
535531 {
536532 public:
537533 /**
538 * Constructor
539 *
540534 * This constructor takes the store entryid from an SObjectEntry.
541535 *
542536 * @param[in] sEntry The SObjectEntry from which the store entryid will be used
545539 StoreCompare(const SObjectEntry &sEntry): m_sEntryId(sEntry.sStoreEntryId.getUnwrapped()) {}
546540
547541 /**
548 * Constructor
549 *
550542 * This constructor takes an explicit entryid.
551543 *
552544 * @param[in] sEntryId The entryid the will be used
2525 #include <kopano/ECLogger.h>
2626 #include <kopano/ecversion.h>
2727 #include "Archiver.h"
28
29 #ifdef LINUX
3028 #include "UnixUtil.cpp"
31 #endif
3229
3330 enum modes
3431 {
244241 const char *lpszConfig = Archiver::GetConfigPath();
245242
246243 static const configsetting_t lpDefaults[] = {
247 #ifdef LINUX
248244 { "pid_file", "/var/run/kopano/archiver.pid" },
249 #endif
250245 { NULL, NULL }
251246 };
252247
451446 cerr << "--force-cleanup is only valid in cleanup mode." << endl;
452447 return 1;
453448 }
454
455449
456450 r = Archiver::Create(&ptrArchiver);
457451 if (r != Success) {
483477 filelogger->Log(EC_LOGLEVEL_FATAL, "* %s = '%s'", i->szName, i->szValue);
484478 }
485479
486 #ifdef LINUX
487480 if (mode == MODE_ARCHIVE || mode == MODE_CLEANUP)
488481 if (unix_create_pidfile(argv[0], ptrArchiver->GetConfig(), ptrArchiver->GetLogger(), false) != 0)
489482 return 1;
490 #endif
491483
492484 ptrArchiver->GetLogger()->Log(EC_LOGLEVEL_DEBUG, "Archiver mode: %d: (%s)", mode, modename(mode));
493485 switch (mode) {
386386 }
387387
388388 /**
389 * Constructor
390 *
391389 * @param[in] lpSession
392390 * Pointer to the session.
393391 * @param[in] lpLogger
396394 * The list of attached archives for this store.
397395 * @param[in] lpExcludeProps
398396 * The list of properties that will not be copied during the archive operation.
399 *
400 * @return HRESULT
401397 */
402398 Copier::Copier(ArchiverSessionPtr ptrSession, ECConfig *lpConfig, ECArchiverLogger *lpLogger, const ObjectEntryList &lstArchives, LPSPropTagArray lpExcludeProps, int ulAge, bool bProcessUnread)
403399 : ArchiveOperationBaseEx(lpLogger, ulAge, bProcessUnread, ARCH_NEVER_ARCHIVE)
2323 namespace za { namespace operations {
2424
2525 /**
26 * Constructor
27 *
2826 * @param[in] lpLogger
2927 * Pointer to the logger.
30 *
31 * @return HRESULT
3228 */
3329 Deleter::Deleter(ECArchiverLogger *lpLogger, int ulAge, bool bProcessUnread)
3430 : ArchiveOperationBaseEx(lpLogger, ulAge, bProcessUnread, ARCH_NEVER_DELETE)
3531 { }
3632
37 /**
38 * Destructor
39 */
4033 Deleter::~Deleter()
4134 {
4235 PurgeQueuedMessages();
6962
7063 /**
7164 * Delete the messages that are queued for deletion.
72 * @return HRESULT
7365 */
7466 HRESULT Deleter::PurgeQueuedMessages()
7567 {
5050 {
5151 GetSystemTimeAsFileTime(&m_ftCurrent);
5252 }
53
54
5553
5654 HRESULT ArchiveOperationBase::GetRestriction(LPMAPIPROP lpMapiProp, LPSRestriction *lppRestriction)
5755 {
106104 )
107105 );
108106
109
110107 hr = resResult.CreateMAPIRestriction(lppRestriction);
111108
112109 exit:
145142 * The number op properties pointed to by lpProps.
146143 * @param[in] lpProps
147144 * Pointer to an array of properties that are used by the Operation object.
148 *
149 * @return HRESULT
150145 */
151146 HRESULT ArchiveOperationBaseEx::ProcessEntry(LPMAPIFOLDER lpFolder, ULONG cProps, const LPSPropValue lpProps)
152147 {
4747 * The number op properties pointed to by lpProps.
4848 * @param[in] lpProps
4949 * Pointer to an array of properties that are used by the Operation object.
50 *
51 * @return HRESULT
5250 */
5351 virtual HRESULT ProcessEntry(LPMAPIFOLDER lpFolder, ULONG cProps, const LPSPropValue lpProps) = 0;
5452
126124 * the source folder is switched.
127125 *
128126 * @param[in] lpFolder The just opened folder.
129 * @return HRESULT
130127 */
131128 virtual HRESULT EnterFolder(LPMAPIFOLDER lpFolder) = 0;
132129
134131 * Called by ProcessEntry before switching source folders. Derived classes will need to
135132 * implement this method. It can be used to perform operations that only need to be done when
136133 * the source folder is switched.
137 *
138 * @return HRESULT
139134 */
140135 virtual HRESULT LeaveFolder() = 0;
141136
146141 * The number op properties pointed to by lpProps.
147142 * @param[in] lpProps
148143 * Pointer to an array of properties that are used by the Operation object.
149 *
150 * @return HRESULT
151144 */
152145 virtual HRESULT DoProcessEntry(ULONG cProps, const LPSPropValue &lpProps) = 0;
153146
2626 namespace za { namespace operations {
2727
2828 /**
29 * Constructor
30 *
3129 * @param[in] lpLogger
3230 * Pointer to the logger.
3331 * @param[in] ulptStubbed
3432 * The proptag of the stubbed property {72e98ebc-57d2-4ab5-b0aad50a7b531cb9}/stubbed
35 *
36 * @return HRESULT
3733 */
3834 Stubber::Stubber(ECArchiverLogger *lpLogger, ULONG ulptStubbed, int ulAge, bool bProcessUnread)
3935 : ArchiveOperationBase(lpLogger, ulAge, bProcessUnread, ARCH_NEVER_STUB)
55 kopano_backup/__init__.py
66
77 install-exec-local:
8 cd ${srcdir} && ${PYTHON} setup.py install -f \
9 $${DESTDIR+--root=${DESTDIR}} \
8 cd ${srcdir} && ${PYTHON} setup.py \
9 build --build-base="${abs_builddir}/build" \
10 install -f $${DESTDIR+--root=${DESTDIR}} \
1011 --prefix ${prefix} --install-purelib ${pythondir}
1112 rm -Rf build
13
14 uninstall-local:
15 rm -Rf ${DESTDIR}${pythondir}/kopano_backup \
16 ${DESTDIR}${pythondir}/kopano_backup-0*.egg-info
236236
237237 # determine stored and specified folders
238238 path_folder = folder_struct(self.data_path, self.options)
239 paths = self.options.folders or sorted(path_folder.keys())
239 paths = [_decode(f) for f in self.options.folders] or sorted(path_folder.keys())
240240 if self.options.recursive:
241 paths = [path2 for path2 in path_folder for path in paths if path2.startswith(path+'/')]
241 paths = [path2 for path2 in path_folder for path in paths if (path2+'//').startswith(path+'/')]
242242
243243 # restore specified folders
244244 for path in paths:
247247 stats['errors'] += 1
248248 else:
249249 # handle --restore-root, filter and start restore
250 restore_path = self.options.restore_root+'/'+path if self.options.restore_root else path
250 restore_path = _decode(self.options.restore_root)+'/'+path if self.options.restore_root else path
251251 folder = store.subtree.folder(restore_path, create=True)
252252 if (not store.public and \
253253 ((self.options.skip_junk and folder == store.junk) or \
261261 def create_jobs(self):
262262 """ check command-line options and determine which stores should be backed up """
263263
264 output_dir = self.options.output_dir or ''
264 output_dir = _decode(self.options.output_dir) if self.options.output_dir else ''
265265 jobs = []
266266
267267 # specified companies/all users
378378 if mapper is None:
379379 mapper = {}
380380 if os.path.exists(data_path+'/path'):
381 path = file(data_path+'/path').read()
381 path = file(data_path+'/path').read().decode('utf8')
382382 mapper[path] = data_path
383383 if os.path.exists(data_path+'/folders'):
384384 for f in os.listdir(data_path+'/folders'):
403403 # setup CSV writer, perform basic checks
404404 writer = csv.writer(sys.stdout)
405405 path_folder = folder_struct(data_path, options)
406 paths = options.folders or sorted(path_folder)
406 paths = [_decode(f) for f in options.folders] or sorted(path_folder)
407407 for path in paths:
408408 if path not in path_folder:
409409 print 'no such folder:', path
428428
429429 # --stats: one entry per folder
430430 if options.stats:
431 writer.writerow([path, len(items)])
431 writer.writerow([path.encode(sys.stdout.encoding or 'utf8'), len(items)])
432432
433433 # --index: one entry per item
434434 elif options.index:
435435 items.sort(key=lambda (k, d): d['last_modified'])
436436 for key, d in items:
437 writer.writerow([key, path, d['last_modified'], d['subject'].encode(sys.stdout.encoding or 'utf8')])
437 writer.writerow([key, path.encode(sys.stdout.encoding or 'utf8'), d['last_modified'], d['subject'].encode(sys.stdout.encoding or 'utf8')])
438438
439439 def dump_props(props):
440440 """ dump given MAPI properties """
473473 entryid = server.group(value).groupid
474474 row[1].Value = entryid.decode('hex')
475475 rows.append(row)
476 except kopano.ZNotFoundException:
476 except kopano.NotFoundError:
477477 log.warning("skipping access control entry for unknown user/group '%s'" % row[1].Value)
478478 acltab = folder.mapiobj.OpenProperty(PR_ACL_TABLE, IID_IExchangeModifyTable, 0, MAPI_MODIFY)
479479 acltab.ModifyTable(0, [ROWENTRY(ROW_ADD, row) for row in rows])
501501 f = movecopy.findall('folder')[0]
502502 path = store.folder(entryid=f.text.decode('base64').encode('hex')).path
503503 f.text = path
504 except kopano.ZNotFoundException:
504 except kopano.NotFoundError:
505505 log.warning("skipping rule for unknown store/folder")
506506 ruledata = ElementTree.tostring(etxml)
507507 return pickle.dumps(ruledata)
523523 s.text = store.entryid.decode('hex').encode('base64').strip()
524524 f = movecopy.findall('folder')[0]
525525 f.text = store.folder(f.text).entryid.decode('hex').encode('base64').strip()
526 except kopano.ZNotFoundException:
526 except kopano.NotFoundError:
527527 log.warning("skipping rule for unknown store/folder")
528528 etxml = ElementTree.tostring(etxml)
529529 folder.create_prop(PR_RULES_DATA, etxml)
530530
531 def _get_fbf(user, flags, log):
532 try:
533 fbeid = user.root.prop(PR_FREEBUSY_ENTRYIDS).value[1]
534 return user.store.mapiobj.OpenEntry(fbeid, None, flags)
535 except MAPIErrorNotFound:
536 log.warning("skipping delegation because of missing freebusy data")
537
531538 def dump_delegates(user, server, log):
532539 """ dump delegate users for given user """
533540
534 # XXX more freebusy stuff?
535 fbeid = user.root.prop(PR_FREEBUSY_ENTRYIDS).value[1]
536 fbf = user.store.mapiobj.OpenEntry(fbeid, None, 0)
541 fbf = _get_fbf(user, 0, log)
542 delegate_uids = []
537543 try:
538 delegate_uids = HrGetOneProp(fbf, PR_SCHDINFO_DELEGATE_ENTRYIDS).Value
544 if fbf:
545 delegate_uids = HrGetOneProp(fbf, PR_SCHDINFO_DELEGATE_ENTRYIDS).Value
539546 except MAPIErrorNotFound:
540 delegate_uids = []
541 usernames = [server.sa.GetUser(uid, MAPI_UNICODE).Username for uid in delegate_uids]
547 pass
548
549 usernames = []
550 for uid in delegate_uids:
551 try:
552 usernames.append(server.sa.GetUser(uid, MAPI_UNICODE).Username)
553 except MAPIErrorNotFound:
554 log.warning("skipping delegate user for unknown userid")
542555 return pickle.dumps(usernames)
543556
544557 def load_delegates(user, server, data, log):
545558 """ load delegate users for given user """
546559
547 data = pickle.loads(data)
548 fbeid = user.root.prop(PR_FREEBUSY_ENTRYIDS).value[1]
549 fbf = user.store.mapiobj.OpenEntry(fbeid, None, MAPI_MODIFY)
550 try:
551 fbf.SetProps([SPropValue(PR_SCHDINFO_DELEGATE_ENTRYIDS, [server.user(name).userid.decode('hex') for name in data])])
560 userids = []
561 for name in pickle.loads(data):
562 try:
563 userids.append(server.user(name).userid.decode('hex'))
564 except kopano.NotFoundError:
565 log.warning("skipping delegation for unknown user '%s'" % name)
566
567 fbf = _get_fbf(user, MAPI_MODIFY, log)
568 if fbf:
569 fbf.SetProps([SPropValue(PR_SCHDINFO_DELEGATE_ENTRYIDS, userids)])
552570 fbf.SaveChanges(0)
553 except kopano.ZNotFoundException:
554 log.warning("skipping delegation for unknown user '%s'" % name)
555571
556572 def main():
557573 # select common options
573589
574590 # parse and check command-line options
575591 options, args = parser.parse_args()
576 options.foreground = True
592 options.service = False
577593 if options.restore or options.stats or options.index:
578594 assert len(args) == 1 and os.path.isdir(args[0]), 'please specify path to backup data'
579595 else:
4242 addCheck("ldap_user_search_filter", 0, &testLdapQuery);
4343 addCheck("ldap_group_search_filter", 0, &testLdapQuery);
4444 addCheck("ldap_company_search_filter", 0, &testLdapQuery);
45
4645
4746 addCheck("ldap_user_unique_attribute", CONFIG_MANDATORY);
4847 addCheck("ldap_user_unique_attribute_type", 0, &testLdapType);
5454 addCheck("enable_distributed_kopano", 0, &testBoolean);
5555 addCheck("server_name", CONFIG_MULTI_USED);
5656 // addCheck("thread_stacksize", 0, &testMinInt, 25);
57
5857
5958 addCheck("enable_gab", 0, &testBoolean);
6059 addCheck("enable_sso_ntlmauth", 0, &testBoolean);
591591 return ValidateRecursiveDuplicateRecipients(lpMessage, bChanged);
592592 }
593593
594
173173 HRESULT FsckContact::ValidateItem(LPMESSAGE lpMessage,
174174 const std::string &strClass)
175175 {
176 HRESULT hr;
176 HRESULT hr = hrSuccess;
177177
178178 if (strClass != "IPM.Contact" && strClass != "IPM.DistList") {
179179 std::cout << "Illegal class: \"" << strClass << "\"" << std::endl;
183183 if (strClass == "IPM.Contact")
184184 hr = ValidateContactNames(lpMessage);
185185 // else: @todo distlist validation
186 if (hr != hrSuccess)
187 return hr;
188 return hrSuccess;
186
187 return hr;
189188 }
461461 pRows = NULL;
462462 }
463463
464
465464 message:
466465 lpTable->Release();
467466 lpTable = NULL;
512511 if (hr != hrSuccess)
513512 goto exit;
514513
515
516514 if (cRows < 1) {
517515 // 0 or 1 row not needed to check
518516 goto exit;
565563 if (!mapiReciptDel.empty()) {
566564 hr = DeleteRecipientList(lpMessage, mapiReciptDel, bChanged);
567565 }
568
569566
570567
571568 exit:
+0
-69
ECtools/hx-time.c less more
0 /*
1 * Copyright Jan Engelhardt, 2012
2 *
3 * This file is taken from libHX. libHX is free software; you can
4 * redistribute it and/or modify it under the terms of the GNU Lesser
5 * General Public License as published by the Free Software Foundation;
6 * either version 2.1 or (at your option) any later version.
7 */
8 #include <time.h>
9 #include "hx-time.h"
10 #define NANOSECOND 1000000000
11
12 struct timespec *
13 HX_timespec_neg(struct timespec *r, const struct timespec *a)
14 {
15 if (a->tv_sec != 0) {
16 r->tv_sec = -a->tv_sec;
17 r->tv_nsec = a->tv_nsec;
18 } else {
19 r->tv_sec = 0;
20 r->tv_nsec = -a->tv_nsec;
21 }
22 return r;
23 }
24
25 struct timespec *HX_timespec_add(struct timespec *r,
26 const struct timespec *a, const struct timespec *b)
27 {
28 /*
29 * Split the value represented by the struct into two
30 * independent values that can be added individually.
31 */
32 long nsec[2];
33 nsec[0] = (a->tv_sec < 0) ? -a->tv_nsec : a->tv_nsec;
34 nsec[1] = (b->tv_sec < 0) ? -b->tv_nsec : b->tv_nsec;
35
36 r->tv_sec = a->tv_sec + b->tv_sec;
37 r->tv_nsec = nsec[0] + nsec[1];
38 if (r->tv_nsec >= NANOSECOND) {
39 ++r->tv_sec;
40 r->tv_nsec -= NANOSECOND;
41 } else if (r->tv_nsec <= -NANOSECOND) {
42 --r->tv_sec;
43 r->tv_nsec += NANOSECOND;
44 }
45
46 /* Combine again */
47 if (r->tv_sec < 0) {
48 if (r->tv_nsec < 0) {
49 r->tv_nsec = -r->tv_nsec;
50 } else if (r->tv_nsec > 0) {
51 if (++r->tv_sec == 0)
52 r->tv_nsec = -NANOSECOND + r->tv_nsec;
53 else
54 r->tv_nsec = NANOSECOND - r->tv_nsec;
55 }
56 } else if (r->tv_sec > 0 && r->tv_nsec < 0) {
57 --r->tv_sec;
58 r->tv_nsec = NANOSECOND + r->tv_nsec;
59 }
60 return r;
61 }
62
63 struct timespec *HX_timespec_sub(struct timespec *r,
64 const struct timespec *a, const struct timespec *b)
65 {
66 struct timespec b2;
67 return HX_timespec_add(r, a, HX_timespec_neg(&b2, b));
68 }
+0
-16
ECtools/hx-time.h less more
0 #ifndef LOCAL_HXTIME_H
1 #define LOCAL_HXTIME_H 1
2
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 extern struct timespec *HX_timespec_neg(struct timespec *, const struct timespec *);
8 extern struct timespec *HX_timespec_add(struct timespec *, const struct timespec *, const struct timespec *);
9 extern struct timespec *HX_timespec_sub(struct timespec *, const struct timespec *, const struct timespec *);
10
11 #ifdef __cplusplus
12 } /* extern "C" */
13 #endif
14
15 #endif /* LOCAL_HXTIME_H */
0 #include <chrono>
01 #include <cerrno>
12 #include <csignal>
23 #include <cstdio>
78 #include <kopano/ECLogger.h>
89 #include <kopano/MAPIErrors.h>
910 #include <kopano/charset/convert.h>
10 #include "hx-time.h"
1111
1212 struct mpt_stat_entry {
1313 struct timespec start, stop;
2626 return;
2727 const struct mpt_stat_entry &first = *mpt_stat_list.begin();
2828 const struct mpt_stat_entry &last = *mpt_stat_list.rbegin();
29 struct timespec delta;
30 HX_timespec_sub(&delta, &last.stop, &first.start);
31 double dt = delta.tv_sec + delta.tv_nsec / 1000000000.0;
32 if (dt == 0)
29 typedef std::chrono::seconds sec;
30 typedef std::chrono::nanoseconds nsec;
31 auto dt = std::chrono::duration<double>(
32 sec(last.stop.tv_sec) + nsec(last.stop.tv_nsec) -
33 (sec(first.start.tv_sec) + nsec(first.start.tv_nsec)));
34 if (dt.count() == 0)
3335 return;
34 printf("\r\e[2K%.1f per second", z / dt);
36 printf("\r\e[2K%.1f per second", z / dt.count());
3537 fflush(stdout);
3638 }
3739
4749 struct sigaction sa;
4850 sa.sa_handler = mpt_stat_dump;
4951 sa.sa_flags = SA_RESTART;
52 sigemptyset(&sa.sa_mask);
5053 if (sigaction(SIGALRM, &sa, NULL) < 0) {
5154 perror("sigaction");
5255 return -errno;
5656 #define QUOTA_CONFIG_MSG "Kopano.Quota"
5757
5858 /**
59 * ECQuotaMonitor constructor
6059 * Takes an extra reference to the passed MAPI objects which have refcounting.
6160 */
6261 ECQuotaMonitor::ECQuotaMonitor(ECTHREADMONITOR *lpThreadMonitor,
7776 }
7877
7978 /**
80 * ECQuotaMonitor destructor
8179 * Releases references to passed MAPI objects.
8280 */
8381 ECQuotaMonitor::~ECQuotaMonitor()
297295
298296 set<string> setServers;
299297 const char *lpszServersConfig;
300 std::set<string, stricmp_comparison> setServersConfig;
298 std::set<string, strcasecmp_comparison> setServersConfig;
301299 set<string>::const_iterator iServers;
302300 char *lpszConnection = NULL;
303301 bool bIsPeer = false;
700698 * @retval MAPI_E_NOT_ENOUGH_MEMORY unable to allocate more memory
701699 */
702700 HRESULT ECQuotaMonitor::CreateMessageProperties(ECUSER *lpecToUser,
703 ECUSER *lpecFromUser, std::string strSubject, std::string strBody,
704 ULONG *lpcPropSize, LPSPropValue *lppPropArray)
701 ECUSER *lpecFromUser, const std::string &strSubject,
702 const std::string &strBody, ULONG *lpcPropSize, LPSPropValue *lppPropArray)
705703 {
706704 HRESULT hr = hrSuccess;
707705 LPSPropValue lpPropArray = NULL;
801799 lpPropArray[ulPropArrayCur].ulPropTag = PR_RCVD_REPRESENTING_EMAIL_ADDRESS_A;
802800 lpPropArray[ulPropArrayCur++].Value.lpszA = (lpecToUser->lpszMailAddress ? (LPSTR)lpecToUser->lpszMailAddress : (LPSTR)"");
803801
804
805802 hr = MAPIAllocateMore(cbToEntryid, lpPropArray,
806803 (void**)&lpPropArray[ulPropArrayCur].Value.bin.lpb);
807804 if (hr != hrSuccess)
4848
4949 private:
5050 HRESULT CreateMailFromTemplate(TemplateVariables *lpVars, std::string *lpstrSubject, std::string *lpstrBody);
51 HRESULT CreateMessageProperties(ECUSER *lpecToUser, ECUSER *lpecFromUser, std::string strSubject, std::string strBody, ULONG *lpcPropSize, LPSPropValue *lppPropArray);
51 HRESULT CreateMessageProperties(ECUSER *touesr, ECUSER *fromuser, const std::string &subj, const std::string &body, ULONG *lpcPropSize, LPSPropValue *lppPropArray);
5252 HRESULT CreateRecipientList(ULONG cToUsers, ECUSER *lpToUsers, LPADRLIST *lppAddrList);
5353
5454 HRESULT SendQuotaWarningMail(IMsgStore* lpMDB, ULONG cPropSize, LPSPropValue lpPropArray, LPADRLIST lpAddrList);
3535 #include "ECQuotaMonitor.h"
3636
3737 #include <kopano/CommonUtil.h>
38 #ifdef LINUX
3938 #include <kopano/UnixUtil.h>
40 #endif
4139 #include <kopano/ecversion.h>
4240 #include "charset/localeutil.h"
4341
8381 {
8482 // In Win32, the signal is sent in a separate, special signal thread. So this test is
8583 // not needed or required.
86 #ifdef LINUX
8784 if (pthread_equal(pthread_self(), mainthread)==0)
8885 return;
89 #endif
9086 if (m_lpThreadMonitor) {
9187 if (m_lpThreadMonitor->lpConfig) {
9288 if (!m_lpThreadMonitor->lpConfig->ReloadSettings() && m_lpThreadMonitor->lpLogger)
106102 }
107103 }
108104
109 #ifdef LINUX
110105 // SIGSEGV catcher
111106 static void sigsegv(int signr, siginfo_t *si, void *uc)
112107 {
113108 generic_sigsegv_handler(m_lpThreadMonitor->lpLogger, "Monitor",
114109 PROJECT_VERSION_MONITOR_STR, signr, si, uc);
115110 }
116 #endif
117111
118112 static void print_help(const char *name)
119113 {
128122 int main(int argc, char *argv[]) {
129123
130124 HRESULT hr = hrSuccess;
131 #ifdef LINUX
132125 const char *szConfig = ECConfig::GetDefaultPath("monitor.cfg");
133 #else
134 const char *szConfig = "monitor.cfg";
135 #endif
136126 const char *szPath = NULL;
137127 int c;
138128 int daemonize = 1;
142132 static const configsetting_t lpDefaults[] = {
143133 { "smtp_server","localhost" },
144134 { "server_socket", "default:" },
145 #ifdef LINUX
146135 { "run_as_user", "kopano" },
147136 { "run_as_group", "kopano" },
148137 { "pid_file", "/var/run/kopano/monitor.pid" },
149138 { "running_path", "/var/lib/kopano" },
150 #endif
151139 { "log_method","file" },
152 #ifdef LINUX
153140 { "log_file","/var/log/kopano/monitor.log" },
154 #else
155 { "log_file","-" },
156 #endif
157141 { "log_level", "3", CONFIGSETTING_RELOADABLE },
158142 { "log_timestamp","1" },
159143 { "log_buffer_size", "0" },
247231 if ((bIgnoreUnknownConfigOptions && m_lpThreadMonitor->lpConfig->HasErrors()) || m_lpThreadMonitor->lpConfig->HasWarnings())
248232 LogConfigErrors(m_lpThreadMonitor->lpConfig);
249233
250
251234 // set socket filename
252235 if (!szPath)
253236 szPath = m_lpThreadMonitor->lpConfig->GetSetting("server_socket");
254237
255238 signal(SIGTERM, sighandle);
256239 signal(SIGINT, sighandle);
257 #ifdef LINUX
258240 signal(SIGHUP, sighup);
259241
260242 // SIGSEGV backtrace support
275257 sigaction(SIGSEGV, &act, NULL);
276258 sigaction(SIGBUS, &act, NULL);
277259 sigaction(SIGABRT, &act, NULL);
278 #endif
279
280 #ifdef LINUX
260
281261 // fork if needed and drop privileges as requested.
282262 // this must be done before we do anything with pthreads
283263 if (unix_runas(m_lpThreadMonitor->lpConfig, m_lpThreadMonitor->lpLogger))
288268 setsid();
289269 if (unix_create_pidfile(argv[0], m_lpThreadMonitor->lpConfig, m_lpThreadMonitor->lpLogger, false) < 0)
290270 goto exit;
291 #endif
292271
293272 // Init exit threads
294273 pthread_mutex_init(&m_hExitMutex, NULL);
55 kopano_presence/plugin_xmpp.py kopano_presence/plugin_spreed.py
66
77 install-exec-local:
8 cd ${srcdir} && ${PYTHON} setup.py install -f \
9 $${DESTDIR+--root=${DESTDIR}} \
8 cd ${srcdir} && ${PYTHON} setup.py \
9 build --build-base="${abs_builddir}/build" \
10 install -f $${DESTDIR+--root=${DESTDIR}} \
1011 --prefix="${prefix}" --install-purelib ${pythondir}
1112 rm -Rf build
13
14 uninstall-local:
15 rm -Rf ${DESTDIR}${pythondir}/kopano_presence \
16 ${DESTDIR}${pythondir}/kopano_presence-0*.egg-info
0 # -*- Makefile -*-
1
2 sbin_PROGRAMS = kopano-pst-import
3
4 PST_LIBS =${top_builddir}/common/libkcmapi.la \
5 ${top_builddir}/common/libkcutil.la \
6 ${top_builddir}/mapi4linux/src/libmapi.la \
7 -lpff \
8 ${PROG_LIBS} ${SSL_LIBS} ${BOOST_FILESYSTEM_LIBS} ${BOOST_SYSTEM_LIBS}
9
10 PST_SOURCES = import.cpp
11
12 AM_CPPFLAGS = ${ZCPPFLAGS} ${DEBUGFLAGS} ${BOOST_CPPFLAGS} \
13 -I${top_srcdir}/mapi4linux/include \
14 ${zcp_CFLAGS}
15
16 kopano_pst_import_LDADD = ${zcp_LIBS} ${PST_LIBS}
17 kopano_pst_import_SOURCES = ${PST_SOURCES}
18
19 include ../../global.am
0 /*
1 * Copyright 2005 - 2016 Zarafa B.V. and its licensors
2 */
3
4 #include <kopano/platform.h>
5
6 #include <iostream>
7 #include <kopano/ECLogger.h>
8 #include <libpff/error.h>
9 #include <libpff.h>
10 #include <kopano/charset/convert.h>
11
12 #include <kopano/mapi_ptr.h>
13 #include <mapiguid.h>
14 #include <mapidefs.h>
15 #include <mapitags.h>
16 #include <mapiutil.h>
17 #include <mapix.h>
18
19 #include <kopano/ecversion.h>
20 #include <kopano/CommonUtil.h>
21
22 using namespace std;
23
24 std::wstring GetPropString(libpff_item_t *item, unsigned int ulPropTag);
25 HRESULT value_to_spropval(uint32_t propid, uint32_t proptype, uint8_t *data, size_t size, void *base, LPSPropValue lpProp);
26 HRESULT item_to_srowset(libpff_item_t *item, LPSRowSet *lppRowSet);
27 HRESULT dump_message( libpff_item_t *item, IMAPIFolder *lpFolder);
28 HRESULT dump_folder(libpff_file_t *file, libpff_item_t *item, IMAPIFolder *lpFolder);
29 HRESULT dump_store(libpff_file_t *file, libpff_item_t *store, libpff_item_t *item, IMAPIFolder *lpFolder);
30
31
32 std::wstring GetPropString(libpff_item_t *item, unsigned int ulPropTag)
33 {
34 libpff_error_t *error = NULL;
35 uint32_t type = 0;
36 uint8_t *data = NULL;
37 size_t size;
38
39 if(libpff_item_get_entry_value(item, 0, PROP_ID(ulPropTag), &type, &data, &size, LIBPFF_ENTRY_VALUE_FLAG_MATCH_ANY_VALUE_TYPE, &error) != 1) {
40 return std::wstring(L"");
41 }
42
43 if(type == PT_STRING8)
44 return convert_to<std::wstring>((char *)data, size, "windows-1252");
45 else
46 return convert_to<std::wstring>((char *)data, size, "UCS-2");
47 }
48
49 HRESULT value_to_spropval(uint32_t propid, uint32_t proptype, uint8_t *data, size_t size, void *base, LPSPropValue lpProp)
50 {
51 HRESULT hr = hrSuccess;
52
53 lpProp->ulPropTag = PROP_TAG(proptype, propid);
54
55 switch(proptype) {
56 case PT_STRING8: {
57 std::string str = convert_to<std::string>("//FORCE", (char *)data, size, "windows-1252");
58
59 if ((hr = MAPIAllocateMore(str.size()+1, base, (void **)&lpProp->Value.lpszA)) != hrSuccess)
60 goto exit;
61 strcpy(lpProp->Value.lpszA, str.c_str());
62 break;
63 }
64 case PT_UNICODE: {
65 std::wstring wstr;
66
67 wstr = convert_to<std::wstring>("WCHAR_T//FORCE",(char *)data, size, "UCS-2LE");
68
69 if ((hr = MAPIAllocateMore((wstr.size()+1) * sizeof(wchar_t), base, (void **)&lpProp->Value.lpszW)) != hrSuccess)
70 goto exit;
71 wcscpy(lpProp->Value.lpszW, wstr.c_str());
72 break;
73 }
74 case PT_BINARY:
75 if ((hr = MAPIAllocateMore(size, base, (void **)&lpProp->Value.bin.lpb)) != hrSuccess)
76 goto exit;
77 memcpy(lpProp->Value.bin.lpb, data, size);
78 lpProp->Value.bin.cb = size;
79 break;
80 case PT_LONG:
81 if(size != sizeof(unsigned int)) {
82 wcerr << "Unexpected data size " << size << " != " << sizeof(unsigned int) << std::endl;
83 hr = MAPI_E_INVALID_PARAMETER;
84 goto exit;
85 }
86 lpProp->Value.ul = *(unsigned int *)data;
87 break;
88 case PT_BOOLEAN:
89 if(size != sizeof(unsigned char)) {
90 wcerr << "Unexpected data size " << size << " != " << sizeof(unsigned char) << std::endl;
91 hr = MAPI_E_INVALID_PARAMETER;
92 goto exit;
93 }
94 lpProp->Value.b = *(unsigned char *)data;
95 break;
96 case PT_I2:
97 if(size != sizeof(unsigned short)) {
98 wcerr << "Unexpected data size " << size << " != " << sizeof(unsigned short) << std::endl;
99 hr = MAPI_E_INVALID_PARAMETER;
100 goto exit;
101 }
102 lpProp->Value.i = *(unsigned short *)data;
103 break;
104 case PT_SYSTIME:
105 if(size != sizeof(FILETIME)) {
106 wcerr << "Unexpected data size " << size << " != " << sizeof(FILETIME) << std::endl;
107 hr = MAPI_E_INVALID_PARAMETER;
108 goto exit;
109 }
110 lpProp->Value.ft = *(FILETIME *)data;
111 break;
112 default:
113 hr = MAPI_E_INVALID_PARAMETER;
114 }
115
116 exit:
117 return hr;
118 }
119
120 HRESULT item_to_srowset(libpff_item_t *item, LPSRowSet *lppRowSet) {
121 HRESULT hr = hrSuccess;
122 libpff_name_to_id_map_entry_t *name_to_id_map_entry = NULL;
123 size_t size = 0;
124 uint32_t entry_type = 0;
125 uint32_t value_type = 0;
126 uint8_t *value_data = NULL;
127 uint32_t rows, columns;
128 LPSRowSet rowset = NULL;
129 libpff_error_t *error = NULL;
130 int n = 0;
131
132 if(libpff_item_get_number_of_sets(item, &rows, &error) != 1) {
133 wcerr << "Unable to get number of sets\n";
134 hr = MAPI_E_NOT_FOUND;
135 goto exit;
136 }
137
138 if(libpff_item_get_number_of_entries(item, &columns, &error) != 1) {
139 wcerr << "Unable to get number of entries\n";
140 hr = MAPI_E_NOT_FOUND;
141 goto exit;
142 }
143
144 if ((hr = MAPIAllocateBuffer(CbNewSRowSet(rows), (void **)&rowset)) != hrSuccess)
145 goto exit;
146
147 memset(rowset, 0, CbNewSRowSet(rows));
148
149 for(uint32_t i = 0; i < rows; i++) {
150 if ((hr = MAPIAllocateBuffer(sizeof(SPropValue) * columns, (void **)&rowset->aRow[i].lpProps)) != hrSuccess)
151 goto exit;
152 memset(rowset->aRow[i].lpProps, 0, sizeof(SPropValue) * columns);
153 n = 0;
154 for(uint32_t j = 0; j < columns; j++) {
155 if(libpff_item_get_entry_type(item, i, j, &entry_type, &value_type, &name_to_id_map_entry, &error) != 1) {
156 wcerr << "Unable to get property tag " << j << endl;
157 continue;
158 }
159
160 if(libpff_item_get_entry_value(item, i, entry_type, &value_type, &value_data, &size, LIBPFF_ENTRY_VALUE_FLAG_MATCH_ANY_VALUE_TYPE | LIBPFF_ENTRY_VALUE_FLAG_IGNORE_NAME_TO_ID_MAP, &error) == -1) {
161 wcerr << "Unable to get property " << j << endl;
162 continue;
163 } else {
164 if(!value_data)
165 continue;
166
167 if(value_to_spropval(entry_type, value_type, value_data, size, rowset->aRow[i].lpProps, &rowset->aRow[i].lpProps[n]) != hrSuccess) {
168 continue;
169 }
170 n++;
171 }
172 }
173 rowset->aRow[i].cValues = n;
174 }
175
176 rowset->cRows = rows;
177
178 *lppRowSet = rowset;
179
180 exit:
181 return hr;
182 }
183
184 HRESULT dump_message( libpff_item_t *item, IMAPIFolder *lpFolder) {
185 HRESULT hr = hrSuccess;
186 MessagePtr lpMessage;
187
188 IAttach *lpAttach = NULL;
189 IStream *lpStream = NULL;
190 ULONG ulAttachId = 0;
191 int attachcount;
192 libpff_error_t *error = NULL;
193 libpff_item_t *recipients = NULL;
194 mapi_rowset_ptr<SRow> props, recipprops, attachprops;
195 libpff_item_t *attachment = NULL, *attachments = NULL;
196
197 hr = item_to_srowset(item, &props);
198 if(hr != hrSuccess) {
199 wcerr << "Unable to get properties\n";
200 goto exit;
201 }
202
203 if(props.size() != 1) {
204 wcerr << "Number of sets is not 1\n";
205 hr = MAPI_E_NOT_FOUND;
206 goto exit;
207 }
208
209 if(libpff_message_get_recipients(item, &recipients, &error) != 1) {
210 wcerr << "Unable to get recipients\n";
211 hr = MAPI_E_NOT_FOUND;
212 goto exit;
213 }
214
215 hr = item_to_srowset(recipients, &recipprops);
216 if(hr != hrSuccess) {
217 wcerr << "Unable to get recipient propers\n";
218 goto exit;
219 }
220
221 hr = lpFolder->CreateMessage(&IID_IMessage, 0, &lpMessage);
222 if(hr != hrSuccess) {
223 wcerr << "Unable to create MAPI message\n";
224 goto exit;
225 }
226
227 hr = lpMessage->SetProps(props[0].cValues, props[0].lpProps, NULL);
228 if(hr != hrSuccess) {
229 wcerr << "Unable to set properties\n";
230 goto exit;
231 }
232
233 hr = lpMessage->ModifyRecipients(0, (LPADRLIST)recipprops.get());
234 if(hr != hrSuccess) {
235 wcerr << "Unable to set recipients\n";
236 goto exit;
237 }
238
239 if(libpff_message_get_number_of_attachments(item, &attachcount, &error) != 1) {
240 hr = MAPI_E_NOT_FOUND;
241 wcerr << "Unable to get number of attachments\n";
242 goto exit;
243 }
244
245 if(attachcount > 0) {
246 if(libpff_message_get_attachments(item, &attachments, &error) != 1) {
247 hr = MAPI_E_NOT_FOUND;
248 wcerr << "Unable to get attachments\n";
249 goto exit;
250 }
251
252 hr = item_to_srowset(attachments, &attachprops);
253 if(hr != hrSuccess) {
254 wcerr << "Unable to get attachment properties\n";
255 goto exit;
256 }
257
258 for(int i = 0; i < attachcount ; i++) {
259 int attachment_type = 0;
260 size64_t data_size;
261
262 if(libpff_message_get_attachment(item, i, &attachment, &error) != 1) {
263 wcerr << "Unable to get attachment " << i << endl;
264 continue;
265 }
266
267 hr = lpMessage->CreateAttach(&IID_IAttachment, 0, &ulAttachId, &lpAttach);
268 if(hr != hrSuccess) {
269 wcerr << "Unable to create attachment " << i << endl;
270 goto exit;
271 }
272
273 hr = lpAttach->SetProps(attachprops[i].cValues, attachprops[i].lpProps, NULL);
274 if(hr != hrSuccess) {
275 wcerr << "Unable to set attachment properties";
276 goto exit;
277 }
278
279 if(libpff_attachment_get_type(attachment, &attachment_type, &error) != 1) {
280 wcerr << "Unable to get attachment type\n";
281 hr = MAPI_E_NOT_FOUND;
282 goto exit;
283 }
284
285 if(attachment_type == LIBPFF_ATTACHMENT_TYPE_DATA) {
286 char buffer[65536];
287 SPropValue sProp;
288
289 sProp.ulPropTag = PR_ATTACH_METHOD;
290 sProp.Value.ul = ATTACH_BY_VALUE;
291 HrSetOneProp(lpAttach, &sProp);
292
293
294 hr = lpAttach->OpenProperty(PR_ATTACH_DATA_BIN, &IID_IStream, STGM_WRITE | STGM_SHARE_EXCLUSIVE, MAPI_CREATE | MAPI_MODIFY, (IUnknown **)&lpStream);
295 if(hr != hrSuccess) {
296 wcerr << "Unable to create attachment data stream\n";
297 goto exit;
298 }
299
300 if(libpff_attachment_get_data_size(attachment, &data_size, &error) != 1) {
301 wcerr << "Unable to get attachment size\n";
302 continue;
303 }
304
305 if(data_size) {
306 if(libpff_attachment_data_seek_offset(attachment, 0, SEEK_SET, &error) != 0) {
307 wcerr << "Unable to seek to attachment data start\n";
308 continue;
309 }
310
311 while( data_size > 0 ) {
312 int read = libpff_attachment_data_read_buffer(attachment, (uint8_t *)buffer, sizeof(buffer) > data_size ? data_size : sizeof(buffer), &error);
313
314 if(read < 0 ) {
315 wcerr << "Read failed on data stream\n";
316 continue;
317 }
318
319 data_size -= read;
320
321 hr = lpStream->Write(buffer, read, NULL);
322 if(hr != hrSuccess)
323 goto exit;
324 }
325 }
326
327 lpStream->Commit(0);
328 lpStream->Release();
329 lpStream = NULL;
330 }
331
332 hr = lpAttach->SaveChanges(0);
333 if(hr != hrSuccess) {
334 wcerr << "Unable to save attachment\n";
335 goto exit;
336 }
337
338 lpAttach->Release();
339 lpAttach = NULL;
340
341 libpff_item_free(&attachment, &error);
342 }
343 }
344
345 hr = lpMessage->SaveChanges(0);
346 if(hr != hrSuccess) {
347 wcerr << "Unable to save MAPI message\n";
348 goto exit;
349 }
350
351 exit:
352 if(attachments)
353 libpff_item_free(&attachments, &error);
354
355 if(recipients)
356 libpff_item_free(&recipients, &error);
357
358 return hr;
359 }
360
361 HRESULT dump_folder(libpff_file_t *file, libpff_item_t *item, IMAPIFolder *lpFolder) {
362 HRESULT hr = hrSuccess;
363 int folders, messages;
364 libpff_error_t *error = NULL;
365 std::wstring wstrDisplay;
366 libpff_item_t *message = NULL, *subfolder = NULL;
367 IMAPIFolder *lpSubFolder = NULL;
368
369 wstrDisplay = GetPropString(item, PR_DISPLAY_NAME_A);
370
371 wcerr << "Processing folder " << wstrDisplay << endl;
372
373 hr = lpFolder->CreateFolder(FOLDER_GENERIC, (TCHAR *)wstrDisplay.c_str(), (TCHAR *)L"", &IID_IMAPIFolder, MAPI_UNICODE | OPEN_IF_EXISTS, &lpSubFolder);
374 if(hr != hrSuccess) {
375 wcerr << "Unable to create folder '" << wstrDisplay << "'\n";
376 goto exit;
377 }
378
379 if(libpff_folder_get_number_of_sub_messages(item, &messages, &error) != 1) {
380 wcerr << "Unable to get number of subfolders\n";
381 hr = MAPI_E_NOT_FOUND;
382 goto exit;
383 }
384
385 for(int i = 0; i < messages; i++) {
386 if(libpff_folder_get_sub_message(item, i, &message, &error) != 1) {
387 wcerr << "Unable to get message number " << i << endl;
388 continue;
389 }
390
391 dump_message(message, lpSubFolder);
392
393 libpff_item_free(&message, &error);
394 }
395
396
397 if(libpff_folder_get_number_of_sub_folders(item, &folders, &error) != 1) {
398 hr = MAPI_E_NOT_FOUND;
399 wcerr << "Unable to get number of subfolders\n";
400 goto exit;
401 }
402
403 for(int i = 0; i < folders; i++) {
404 if(libpff_folder_get_sub_folder(item, i, &subfolder, &error) != 1) {
405 wcerr << "Unable to get folder number " << i << endl;
406 continue;
407 }
408
409 dump_folder(file, subfolder, lpSubFolder);
410
411 libpff_item_free(&subfolder, &error);
412 }
413
414 exit:
415 if (lpSubFolder)
416 lpSubFolder->Release();
417
418 return hr;
419 }
420
421 HRESULT dump_store(libpff_file_t *file, libpff_item_t *store, libpff_item_t *item, IMAPIFolder *lpFolder)
422 {
423 HRESULT hr = hrSuccess;
424 libpff_item_t *subfolder = NULL;
425 uint32_t type = PROP_TYPE(PR_IPM_SUBTREE_ENTRYID);
426 libpff_error_t *error = NULL;
427 uint8_t *data = NULL;
428 size_t size;
429 mapi_rowset_ptr<SRow> r;
430
431 std::wstring strStore = GetPropString(store, PR_DISPLAY_NAME_W);
432
433 wcerr << "Store name " << strStore << endl;
434
435 if(libpff_item_get_entry_value(store, 0, PROP_ID(PR_IPM_SUBTREE_ENTRYID), &type, &data, &size, 0, &error) != 1) {
436 wcerr << "Unable to get ipm subtree\n";
437 hr = MAPI_E_NOT_FOUND;
438 goto exit;
439 }
440
441 if(size != 4 + sizeof(GUID) + sizeof(unsigned int)) {
442 wcerr << "Unexpected entryid size for IPM subtree:" << size << endl;
443 hr = MAPI_E_NOT_FOUND;
444 goto exit;
445 }
446
447 if(libpff_file_get_item_by_identifier(file, *(unsigned int *)(data + 4 + sizeof(GUID)), &subfolder, &error) != 1) {
448 wcerr << "Unable to get IPM subtree\n";
449 hr = MAPI_E_NOT_FOUND;
450 goto exit;
451 }
452
453 dump_folder(file, subfolder, lpFolder);
454
455 libpff_item_free(&subfolder, &error);
456
457 exit:
458 return hr;
459 }
460
461 int main(int argc, char *argv[]) {
462 libpff_file_t *file = NULL;
463 libpff_error_t *error = NULL;
464 libpff_item_t *pff_root_item = NULL;
465 libpff_item_t *pff_store_item = NULL;
466
467 char *filename;
468 char *username;
469
470 ULONG ulType = 0;
471 HRESULT hr = hrSuccess;
472
473 setlocale(LC_CTYPE, "");
474
475 if(argc != 3) {
476 wcerr << "Usage: pstexport <filename> <user>\n";
477 return 1;
478 }
479
480 filename = argv[1];
481 username = argv[2];
482
483 hr = MAPIInitialize(NULL);
484 if(hr != hrSuccess) {
485 wcerr << "Unable to initialize MAPI\n";
486 return 1;
487 }
488
489 {
490 MAPISessionPtr lpSession;
491 MsgStorePtr lpStore;
492 MAPIFolderPtr lpFolder;
493 SPropValuePtr lpPropIPM;
494
495 if(libpff_file_initialize(&file, &error) != 1) {
496 wcerr << "Init failed\n";
497 return 1;
498 }
499
500 if(libpff_file_open(file, filename, LIBPFF_OPEN_READ, &error) != 1) {
501 wcerr << "Unable to open file\n";
502 return 1;
503 }
504
505 hr = HrOpenECSession(ec_log_get(), &lpSession, "PST importer", PROJECT_SVN_REV_STR, convert_to<std::wstring>(username).c_str(), L"", "default:");
506 if(hr != hrSuccess) {
507 wcerr << "Unable to open MAPI session\n";
508 return 1;
509 }
510
511 if(libpff_file_get_message_store(file, &pff_store_item, &error) != 1) {
512 wcerr << "Unable to get store item\n";
513 hr = MAPI_E_NOT_FOUND;
514 goto exit;
515 }
516
517 if(libpff_file_get_root_folder(file, &pff_root_item, &error) != 1) {
518 wcerr << "Unable to get root folder\n";
519 hr = MAPI_E_NOT_FOUND;
520 goto exit;
521 }
522
523 hr = HrOpenDefaultStore(lpSession, &lpStore);
524 if(hr != hrSuccess) {
525 wcerr << "Unable to get default store\n";
526 goto exit;
527 }
528
529 hr = HrGetOneProp(lpStore, PR_IPM_SUBTREE_ENTRYID, &lpPropIPM);
530 if(hr != hrSuccess) {
531 wcerr << "Unable to get ipm subtree root\n";
532 goto exit;
533 }
534
535 hr = lpStore->OpenEntry(lpPropIPM->Value.bin.cb, (LPENTRYID)lpPropIPM->Value.bin.lpb, NULL, MAPI_MODIFY, &ulType, (IUnknown **)&lpFolder);
536 if(hr != hrSuccess) {
537 wcerr << "Unable to open ipm subtree\n";
538 goto exit;
539 }
540
541 hr = dump_store(file, pff_store_item, pff_root_item, lpFolder);
542 if(hr != hrSuccess) {
543 wcerr << "Import failed\n";
544 goto exit;
545 }
546
547 wcerr << "Import complete\n";
548
549 exit:
550 if(pff_root_item)
551 libpff_item_free(&pff_root_item, &error);
552
553 if(pff_store_item)
554 libpff_item_free(&pff_store_item, &error);
555
556 if(file) {
557 libpff_file_close(file, &error);
558 libpff_file_free(&file, &error);
559 }
560
561 }
562 MAPIUninitialize();
563
564 return hr == hrSuccess ? 0 : 2;
565 }
88 kopano_search/xmltotext.xslt
99
1010 install-exec-local:
11 cd ${srcdir} && ${PYTHON} setup.py install -f \
12 $${DESTDIR+--root=${DESTDIR}} \
11 cd ${srcdir} && ${PYTHON} setup.py \
12 build --build-base="${abs_builddir}/build" \
13 install -f $${DESTDIR+--root=${DESTDIR}} \
1314 --prefix="${prefix}" --install-purelib ${pythondir}
1415 rm -Rf build
1516
1617 install-data-local:
1718 mkdir -p "${DESTDIR}${localstatedir}/lib/kopano/search"
19
20 uninstall-local:
21 rm -Rf ${DESTDIR}${pythondir}/kopano_search \
22 ${DESTDIR}${pythondir}/kopano_search-0*.egg-info
5959
6060 db = self.open_db(server_guid, store_guid, log=log)
6161 if not db:
62 return [], ''
62 return []
63
6364 qp = xapian.QueryParser()
6465 qp.add_prefix("sourcekey", "XK:")
6566 qp.add_prefix("folderid", "XF:")
8081 def suggest(self, server_guid, store_guid, terms, orig, log):
8182 """ update original search text with suggested terms """
8283
83 with closing(self.open_db(server_guid, store_guid)) as db:
84 db = self.open_db(server_guid, store_guid, log=log)
85 if not db:
86 return orig
87
88 with closing(db) as db:
8489 # XXX revisit later. looks like xapian cannot do this for us? :S
8590 for term in sorted(terms, key=lambda s: len(s), reverse=True):
8691 suggestion = db.get_spelling_suggestion(term).decode('utf8') or term
1010 endif
1111 SUBDIRS += ECtools spooler gateway caldav installer po doc swig
1212
13 #EXTRA_DIST = version php-webclient-ajax
14 EXTRA_DIST = version versionheader.sh php-webclient-ajax \
15 LICENSE.txt CONTRIBUTORS.txt AGPL-3 \
13 EXTRA_DIST = version versionheader.sh \
14 LICENSE.txt AGPL-3 \
1615 lddcheck global.am pwdcheck.sh
1716
1817 BUILT_SOURCES = source-moved-check common/include/kopano/ecversion.h
1918
20 sbin_SCRIPTS = tools/python-scripts/kopano-cachestat.py
19 dist_sbin_SCRIPTS = tools/python-scripts/kopano-cachestat.py
2120 gdbautoloaddir = ${datadir}/gdb/auto-load/${libdir}
22 gdbautoload_DATA = tools/libmapi.so.1.0.0-gdb.py
21 dist_gdbautoload_DATA = tools/libmapi.so.1.0.0-gdb.py
22
23 DISTCHECK_CONFIGURE_FLAGS = --with-dcprefix='$${prefix}'
2324
2425 .PHONY: source-moved-check
2526 source-moved-check:
3132 dist-hook:
3233 find $(distdir) -type d -name .svn -exec rm -rf {} \; 2>/dev/null || true
3334
34 install-ajax-webaccess:
35 install -d -m 755 $(DESTDIR)/usr/share
36 cp -a $(top_srcdir)/php-webclient-ajax $(DESTDIR)/usr/share/kopano-webaccess
37 rm -rf $(DESTDIR)/usr/share/kopano-webaccess/plugins
38 install -d -m 755 $(DESTDIR)/var/lib/kopano-webaccess/plugins
39 install -d -m 755 $(DESTDIR)/var/lib/kopano-webaccess/tmp
40 install -d -m 755 $(DESTDIR)/etc/kopano/webaccess-ajax
41 mv $(DESTDIR)/usr/share/kopano-webaccess/config.php.dist $(DESTDIR)/etc/kopano/webaccess-ajax/config.php
42 rm -f $(DESTDIR)/usr/share/kopano-webaccess/debug.php
43 for podir in $(DESTDIR)/usr/share/kopano-webaccess/server/language/*; do \
44 if [ `grep msgstr $$podir/LC_MESSAGES/*po | grep -v 'msgstr ""' |wc -l` = 0 ]; then \
45 echo "Remove empty language $$podir"; \
46 rm -rf $$podir; \
47 fi; \
48 done; \
49 for po in $(DESTDIR)/usr/share/kopano-webaccess/server/language/*/LC_MESSAGES/*.po; do \
50 msgfmt -f -v -o $${po%.po}.mo $$po; \
51 rm $$po; \
52 done
53
5435 default.sym: ${top_builddir}/config.status
0 Release notes for 8.1.0
1 =======================
0 Release notes for 8.1.0 [2016-10-05]
1 ====================================
22 Fixes:
33 * server: A fast-growing memory leak was resolved [KC-12]
44 * sql schema: all PRIMARY keys need to be NOT NULL, otherwise a UNIQUE
55 key would be required. / MySQL 5.7 support [KC-2]
6 * server: avoid "netlink: 4 bytes leftover" in dmesg
6 * server: avoid "netlink: 4 bytes leftover" in dmesg [KC-82]
77 * ldapplugin: hopefully avoid "Timed out" errors from ldap_search [KC-74]
88 * swig: resolve a memory leak when using python components [KC-72]
99 * server: better guard against off-size EntryIDs [KC-60]
1111 * backup: restore container classes [KC-22]
1212 * all daemons: fixed coredumps not getting generated most of the time [KC-61]
1313 * all: issue setgroups(2) before setuid(2) [KC-37]
14 * server: avoid infinite do-nothing loop if tmp_path is unwritable [KC-77]
15 * backup: users without a store are now ignored [KC-78]
16 * kopano-mailbox-permissions: resolve a crash involving Unicode [KC-100]
17 * inetmapi: Message-Id was truncated on send [KC-101]
18 * inetmapi: character set was ignored when reading TNEF mails
19 (mails with a winmail.dat part/attachment) [KC-83]
20 * python: avoid terminal exception when handling a date past year 9999 [KC-184]
21 * caldav: Lightning workaround is not to apply to Apple mail client [KC-145]
22 * search: continue even if xapian db cannot be opened [KC-174]
23 * search: cure an infinite loop [KC-157]
24 * backup: miscellaneous [KC-161, KC-162, KC-192]
25 * init: classic init scripts showed wrong status for python daemons [KC-220]
1426 Enhancements:
15 * PHP7 support
1627 * server: add ICS log messages [KC-18]
1728 * server: ship example config files for ldap multi-server [KC-65]
1829 * server: speed up REPLACE-type sql queries [KC-58]
1930 * server: speed up login phase by caching PR_LOGON_TIME [KC-6]
31 * server: indexing of junk folders can be controlled now [KC-17]
32 * server: warn about on-disk attachments that have wrong metadata [KC-104]
2033 * libicalmapi: improve fallback scenario to server_timezone in ical.cfg [KC-11]
34 * tools: add an SPropValue pretty printer for use with gdb
35 * `systemctl reload` for kopano services is now usable where supported [KC-71]
36 * RHEL(6) initscripts did not cope with python daemons well [KC-96]
37 * backup: add option to skip broken attachments [KC-45]
38 * spooler: rule name is now logged [KC-102]
39 * archiver: new scripts kopano-archiver-{aclsync,aclset,restore} [KC-39]
40 * python/swig: resolve some memory leaks [KC-92, KC-95]
41 * client: permit self-signed certificates [KC-155]
42 * Add scripts (source tarball only) to inspect/delete stale search folders
43 which slow down kopano-server startup and message modification when too many
44 have accumulated [KC-140]
45 * server: the allocator library is now switchable [KC-191, KC-216],
46 there is a new option "allocator_library" in server.cfg to control it.
47 * Initial PHP7 support [KC-130, KC-131, KC-134, KC-158]
48 (not complete for Z-Push yet)
2149 Changes:
2250 * search: no longer do indexing on root and Draft folders [KC-57]
2351 * search: index junk folders, but skip updating suggestion list [KC-57]
2452 * Python 2.5 support is removed
53 * server: libs3 is now dlopened to workaround libldap effects [KC-64]
1818 #include <kopano/platform.h>
1919 #include <climits>
2020 #include "mapidefs.h"
21 #include <kopano/ECChannel.h>
2221 #include <mapix.h>
2322 #include <kopano/MAPIErrors.h>
2423 #include "Http.h"
4342
4443 using namespace std;
4544
46 #ifdef LINUX
4745 #include <execinfo.h>
4846 #include <kopano/UnixUtil.h>
49 #endif
50
5147 #ifdef ZCP_USES_ICU
5248 #include <unicode/uclean.h>
5349 #endif
54
55
56 #ifdef _DEBUG
57 #define new DEBUG_NEW
58 #endif
59
6050
6151 struct HandlerArgs {
6252 ECChannel *lpChannel;
8777
8878 static void sighup(int)
8979 {
90 // In Win32, the signal is sent in a separate, special signal thread. So this test is
91 // not needed or required.
92 #ifdef LINUX
9380 if (g_bThreads && pthread_equal(pthread_self(), mainthread)==0)
9481 return;
95 #endif
9682 if (g_lpConfig) {
9783 if (!g_lpConfig->ReloadSettings() && g_lpLogger)
9884 g_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to reload configuration file, continuing with current settings.");
11096 }
11197 }
11298
113
114 #ifdef LINUX
11599 static void sigchld(int)
116100 {
117101 int stat;
124108 generic_sigsegv_handler(g_lpLogger, "CalDAV",
125109 PROJECT_VERSION_GATEWAY_STR, signr, si, uc);
126110 }
127 #endif
128111
129112 static void PrintHelp(const char *name)
130113 {
142125 cout << "Product version:\t" << PROJECT_VERSION_CALDAV_STR << endl << "File version:\t\t" << PROJECT_SVN_REV_STR << endl;
143126 }
144127
145
146128 int main(int argc, char **argv) {
147129 HRESULT hr = hrSuccess;
148130 int ulListenCalDAV = 0;
149131 int ulListenCalDAVs = 0;
150132 bool bIgnoreUnknownConfigOptions = false;
151
152 #ifdef LINUX
153133 stack_t st = {0};
154134 struct sigaction act = {{0}};
155 #endif
156135
157136 // Configuration
158137 int opt = 0;
159138 const char *lpszCfg = ECConfig::GetDefaultPath("ical.cfg");
160139 static const configsetting_t lpDefaults[] = {
161 #ifdef LINUX
162140 { "run_as_user", "kopano" },
163141 { "run_as_group", "kopano" },
164142 { "pid_file", "/var/run/kopano/ical.pid" },
165143 { "running_path", "/var/lib/kopano" },
166144 { "process_model", "fork" },
167 #endif
168145 { "server_bind", "" },
169146 { "ical_port", "8080" },
170147 { "ical_enable", "yes" },
175152 { "server_timezone","Europe/Amsterdam"},
176153 { "default_charset","utf-8"},
177154 { "log_method", "file" },
178 #ifdef LINUX
179155 { "log_file", "/var/log/kopano/ical.log" },
180 #else
181 { "log_file", "ical.log" },
182 #endif
183156 { "log_level", "3", CONFIGSETTING_RELOADABLE },
184157 { "log_timestamp", "1" },
185158 { "log_buffer_size", "0" },
186 #ifdef LINUX
187159 { "ssl_private_key_file", "/etc/kopano/ical/privkey.pem" },
188160 { "ssl_certificate_file", "/etc/kopano/ical/cert.pem" },
189 #else
190 { "ssl_private_key_file", "privkey.pem" },
191 { "ssl_certificate_file", "cert.pem" },
192 #endif
193161 { "ssl_protocols", "!SSLv2" },
194162 { "ssl_ciphers", "ALL:!LOW:!SSLv2:!EXP:!aNULL" },
195163 { "ssl_prefer_server_ciphers", "no" },
275243 if (hr != hrSuccess)
276244 goto exit;
277245
278
279246 // setup signals
280247 signal(SIGTERM, sigterm);
281248 signal(SIGINT, sigterm);
282 #ifdef LINUX
283249 signal(SIGHUP, sighup);
284250 signal(SIGCHLD, sigchld);
285251 signal(SIGPIPE, SIG_IGN);
313279 else
314280 g_lpLogger->SetLogprefix(LP_TID);
315281 ec_log_set(g_lpLogger);
316 #endif
282
317283 hr = MAPIInitialize(NULL);
318284 if (hr != hrSuccess) {
319285 fprintf(stderr, "Messaging API could not be initialized: %s (%x)",
330296 if (hr != hrSuccess)
331297 goto exit2;
332298
333
334299 g_lpLogger->Log(EC_LOGLEVEL_ALWAYS, "CalDAV Gateway will now exit");
335300
336 #ifdef LINUX
337301 // in forked mode, send all children the exit signal
338302 if (g_bThreads == false) {
339303 int i;
353317 else
354318 g_lpLogger->Log(EC_LOGLEVEL_ALWAYS, "CalDAV Gateway shutdown complete");
355319 }
356 #endif
357
358320 exit2:
359321 MAPIUninitialize();
360322 exit:
361
362 #ifdef LINUX
363323 free(st.ss_sp);
364 #endif
365
366324 ECChannel::HrFreeCtx();
367325 delete g_lpConfig;
368326 DeleteLogger(g_lpLogger);
369
370327
371328 SSL_library_cleanup(); // Remove ssl data for the main application and other related libraries
372329
396353 int ulSecureSocket = 0;
397354
398355 // setup sockets
399 bListenSecure = (stricmp(g_lpConfig->GetSetting("icals_enable"), "yes") == 0);
400 bListen = (stricmp(g_lpConfig->GetSetting("ical_enable"), "yes") == 0);
356 bListenSecure = (strcasecmp(g_lpConfig->GetSetting("icals_enable"), "yes") == 0);
357 bListen = (strcasecmp(g_lpConfig->GetSetting("ical_enable"), "yes") == 0);
401358
402359 if (!bListen && !bListenSecure) {
403360 g_lpLogger->Log(EC_LOGLEVEL_FATAL, "No ports to open for listening.");
2121 #include <kopano/MAPIErrors.h>
2222
2323 using namespace std;
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
2924
3025 /**
3126 * Maping of caldav properties to Mapi properties
9893 }
9994
10095 /**
101 * Default constructor
10296 * @param[in] lpRequest Pointer to Http class object
10397 * @param[in] lpSession Pointer to Mapi session object
10498 * @param[in] lpLogger Pointer to ECLogger object
345339 goto exit;
346340 }
347341
348
349342 // restrict on meeting requests and appointments
350343 CREATE_RESTRICTION(lpsRestriction);
351344 CREATE_RES_OR(lpsRestriction, lpsRestriction, 3);
394387 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to receive folder properties, error 0x%08X %s", hr, GetMAPIErrorMessage(hr));
395388 goto exit;
396389 }
397
398390
399391 // @todo, add "start time" property and recurrence data to table and filter in loop
400392 // if lpsWebRCalQry->sFilter.tStart is set.
897889 return hr;
898890 }
899891
900
901892 /**
902893 * Function moves a folder or message to the deleted items folder
903894 * @note does not check if-match: if you had a message modified which you now want to delete, we delete anyway
924915 bool bisFolder = false;
925916 SizedSPropTagArray(3, lpPropTagArr) = {3, {PR_ENTRYID, PR_LAST_MODIFICATION_TIME, PR_DISPLAY_NAME_W}};
926917
927
928918 m_lpRequest->HrGetUrl(&strUrl);
929919 bisFolder = m_ulUrlFlag & REQ_COLLECTION;
930920
14341424 sPropValSet[1].ulPropTag = PR_COMMENT_A;
14351425 sPropValSet[1].Value.lpszA = const_cast<char *>("Created by CalDAV Gateway");
14361426
1437 hr = lpUsrFld->SetProps(2, (LPSPropValue)&sPropValSet, NULL);
1427 hr = lpUsrFld->SetProps(2, sPropValSet, NULL);
14381428 if (hr != hrSuccess) {
14391429 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "CalDAV::HrHandleMkCal SetProps failed: 0x%x %s", hr, GetMAPIErrorMessage(hr));
14401430 goto exit;
15031493 else
15041494 strReqUrl = "/caldav/public/";
15051495
1506
15071496 // all folder properties to fill request.
15081497 cbsize = lpsDavProp->lstProps.size() + 2;
15091498
15231512 iter = lpsDavProp->lstProps.begin();
15241513 for (int i = 2; iter != lpsDavProp->lstProps.end(); ++iter, ++i)
15251514 lpPropTagArr->aulPropTag[i] = GetPropIDForXMLProp(m_lpUsrFld, iter->sPropName, m_converter);
1526
15271515
15281516 if (m_ulFolderFlag & SINGLE_FOLDER)
15291517 {
21292117 HrGetOneProp(m_lpActiveUser, PR_SMTP_ADDRESS_A, &ptrEmail);
21302118 HrGetOneProp(m_lpActiveUser, PR_DISPLAY_NAME_W, &ptrFullname);
21312119
2132
21332120 // owner is DAV namespace, the owner of the resource (url)
21342121 strOwnerURL = "/caldav/" + urlEncode(m_wstrFldOwner, "utf-8") + "/";
21352122 strCurrentUserURL = "/caldav/" + urlEncode(m_wstrUser, "utf-8") + "/";
23242311 // do not set on public, so thunderbird/lightning doesn't require calendar-user-address-set, schedule-inbox-URL and schedule-outbox-URL
23252312 // public doesn't do meeting requests
23262313 // check here, because lpFoundProp is set to display name and isn't binary
2327 if ((m_ulUrlFlag & REQ_PUBLIC) == 0) {
2314 if ((m_ulUrlFlag & REQ_PUBLIC) == 0 || strAgent.find("Lightning") == string::npos) {
23282315 // Purpose: Identifies the URL of any WebDAV collections that contain
23292316 // calendar collections owned by the associated principal resource.
23302317 // apple seems to use this as the root container where you have your calendars (and would create more)
2121 #include <kopano/mapi_ptr.h>
2222
2323 using namespace std;
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
2824
2925 /**
3026 * Open MAPI session
194190 // we're done either way
195191 goto exit;
196192 }
197
198193
199194 hr = lpRootFolder->GetHierarchyTable(CONVENIENT_DEPTH, &lpHichyTable);
200195 if(hr != hrSuccess)
850845 hr = lpAddrBook->OpenEntry(cbEntryId, ptrEntryId, NULL, 0, &ulObj, &ptrABDir);
851846 if (hr != hrSuccess)
852847 goto exit;
853
854848
855849 cUsers = lplstUsers->size();
856850
2222 #include <kopano/ECConfig.h>
2323
2424 using namespace std;
25
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #endif
2925
3026 /**
3127 * Parse the incoming URL into known pieces:
133129 m_ulRetCode = 0;
134130 }
135131
136 /**
137 * Default destructor
138 */
139132 Http::~Http()
140133 {
141134 m_lpLogger->Release();
211204 {
212205 HRESULT hr;
213206 std::string strAuthdata;
214 std::string strLength;
215207 std::string strUserAgent;
216208
217209 std::vector<std::string> items;
390382 }
391383
392384 /**
393 * Checks the etag of a MAPI object agains If-(None)-Match headers
385 * Checks the etag of a MAPI object against If-(None)-Match headers
394386 *
395387 * @param[in] lpProp Object to check etag (PR_LAST_MODIFICATION_TIME) to
396388 *
791783 strftime(lpszChar, 127, "%a, %d %b %Y %H:%M:%S GMT", gmtime_safe(&tmCurrenttime, &dummy));
792784
793785 HrResponseHeader("Date", lpszChar);
794 if (m_ulKeepAlive != 0 && stricmp(strConnection.c_str(), "keep-alive") == 0) {
786 if (m_ulKeepAlive != 0 && strcasecmp(strConnection.c_str(), "keep-alive") == 0) {
795787 HrResponseHeader("Connection", "Keep-Alive");
796788 HrResponseHeader("Keep-Alive", stringify(m_ulKeepAlive, false));
797789 }
88
99 sbin_PROGRAMS = kopano-ical
1010 noinst_DATA = kopano-ical.ldx
11 CLEANFILES = ${noinst_DATA}
1112
1213 kopano_ical_SOURCES = CalDAV.cpp \
1314 CalDavProto.cpp CalDavProto.h \
8383 HRESULT hr = hrSuccess;
8484 std::string strUrl;
8585 std::string strMethod;
86 std::string strAgent;
8786 string strFldOwner;
8887 string strFldName;
8988 LPSPropValue lpDefaultProp = NULL;
175174 if(hr != hrSuccess)
176175 goto exit;
177176
178
179177 /*
180178 * Set m_lpIPMSubtree, used for CopyFolder, CreateFolder, DeleteFolder
181179 */
185183 m_lpLogger->Log(EC_LOGLEVEL_ERROR, "Error opening IPM SUBTREE, using user %ls, error code : 0x%08X", m_wstrUser.c_str(), hr);
186184 goto exit;
187185 }
188
189186
190187 // Get active store default calendar to prevent delete action on this folder
191188 hr = m_lpActiveStore->OpenEntry(0, NULL, NULL, 0, &ulType, &lpRoot);
261258 }
262259 }
263260
264
265261 /*
266262 * Workaround for old users with sunbird / lightning on old url base.
267263 */
324320 m_blFolderAccess = false;
325321 }
326322
327
328323 exit:
329324 MAPIFreeBuffer(lpFldProp);
330325 MAPIFreeBuffer(lpDefaultProp);
6161 std::string W2U(const WCHAR* lpwWideChar);
6262 std::wstring U2W(const std::string&); //!< convert utf-8 to widestring
6363 std::string SPropValToString(SPropValue * lpSprop);
64
65 std::string strAgent;
6466 };
6567
6668 #endif
2222
2323 using namespace std;
2424
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
29 /**
30 * Default constructor
25 /**
3126 * @param[in] lpRequest Pointer to http Request object
3227 * @param[in] lpSession Pointer to mapi session of the user
3328 * @param[in] lpLogger Pointer to logger object to log errors and information
3732 m_lpXmlDoc = NULL;
3833 }
3934
40 /**
41 * Default Destructor
42 */
4335 WebDav::~WebDav()
4436 {
4537 if (m_lpXmlDoc)
147139 hr = RespStructToXml(&sDavMStatus, &strXml);
148140 if (hr != hrSuccess)
149141 {
150 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Unable to convert reponse to xml: 0x%08X", hr);
142 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Unable to convert response to xml: 0x%08X", hr);
151143 goto exit;
152144 }
153145
167159
168160 return hr;
169161 }
170
171162
172163 /**
173164 * Converts WEBDAVMULTISTATUS response structure to xml data
967958 {
968959 HRESULT hr;
969960 WEBDAVRESPONSE sWebResp;
970 std::string strNsPrefix;
971961 std::list<WEBDAVPROPSTAT>::const_iterator iterPropStat;
972962 std::list<WEBDAVPROPERTY>::const_iterator iterProperty;
973963 int ulRet;
14011391 hr = RespStructToXml(&sDavMStatus, &strXml);
14021392 if (hr != hrSuccess)
14031393 {
1404 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Unable to convert reponse to xml: 0x%08X", hr);
1394 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Unable to convert response to xml: 0x%08X", hr);
14051395 goto exit;
14061396 }
14071397
2020 #include <libxml/tree.h>
2121 #include <libxml/xmlwriter.h>
2222 #include <libxml/parser.h>
23 #include <libxml/tree.h>
2423
2524 #include <mapi.h>
2625 #include <map>
3232
3333 using namespace std;
3434
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
38
39 /**
40 * Default constructor
41 */
4235 iCal::iCal(Http *lpRequest, IMAPISession *lpSession, ECLogger *lpLogger, std::string strSrvTz, std::string strCharset) : ProtocolBase(lpRequest, lpSession, lpLogger, strSrvTz, strCharset)
4336 {
4437 }
171164
172165 map<std::string, int>::const_iterator mpIterI;
173166 map<std::string,SBinary>::const_iterator mpIterJ;
174
175167
176168 ulProptag = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_GOID], PT_BINARY);
177169 cValues = 3;
198198 */
199199 void ConsoleTable::PrintTable()
200200 {
201 size_t nRow, nCol;
202 size_t total;
203
204201 if (bHaveHeader) {
205202 PrintRow(m_vHeader);
206 total = 0;
207 for (nCol = 0; nCol < m_iColumns; ++nCol)
203 size_t total = 0;
204
205 for (size_t nCol = 0; nCol < m_iColumns; ++nCol)
208206 total += m_vMaxLengths[nCol];
207
209208 total += (m_iColumns -1) * 8;
210209 cout << "\t" << string(total, '-') << endl;
211210 }
212211
213 for (nRow = 0; nRow < m_nRow; ++nRow)
212 for (size_t nRow = 0; nRow < m_nRow; ++nRow)
214213 PrintRow(m_vTable[nRow]);
215214 }
216215
1919 #include <kopano/ECGuid.h>
2020
2121 #include <mapicode.h>
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
2622
2723 /* This is a copy from the definition in kcore.hpp. It's for internal use only as we
2824 * don't want to expose the format of the entry id. */
2020 #include "ECCache.h"
2121 #include <kopano/ECLogger.h>
2222 #include <kopano/stringutil.h>
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
27
2823
2924 ECCacheBase::ECCacheBase(const std::string &strCachename, size_type ulMaxSize, long lMaxAge)
3025 : m_strCachename(strCachename)
1919 #include <kopano/ECChannel.h>
2020 #include <kopano/stringutil.h>
2121 #include <csignal>
22 #ifdef LINUX
2322 #include <netdb.h>
2423 #include <sys/types.h>
2524 #include <sys/select.h>
2928 #include <netinet/in.h>
3029 #include <netinet/tcp.h>
3130 #include <arpa/inet.h>
31 #ifdef LINUX
3232 #include <linux/rtnetlink.h>
3333 #endif
3434
3535 #include <cerrno>
3636 #include <mapicode.h>
37
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #endif
41
4237
4338 #ifndef hrSuccess
4439 #define hrSuccess 0
9994 ssl_neg = true;
10095 }
10196
102 if (strcmp_ci(ssl_name, SSL_TXT_SSLV2) == 0)
97 if (strcasecmp(ssl_name, SSL_TXT_SSLV2) == 0)
10398 ssl_proto = 0x01;
104 else if (strcmp_ci(ssl_name, SSL_TXT_SSLV3) == 0)
99 else if (strcasecmp(ssl_name, SSL_TXT_SSLV3) == 0)
105100 ssl_proto = 0x02;
106 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1) == 0)
101 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1) == 0)
107102 ssl_proto = 0x04;
108103 #ifdef SSL_TXT_TLSV1_1
109 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1_1) == 0)
104 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1_1) == 0)
110105 ssl_proto = 0x08;
111106 #endif
112107 #ifdef SSL_TXT_TLSV1_2
113 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1_2) == 0)
108 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1_2) == 0)
114109 ssl_proto = 0x10;
115110 #endif
116111 else {
243238 SSL_free(lpSSL);
244239 lpSSL = NULL;
245240 }
246 closesocket(fd);
241 close(fd);
247242 }
248243
249244 HRESULT ECChannel::HrEnableTLS(ECLogger *const lpLogger) {
510505 int res = 0;
511506 struct timeval timeout = { seconds, 0 };
512507
513 #ifdef LINUX
514508 if(fd >= FD_SETSIZE)
515509 return MAPI_E_NOT_ENOUGH_MEMORY;
516 #endif
517510 if(lpSSL && SSL_pending(lpSSL))
518511 return hrSuccess;
519512
818811
819812 memset(&sun_addr, 0, sizeof(sun_addr));
820813 sun_addr.sun_family = AF_UNIX;
821 strncpy(sun_addr.sun_path, szPath, sizeof(sun_addr.sun_path));
814 kc_strlcpy(sun_addr.sun_path, szPath, sizeof(sun_addr.sun_path));
822815
823816 if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1) {
824817 if (lpLogger)
835828 if (bind(fd, (struct sockaddr *)&sun_addr, sizeof(sun_addr)) == -1) {
836829 if (lpLogger)
837830 lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to bind to socket %s (%s). This is usually caused by another process (most likely another kopano-server) already using this port. This program will terminate now.", szPath, strerror(errno));
838 #ifdef LINUX
839831 kill(0, SIGTERM);
840 #endif
841832 exit(1);
842833 }
843834
975966 if (sock_res != NULL)
976967 freeaddrinfo(sock_res);
977968 if (hr != hrSuccess && fd >= 0)
978 closesocket(fd);
969 close(fd);
979970 return hr;
980971 }
981972
2020 #include <mapidefs.h>
2121 #include <mapiutil.h>
2222 #include <mapix.h>
23
24 #ifdef LINUX
2523 #include <netdb.h>
2624 #include <arpa/inet.h>
2725 #include <netinet/in.h>
2826 #include <sys/un.h>
2927 #include <sys/socket.h>
30 #endif
31
3228 #include <kopano/base64.h>
3329 #include <kopano/ECChannel.h>
3430 #include <kopano/ECDefs.h>
132128
133129 exit:
134130 if (er != erSuccess && fd != -1)
135 closesocket(fd);
131 close(fd);
136132
137133 return er;
138134 }
161157 fd = socket(sock_addr->ai_family, sock_addr->ai_socktype,
162158 sock_addr->ai_protocol);
163159 if (fd < 0)
160 /* Socket type could not be created */
164161 continue;
165162
166163 if (connect(fd, sock_addr->ai_addr,
167164 sock_addr->ai_addrlen) < 0) {
165 /* No route */
168166 int saved_errno = errno;
169 closesocket(fd);
167 close(fd);
170168 fd = -1;
171169 errno = saved_errno;
172170 continue;
173171 }
172 /* Good connected socket, use it */
173 break;
174174 }
175175 if (fd < 0) {
176176 er = KCERR_NETWORK_ERROR;
187187 if (sock_res != NULL)
188188 freeaddrinfo(sock_res);
189189 if (er != erSuccess && fd != -1)
190 closesocket(fd);
190 close(fd);
191191
192192 return er;
193193 }
1818 #include "ECConfigImpl.h"
1919 #include <kopano/charset/convert.h>
2020
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
24
2521 ECConfig *ECConfig::Create(const configsetting_t *lpDefaults,
2622 const char *const *lpszDirectives)
2723 {
3329 convert_context converter;
3430 return LoadSettings(converter.convert_to<char*>(szFilename));
3531 }
36
3732
3833 /**
3934 * Get the default path for the configuration file specified with lpszBasename.
2121 #include <cstdlib>
2222 #include <algorithm>
2323 #include <cassert>
24 #ifdef LINUX
2524 #include <climits>
26 #endif
27
28 #include <algorithm>
2925 #include <kopano/stringutil.h>
3026 #include "ECConfigImpl.h"
3127
3329 #include <kopano/boost_compat.h>
3430
3531 using namespace std;
36
37 #ifdef _DEBUG
38 #define new DEBUG_NEW
39 #endif
4032
4133 #include <boost/filesystem.hpp>
4234 namespace fs = boost::filesystem;
509501 return true;
510502 }
511503
512
513504 bool ECConfigImpl::HandleInclude(const char *lpszArgs, unsigned int ulFlags)
514505 {
515506 string strValue;
542533 return false;
543534
544535 memset(lpsKey, 0, sizeof(*lpsKey));
545 strncpy(lpsKey->s, lpsSetting->szName, sizeof(lpsKey->s));
536 kc_strlcpy(lpsKey->s, lpsSetting->szName, sizeof(lpsKey->s));
546537 lpsKey->ulFlags = lpsSetting->ulFlags;
547538 lpsKey->ulGroup = lpsSetting->ulGroup;
548539
578569 if (szAlias) {
579570 if (!(ulFlags & LOADSETTING_INITIALIZING))
580571 warnings.push_back("Option '" + string(lpsConfig->szName) + "' is deprecated! New name for option is '" + szAlias + "'.");
581 strncpy(s.s, szAlias, sizeof(s.s));
572 kc_strlcpy(s.s, szAlias, sizeof(s.s));
582573 }
583574
584575 pthread_rwlock_wrlock(&m_settingsRWLock);
785776 return true;
786777 }
787778
788
789779 void ECConfigImpl::WriteLinesToFile(const char* szName, const char* szValue, ifstream& in, ofstream& out, bool bWriteAll)
790780 {
791781 string strLine;
2626 #include <mapidefs.h>
2727 #include <kopano/CommonUtil.h>
2828
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3229 #ifdef DEBUG
3330 #define DEBUG_SQL 0
3431 #define DEBUG_TRANSACTION 0
399396 return (unsigned int)mysql_num_rows((MYSQL_RES *)sResult);
400397 }
401398
402 unsigned int ECDatabaseMySQL::GetNumRowFields(DB_RESULT sResult) {
403
404 return mysql_num_fields((MYSQL_RES *)sResult);
405 }
406
407399 DB_ROW ECDatabaseMySQL::FetchRow(DB_RESULT sResult) {
408400
409401 return mysql_fetch_row((MYSQL_RES *)sResult);
508500 }
509501
510502 while ((lpDBRow = FetchRow(lpResult)) != NULL) {
511 if (stricmp(lpDBRow[0], "InnoDB") != 0)
503 if (strcasecmp(lpDBRow[0], "InnoDB") != 0)
512504 continue;
513505
514 if (stricmp(lpDBRow[1], "DISABLED") == 0) {
506 if (strcasecmp(lpDBRow[1], "DISABLED") == 0) {
515507 // mysql has run with innodb enabled once, but disabled this.. so check your log.
516508 m_lpLogger->Log(EC_LOGLEVEL_FATAL, "INNODB engine is disabled. Please re-enable the INNODB engine. Check your MySQL log for more information or comment out skip-innodb in the mysql configuration file.");
517509 er = KCERR_DATABASE_ERROR;
518510 goto exit;
519 } else if (stricmp(lpDBRow[1], "YES") != 0 && stricmp(lpDBRow[1], "DEFAULT") != 0) {
511 } else if (strcasecmp(lpDBRow[1], "YES") != 0 && strcasecmp(lpDBRow[1], "DEFAULT") != 0) {
520512 // mysql is incorrectly configured or compiled.
521513 m_lpLogger->Log(EC_LOGLEVEL_FATAL, "INNODB engine is not supported. Please enable the INNODB engine in the mysql configuration file.");
522514 er = KCERR_DATABASE_ERROR;
544536 const char *lpDatabase = lpConfig->GetSetting("mysql_database");
545537 const char *lpMysqlPort = lpConfig->GetSetting("mysql_port");
546538 const char *lpMysqlSocket = lpConfig->GetSetting("mysql_socket");
547
548539
549540 if(*lpMysqlSocket == '\0')
550541 lpMysqlSocket = NULL;
6262
6363 //Result functions
6464 unsigned int GetNumRows(DB_RESULT sResult);
65 unsigned int GetNumRowFields(DB_RESULT sResult);
66
6765 DB_ROW FetchRow(DB_RESULT sResult);
6866 DB_LENGTHS FetchRowLengths(DB_RESULT sResult);
6967
3535
3636 #include "freebusyguid.h"
3737
38 #include <kopano/stringutil.h>
39
4038 #include <iostream>
4139 #include <sstream>
4240 #include <kopano/mapi_ptr.h>
4341
4442 using namespace std;
4543
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
49
5044 #define RETURN_ERROR_CASE(x) \
5145 case x: \
5246 return (HR_FAILED(x) ? "FAILED: " #x : ((x == hrSuccess) ? #x : "WARNING: " #x));
5448 #define RETURN_CASE(x) \
5549 case x: \
5650 return #x;
57
5851
5952 #define RETURN_PROP_CASE(pt) case PROP_ID(pt): return((#pt))
6053
260253 {3, (GUID*)&KOPANO_STORE_DELEGATE_GUID, "Kopano Delegate Store"},
261254 {3, (GUID*)&GUID_NULL , "GUID_NULL"},
262255
263 #ifndef LINUX
264 {4, (GUID*)&IID_IExternalConnection, "IID_IExternalConnection"},
265 {4, (GUID*)&IID_IMarshal, "IID_IMarshal"},
266 // {4, (GUID*)&IID_IMarshal2, "IID_IMarshal2"},
267 {4, (GUID*)&IID_IMalloc, "IID_IMalloc"},
268 {4, (GUID*)&IID_IStdMarshalInfo, "IID_IStdMarshalInfo"},
269 {4, (GUID*)&IID_IStorage, "IID_IStorage"},
270 {4, (GUID*)&IID_IClassFactory, "IID_IClassFactory"},
271
272 #endif
273256 {4, (GUID*)&IID_IMSCapabilities, "IID_IMSCapabilities"},
274257 {4, (GUID*)&IID_IFolderSupport, "IID_IFolderSupport"},
275258 {4, (GUID*)&IID_IMessageRaw , "IID_IMessageRaw"},
305288 //End of list
306289 {0, NULL}
307290 };
308
309291
310292 std::string GetMAPIErrorDescription(HRESULT hResult)
311293 {
403385
404386 char szResult[DEBUGBUFSIZE+1];
405387
406 _snprintf(szResult, DEBUGBUFSIZE, "0x%08X", hResult);
388 snprintf(szResult, DEBUGBUFSIZE, "0x%08X", hResult);
407389
408390 return szResult;
409391 }
11171099
11181100 RETURN_PROP_CASE(PR_AUTO_ADD_NEW_SUBS);
11191101 RETURN_PROP_CASE(PR_NEW_SUBS_GET_AUTO_ADD);
1120
11211102
11221103 RETURN_PROP_CASE(PR_OFFLINE_FLAGS);
11231104 RETURN_PROP_CASE(PR_SYNCHRONIZE_FLAGS);
19171898 }
19181899 }//PropNameFromPropTag
19191900
1920
19211901 const char *RelationalOperatorToString(ULONG relop)
19221902 {
19231903 switch(relop) {
21422122 }
21432123
21442124 return strResult;
2145 }
2146
2147 std::string unicodetostr(const wchar_t *lpszW)
2148 {
2149 return convert_to<std::string>(lpszW);
21502125 }
21512126
21522127 std::string PropValueToString(const SPropValue *lpPropValue)
27372712 }
27382713
27392714 if (guidIDD.empty()) {
2740 _snprintf(szGuidId, DEBUGBUFSIZE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", iid.Data1, iid.Data2, iid.Data3, iid.Data4[0], iid.Data4[1], iid.Data4[2], iid.Data4[3], iid.Data4[4], iid.Data4[5], iid.Data4[6], iid.Data4[7]);
2715 snprintf(szGuidId, DEBUGBUFSIZE, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", iid.Data1, iid.Data2, iid.Data3, iid.Data4[0], iid.Data4[1], iid.Data4[2], iid.Data4[3], iid.Data4[4], iid.Data4[5], iid.Data4[6], iid.Data4[7]);
27412716 guidIDD = "Unknown ";
27422717 guidIDD+=szGuidId;
27432718 }
2744
27452719
27462720 return guidIDD;
27472721 }
27712745 {
27722746 std::string str;
27732747 ULONG i;
2774
27752748
27762749 if(ppNames == NULL)
27772750 return "NULL";
2222
2323 using namespace std;
2424
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
29
3025 namespace details {
3126 string conversion_helpers<string>::convert_from(const wstring &s) {
3227 return convert_to<string>(s);
4338 const string conversion_helpers<string>::strNULL = "NULL";
4439 const string conversion_helpers<string>::strCOMMA= ",";
4540
46
4741 wstring conversion_helpers<wstring>::convert_from(const string &s) {
4842 return convert_to<wstring>(s);
4943 }
1616
1717 #include <kopano/platform.h>
1818 #include "ECFifoBuffer.h"
19
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #endif
2319
2420 ECFifoBuffer::ECFifoBuffer(size_type ulMaxSize)
2521 : m_ulMaxSize(ulMaxSize)
2424
2525 #include <pthread.h>
2626 #include <cassert>
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
3127
3228 namespace detail {
3329
117113
118114 } // namespace detail
119115
120
121116 /**
122117 * Performs a 'regular' gettext and converts the result to a wide character string.
123118 *
1717 #include <kopano/platform.h>
1818 #include <kopano/ECIConv.h>
1919
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #endif
23
2420 ECIConv::ECIConv(const std::string &strToCharset, const std::string &strFromCharset) {
2521 try {
2622 m_lpContext = new context_t(strToCharset.c_str(), strFromCharset.c_str());
1818 #include <cassert>
1919 #include <kopano/ECKeyTable.h>
2020 #include <kopano/ustringutil.h>
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
2421
2522 bool operator!=(const sObjectTableKey& a, const sObjectTableKey& b)
2623 {
10198 void ECTableRow::initSortCols(unsigned int ulSortCols, const int *lpSortLen,
10299 const unsigned char *lpFlags, unsigned char **lppSortData)
103100 {
104 unsigned int i=0;
105101 int len = 0;
106102
107103 this->ulSortCols = ulSortCols;
121117 memcpy(this->lpSortLen, lpSortLen, sizeof(unsigned int) * ulSortCols);
122118
123119 // Copy sort keys
124 for (i = 0; i < ulSortCols; ++i) {
120 for (unsigned int i = 0; i < ulSortCols; ++i) {
125121 len = lpSortLen[i];
126122 len = len < 0 ? -len : len;
127123
315311 // The start of bookmark, the first 3 (0,1,2) are default
316312 m_ulBookmarkPosition = 3;
317313
318
319314 // g++ doesn't like static initializers on existing variables
320315 pthread_mutexattr_t mattr;
321316 pthread_mutexattr_init(&mattr);
838833 return erSuccess;
839834 }
840835
841
842836 ECRESULT ECKeyTable::SeekRow(unsigned int lbkOrgin, int lSeekTo, int *lplRowsSought)
843837 {
844838 ECRESULT er = erSuccess;
846840 unsigned int ulCurrentRow = 0;
847841 unsigned int ulRowCount = 0;
848842 ECTableRow *lpRow = NULL;
849
850843
851844 pthread_mutex_lock(&mLock);
852845
2525 #include <zlib.h>
2626 #include <kopano/stringutil.h>
2727 #include "charset/localeutil.h"
28
29 #ifdef LINUX
3028 #include "config.h"
3129 #include <poll.h>
3230 #if HAVE_SYSLOG_H
4038 #include <sys/time.h>
4139 #include <sys/types.h>
4240 #include <sys/utsname.h>
43 #endif
44
4541 #include <kopano/ECConfig.h>
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
4942
5043 using namespace std;
5144
173166 void ECLogger_Null::LogVA(unsigned int loglevel, const char *format, va_list& va) {}
174167
175168 /**
176 * ECLogger_File constructor
177 *
178169 * @param[in] max_ll max loglevel passed to ECLogger
179170 * @param[in] add_timestamp true if a timestamp before the logmessage is wanted
180171 * @param[in] filename filename of log in current locale
395386 Log(loglevel, std::string(msgbuffer));
396387 }
397388
398 #ifdef LINUX
399389 ECLogger_Syslog::ECLogger_Syslog(unsigned int max_ll, const char *ident, int facility) : ECLogger(max_ll) {
400390 /*
401391 * Because @ident can go away, and openlog(3) does not make a copy for
454444 syslog(levelmap[loglevel & EC_LOGLEVEL_MASK], "%s", msgbuffer);
455445 #endif
456446 }
457 #endif
458
459 /**
460 * Consructor
461 */
447
462448 ECLogger_Tee::ECLogger_Tee(): ECLogger(EC_LOGLEVEL_DEBUG) {
463449 }
464450
465451 /**
466 * Destructor
467 *
468452 * The destructor calls Release on each attached logger so
469453 * they'll be deleted if it was the last reference.
470454 */
556540 }
557541 }
558542
559 #ifdef LINUX
560543 ECLogger_Pipe::ECLogger_Pipe(int fd, pid_t childpid, int loglevel) : ECLogger(loglevel) {
561544 m_fd = fd;
562545 m_childpid = childpid;
704687 static int PipePassLoop(int readfd, ECLogger_File *lpFileLogger,
705688 ECConfig *lpConfig)
706689 {
707 int ret = 0;
690 ssize_t ret;
708691 char buffer[_LOG_BUFSIZE] = {0};
709692 std::string complete;
710693 const char *p = NULL;
762745 do {
763746 // if we don't read anything from the fd, it was the end
764747 ret = read(readfd, buffer, sizeof buffer);
765
748 if (ret <= 0)
749 break;
766750 complete.append(buffer,ret);
767751 } while (ret == sizeof buffer);
768752
814798 ECLogger_Pipe *lpPipeLogger = NULL;
815799 int filefd;
816800 int pipefds[2];
817 int t, i;
818801 pid_t child = 0;
819802
820803 if (lpFileLogger == NULL)
832815
833816 if (child == 0) {
834817 // close all files except the read pipe and the logfile
835 t = getdtablesize();
836 for (i = 3; i < t; ++i) {
818 int t = getdtablesize();
819 for (int i = 3; i < t; ++i) {
837820 if (i == pipefds[0] || i == filefd) continue;
838821 close(i);
839822 }
862845
863846 return lpPipeLogger;
864847 }
865 #endif
866848
867849 /**
868850 * Create ECLogger object from configuration.
880862 ECLogger *lpLogger = NULL;
881863 string prepend;
882864 int loglevel = 0;
883
884 #ifdef LINUX
885865 int syslog_facility = LOG_MAIL;
886 #endif
887866
888867 if (bAudit) {
889 #ifdef LINUX
868 #if 1 /* change to ifdef HAVE_LOG_AUTHPRIV */
890869 if (!parseBool(lpConfig->GetSetting("audit_log_enabled")))
891870 return NULL;
892871 prepend = "audit_";
898877
899878 loglevel = strtol(lpConfig->GetSetting((prepend+"log_level").c_str()), NULL, 0);
900879
901 if (stricmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "syslog") == 0) {
902 #ifdef LINUX
880 if (strcasecmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "syslog") == 0) {
903881 char *argzero = strdup(argv0);
904882 lpLogger = new ECLogger_Syslog(loglevel, basename(argzero), syslog_facility);
905883 free(argzero);
906 #else
907 fprintf(stderr, "syslog logging is only available on linux.\n");
908 #endif
909 } else if (stricmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "eventlog") == 0) {
884 } else if (strcasecmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "eventlog") == 0) {
910885 fprintf(stderr, "eventlog logging is only available on windows.\n");
911 } else if (stricmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "file") == 0) {
886 } else if (strcasecmp(lpConfig->GetSetting((prepend+"log_method").c_str()), "file") == 0) {
912887 int ret = 0;
913 #ifdef LINUX
914888 const struct passwd *pw = NULL;
915889 const struct group *gr = NULL;
916890 if (strcmp(lpConfig->GetSetting((prepend+"log_file").c_str()), "-")) {
952926 }
953927 }
954928 }
955 #endif
956929 if (ret == 0) {
957930 bool logtimestamp = parseBool(lpConfig->GetSetting((prepend + "log_timestamp").c_str()));
958931
963936 ECLogger_File *log = new ECLogger_File(loglevel, logtimestamp, lpConfig->GetSetting((prepend + "log_file").c_str()), false);
964937 log->reinit_buffer(log_buffer_size);
965938 lpLogger = log;
966 #ifdef LINUX
967939 // chown file
968940 if (pw || gr) {
969941 uid_t uid = -1;
974946 gid = gr->gr_gid;
975947 chown(lpConfig->GetSetting((prepend+"log_file").c_str()), uid, gid);
976948 }
977 #endif
978949 } else {
979950 fprintf(stderr, "Not enough permissions to append logfile '%s'. Reverting to stderr.\n", lpConfig->GetSetting((prepend+"log_file").c_str()));
980951 bool logtimestamp = parseBool(lpConfig->GetSetting((prepend + "log_timestamp").c_str()));
2121 #include "ECMemStream.h"
2222 #include <kopano/Trace.h>
2323 #include <kopano/ECDebug.h>
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
29 /*
30 * ECMemBlock implementation
31 *
32 */
33
3424 #define EC_MEMBLOCK_SIZE 8192
3525
3626 ECMemBlock::ECMemBlock(char *buffer, ULONG ulDataLen, ULONG ulFlags) : ECUnknown("ECMemBlock")
113103 memset(lpCurrent+cbTotal, 0, newsize-cbTotal); // clear new alloced mem
114104 cbTotal = newsize; // set new size
115105 }
116
117106
118107 if (dsize > cbCurrent) // if write part is bigger than actual data
119108 cbCurrent = ulPos + ulLen; // set _real_ buffer size
525514 HRESULT ECMemStream::xStream::QueryInterface(REFIID refiid, LPVOID *lppInterface)
526515 {
527516 char szGuidId[1024+1];
528 _snprintf(szGuidId, 1024, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", refiid.Data1, refiid.Data2, refiid.Data3, refiid.Data4[0], refiid.Data4[1], refiid.Data4[2], refiid.Data4[3], refiid.Data4[4], refiid.Data4[5], refiid.Data4[6], refiid.Data4[7]);
517 snprintf(szGuidId, 1024, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", refiid.Data1, refiid.Data2, refiid.Data3, refiid.Data4[0], refiid.Data4[1], refiid.Data4[2], refiid.Data4[3], refiid.Data4[4], refiid.Data4[5], refiid.Data4[6], refiid.Data4[7]);
529518
530519 TRACE_STREAM(TRACE_ENTRY, "IStream::QueryInterface", "%s", szGuidId);
531520 METHOD_PROLOGUE_(ECMemStream, Stream);
534523 return hr;
535524 }
536525
537
538526 HRESULT ECMemStream::xStream::Read(void *pv, ULONG cb, ULONG *pcbRead)
539527 {
540528 TRACE_STREAM(TRACE_ENTRY, "IStream::Read", "size=%d", cb);
1616
1717 #include <kopano/platform.h>
1818 #include <kopano/ECScheduler.h>
19 #ifdef LINUX
20 // ETIMEDOUT in linux is in errno, windows has this though pthread.h
2119 #include <cerrno>
22 #endif
2320 #include <sys/time.h> /* gettimeofday */
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
2821
2922 #define SCHEDULER_POLL_FREQUENCY 5
3023
1515 */
1616
1717 #include <kopano/platform.h>
18
19 #ifdef LINUX
2018 #include <arpa/inet.h>
21 #endif
22
2319 #include "ECFifoBuffer.h"
2420 #include "ECSerializer.h"
25
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #endif
29
3021
3122 ECStreamSerializer::ECStreamSerializer(IStream *lpBuffer)
3223 {
2222
2323 #include <kopano/ECUnknown.h>
2424 #include <kopano/ECGuid.h>
25
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #endif
2925
3026 ECUnknown::ECUnknown(const char *szClassName)
3127 {
523523 return wcscmp( e1->s, e2->s );
524524 }
525525
526
527526 static int compareHTMLEntityToName(const void *m1, const void *m2)
528527 {
529528 const HTMLEntityToName_t *e1 = static_cast<const HTMLEntityToName_t *>(m1);
626625 return false;
627626
628627 std::wstring str;
629 int base = 10;
630628
631629 if (strEntity[1] == '#') {
630 int base = 10;
632631 str = strEntity.substr(2, pos-2);
633632
634633 if(str[0] == 'x')
1818 #include "HtmlToTextParser.h"
1919 #include "HtmlEntity.h"
2020 #include <cwctype>
21
2221
2322 CHtmlToTextParser::CHtmlToTextParser(void)
2423 {
338337 addNewLine( true );
339338 }
340339
341
342340 void CHtmlToTextParser::parseTagBR()
343341 {
344342 addNewLine( true );
1515 noinst_DATA = \
1616 libkcutil.ldd libkcmapi.ldd \
1717 libkcssl.ldd libkcservice.ldd
18 CLEANFILES = ${noinst_DATA}
1819
1920 #
2021 # libkcutil
2222 #include <openssl/ssl.h>
2323 #include <openssl/conf.h>
2424 #include <openssl/engine.h>
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
2925
3026 static pthread_mutex_t *ssl_locks;
3127
157157 }
158158 pthread_mutex_destroy(&mapsLock);
159159
160 closesocket(fd);
160 close(fd);
161161
162162 logger -> Log(EC_LOGLEVEL_DEBUG, "StatsClient terminated");
163163 }
3737 * @retval true The provided string was encrypted.
3838 * @retval false The provided string was not encrypted.
3939 */
40 #ifdef _DEBUG
41 #define new DEBUG_NEW
42 #endif
4340
4441 bool SymmetricIsCrypted(const char *c)
4542 {
6461 bool SymmetricIsCrypted(const wchar_t *c)
6562 {
6663 return wcsncmp(c, L"{1}:", 4) == 0 || wcsncmp(c, L"{2}:", 4) == 0;
67 }
68
69 /**
70 * Crypt a pasword using algorithm 2.
71 *
72 * @param[in] strPlain
73 * The string to encrypt.
74 *
75 * @return The encrypted string encoded in UTF-8.
76 */
77 std::string SymmetricCrypt(const std::wstring &strPlain)
78 {
79 std::string u = convert_to<std::string>("UTF-8", strPlain, rawsize(strPlain), CHARSET_WCHAR);
80 size_t z = u.size();
81
82 for (size_t i = 0; i < z; ++i)
83 u[i] ^= 0xA5;
84 // Do the base64 encode
85 return "{2}:" + base64_encode(reinterpret_cast<const unsigned char *>(u.c_str()), z);
86 }
87
88 /**
89 * Crypt a pasword using algorithm 2.
90 *
91 * @param[in] strPlain
92 * The string to encrypt.
93 *
94 * @return The encrypted string encoded in UTF-16/32 (depending on type of wchar_t).
95 */
96 std::wstring SymmetricCryptW(const std::wstring &strPlain)
97 {
98 return convert_to<std::wstring>(SymmetricCrypt(strPlain));
9964 }
10065
10166 /**
165130 return SymmetricDecryptBlob(wstrCrypted[1] - '0',
166131 base64_decode(convert_to<std::string>(wstrCrypted + 4)));
167132 }
168
169 /**
170 * Decrypt an encrypted password.
171 *
172 * Depending on the N value, the password is decrypted using algorithm 1 or 2.
173 *
174 * @param[in] strCrypted
175 * The encrypted password to decrypt.
176 *
177 * @return THe decrypted password encoded in in UTF-16/32 (depending on type of wchar_t).
178 */
179 std::wstring SymmetricDecryptW(const wchar_t *wstrCrypted)
180 {
181 const std::string strDecrypted = SymmetricDecrypt(wstrCrypted);
182 return convert_to<std::wstring>(strDecrypted, rawsize(strDecrypted), "UTF-8");
183 }
1919
2020 bool SymmetricIsCrypted(const wchar_t *);
2121 bool SymmetricIsCrypted(const char *);
22
23 std::string SymmetricCrypt(const std::wstring &strPlain);
24 std::wstring SymmetricCryptW(const std::wstring &strPlain);
25
2622 std::string SymmetricDecrypt(const char *strCrypted);
2723 std::string SymmetricDecrypt(const wchar_t *wstrCrypted);
28 std::wstring SymmetricDecryptW(const wchar_t *wstrCrypted);
2924
3025 #endif
1717 #include <kopano/platform.h>
1818
1919 #include "TimeUtil.h"
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
2420
2521 /**
2622 * Get a timestamp for the given date/time point
1919 #include <cstdio>
2020 #include <cstdarg>
2121 #include <kopano/Trace.h>
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
2622
2723 #ifdef WITH_TRACING
2824 // Turn these on/off
8783 break;
8884 }
8985
90
91 pos = _snprintf(debug, sizeof(debug), "%lu %08X %s %s: %s(", GetTickCount(), GetCurrentThreadId(), lpMsg, lpTraceType, func);
86 pos = snprintf(debug, sizeof(debug), "%lu %08X %s %s: %s(", GetTickCount(), GetCurrentThreadId(), lpMsg, lpTraceType, func);
9287
9388 len = pos + 3;
9489
9590 if (format) {
9691 va_copy(va_lentest, va);
97 #ifdef LINUX
9892 len += _vsnprintf(NULL, 0, format, va_lentest);
99 #else
100 len += _vscprintf(format, va_lentest);
101 #endif
10293 va_end(va_lentest);
10394 }
10495
200191 va_end(va);
201192 }
202193
203
204194 void TraceStream(int time, const char *func, const char *format, ...)
205195 {
206196 va_list va;
1717 #include <kopano/platform.h>
1818 #include <kopano/base64.h>
1919 #include <cctype>
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
2420
2521 static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2622
2626 #include <cerrno>
2727 #define BUFSIZE 4096
2828
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
32
3329 convert_exception::convert_exception(enum exception_type type, const std::string &message)
3430 : std::runtime_error(message)
3531 , m_type(type)
4238 illegal_sequence_exception::illegal_sequence_exception(const std::string &message)
4339 : convert_exception(eIllegalSequence, message)
4440 {}
45
4641
4742 namespace details {
4843
133128 m_bForce = true;
134129 } else if (*i == "NOIGNORE" || *i == "NOFORCE") {
135130 m_bForce = false;
136 } else if(*i == "HTMLENTITIES" && stricmp(fromcode, CHARSET_WCHAR) == 0) {
131 } else if(*i == "HTMLENTITIES" && strcasecmp(fromcode, CHARSET_WCHAR) == 0) {
137132 m_bHTML = true;
138133 } else vOptionsFiltered.push_back(*i);
139134 ++i;
144139 strto += join(vOptionsFiltered.begin(), vOptionsFiltered.end(), std::string(","));
145140 }
146141 }
147
148142
149143 m_cd = iconv_open(strto.c_str(), fromcode);
150144 if (m_cd == (iconv_t)(-1))
1717 #include <kopano/platform.h>
1818 #include <kopano/charset/convstring.h>
1919
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #endif
23
2420 /** Create a convstring instance from a SPropValue.
2521 *
2622 * Extarcts the lpszA or lpszW depending on the PROP_TYPE of the provided
7369 return from_SPropValue(&sPropVal, bCheapCopy);
7470 }
7571
76 /** Default constructor
77 *
78 * Creates an empty convstring
79 */
8072 convstring::convstring()
8173 : m_lpsz(NULL)
8274 , m_ulFlags(0)
8375 {}
8476
85 /** Copy constructor
86 *
77 /**
8778 * Create a new convstring object based on another convstring object.
8879 *
8980 * @param[in] other
217208 }
218209 }
219210
220
221211 /** Check if the convstring is initialized with a NULL pointer or with an empty string.
222212 *
223213 * @return A boolean specifying of the internal string is a NULL pointer or an empty string.
275265 return (m_lpsz ? convert_to<char*>() : NULL);
276266 }
277267
278
279268 /**
280269 * Convert this convstring object to a raw wchar_t pointer.
281270 *
289278 return (m_lpsz ? convert_to<wchar_t*>() : NULL);
290279 }
291280
292
293281 /**
294282 * Convert this convstring object to a raw char pointer encoded in UTF-8.
295283 *
1818 #include <kopano/charset/utf16string.h>
1919 #include "utf32string.h"
2020
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
24
2521 /**
2622 * Make charset string ignore invalid characters, possebly converting
2723 * them with '?' character in iconv.
4137 return len;
4238 }
4339
44 #ifdef LINUX
4540 size_t iconv_charset<unsigned short*>::rawsize(const unsigned short *from) {
4641 return ucslen(from) * sizeof(unsigned short);
4742 }
4944 size_t iconv_charset<const unsigned short*>::rawsize(const unsigned short *from) {
5045 return ucslen(from) * sizeof(unsigned short);
5146 }
52
53 #else
54 size_t iconv_charset<unsigned int*>::rawsize(const unsigned int *from) {
55 return ucslen(from) * sizeof(unsigned int);
56 }
57
58 size_t iconv_charset<const unsigned int*>::rawsize(const unsigned int *from) {
59 return ucslen(from) * sizeof(unsigned int);
60 }
61
62 #endif
2020 #include <kopano/zcdefs.h>
2121 #include <kopano/charset/traits.h>
2222
23 #ifdef LINUX
2423 // The utf32string type
2524 typedef std::wstring utf32string;
2625
27 #else
28 // The utf32string type
29 typedef std::basic_string<unsigned int> utf32string;
30
31 namespace std {
32
33 template<>
34 struct char_traits<unsigned int>
35 {
36 typedef unsigned int char_type;
37 typedef wint_t int_type;
38 typedef streamoff off_type;
39 typedef wstreampos pos_type;
40 typedef mbstate_t state_type;
41
42 static void
43 assign(char_type& __c1, const char_type& __c2)
44 { __c1 = __c2; }
45
46 static bool
47 eq(const char_type& __c1, const char_type& __c2)
48 { return __c1 == __c2; }
49
50 static bool
51 lt(const char_type& __c1, const char_type& __c2)
52 { return __c1 < __c2; }
53
54 static int
55 compare(const char_type* __s1, const char_type* __s2, size_t __n)
56 { while(*__s1 != 0 && *__s2 != 0 && __n != 0) {
57 if(*__s1 != *__s2) return *__s1 - *__s2;
58 ++__s1;
59 ++__s2;
60 --__n;
61 }
62 if((*__s1 == 0 && *__s2 == 0) || __n == 0) return 0;
63 if(*__s1 != 0) return -1;
64 return 1;
65 }
66
67 static size_t
68 length(const char_type* __s)
69 { int l = 0;
70 while (*__s != 0) { ++l; ++__s; }
71 return l;
72 }
73
74 static const char_type*
75 find(const char_type* __s, size_t __n, const char_type& __a)
76 { while(*__s != 0 && __n > 0) {
77 if(*__s == __a) return __s;
78 ++__s; --__n;
79 }
80 return NULL;
81 }
82
83 static char_type*
84 move(char_type* __s1, const char_type* __s2, int_type __n)
85 { return (unsigned int *)memmove((void *)__s1, (void *)__s2, __n*sizeof(unsigned int)); }
86
87 static char_type*
88 copy(char_type* __s1, const char_type* __s2, size_t __n)
89 { return (unsigned int *)memcpy((void *)__s1, (void *)__s2, __n*sizeof(unsigned int)); }
90
91 static char_type*
92 assign(char_type* __s, size_t __n, char_type __a)
93 { char_type *__o = __s;
94 while (__n > 0) { *__s = __a; --__n; ++__s; }
95 return __o;
96 }
97
98 static char_type
99 to_char_type(const int_type& __c) { return char_type(__c); }
100
101 static int_type
102 to_int_type(const char_type& __c) { return int_type(__c); }
103
104 static bool
105 eq_int_type(const int_type& __c1, const int_type& __c2)
106 { return __c1 == __c2; }
107
108 static int_type
109 eof() { return static_cast<int_type>(-1); }
110
111 static int_type
112 not_eof(const int_type& __c)
113 { return eq_int_type(__c, eof()) ? 0 : __c; }
114 };
115 }
116
117 // 32-bit character specializations
118 template <>
119 class iconv_charset<utf32string> _zcp_final {
120 public:
121 static const char *name() {
122 return "UTF-32LE";
123 }
124 static const char *rawptr(const utf32string &from) {
125 return reinterpret_cast<const char*>(from.c_str());
126 }
127 static size_t rawsize(const utf32string &from) {
128 return from.size() * sizeof(utf32string::value_type);
129 }
130 };
131
132 template <>
133 class iconv_charset<unsigned int *> _zcp_final {
134 public:
135 static const char *name() {
136 return "UTF32LE//TRANSLIT";
137 }
138 static const char *rawptr(const unsigned int *from) {
139 return reinterpret_cast<const char*>(from);
140 }
141 static size_t rawsize(const unsigned int *from);
142 };
143
144 template <>
145 class iconv_charset<const unsigned int *> _zcp_final {
146 public:
147 static const char *name() {
148 return "UTF32LE//TRANSLIT";
149 }
150 static const char *rawptr(const unsigned int *from) {
151 return reinterpret_cast<const char*>(from);
152 }
153 static size_t rawsize(const unsigned int *from);
154 };
155
156 #endif
157
15826 #endif // ndef utf32string_INCLUDED
2020 #include <mapicode.h>
2121
2222 #include <kopano/codepage.h>
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
2723
2824 // These charset should all be supported by iconv
2925
114110 HRESULT HrGetCPByCharset(const char *lpszCharset,ULONG *codepage)
115111 {
116112 for (size_t i = 0; i < ARRAY_SIZE(CPMAP); ++i) {
117 if(stricmp(CPMAP[i].charset, lpszCharset) == 0) {
113 if(strcasecmp(CPMAP[i].charset, lpszCharset) == 0) {
118114 *codepage = CPMAP[i].codepage;
119115 return hrSuccess;
120116 }
1313 #include <mapidefs.h>
1414 class I {
1515 public:
16 virtual ~I(void) {}
1617 /* ptr-to-non-const on purpose */
1718 virtual void SetProps(SPropValue *, size_t) {}
1819 };
4546 else
4647 obj = new Y();
4748 obj->SetProps(prop, ARRAY_SIZE(prop));
49 memset(prop, '\0', sizeof(prop));
50 delete obj;
4851 return 0;
4952 }
2323 #include <kopano/ECIConv.h>
2424 #include <kopano/ECLogger.h>
2525
26 #include <mapicode.h> // only for MAPI error codes
27 #include <mapidefs.h> // only for MAPI error codes
28
29 #ifdef LINUX
26 #include <mapicode.h>
27 #include <mapidefs.h>
3028 #include <sys/mman.h>
3129 #include <sys/socket.h>
3230 #include <sys/stat.h>
3331 #include <arpa/inet.h>
34 #endif
3532 #include "fileutil.h"
36
37 #ifdef _DEBUG
38 #define new DEBUG_NEW
39 #endif
4033
4134 #define BLOCKSIZE 65536
4235
123116
124117 *lpImmap = false;
125118
126 #ifdef LINUX
127119 /* Try mmap first */
128120 if (fstat(fd, &stat) != 0) {
129121 perror("Stat failed");
138130 *lpSize = stat.st_size;
139131 return hrSuccess;
140132 }
141 #endif /* LINUX */
142133
143134 /* mmap failed (probably reading from STDIN as a stream), just read the file into memory, and return that */
144135 lpBuffer = (char*)malloc(BLOCKSIZE); // will be deleted as soon as possible
185176 */
186177 HRESULT HrUnmapFileBuffer(char *lpBuffer, int ulSize, bool bImmap)
187178 {
188 #ifdef LINUX
189179 if (bImmap)
190180 munmap(lpBuffer, mmapsize(ulSize));
191181 else
192 #endif
193182 free(lpBuffer);
194
195183 return hrSuccess;
196184 }
197185
290278
291279 return bResult;
292280 }
293
294 /**
295 * Convert file from UCS2 to UTF8
296 *
297 * @param[in] strSrcFileName Source filename
298 * @param[in] strDstFileName Destination filename
299 */
300 bool ConvertFileFromUCS2ToUTF8(const std::string &strSrcFileName, const std::string &strDstFileName)
301 {
302 bool bResult = false;
303 int ulBufferSize = 0;
304 FILE *pfSrc = NULL;
305 FILE *pfDst = NULL;
306 char *lpBuffer = NULL;
307 bool bImmap = false;
308 std::string strConverted;
309
310 pfSrc = fopen(strSrcFileName.c_str(), "rb");
311 if(pfSrc == NULL) {
312 ec_log_err("%s: Unable to open file \"%s\": %s", __PRETTY_FUNCTION__, strSrcFileName.c_str(), strerror(errno));
313 goto exit;
314 }
315
316 // create new file
317 pfDst = fopen(strDstFileName.c_str(), "wb");
318 if(pfDst == NULL) {
319 ec_log_err("%s: Unable to create file \"%s\": %s", __PRETTY_FUNCTION__, strDstFileName.c_str(), strerror(errno));
320 goto exit;
321 }
322
323 if(HrMapFileToBuffer(pfSrc, &lpBuffer, &ulBufferSize, &bImmap))
324 goto exit;
325
326 try {
327 strConverted = convert_to<std::string>("UTF-8", lpBuffer, ulBufferSize, "UCS-2//IGNORE");
328 } catch (const std::runtime_error &) {
329 goto exit;
330 }
331
332 if (fwrite(strConverted.c_str(), 1, strConverted.size(), pfDst) != strConverted.size()) {
333 ec_log_crit("%s: Unable to write to file \"%s\": %s", __PRETTY_FUNCTION__, strDstFileName.c_str(), strerror(errno));
334 goto exit;
335 }
336
337 bResult = true;
338
339 exit:
340 if (lpBuffer)
341 HrUnmapFileBuffer(lpBuffer, ulBufferSize, bImmap);
342
343 if (pfSrc)
344 fclose(pfSrc);
345
346 if (pfDst)
347 fclose(pfDst);
348
349 return bResult;
350 }
2626
2727 bool DuplicateFile(FILE *lpFile, std::string &strFileName);
2828
29 bool ConvertFileFromUCS2ToUTF8(const std::string &strSrcFileName, const std::string &strDstFileName);
30
3129 #endif
6565 std::string NotificationToString(ULONG cNotification, const NOTIFICATION *lpNotification);
6666
6767 std::string ProblemArrayToString(const SPropProblemArray *lpProblemArray);
68 std::string unicodetostr(const wchar_t *lpszW);
6968
7069 const char *MsgServiceContextToString(ULONG ulContext);
7170 const char *ResourceTypeToString(ULONG ulResourceType);
259259 /**
260260 * Linux syslog logger. Output is whatever syslog does, probably LC_CTYPE.
261261 */
262 #ifdef LINUX
263262 class ECLogger_Syslog _zcp_final : public ECLogger {
264263 private:
265264 char *m_ident;
274273 virtual void Log(unsigned int loglevel, const char *format, ...) _zcp_override __LIKE_PRINTF(3, 4);
275274 virtual void LogVA(unsigned int loglevel, const char *format, va_list &va) _zcp_override;
276275 };
277 #endif
278
279 #ifdef LINUX
276
280277 /**
281278 * Pipe Logger, only used by forked model processes. Redirects every
282279 * log message to an ECLogger_File object. This ECLogger_Pipe object
301298 };
302299
303300 ECLogger* StartLoggerProcess(ECConfig *lpConfig, ECLogger *lpFileLogger);
304 #endif
305301
306302 /**
307303 * This class can be used if log messages need to go to
4848 #define TRACE_STREAM TraceStream
4949 #define TRACE_EXT TraceExt
5050 #else
51 # ifdef LINUX
5251 # define TRACE_MAPI(...)
5352 # define TRACE_MAPILIB(...)
5453 # define TRACE_ECMAPI(...)
5756 # define TRACE_SOAP(...)
5857 # define TRACE_STREAM(...)
5958 # define TRACE_EXT(...)
60 # else
61 # define TRACE_MAPI __noop
62 # define TRACE_MAPILIB __noop
63 # define TRACE_ECMAPI __noop
64 # define TRACE_NOTIFY __noop
65 # define TRACE_INTERNAL __noop
66 # define TRACE_SOAP __noop
67 # define TRACE_STREAM __noop
68 # define TRACE_EXT __noop
69 # endif
7059 #endif
7160
7261 #endif // TRACE_H
1616
1717 #ifndef __UNIXUTIL_H
1818 #define __UNIXUTIL_H
19
20 #ifdef LINUX
2119
2220 #include <sys/resource.h>
2321
5048 extern bool unix_system(const char *szLogName, const char *command, const char **env);
5149
5250 #endif
53
54 #endif
2323
2424 #include <kopano/charset/traits.h>
2525
26 #ifdef LINUX
2726 typedef unsigned short UTF16_CHAR;
2827 typedef std::basic_string<unsigned short> utf16string;
2928
150149 static size_t rawsize(const unsigned short *from);
151150 };
152151
153 #else
154 typedef wchar_t UTF16_CHAR;
155
156 // The utf16string type
157 typedef std::wstring utf16string;
158
159 #endif
160
161152 #endif //ndef utf16string_INCLUDED
8181 HRESULT UnixTimeToRTime(time_t unixtime, LONG *rtime);
8282 HRESULT RTimeToUnixTime(LONG rtime, time_t *unixtime);
8383 extern time_t SystemTimeToUnixTime(const SYSTEMTIME &);
84 SYSTEMTIME UnixTimeToSystemTime(time_t unixtime);
8584 extern SYSTEMTIME TMToSystemTime(const struct tm &);
86 extern struct tm SystemTimeToTM(const SYSTEMTIME &);
8785 double GetTimeOfDay();
8886 ULONG CreateIntDate(ULONG day, ULONG month, ULONG year);
8987 ULONG CreateIntTime(ULONG seconds, ULONG minutes, ULONG hours);
9088 extern ULONG FileTimeToIntDate(const FILETIME &);
9189 ULONG SecondsToIntTime(ULONG seconds);
92
93 int strcmp_ci(const char *s1, const char *s2);
9490
9591 inline double difftimeval(struct timeval *ptstart, struct timeval *ptend) {
9692 return 1000000 * (ptend->tv_sec - ptstart->tv_sec) + (ptend->tv_usec - ptstart->tv_usec);
156152
157153 bool force_buffers_to_disk(const int fd);
158154 extern int ec_relocate_fd(int);
155 extern int kc_reexec_with_allocator(char **, const char *);
159156
160157 #endif // PLATFORM_H
5757 #define ASSERT assert
5858 #define _ASSERT assert
5959
60 #ifdef _DEBUG
61 #error _DEBUG is defined in linux, which should not be used!
62 #endif
63
6460 #define _vsnprintf vsnprintf
65 #define _snprintf snprintf
6661 #ifdef HAVE_VSNPRINTF_L
6762 #define _vsnprintf_l vsnprintf_l
6863 #else
8580
8681 #define STDAPI_(__type) __type __stdcall
8782
88 /* Defines for some windows function that have a different name in Linux */
89 #define _snprintf snprintf
90 #define strnicmp strncasecmp
91 #define stricmp strcasecmp
92
93 #define _atoi64 atoll
94
95 #define CreateDir(dir, mode) mkdir(dir, mode)
96 #define closesocket(fd) close(fd)
97
9883 /* base types */
99 #include <sys/types.h>
10084 typedef void VOID;
10185 typedef unsigned char BYTE;
10286 typedef unsigned char UCHAR;
583567 bool operator==(REFIID, const GUID &);
584568 HRESULT CoCreateGuid(LPGUID);
585569
586 __int64_t Int32x32To64(ULONG, ULONG);
587
588570 void GetSystemTimeAsFileTime(FILETIME *ft);
589571 DWORD GetTempPath(DWORD inLen, char *lpBuffer);
590 #define GetTempPathA GetTempPath
591
592 #define utf32len wcslen
593572
594573 /* Some wrappers to map Windows unicode functions */
595574 static inline int lstrcmpW(LPCWSTR str1, LPCWSTR str2)
617596 #define _tcslen strlen
618597 #define _tcscpy strcpy
619598 #define _tcscmp strcmp
620 #define _tcsicmp stricmp
621 #endif
622
623 inline int strcmp_ci(const char *s1, const char *s2) { return strcasecmp(s1, s2); }
599 #define _tcsicmp strcasecmp
600 #endif
624601
625602 void Sleep(unsigned int usec);
626603
639616 #endif
640617 #define PATH_SEPARATOR '/'
641618
642 // timezone compatability
643 #define _tzset tzset
644 #define _timezone timezone
645 #define _daylight daylight
646 #define _tzname tzname
647619 // unavailable in linux
648620 #define _dstbias 0
649621
697669 **/
698670 #define __LIKE_PRINTF(_fmt, _va) __attribute__((format(printf, _fmt, _va)))
699671
700 #define z_tms tms
701 #define z_times times
702
703672 std::vector<std::string> get_backtrace();
704673
705674 #endif // PLATFORM_LINUX_H
2626 /*
2727 * Comparison handler for case-insensitive keys in maps
2828 */
29 struct stricmp_comparison {
29 struct strcasecmp_comparison {
3030 bool operator()(const std::string &left, const std::string &right) const
3131 {
32 return left.size() < right.size() || (left.size() == right.size() && stricmp(left.c_str(), right.c_str()) < 0);
32 return left.size() < right.size() || (left.size() == right.size() && strcasecmp(left.c_str(), right.c_str()) < 0);
3333 }
3434 };
3535
8888
8989 std::string GetServerNameFromPath(const char *szPath);
9090 std::string GetServerPortFromPath(const char *szPath);
91 std::string ServerNamePortToURL(const char *lpszType, const char *lpszServerName, const char *lpszServerPort, const char *lpszExtra = "zarafa");
9291
9392 static inline bool parseBool(const std::string &s) {
9493 return !(s == "0" || s == "false" || s == "no");
9695
9796 extern std::string shell_escape(const std::string &str);
9897 extern std::string shell_escape(const std::wstring &wstr);
99 std::string forcealnum(const std::string& str, const char *additional = NULL);
10098
10199 std::vector<std::wstring> tokenize(const std::wstring &strInput, const WCHAR sep, bool bFilterEmpty = false);
102100 std::vector<std::string> tokenize(const std::string &strInput, const char sep, bool bFilterEmpty = false);
180178 }
181179
182180 std::string format(const char *const fmt, ...) __LIKE_PRINTF(1, 2);
181 extern "C" char *kc_strlcpy(char *, const char *, size_t);
183182
184183 #endif
1818 #include <mapicode.h>
1919 #include <kopano/kcodes.h>
2020 #include <kopano/mapiext.h>
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
25
2621
2722 /*
2823 * Some helper functions to convert the SOAP-style objects
1515 */
1616
1717 #include <kopano/platform.h>
18 #include <cerrno>
19 #include <cstdlib>
1820 #include <fcntl.h>
1921 #include <mapidefs.h>
2022 #include <mapicode.h>
2123 #include <climits>
2224 #include <pthread.h>
25 #include <unistd.h>
2326
2427 #include <sys/stat.h>
2528 #include <sys/time.h> /* gettimeofday */
26
29 #include <kopano/ECLogger.h>
2730 #include "TmpPath.h"
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3231
3332 HRESULT UnixTimeToFileTime(time_t t, FILETIME *ft)
3433 {
140139 return stime.wSecond + (stime.wMinute*60) + ((stime.wHour)*60*60);
141140 }
142141
143 SYSTEMTIME UnixTimeToSystemTime(time_t unixtime)
144 {
145 SYSTEMTIME stime = {0};
146 stime.wSecond = unixtime%60;
147 unixtime /= 60;
148 stime.wMinute = unixtime%60;
149 unixtime /= 60;
150 stime.wHour = unixtime;
151 return stime;
152 }
153
154142 SYSTEMTIME TMToSystemTime(const struct tm &t)
155143 {
156144 SYSTEMTIME stime = {0};
165153 return stime;
166154 }
167155
168 struct tm SystemTimeToTM(const SYSTEMTIME &stime)
169 {
170 // not quite, since we miss tm_yday
171 struct tm t = {0};
172 t.tm_year = stime.wYear;
173 t.tm_mon = stime.wMonth;
174 t.tm_wday = stime.wDayOfWeek;
175 t.tm_mday = stime.wDay;
176 t.tm_hour = stime.wHour;
177 t.tm_min = stime.wMinute;
178 t.tm_sec = stime.wSecond;
179 t.tm_isdst = -1;
180 return t;
181 }
182
183156 /* The 'IntDate' and 'IntTime' date and time encoding are used for some CDO calculations. They
184157 * are basically a date or time encoded in a bitshifted way, packed so that it uses the least amount
185158 * of bits. Eg. a date (day,month,year) is encoded as 5 bits for the day (1-31), 4 bits for the month (1-12),
304277
305278 // SuSE 9.1 segfaults when putenv() is used in a detached thread on the next getenv() call.
306279 // so use setenv() on linux, putenv() on others.
307
308 #ifdef LINUX
309280 setenv("TZ", "UTC0", 1);
310281 tzset();
311 #else
312 if(putenv("TZ=UTC0") != -1)
313 _tzset();
314 #endif
315
316282 convert = mktime(t);
317
318 #ifdef LINUX
319283 if (s_tz) {
320284 setenv("TZ", s_tz, 1);
321285 tzset();
323287 unsetenv("TZ");
324288 tzset();
325289 }
326 #else
327 if (s_tz) {
328 putenv(s_tz);
329 _tzset();
330 } else {
331 putenv("TZ=");
332 _tzset();
333 }
334 #endif
335290 free(s_tz);
336291 return convert;
337292 }
411366 }
412367
413368 // Create the actual directory
414 int ret = CreateDir(createpath, 0700);
369 int ret = mkdir(createpath, 0700);
415370 free(path);
416371 return ret;
417372 }
499454 // inserted
500455 posix_fallocate(fd, 0, len);
501456 }
457
458 /**
459 * Restart the program with a new preloaded library.
460 * @argv: full argv of current invocation
461 * @lib: library to load via LD_PRELOAD
462 *
463 * As every program under Linux is linked to libc and symbol resolution is done
464 * breadth-first, having just libkcserver.so linked to the alternate allocator
465 * is not enough to ensure the allocator is being used in favor of libc malloc.
466 *
467 * A program built against glibc will have a record for e.g.
468 * "malloc@GLIBC_2.2.5". The use of LD_PRELOAD appears to relax the version
469 * requirement, though; the benefit would be that libtcmalloc's malloc will
470 * take over _all_ malloc calls.
471 */
472 int kc_reexec_with_allocator(char **argv, const char *lib)
473 {
474 if (lib == NULL || *lib == '\0')
475 return 0;
476 const char *s = getenv("KC_ALLOCATOR_DONE");
477 if (s != NULL)
478 /* avoid repeatedly reexecing ourselves */
479 return 0;
480 s = getenv("LD_PRELOAD");
481 if (s == NULL)
482 setenv("LD_PRELOAD", lib, true);
483 else if (strstr(s, "/valgrind/") != NULL)
484 /*
485 * Within vg, everything is a bit different — since it catches
486 * execve itself. Execing /proc/self/exe therefore won't work,
487 * we would need to use argv[0]. But… don't bother.
488 */
489 return 0;
490 else
491 setenv("LD_PRELOAD", (std::string(s) + ":" + lib).c_str(), true);
492 void *handle = dlopen(lib, RTLD_LAZY | RTLD_LOCAL);
493 if (handle == NULL)
494 /*
495 * Ignore libraries that won't load anyway. This avoids
496 * ld.so emitting a scary warning if we did re-exec.
497 */
498 return 0;
499 dlclose(handle);
500 setenv("KC_ALLOCATOR_DONE", lib, true);
501
502 /* Resolve "exe" symlink before exec to please the sysadmin */
503 std::vector<char> linkbuf(16);
504 ssize_t linklen;
505 while (true) {
506 linklen = readlink("/proc/self/exe", &linkbuf[0], linkbuf.size());
507 if (linklen < 0 || static_cast<size_t>(linklen) < linkbuf.size())
508 break;
509 linkbuf.resize(linkbuf.size() * 2);
510 }
511 if (linklen < 0) {
512 int ret = -errno;
513 ec_log_warn("kc_reexec_with_allocator: readlink: %s", strerror(errno));
514 return ret;
515 }
516 linkbuf[linklen] = '\0';
517 ec_log_debug("Reexecing %s with %s", &linkbuf[0], lib);
518 execv(&linkbuf[0], argv);
519 int ret = -errno;
520 ec_log_info("Failed to reexec self: %s. Continuing with standard allocator.", strerror(errno));
521 return ret;
522 }
101101 #endif
102102
103103 return S_OK;
104 }
105
106 __int64_t Int32x32To64(ULONG a, ULONG b) {
107 return (__int64_t)a*(__int64_t)b;
108104 }
109105
110106 void GetSystemTimeAsFileTime(FILETIME *ft) {
3131 #include <sstream>
3232
3333 using namespace std;
34
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
3834
3935 static const char szHex[] = "0123456789ABCDEF";
4036
2020 #include <sstream>
2121
2222 #include <kopano/ECIConv.h>
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
2723
2824 std::string stringify(unsigned int x, bool usehex, bool _signed) {
2925 char szBuff[33];
255251 path.erase(pos, std::string::npos);
256252
257253 return path.c_str();
258 }
259
260 std::string ServerNamePortToURL(const char *lpszType, const char *lpszServerName, const char *lpszServerPort, const char *lpszExtra) {
261 std::string strURL;
262
263 if (lpszType && lpszType[0]) {
264 strURL.append(lpszType);
265 strURL.append("://");
266 }
267
268 strURL.append(lpszServerName);
269
270 if (lpszServerPort && lpszServerPort[0]) {
271 strURL.append(":");
272 strURL.append(lpszServerPort);
273 }
274
275 if (strnicmp(lpszType,"http", 4) == 0 && lpszExtra && lpszExtra[0]) {
276 strURL.append("/");
277 strURL.append(lpszExtra);
278 }
279
280 return strURL;
281254 }
282255
283256 std::string shell_escape(const std::string &str)
559532 return output;
560533 }
561534
562
563535 /**
564536 * Convert a memory buffer with strings with Unix \n enters to DOS
565537 * \r\n enters.
661633 swap(strInOut, strOutput);
662634 }
663635
664
665 /**
666 * Force a string to contain alphanumerics only
667 *
668 * Replaces all other characters with _ unless they are in szAdditional
669 *
670 * @param[in] str Input string
671 * @param[in] szAdditional Additional characters to accept
672 * @return Modified string
673 */
674 std::string forcealnum(const std::string& str, const char *szAdditional)
675 {
676 std::string out;
677
678 for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
679 if(isalnum(*i))
680 out += *i;
681 else if(szAdditional && strchr(szAdditional, *i) != NULL)
682 out += *i;
683 else
684 out += '_';
685
686 return out;
687 }
688
689636 std::string format(const char *const fmt, ...) {
690637 char *buffer = NULL;
691638 va_list ap;
699646
700647 return result;
701648 }
649
650 char *kc_strlcpy(char *dest, const char *src, size_t n)
651 {
652 strncpy(dest, src, n);
653 dest[n-1] = '\0';
654 return dest;
655 }
8787 #include <kopano/charset/convert.h>
8888 #endif
8989
90 #ifdef _DEBUG
91 #define new DEBUG_NEW
92 #endif
93
9490 #ifndef ZCP_USES_ICU
9591 ECSortKey::ECSortKey(const unsigned char *lpSortData, unsigned int cbSortData)
9692 : m_lpSortData(lpSortData)
396392 return strcasestr(haystack, needle) != NULL;
397393 #endif
398394 }
399
400
401395
402396 /**
403397 * Check if two strings are canonical equivalent.
652646 #endif
653647 }
654648
655
656
657
658649 /**
659650 * Check if two strings are canonical equivalent.
660651 *
913904 return wcs_icontains(ws1, ws2, locale);
914905 #endif
915906 }
916
917907
918908 /**
919909 * Copy at most n characters from the utf8 string src to lpstrDest.
12291219 {"zu_ZA",1077,"Zulu_South Africa"},
12301220 };
12311221
1232
12331222 ECLocale createLocaleFromName(const char *lpszLocale)
12341223 {
12351224 #ifdef ZCP_USES_ICU
12501239 ASSERT(lpulLcid != NULL);
12511240
12521241 for (unsigned i = 0; !lpMapEntry && i < arraySize(localeMap); ++i)
1253 if (stricmp(localeMap[i].lpszLocaleID, lpszLocaleID) == 0)
1242 if (strcasecmp(localeMap[i].lpszLocaleID, lpszLocaleID) == 0)
12541243 lpMapEntry = &localeMap[i];
12551244
12561245 if (lpMapEntry == NULL)
12831272 ASSERT(lppszLocaleName != NULL);
12841273
12851274 for (unsigned i = 0; !lpMapEntry && i < arraySize(localeMap); ++i)
1286 if (stricmp(localeMap[i].lpszLocaleID, lpszLocaleID) == 0)
1275 if (strcasecmp(localeMap[i].lpszLocaleID, lpszLocaleID) == 0)
12871276 lpMapEntry = &localeMap[i];
12881277
12891278 if (lpMapEntry == NULL)
14321421 createSortKeyData(wstrTmp.c_str(), nCap, locale, lpcbKey, lppKey);
14331422 #endif
14341423 }
1435
14361424
14371425 /**
14381426 * Create a locale independant blob that can be used to sort
215215 ])
216216 AC_SUBST([tmpfilesdir])
217217
218 dnl Not all files will be installed to ${prefix}, so we need to cheat a bit
219 dnl to make "distcheck" succeed.
220 AC_ARG_WITH([dcprefix],
221 [AS_HELP_STRING([Extra path inserted for distcheck])],
222 [dcprefix="$withval"])
223 AC_SUBST([dcprefix])
224
218225 # stats client requires ncurses(w) for --top
219226 # check wide version before non-wide version
220227 AC_DEFUN([LIBNCURSES_WITH_CONFIG],[
241248 ])
242249 LIBNCURSES_WITH_CONFIG
243250
244 AC_CHECK_HEADERS([syslog.h sys/un.h sys/stat.h])
245 AC_CHECK_FUNCS([timegm getpeereid getpwnam_r vsyslog vsnprintf_l])
251 AC_CHECK_HEADERS([syslog.h sys/un.h sys/stat.h malloc.h])
252 AC_CHECK_FUNCS([mallinfo timegm getpeereid getpwnam_r vsyslog vsnprintf_l])
246253
247254
248255 #
745752 m4lcommon/include/kopano/Makefile
746753 php-ext/Makefile php7-ext/Makefile
747754 provider/Makefile
748 provider/client/Makefile
749 provider/contacts/Makefile
750 provider/common/Makefile
751755 provider/include/Makefile
752 provider/libserver/Makefile
753 provider/plugins/Makefile
754 provider/server/Makefile
755 provider/soap/Makefile
756756 inetmapi/Makefile
757757 inetmapi/include/inetmapi/Makefile
758758 spooler/Makefile
55 kopano-admin.8 \
66 kopano-archiver.8 kopano-archiver.cfg.5 \
77 kopano-autorespond.8 \
8 kopano-cfgchecker.8 \
89 kopano-dagent.8 kopano-dagent.cfg.5 \
910 kopano-mr-accept.8 kopano-mr-process.8 \
1011 kopano-fsck.1 \
603603 <title>Config</title>
604604
605605 <para>Normally, no configuration file is used or required. The
606 following options can be set in the configuation file:</para>
606 following options can be set in the configuration file:</para>
607607
608608 <variablelist>
609609 <varlistentry>
27282728 </para>
27292729 </listitem>
27302730 </varlistentry>
2731
2732 <varlistentry>
2733 <term><option>--utf8</option></term>
2734 <listitem>
2735 <para>Force the current locale to UTF-8</para>
2736 </listitem>
2737 </varlistentry>
27312738 </variablelist>
27322739
27332740 <para>
27872794 checking is performed. This way, you can use any config file
27882795 from a kopano program, eg. kopano-spooler or kopano-dagent, to
27892796 load SSL settings.</para><para>The following options can be set in the
2790 configuation file:</para>
2797 configuration file:</para>
27912798
27922799 <variablelist>
27932800 <varlistentry>
39223929 </listitem>
39233930 </varlistentry>
39243931
3932 <varlistentry>
3933 <term><option>allocator_library</option></term>
3934 <listitem>
3935
3936 <para>This setting allows to preload a special library (such
3937 as an allocator). On startup, the server will set the
3938 LD_PRELOAD environment variable for itself and then
3939 re-execute itself to get it loaded with high priority. If
3940 this option is empty, the default system allocator (from
3941 libc) will be used instead, which is probably a better choice
3942 when debugging with gdb, valgrind or ASAN/UBSAN. The
3943 environment variable KC_ALLOCATOR_DONE may also be set to a
3944 non-empty value to disable re-exec.</para>
3945
3946 <para>Default: <replaceable>libtcmalloc_minimal.so.4</replaceable></para>
3947 </listitem>
3948 </varlistentry>
39253949 </variablelist>
39263950 </refsection>
39273951
48004824 <para>Retrieve the users and groups information
48014825 from the Linux password files. User information
48024826 will be read the /etc/passwd file. Passwords will
4803 be checked agains /etc/shadow. Group information
4827 be checked against /etc/shadow. Group information
48044828 will read from /etc/group. Use the
48054829 <citerefentry><refentrytitle>kopano-admin</refentrytitle><manvolnum>8</manvolnum></citerefentry>
48064830 tool to set Kopano specific attributes on a
55415565 <para>An object is defined by this attribute what type
55425566 it is, eg. user, group, etc. Every object type should
55435567 have a unique value in this attribute in order to define
5544 what which enrty is.</para>
5568 what which entry is.</para>
55455569 <para>The value of this attribute must be specified in the
55465570 ldap_*_type_attribute_value settings. Each of those settings
55475571 may specify multiple values for the type attribute, separated
66146638 <title>User attributes</title>
66156639
66166640 <para>Not all Kopano attributes can be used from the system
6617 files. The following attibutes are used from the system files:
6641 files. The following attributes are used from the system files:
66186642 </para>
66196643
66206644 <variablelist>
4848 #include <kopano/ecversion.h>
4949
5050 #include "SSLUtil.h"
51 #include <kopano/stringutil.h>
5251
5352 #include "TmpPath.h"
54
55 #ifdef LINUX
5653 #include <kopano/UnixUtil.h>
57 #endif
58
5954 #ifdef ZCP_USES_ICU
6055 #include <unicode/uclean.h>
6156 #endif
8075 quit = 1;
8176 }
8277
83 #ifdef LINUX
8478 static void sighup(int sig)
8579 {
8680 // In Win32, the signal is sent in a separate, special signal thread. So this test is
8781 // not needed or required.
88 #ifdef LINUX
8982 if (bThreads && pthread_equal(pthread_self(), mainthread)==0)
9083 return;
91 #endif
9284 if (g_lpConfig) {
9385 if (!g_lpConfig->ReloadSettings() && g_lpLogger)
9486 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to reload configuration file, continuing with current settings.");
119111 generic_sigsegv_handler(g_lpLogger, "Gateway",
120112 PROJECT_VERSION_GATEWAY_STR, signr, si, uc);
121113 }
122 #endif
123114
124115 static HRESULT running_service(const char *szPath, const char *servicename);
125116
161152 // not required anymore
162153 delete lpHandlerArgs;
163154
164 #ifdef LINUX
165155 // make sure the pipe logger does not exit when this handler exits, but only frees the memory.
166156 if (dynamic_cast<ECLogger_Pipe*>(lpLogger) != NULL)
167157 dynamic_cast<ECLogger_Pipe*>(lpLogger)->Disown();
168 #endif
169158
170159 std::string inBuffer;
171160 HRESULT hr;
274263 bool bIgnoreUnknownConfigOptions = false;
275264
276265 ssl_threading_setup();
277
278 #ifdef LINUX
279266 const char *szConfig = ECConfig::GetDefaultPath("gateway.cfg");
280 #else
281 const char *szConfig = "gateway.cfg";
282 ECNTService ecNTService;
283 #endif
284
285267 static const configsetting_t lpDefaults[] = {
286268 { "server_bind", "" },
287 #ifdef LINUX
288269 { "run_as_user", "kopano" },
289270 { "run_as_group", "kopano" },
290271 { "pid_file", "/var/run/kopano/gateway.pid" },
291272 { "running_path", "/var/lib/kopano" },
292273 { "process_model", "fork" },
293274 { "coredump_enabled", "no" },
294 #endif
295275 { "pop3_enable", "yes" },
296276 { "pop3_port", "110" },
297277 { "pop3s_enable", "no" },
478458 pthread_attr_t ThreadAttr;
479459 const char *const interface = g_lpConfig->GetSetting("server_bind");
480460
481 #ifdef LINUX
482461 // SIGSEGV backtrace support
483462 stack_t st;
484463 struct sigaction act;
485464
486465 memset(&st, 0, sizeof(st));
487466 memset(&act, 0, sizeof(act));
488 #endif
489467
490468 if (bThreads) {
491469 pthread_attr_init(&ThreadAttr);
493471 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Can't set thread attribute to detached");
494472 goto exit;
495473 }
496 #ifdef LINUX
497474 // 1Mb of stack space per thread
498475 if (pthread_attr_setstacksize(&ThreadAttr, 1024 * 1024)) {
499476 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Can't set thread stack size to 1Mb");
500477 goto exit;
501478 }
502 #endif
503479 }
504480
505481 bListenPOP3 = (strcmp(g_lpConfig->GetSetting("pop3_enable"), "yes") == 0);
506482 bListenPOP3s = (strcmp(g_lpConfig->GetSetting("pop3s_enable"), "yes") == 0);
507483 bListenIMAP = (strcmp(g_lpConfig->GetSetting("imap_enable"), "yes") == 0);
508484 bListenIMAPs = (strcmp(g_lpConfig->GetSetting("imaps_enable"), "yes") == 0);
509
510485
511486 // Setup ssl context
512487 if ((bListenPOP3s || bListenIMAPs) && ECChannel::HrSetCtx(g_lpConfig, g_lpLogger) != hrSuccess) {
550525 // Setup signals
551526 signal(SIGTERM, sigterm);
552527 signal(SIGINT, sigterm);
553 #ifdef LINUX
554528 signal(SIGHUP, sighup);
555529 signal(SIGCHLD, sigchld);
556530 signal(SIGPIPE, SIG_IGN);
566540 sigaction(SIGSEGV, &act, NULL);
567541 sigaction(SIGBUS, &act, NULL);
568542 sigaction(SIGABRT, &act, NULL);
569 #endif
570
571 #ifdef LINUX
543
572544 // Set max open file descriptors to FD_SETSIZE .. higher than this number
573545 // is a bad idea, as it will start breaking select() calls.
574546 struct rlimit file_limit;
594566 if (bThreads == false)
595567 g_lpLogger = StartLoggerProcess(g_lpConfig, g_lpLogger); // maybe replace logger
596568 ec_log_set(g_lpLogger);
597 #endif
569
598570 hr = MAPIInitialize(NULL);
599571 if (hr != hrSuccess) {
600572 g_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to initialize MAPI: %s (%x)",
763735
764736 g_lpLogger->Log(EC_LOGLEVEL_ALWAYS, "POP3/IMAP Gateway will now exit");
765737
766 #ifdef LINUX
767738 // in forked mode, send all children the exit signal
768739 if (bThreads == false) {
769740 signal(SIGTERM, SIG_IGN);
770741 kill(0, SIGTERM);
771742 }
772 #endif
773743
774744 // wait max 10 seconds (init script waits 15 seconds)
775745 for (int i = 10; nChildren != 0 && i != 0; --i) {
783753 else
784754 g_lpLogger->Log(EC_LOGLEVEL_NOTICE, "POP3/IMAP Gateway shutdown complete");
785755
786
787756 MAPIUninitialize();
788757
789758 exit:
793762
794763 if (bThreads)
795764 pthread_attr_destroy(&ThreadAttr);
796
797 #ifdef LINUX
798765 free(st.ss_sp);
799 #endif
800766 #ifdef ZCP_USES_ICU
801767 // cleanup ICU data so valgrind is happy
802768 u_cleanup();
7979 return (strInput.compare(0, strPrefix.size(), strPrefix) == 0);
8080 }
8181
82 /**
83 * IMAP class constructor
84 */
8582 IMAP::IMAP(const char *szServerPath, ECChannel *lpChannel, ECLogger *lpLogger,
8683 ECConfig *lpConfig) :
8784 ClientProto(szServerPath, lpChannel, lpLogger, lpConfig)
115112 pthread_mutex_init(&m_mIdleLock, NULL);
116113 }
117114
118 /**
119 * IMAP class destructor
120 */
121115 IMAP::~IMAP() {
122116 if (m_lpTable)
123117 m_lpTable->Release();
198192 */
199193 bool IMAP::CaseCompare(const string& strA, const string& strB)
200194 {
201 return stricmp(strA.c_str(), strB.c_str()) == 0;
195 return strcasecmp(strA.c_str(), strB.c_str()) == 0;
202196 }
203197
204198 /**
439433 }
440434
441435 // process {} and end of line
442
443436
444437 if (strCommand.compare("CAPABILITY") == 0) {
445438 if (!strvResult.empty()) {
824817 return hr;
825818 }
826819
827
828820 /**
829821 * @brief Handles the STARTTLS command
830822 *
10531045
10541046 m_lpsIMAPTags->aulPropTag[0] = PROP_ENVELOPE;
10551047 }
1056
10571048
10581049 hr = HrGetSubscribedList();
10591050 // ignore error, empty list of subscribed folder
21482139 HrSetOneProp(lpMessage, lpPropVal);
21492140 }
21502141
2151
21522142 hr = lpMessage->SaveChanges(KEEP_OPEN_READWRITE | FORCE_SAVE);
21532143 if (hr != hrSuccess) {
21542144 hr2 = HrResponse(RESP_TAGGED_NO, strTag, "APPEND error saving message");
26912681 }
26922682
26932683 return strFlags;
2694 }
2695
2696 /**
2697 * Convert MAPI properties to a RFC-822 email address string, with optional fullname
2698 *
2699 * @param[in] lpProps Array of properties containing atleast the tags given in ulEmailPropTag and ulNamePropTag
2700 * @param[in] cValues The number of properties in lpProps
2701 * @param[in] ulEmailPropTag The PropTag to use for the email address
2702 * @param[in] ulNamePropTag The PropTag to use for the fullname
2703 *
2704 * @return String with email address, or empty
2705 */
2706 std::string IMAP::PropsToEmailAddress(LPSPropValue lpProps, unsigned int cValues, ULONG ulEmailPropTag, ULONG ulNamePropTag)
2707 {
2708 const SPropValue *lpPropEmail = PpropFindProp(lpProps, cValues, ulEmailPropTag);
2709 const SPropValue *lpPropName = PpropFindProp(lpProps, cValues, ulNamePropTag);
2710 std::string strAddress;
2711
2712 if(lpPropEmail && lpPropName && strcmp(lpPropEmail->Value.lpszA, lpPropName->Value.lpszA) == 0) {
2713 strAddress = (string)"<" + lpPropEmail->Value.lpszA + ">";
2714 } else if(lpPropEmail && lpPropName) {
2715 strAddress = (string)"\"" + lpPropName->Value.lpszA + "\" <" + lpPropEmail->Value.lpszA + ">";
2716 } else if(lpPropEmail) {
2717 strAddress = (string)"<" + lpPropEmail->Value.lpszA + ">";
2718 } else {
2719 // Only a name ??
2720 }
2721
2722 return strAddress;
27232684 }
27242685
27252686 /**
28572818 enum { EID, IKEY, IMAPID, MESSAGE_FLAGS, FLAG_STATUS, MSG_STATUS, LAST_VERB, NUM_COLS };
28582819 SizedSPropTagArray(NUM_COLS, spt) = { NUM_COLS, {PR_ENTRYID, PR_INSTANCE_KEY, PR_EC_IMAP_ID, PR_MESSAGE_FLAGS, PR_FLAG_STATUS, PR_MSG_STATUS, PR_LAST_VERB_EXECUTED} };
28592820
2860
28612821 // Outlook (express) IDLEs without selecting a folder.
28622822 // When sending an error from this command, Outlook loops on the IDLE command forever :(
28632823 // Therefore, we can never return an HrResultBad() or ...No() here, so we always "succeed"
29072867 hr = HrResponse(RESP_CONTINUE, "waiting for notifications");
29082868
29092869 pthread_mutex_unlock(&m_mIdleLock);
2910
29112870
29122871 exit:
29132872 if (hr != hrSuccess || hr2 != hrSuccess) {
33363295
33373296 hr = HrGetOneProp(lpPublicStore, PR_IPM_PUBLIC_FOLDERS_ENTRYID, &lpPropVal);
33383297 if (hr != hrSuccess) {
3339 lpLogger->Log(EC_LOGLEVEL_WARNING, "Public store is enabled in configuation, but Public Folders inside public store could not be found.");
3298 lpLogger->Log(EC_LOGLEVEL_WARNING, "Public store is enabled in configuration, but Public Folders inside public store could not be found.");
33403299 hr = hrSuccess;
33413300 goto exit;
33423301 }
33443303 // make public folder folders list
33453304 hr = HrGetSubTree(lstFolders, lpPropVal->Value.bin, PUBLIC_FOLDERS_NAME, --lstFolders.end());
33463305 if (hr != hrSuccess) {
3347 lpLogger->Log(EC_LOGLEVEL_WARNING, "Public store is enabled in configuation, but Public Folders inside public store could not be found.");
3306 lpLogger->Log(EC_LOGLEVEL_WARNING, "Public store is enabled in configuration, but Public Folders inside public store could not be found.");
33483307 hr = hrSuccess;
33493308 }
33503309
33523311 MAPIFreeBuffer(lpPropVal);
33533312 MAPIFreeBuffer(lpEntryID);
33543313 return hr;
3355 }
3356
3357 bool IMAP::IsSubscribed(BinaryArray sEntryId) {
3358 vector<BinaryArray>::const_iterator iFld;
3359
3360 iFld = find(m_vSubscriptions.begin(), m_vSubscriptions.end(), sEntryId);
3361 return iFld != m_vSubscriptions.end();
33623314 }
33633315
33643316 /**
49204872 return hr;
49214873 }
49224874
4923 /**
4924 * Returns the INTERNALDATE for a given message. The value comes
4925 * either from PR_MESSAGE_DELIVERY_TIME or PR_CLIENT_SUBMIT_TIME.
4926 *
4927 * @param[out] strResponse the INTERNALDATE reply for the given message
4928 * @param[in] lpMessage the MAPI message to get the date for
4929 *
4930 * @return MAPI Error code
4931 */
4932 HRESULT IMAP::HrGetMessageInterDate(string &strResponse, LPMESSAGE lpMessage) {
4933 HRESULT hr = hrSuccess;
4934 LPSPropValue lpPropVal = NULL;
4935
4936 if (!lpMessage) {
4937 hr = MAPI_E_CALL_FAILED;
4938 goto exit;
4939 }
4940
4941 strResponse += "INTERNALDATE ";
4942 if (HrGetOneProp(lpMessage, PR_MESSAGE_DELIVERY_TIME, &lpPropVal) == hrSuccess
4943 || HrGetOneProp(lpMessage, PR_CLIENT_SUBMIT_TIME, &lpPropVal) == hrSuccess) {
4944 strResponse += "\"";
4945 strResponse += FileTimeToString(lpPropVal->Value.ft);
4946 strResponse += "\"";
4947 } else {
4948 strResponse += "NIL";
4949 }
4950
4951 exit:
4952 MAPIFreeBuffer(lpPropVal);
4953 return hr;
4954 }
4955
49564875 /*
49574876 * RFC 3501, section 6.4.5:
49584877 *
62186137 lpExtraRestriction[1].res.resAnd.lpRes[1].res.resProperty.relop = RELOP_GT;
62196138 lpExtraRestriction[1].res.resAnd.lpRes[1].res.resProperty.ulPropTag = PR_MESSAGE_SIZE;
62206139 lpExtraRestriction[1].res.resAnd.lpRes[1].res.resProperty.lpProp = lpPropVal;
6221
62226140
62236141 ulStartCriteria += 2;
62246142 // NEW done with ALL
77877705 goto exit;
77887706 }
77897707
7790 result = stricmp(lpProp->Value.lpszA, "IPM") == 0 || stricmp(lpProp->Value.lpszA, "IPF.NOTE") == 0;
7708 result = strcasecmp(lpProp->Value.lpszA, "IPM") == 0 || strcasecmp(lpProp->Value.lpszA, "IPF.NOTE") == 0;
77917709
77927710 exit:
77937711 MAPIFreeBuffer(lpProp);
297297
298298 /* subscribed folders */
299299 vector<BinaryArray> m_vSubscriptions;
300 bool IsSubscribed(BinaryArray sEntryId);
301300 HRESULT HrGetSubscribedList();
302301 HRESULT HrSetSubscribedList();
303302 HRESULT ChangeSubscribeList(bool bSubscribe, ULONG cbEntryID, LPENTRYID lpEntryID);
319318 std::string HrEnvelopeSender(LPMESSAGE lpMessage, ULONG ulTagName, ULONG ulTagEmail, std::string& strCharset, bool bIgnore);
320319 HRESULT HrGetMessageEnvelope(string &strResponse, LPMESSAGE lpMessage);
321320 HRESULT HrGetMessageFlags(string &strResponse, LPMESSAGE lpMessage, bool bRecent);
322 HRESULT HrGetMessageInterDate(string &strResponse, LPMESSAGE lpMessage);
323321
324322 HRESULT HrGetMessagePart(string &strMessagePart, string &strMessage, string strPartName);
325323
363361
364362 // Various conversion functions
365363 string PropsToFlags(LPSPropValue lpProps, unsigned int cValues, bool bRecent, bool bRead);
366 string PropsToEmailAddress(LPSPropValue lpProps, unsigned int cValues, ULONG ulEmailPropTag, ULONG ulNamePropTag);
367364
368365 void HrParseHeaders(const std::string &, std::list<std::pair<std::string, std::string> > &);
369366 void HrGetSubString(string &strOutput, const std::string &strInput, const std::string &strBegin, const std::string &strEnd);
77
88 sbin_PROGRAMS = kopano-gateway
99 noinst_DATA = kopano-gateway.ldx
10 CLEANFILES = ${noinst_DATA}
1011
1112 kopano_gateway_LDADD = ${top_builddir}/inetmapi/libkcinetmapi.la \
1213 ${top_builddir}/mapi4linux/src/libmapi.la \
00 # -*- Makefile -*-
11
22 .la.ldd:
3 ${AM_V_GEN}${top_srcdir}/lddcheck $< $@
3 ${AM_V_GEN}${top_srcdir}/lddcheck ${top_builddir}/libtool $< $@
44
55 # There is no good POSIX syntax for the following one.. resort to GNUmake
66 %.ldx: %
7 ${AM_V_GEN}${top_srcdir}/lddcheck $< $@
7 ${AM_V_GEN}${top_srcdir}/lddcheck ${top_builddir}/libtool $< $@
161161 return hr;
162162 }
163163
164
165164 /**
166165 * Takes a group entry of a recipient table and expands the recipients for the group recursively by adding them to the recipients list
167166 *
315314 return hr;
316315 }
317316
318
319317 // This function does not catch the vmime exception
320318 // it should be handled by the calling party.
321319
386384 if (mapiTransport && HrGetOneProp(lpMessage, PR_ORIGINATOR_DELIVERY_REPORT_REQUESTED, &ptrDeliveryReport) == hrSuccess && ptrDeliveryReport->Value.b == TRUE) {
387385 mapiTransport->requestDSN(true, "");
388386 }
389
390387
391388 // Generate the message, "stream" it and delegate the sending
392389 // to the generic send() function.
6666 #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp"
6767 #endif // VMIME_HAVE_TLS_SUPPORT
6868
69
7069 // Helpers for service properties
7170 #define GET_PROPERTY(type, prop) \
7271 (getInfos().getPropertyValue <type>(getSession(), \
8382 namespace net {
8483 namespace smtp {
8584
86
8785 MAPISMTPTransport::MAPISMTPTransport(ref <session> sess, ref <security::authenticator> auth, const bool secured)
8886 : transport(sess, getInfosInstance(), auth), m_socket(NULL),
8987 m_authentified(false), m_extendedSMTP(false), m_timeoutHandler(NULL),
9189 m_bDSNRequest(false)
9290 {
9391 }
94
9592
9693 MAPISMTPTransport::~MAPISMTPTransport()
9794 {
215212 m_authentified = true;
216213 }
217214
218
219215 void MAPISMTPTransport::helo()
220216 {
221217 // First, try Extended SMTP (ESMTP)
280276 }
281277 }
282278 }
283
284279
285280 void MAPISMTPTransport::authenticate()
286281 {
327322 // No other authentication method is possible
328323 throw exceptions::authentication_error("All authentication methods failed");
329324 }
330
331325
332326 #if VMIME_HAVE_SASL_SUPPORT
333327
456450
457451 #endif // VMIME_HAVE_SASL_SUPPORT
458452
459
460453 #if VMIME_HAVE_TLS_SUPPORT
461454
462455 void MAPISMTPTransport::startTLS()
499492
500493 #endif // VMIME_HAVE_TLS_SUPPORT
501494
502
503495 bool MAPISMTPTransport::isConnected() const
504496 {
505497 return (m_socket && m_socket->isConnected() && m_authentified);
513505 internalDisconnect();
514506 }
515507
516
517508 void MAPISMTPTransport::internalDisconnect()
518509 {
519510 try
537528 m_cntInfos = NULL;
538529 }
539530
540
541531 void MAPISMTPTransport::noop()
542532 {
543533 if (!isConnected())
550540 if (resp->getCode() != 250)
551541 throw exceptions::command_error("NOOP", resp->getText());
552542 }
553
554543
555544 //
556545 // Only this function is altered, to return per recipient failure.
705694 m_socket->send(buffer);
706695 }
707696
708
709697 ref <SMTPResponse> MAPISMTPTransport::readResponse()
710698 {
711699 ref <SMTPResponse> resp = SMTPResponse::readResponse(m_socket, m_timeoutHandler);
714702 return resp;
715703 }
716704
717
718
719705 // Service infos
720706
721707 SMTPServiceInfos MAPISMTPTransport::sm_infos(false);
135135 #define PR_EC_OUTLOOK_VERSION PROP_TAG(PT_STRING8, 0x81F4)
136136
137137 /**
138 * Default constructor
139 *
140138 * Inits the class with empty/default values.
141139 */
142140 MAPIToVMIME::MAPIToVMIME()
148146 }
149147
150148 /**
151 * Constructor with parameters
152 *
153149 * @param[in] lpSession current mapi session, used to open contact entryid's
154150 * @param[in] lpAddrBook global addressbook
155151 * @param[in] newlogger logger object
175171 m_lpSession = lpSession;
176172 }
177173
178 /**
179 * Destructor
180 */
181174 MAPIToVMIME::~MAPIToVMIME()
182175 {
183176 lpLogger->Release();
344337 std::string strBoundary;
345338 bool bSendBinary = true;
346339 MapiToICal *mapiical = NULL;
347
348340
349341 pPropAttachNum = PpropFindProp(lpRow->lpProps, lpRow->cValues, PR_ATTACH_NUM);
350342 if (pPropAttachNum == NULL) {
649641 strMedType = "video/x-msvideo";
650642 }
651643
652
653644 else {
654645 strMedType = "application/octet-stream";
655646 }
823814 std::string name = vmField->getName();
824815
825816 // Received checks start of string to accept Received-SPF
826 if (strnicmp(name.c_str(), vmime::fields::RECEIVED, strlen(vmime::fields::RECEIVED)) == 0 ||
827 stricmp(name.c_str(), vmime::fields::RETURN_PATH) == 0) {
817 if (strncasecmp(name.c_str(), vmime::fields::RECEIVED, strlen(vmime::fields::RECEIVED)) == 0 ||
818 strcasecmp(name.c_str(), vmime::fields::RETURN_PATH) == 0) {
828819 // Insert in same order at start of headers
829820 vmHeader->insertFieldBefore(j++, vmField);
830 } else if (strnicmp(name.c_str(), "list-", strlen("list-")) == 0 ||
831 stricmp(name.c_str(), "precedence") == 0) {
821 } else if (strncasecmp(name.c_str(), "list-", strlen("list-")) == 0 ||
822 strcasecmp(name.c_str(), "precedence") == 0) {
832823 // Just append at the end of this list, order is not important
833824 vmHeader->appendField(vmField->clone().dynamicCast<vmime::headerField>());
834825 }
983974 goto exit;
984975 }
985976
986 if(stricmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNNRN") == 0)
977 if(strcasecmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNNRN") == 0)
987978 dispo.setType(vmime::dispositionTypes::DELETED);
988 else // if(stricmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNRN") == 0)
979 else // if(strcasecmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNRN") == 0)
989980 dispo.setType(vmime::dispositionTypes::DISPLAYED);
990981
991982 strMDNText.clear();// Default Empty body
11241115 m_vmCharset = MAPI_CHARSET_STRING;
11251116 }
11261117
1127 if (strnicmp(lpMsgClass->Value.lpszA, "IPM.Note", 8) && strnicmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note", 15)) {
1118 if (strncasecmp(lpMsgClass->Value.lpszA, "IPM.Note", 8) && strncasecmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note", 15)) {
11281119 // Outlook sets some other incorrect charset for meeting requests and such,
11291120 // so for non-email we upgrade this to utf-8
11301121 m_vmCharset = MAPI_CHARSET_STRING;
11381129
11391130 // Add iconv tag to convert non-exising chars without a fuss
11401131 m_strCharset = m_vmCharset.getName() + "//TRANSLIT";
1141 if ((stricmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNNRN") == 0 ||
1142 stricmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNRN") == 0)
1132 if ((strcasecmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNNRN") == 0 ||
1133 strcasecmp(lpMsgClass->Value.lpszA, "REPORT.IPM.Note.IPNRN") == 0)
11431134 )
11441135 {
11451136 // Create a read receipt message
11461137 hr = BuildMDNMessage(lpMessage, &vmMessage);
11471138 if(hr != hrSuccess)
11481139 goto exit;
1149 } else if ((stricmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME.MultiPartSigned") == 0) ||
1150 (stricmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME") == 0))
1140 } else if ((strcasecmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME.MultiPartSigned") == 0) ||
1141 (strcasecmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME") == 0))
11511142 {
11521143 // - find attachment, and convert to char, and place in lpszRawSMTP
11531144 // - normal convert the message, but only from/to headers and such .. nothing else
12181209 vmMessage->getHeader()->removeField(vmMessage->getHeader()->findField(vmime::fields::CONTENT_TYPE));
12191210 vmMessage->getHeader()->removeField(vmMessage->getHeader()->findField(vmime::fields::CONTENT_TRANSFER_ENCODING));
12201211
1221 if (stricmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME") != 0) {
1212 if (strcasecmp(lpMsgClass->Value.lpszA, "IPM.Note.SMIME") != 0) {
12221213 std::string strRawSMTP = lpszRawSMTP;
12231214 vmime::ref<SMIMEMessage> vmSMIMEMessage = vmime::create<SMIMEMessage>();
12241215
16781669
16791670 // keep the original x-mailer header under a different name
16801671 // we still want to know that this mail was generated by kopano in the x-mailer header from handleExtraHeaders
1681 if (stricmp(str, "X-Mailer") == 0) {
1672 if (strcasecmp(str, "X-Mailer") == 0) {
16821673 delete [] str;
16831674 str = new char[18];
16841675 strcpy(str, "X-Original-Mailer");
20772068 LPSPropTagArray lpNameTagArray = NULL;
20782069 LPSPropValue lpAddressProps = NULL;
20792070
2080
20812071 if (HrGetOneProp(lpMessage, PR_REPLY_RECIPIENT_ENTRIES, &lpReplyTo) != hrSuccess)
20822072 goto exit;
20832073
20842074 if (lpReplyTo->Value.bin.cb == 0)
20852075 goto exit;
2086
20872076
20882077 lpEntryList = (FLATENTRYLIST *)lpReplyTo->Value.bin.lpb;
20892078
22682257 strTnefReason = "Force TNEF on request";
22692258
22702259 // currently no task support for ical
2271 if (iUseTnef <= 0 && lpMessageClass && strnicmp("IPM.Task", lpMessageClass->Value.lpszA, 8) == 0) {
2260 if (iUseTnef <= 0 && lpMessageClass && strncasecmp("IPM.Task", lpMessageClass->Value.lpszA, 8) == 0) {
22722261 iUseTnef = 1;
22732262 strTnefReason = "Force TNEF because of task request";
22742263 }
22932282 if (iUseTnef == 1 ||
22942283 (lpSendAsICal && lpSendAsICal->Value.b) ||
22952284 (lpSendAsICal && lpOutlookVersion && strcmp(lpOutlookVersion->Value.lpszA, "9.0") == 0) ||
2296 (lpMessageClass && (strnicmp("IPM.Note", lpMessageClass->Value.lpszA, 8) != 0) ) ||
2285 (lpMessageClass && (strncasecmp("IPM.Note", lpMessageClass->Value.lpszA, 8) != 0) ) ||
22972286 bestBody == realRTF)
22982287 {
22992288 // Send either TNEF or iCal data
23052294 * Send TNEF information for this message if we really need to, or otherwise iCal
23062295 */
23072296
2308 if (lstOLEAttach.size() == 0 && iUseTnef <= 0 && lpMessageClass && (strnicmp("IPM.Note", lpMessageClass->Value.lpszA, 8) != 0)) {
2297 if (lstOLEAttach.size() == 0 && iUseTnef <= 0 && lpMessageClass && (strncasecmp("IPM.Note", lpMessageClass->Value.lpszA, 8) != 0)) {
23092298 // iCAL
23102299 string ical, method;
23112300 vmime::ref<mapiAttachment> vmAttach = NULL;
66 -I$(top_srcdir)/mapi4linux/include -I$(top_srcdir)/provider/common \
77 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon \
88 -I${top_srcdir}/libfreebusy -I${top_srcdir}/libicalmapi \
9 -I/usr/include/libxml2
9 ${XML2_CFLAGS}
1010
1111 lib_LTLIBRARIES = libkcinetmapi.la
1212 noinst_DATA = libkcinetmapi.ldd
13 CLEANFILES = ${noinst_DATA}
1314
1415 # Add '-z now' -> -Wl,-z, -Wl,now to LD flags so that we do early binding of symbols. This fixes
1516 # a problem in which libvmime attempts to resolve a symbol in libinetmapi.so during the unload
3031 #CXXLD=--tag=none gcc
3132
3233 libinetmapidir = $(includedir)/inetmapi
33 libinetmapi_HEADERS = ECMapiUtils.h ECVMIMEUtils.h \
34 noinst_HEADERS = ECMapiUtils.h ECVMIMEUtils.h \
3435 MAPIToVMIME.h VMIMEToMAPI.h \
3536 outputStreamMAPIAdapter.h \
3637 inputStreamMAPIAdapter.h \
7878 static const char im_charset_unspec[] = "unspecified";
7979
8080 /**
81 * VMIMEToMAPI default constructor
82 *
8381 * Default empty constructor for the inetmapi library. Sets all member
8482 * values to sane defaults.
8583 */
9391 }
9492
9593 /**
96 * VMIMEToMAPI parameterized constructor.
97 *
9894 * Adds user set addressbook (to minimize opens on this object) and delivery options.
9995 *
10096 * @param[in] lpAdrBook Addressbook of a user.
114110 m_lpDefaultDir = NULL;
115111 }
116112
117 /**
118 * VMIMEToMAPI destructor.
119 */
120113 VMIMEToMAPI::~VMIMEToMAPI()
121114 {
122115 lpLogger->Release();
245238 MAPI_CREATE|MAPI_MODIFY, (LPUNKNOWN *)&lpStream);
246239 if (hr != hrSuccess)
247240 goto exit;
248
249241
250242 outputStreamMAPIAdapter os(lpStream);
251243 // get the content-type string from the headers
11741166 return hr;
11751167 }
11761168
1177
11781169 /**
11791170 * Adds recipients from a vmime list to rows for the recipient
11801171 * table. Starts adding at offset in cEntries member of the lpRecipients
13801371 goto exit;
13811372 }
13821373
1383
13841374 if (!m_lpDefaultDir) {
13851375 hr = m_lpAdrBook->GetDefaultDir(&cbDDEntryID, &lpDDEntryID);
13861376 if (hr != hrSuccess)
15101500 }
15111501 ++cValues;
15121502 }
1513
15141503
15151504 if (PROP_TYPE(lpPropsList->aulPropTag[6]) != PT_NULL) {
15161505 lpProp = PpropFindProp(lpAdrList->aEntries[0].rgPropVals, lpAdrList->aEntries[0].cValues, PR_SMTP_ADDRESS_W);
17711760 sAttProps[2].ulPropTag = PR_ATTACH_FLAGS;
17721761 sAttProps[2].Value.ul = 0;
17731762
1774 hr = ptrAttach->SetProps(3, (LPSPropValue)sAttProps, NULL);
1763 hr = ptrAttach->SetProps(3, sAttProps, NULL);
17751764 if (hr != hrSuccess) {
17761765 lpLogger->Log(EC_LOGLEVEL_ERROR, "dissect_ical-1811: Unable to create message attachment for ical data: %s (%x)", GetMAPIErrorMessage(hr), hr);
17771766 goto exit;
25602549 return hr;
25612550 }
25622551
2563
25642552 /**
25652553 * Handle Attachments.. Now works for inlines and attachments...
25662554 *
27932781 static vmime::charset vtm_upgrade_charset(const vmime::charset &cset)
27942782 {
27952783 for (size_t i = 0; i < ARRAY_SIZE(charsetHelper::fixes); ++i)
2796 if (stricmp(charsetHelper::fixes[i].original, cset.getName().c_str()) == 0)
2784 if (strcasecmp(charsetHelper::fixes[i].original, cset.getName().c_str()) == 0)
27972785 return charsetHelper::fixes[i].update;
27982786
27992787 return cset;
28422830 while (isspace(*in)) /* skip WS after ';' */
28432831 ++in;
28442832 }
2845 if (strnicmp(in, "charset=", 8) == 0) {
2833 if (strncasecmp(in, "charset=", 8) == 0) {
28462834 in += 8;
28472835 cset = in;
28482836 while (!isspace(*in) && *in != ';' && *in != '\0')
30783066 if (hr != hrSuccess)
30793067 goto exit;
30803068
3081 if (strnicmp(lpMessageClass->Value.lpszA, "IPM.Schedule.Meeting.", strlen( "IPM.Schedule.Meeting." )) == 0)
3069 if (strncasecmp(lpMessageClass->Value.lpszA, "IPM.Schedule.Meeting.", strlen( "IPM.Schedule.Meeting." )) == 0)
30823070 {
30833071 // IPM.Schedule.Meeting.*
30843072
34793467
34803468 // ((cc),(cc))
34813469 try {
3482 list<string> lAddr;
34833470 vmime::ref<vmime::addressList> aList = vmHeader->Cc()->getValue().dynamicCast<vmime::addressList>();
34843471 int aCount = aList->getAddressCount();
34853472 for (int i = 0; i < aCount; ++i)
34923479
34933480 // ((bcc),(bcc))
34943481 try {
3495 list<string> lAddr;
34963482 vmime::ref<vmime::addressList> aList = vmHeader->Bcc()->getValue().dynamicCast<vmime::addressList>();
34973483 int aCount = aList->getAddressCount();
34983484 for (int i = 0; i < aCount; ++i)
36123598
36133599 lBodyStructure.clear();
36143600 lBodyStructure.push_back(strBodyStructure);
3615
36163601
36173602 // body:
36183603 // (<SUB> "subtype")
38713856 return lines;
38723857 }
38733858
3874
38753859 // options.h code
38763860 /**
38773861 * Set all members in the delivery_options struct to their defaults
39063890 sopt->charset_upgrade = const_cast<char *>("windows-1252");
39073891 sopt->allow_send_to_everyone = true;
39083892 sopt->enable_dsn = true;
3909 }
3893 sopt->always_expand_distr_list = false;
3894 }
217217 return hr;
218218 }
219219
220
221220 // Read properties from lpMessage object and to internet rfc2822 format message
222221 // then send it using the provided ECSender object
223222 INETMAPI_API HRESULT IMToINet(IMAPISession *lpSession, IAddrBook *lpAddrBook, IMessage *lpMessage, ECSender *mailer_base, sending_options sopt, ECLogger *lpLogger)
3737 {
3838 vmime::defaultAttachment::generatePart(part);
3939
40
4140 part->getHeader()->ContentDisposition().dynamicCast <vmime::contentDispositionField>()->setFilename(m_filename);
4241
4342 vmime::ref<vmime::contentTypeField> ctf = part->getHeader()->ContentType().dynamicCast <vmime::contentTypeField>();
5151 #include "vmime/emptyContentHandler.hpp"
5252 #include "vmime/stringContentHandler.hpp"
5353
54
5554 namespace vmime
5655 {
5756
8281 else
8382 return (mediaType(mediaTypes::TEXT, mediaTypes::TEXT_HTML));
8483 }
85
8684
8785 int mapiTextPart::getPartCount() const
8886 {
9694 return count;
9795 }
9896
99
10097 void mapiTextPart::generateIn(ref <bodyPart> /* message */, ref <bodyPart> parent) const
10198 {
10299 // Plain text
194191 }
195192 }
196193
197
198194 void mapiTextPart::findEmbeddedParts(const bodyPart& part,
199195 std::vector <ref <const bodyPart> >& cidParts, std::vector <ref <const bodyPart> >& locParts)
200196 {
227223 findEmbeddedParts(*p, cidParts, locParts);
228224 }
229225 }
230
231226
232227 void mapiTextPart::addEmbeddedObject(const bodyPart& part, const string& id)
233228 {
253248 part.getBody()->getEncoding(), id, type, string(), string()));
254249 }
255250
256
257251 void mapiTextPart::parse(ref <const bodyPart> message, ref <const bodyPart> parent, ref <const bodyPart> textPart)
258252 {
259253 // Search for possible embedded objects in the _whole_ message.
328322 m_plainText = vmime::create <emptyContentHandler>();
329323 }
330324 }
331
332325
333326 bool mapiTextPart::findPlainTextPart(const bodyPart& part, const bodyPart& parent, const bodyPart& textPart)
334327 {
462455 throw exceptions::no_object_found();
463456 }
464457
465
466458 bool mapiTextPart::hasObject(const string& id_) const
467459 {
468460 const string id = cleanId(id_);
477469 return false;
478470 }
479471
480
481472 const string mapiTextPart::addObject(ref <contentHandler> data,
482473 const encoding& enc, const mediaType& type)
483474 {
487478 return "CID:" + addObject(data, enc, type, id);
488479 }
489480
490
491481 const string mapiTextPart::addObject(ref <contentHandler> data, const mediaType& type)
492482 {
493483 return addObject(data, encoding::decide(data), type);
494484 }
495
496485
497486 const string mapiTextPart::addObject(const string& data, const mediaType& type)
498487 {
505494 m_objects.push_back(vmime::create <embeddedObject>(data, enc, id, type, name, loc));
506495 return (id);
507496 }
508
509497
510498 // static
511499 const string mapiTextPart::cleanId(const string& id)
524512 }
525513 }
526514
527
528
529515 //
530516 // mapiTextPart::embeddedObject
531517 //
8282 static const char *FindMAPIClassByScheduleClass(const char *szSClass)
8383 {
8484 for (size_t i = 0; i < ARRAY_SIZE(sClassMap); ++i)
85 if(stricmp(szSClass, sClassMap[i].szScheduleClass) == 0) {
85 if(strcasecmp(szSClass, sClassMap[i].szScheduleClass) == 0) {
8686 return sClassMap[i].szMAPIClass;
8787 }
8888
8989 return NULL;
9090 }
91
92 #if 0
93 static const char *FindScheduleClassByMAPIClass(const char *szMAPIClass)
94 {
95 for (size_t i = 0; i < ARRAY_SIZE(sClassMap); ++i)
96 if(stricmp(szMAPIClass, sClassMap[i].szMAPIClass) == 0) {
97 return sClassMap[i].szScheduleClass;
98 }
99
100 return NULL;
101 }
102 #endif
10391
10492 /**
10593 * Returns TRUE if the given property tag is in the given property tag array
00 # -*- Makefile -*-
11
2 systemunit_DATA = kopano-dagent.service kopano-gateway.service \
2 systemunitdir = ${dcprefix}@systemunitdir@
3 sysusersdir = ${dcprefix}@sysusersdir@
4 tmpfilesdir = ${dcprefix}@tmpfilesdir@
5
6 dist_systemunit_DATA = kopano-dagent.service kopano-gateway.service \
37 kopano-ical.service kopano-monitor.service \
48 kopano-presence.service kopano-search.service \
59 kopano-server.service kopano-spooler.service
6 sysusers_DATA = kopano-sysusers.conf
7 tmpfiles_DATA = kopano-tmpfiles.conf
10 dist_sysusers_DATA = kopano-sysusers.conf
11 dist_tmpfiles_DATA = kopano-tmpfiles.conf
812
913 config_files = \
1014 server.cfg unix.cfg ldap.propmap.cfg presence.cfg \
5963 db-calc-storesize db-convert-attachments-to-files \
6064 createuser.dotforward ssl-certificates.sh ldap-switch-sendas.pl \
6165 audit-parse.pl db-remove-orphaned-attachments \
62 ${top_srcdir}/tools/python-scripts/optimize-imap.py ${top_srcdir}/tools/python-scripts/update-resource-recipients
66 ${top_srcdir}/tools/python-scripts/update-resource-recipients
67 kgwdocdir = ${docdir}/../kopano-gateway
68 dist_kgwdoc_DATA = ${top_srcdir}/tools/python-scripts/optimize-imap.py
6369
6470 BUILT_SOURCES = ldap.openldap.cfg ldap.active-directory.cfg
6571
8995 sysconf_certdir = ${sysconfdir}/kopano/report-ca
9096
9197 config_files += $(BUILT_SOURCES)
92 EXTRA_DIST = $(BUILT_SOURCES) \
98 EXTRA_DIST = ${BUILT_SOURCES} ldap.m4 \
9399 $(rhel_initscript_files) $(suse_initscript_files) $(cbs4_initscript_files) $(alt_initscript_files) \
94100 sysconfig.txt
95101
107113 newf=`echo "$$f" | sed -e 's/\(kopano-.*\).init.*/\1/'`; \
108114 mv -v "${DESTDIR}${sysconf_initdir}/$$f" "${DESTDIR}${sysconf_initdir}/$$newf"; \
109115 done
110 mkdir -p ${DESTDIR}/${docdir}/../kopano-gateway
111 mv -v ${DESTDIR}/${docdir}/optimize-imap.py ${DESTDIR}/${docdir}/../kopano-gateway
112 rm -f ${DESTDIR}/${sysconf_configdir}/example-msr.cfg
116
117 uninstall-local:
118 rm -f "${DESTDIR}${sysconf_rotatedir}/kopano" \
119 "${DESTDIR}${sysconf_crondir}/kopano-client-update"
120 if test ${DISTRO} = "sles" -o ${DISTRO} = "suse"; then \
121 rm -f "${DESTDIR}${sysconf_sysconfigdir}/sysconfig.kopano"; \
122 elif test ${DISTRO} = "rhel" -o ${DISTRO} = "alt"; then \
123 rm -f "${DESTDIR}${sysconf_sysconfigdir}/kopano"; \
124 fi
125 for f in ${sysconf_init_SCRIPTS}; do \
126 newf=$$(echo "$$f" | sed -e 's/\(kopano-.*\).init.*/\1/'); \
127 rm -f "${DESTDIR}${sysconf_initdir}/$$newf"; \
128 done
6363 $0 start
6464 ;;
6565 status)
66 status_of_proc "$PRESENCE" "$NAME" && exit 0 || exit $?
66 status_of_proc -p $PIDFILE "$PRESENCE" "$NAME" && exit 0 || exit $?
6767 ;;
6868 reload|force-reload)
6969 log_begin_msg "Reloading $DESC: $NAME"
6262 $0 start
6363 ;;
6464 status)
65 status_of_proc "$SEARCH" "$NAME" && exit 0 || exit $?
65 status_of_proc -p $PIDFILE "$SEARCH" "$NAME" && exit 0 || exit $?
6666 ;;
6767 reload|force-reload)
6868 log_begin_msg "Reloading $DESC: $NAME"
+0
-525
installer/linux/ldapms.active-directory.cfg less more
0 ##############################################################
1 # LDAP/ACTIVE DIRECTORY USER PLUGIN SETTINGS
2 #
3 # Any of these directives that are required, are only required if the
4 # userplugin parameter is set to ldap.
5
6 # LDAP host name/IP address
7 # Optional, default = localhost
8 #ldap_host =
9
10 # LDAP port
11 # Optional, default = 389
12 # Use 636 for ldaps
13 #ldap_port = 389
14
15 # LDAP protocol
16 # Optional, default = ldap
17 # use "ldaps" for SSL encryption. Make sure /etc/ldap/ldap.conf is
18 # configured correctly with TLS_CACERT
19 #ldap_protocol = ldap
20
21 # LDAP URI
22 # Optional, override ldap_host, ldap_port and ldap_protocol if set
23 # e.g. ldaps://servername:port. You may also specify multiple space-separated
24 # URIs
25 #ldap_uri =
26
27 # The charset that strings are stored in on the LDAP server. Normally this
28 # is utf-8, but this can differ according to your setup. The charset specified
29 # here must be supported by your iconv(1) setup. See iconv -l for all charset
30 #ldap_server_charset = utf-8
31
32 # The DN of the user to bind as for normal operations (not used for
33 # authentication if ldap_authentication_method is set to "bind"
34 # Optional, default = empty (anonymous bind)
35 # The userPassword attribute must be readable for this user if the
36 # ldap_authentication_method option is set to password.
37 #ldap_bind_user = cn=Administrator,cn=users,dc=kopano,dc=com
38
39 # LDAP bind password
40 # Optional, default = empty (no password)
41 #ldap_bind_passwd =
42
43 # The timeout for network operations in seconds
44 #ldap_network_timeout = 30
45
46 # When an object (user/group/company) is changed, this attribute will also change:
47 # Active directory: uSNChanged
48 # LDAP: modifyTimestamp
49 #ldap_last_modification_attribute = uSNChanged
50
51 # ldap_page_size limits the number of results from a query that will be downloaded at a time.
52 # Default ADS MaxPageSize is 1000.
53 #ldap_page_size = 1000
54
55 ##########
56 # Object settings
57
58 # Top level search base, every object should be available under this tree
59 #ldap_search_base = dc=kopano,dc=com
60
61 # attribute name which is/(should: was) used in ldap_user_search_filter
62 #ldap_object_type_attribute = objectClass
63 #ldap_user_type_attribute_value = user
64 #ldap_group_type_attribute_value = group
65 #ldap_contact_type_attribute_value = contact
66 #ldap_company_type_attribute_value = organizationalUnit
67 #ldap_addresslist_type_attribute_value = kopanoAddresslist
68 #ldap_dynamicgroup_type_attribute_value = kopanoDynamicGroup
69 #ldap_server_type_attribute_value = computer
70
71 ##########
72 # There should be no need to edit any values below this line
73 ##########
74
75 ##########
76 # User settings
77
78 # Extra search for users using this LDAP filter. See ldap_search(3) or RFC
79 # 2254 for details on the filter syntax.
80 #
81 # Hint: Use the kopanoAccount attribute in the filter to differentiate
82 # between non-kopano and kopano users.
83 #
84 # Note: This filter should include contacts.
85 #
86 # Optional, default = empty (match everything)
87 # For active directory, use:
88 # (objectCategory=Person)
89 # For LDAP with posix users:
90 # no need to use the search filter.
91 #ldap_user_search_filter = (objectCategory=Person)
92
93 # unique user id for find the user
94 # Required
95 # For active directory, use:
96 # objectGuid ** WARNING: This WAS: objectSid ** Updates *WILL* fail! **
97 # For LDAP with posixAccount, use:
98 # uidNumber
99 #ldap_user_unique_attribute = objectGuid
100
101 # Type of unique user id
102 # default: text
103 # For active directory, use:
104 # binary
105 # For LDAP with posix user, use:
106 # text
107 #ldap_user_unique_attribute_type = binary
108
109 # Optional, default = cn
110 # For active directory, use:
111 # cn or displayName
112 # For LDAP with posix user, use:
113 # cn
114 #ldap_fullname_attribute = cn
115
116 # Optional, default = uid
117 # Active directory: sAMAccountName
118 # LDAP: uid
119 #ldap_loginname_attribute = sAMAccountName
120
121 # Optional, default = userPassword
122 # Active directory: unicodePwd
123 # LDAP: userPassword
124 #ldap_password_attribute = unicodePwd
125
126 # If set to bind, users are authenticated by trying to bind to the
127 # LDAP tree using their username + password. Otherwise, the
128 # ldap_password_attribute is requested and checked.
129 # Optional, default = bind
130 # Choices: bind, password
131 # Active directory: bind
132 # LDAP: bind
133 #ldap_authentication_method = bind
134
135 # Optional, default = mail
136 # Active directory: mail
137 # LDAP: mail
138 #ldap_emailaddress_attribute = mail
139
140 # Optional, default = kopanoAliases
141 # Active directory: kopanoAliases
142 # LDAP: kopanoAliases
143 #ldap_emailaliases_attribute = otherMailbox
144
145 # Whether the user is an admin. The field is interpreted as a
146 # boolean, 0 and false (case insensitive) meaning no, all other values
147 # yes.
148 # Optional, default = kopanoAdmin
149 # Active directory: kopanoAdmin
150 # LDAP: kopanoAdmin
151 #ldap_isadmin_attribute = kopanoAdmin
152
153 # Whether a user is a non-active user. This means that the user will
154 # not count towards your user count, but the user will also not be
155 # able to log in
156 # Optional, default = kopanoSharedStoreOnly
157 # Active directory: kopanoSharedStoreOnly
158 # LDAP: kopanoSharedStoreOnly
159 #ldap_nonactive_attribute = kopanoSharedStoreOnly
160
161 # A nonactive store, or resource, can be specified to be a user, room or equipment.
162 # Set it to "room" or "equipment" to make such types. If set to empty,
163 # or wrong word, or "user" it will be a nonactive user.
164 # Optional, default = kopanoResourceType
165 # Active directory: kopanoResourceType
166 # LDAP: kopanoResourceType
167 #ldap_resource_type_attribute = kopanoResourceType
168
169 # Numeric resource capacity
170 # Optional, default = kopanoResourceCapacity
171 # Active directory: kopanoResourceCapacity
172 # LDAP: kopanoResourceCapacity
173 #ldap_resource_capacity_attribute = kopanoResourceCapacity
174
175 # Optional
176 # The attribute which indicates which users are allowed
177 # to send on behalf of the selected user
178 #ldap_sendas_attribute = kopanoSendAsPrivilege
179
180 # Optional, default = text
181 # Active directory: dn
182 # LDAP: text
183 #ldap_sendas_attribute_type = dn
184
185 # The attribute of the user and group which is listed in
186 # the ldap_sendas_attribute
187 # Empty default, using ldap_user_unique_attribute
188 #ldap_sendas_relation_attribute = distinguishedName
189
190 # Optional, default = userCertificate
191 # Active directory: userCertificate
192 # LDAP: userCertificate;binary
193 #ldap_user_certificate_attribute = userCertificate
194
195 # Load extra user properties from the propmap file
196 !propmap /etc/kopano/ldap.propmap.cfg
197
198 ##########
199 # Group settings
200
201 # Search for groups using this LDAP filter. See ldap_search(3) for
202 # details on the filter syntax.
203 # Hint: Use the kopanoAccount attribute in the filter to differentiate
204 # between non-kopano and kopano groups.
205 # Optional, default = empty (match everything)
206 # For active directory, use:
207 # (objectCategory=Group)
208 # For LDAP with posix groups, use:
209 # no need to set the search filter
210 #ldap_group_search_filter = (objectCategory=Group)
211
212 # unique group id for find the group
213 # Required
214 # For active directory, use:
215 # objectSid
216 # For LDAP with posix group, use:
217 # gidNumber
218 #ldap_group_unique_attribute = objectSid
219
220 # Type of unique group id
221 # default: text
222 # For active directory, use:
223 # binary
224 # For LDAP with posix group, use:
225 # text
226 #ldap_group_unique_attribute_type = binary
227
228 # Optional, default = cn
229 # Active directory: cn
230 # LDAP: cn
231 #ldap_groupname_attribute = cn
232
233 # Optional, default = member
234 # Active directory: member
235 # LDAP: memberUid
236 #ldap_groupmembers_attribute = member
237
238 # Optional, default = text
239 # Active directory: dn
240 # LDAP: text
241 #ldap_groupmembers_attribute_type = dn
242
243 # The attribute of the user which is listed in ldap_groupmember_attribute
244 # Active directory: empty, matching DNs
245 # LDAP: uid, matching users in ldap_loginname_attribute
246 #ldap_groupmembers_relation_attribute =
247
248 # A group can also be used for security, eg. setting permissions on folders.
249 # This makes a group a security group. The kopanoSecurityGroup value is boolean.
250 # Optional, default = kopanoSecurityGroup
251 # Active directory = groupType
252 # LDAP: kopanoSecurityGroup
253 #ldap_group_security_attribute = groupType
254
255 # In ADS servers, a special bitmask action is required on the groupType field.
256 # This is actived by setting the ldap_group_security_attribute_type to "ads"
257 # Otherwise, just the presence of the field will make the group security enabled.
258 # Optional, default = boolean
259 # Active directory = ads
260 # LDAP: boolean
261 #ldap_group_security_attribute_type = ads
262
263 ##########
264 # Company settings
265
266 # Search for companies using this LDAP filter.
267 # Hint: Use the kopanoAccount attribute in the filter to differentiate
268 # between non-kopano and kopano companies.
269 # Optional, default = empty (match everything)
270 # For active directory, use:
271 # (objectCategory=Company)
272 # For LDAP with posix users, use:
273 # no need to set the filter
274 #ldap_company_search_filter =
275
276 # unique company id for find the company
277 # Active directory: objectGUID
278 # LDAP: ou
279 #ldap_company_unique_attribute = objectGUID
280
281 # Optional, default = text
282 # Active directory: binary
283 # LDAP: text
284 #ldap_company_unique_attribute_type = binary
285
286 # Optional, default = ou
287 # Active directory: ou
288 # LDAP: ou
289 #ldap_companyname_attribute = ou
290
291 # Optional
292 # The attribute which indicates which companies are allowed
293 # to view the members of the selected company
294 #ldap_company_view_attribute = kopanoViewPrivilege
295
296 # Optional, default = text
297 #ldap_company_view_attribute_type = dn
298
299 # The attribute of the company which is listed in the
300 # ldap_company_view_attribute
301 # Empty default, using ldap_company_unique_attribute
302 #ldap_company_view_relation_attribute =
303
304 # Optional
305 # The attribute which indicates which users from different companies
306 # are administrator over the selected company.
307 #ldap_company_admin_attribute = kopanoAdminPrivilege
308
309 # Optional, default = text
310 # Active directory: dn
311 # LDAP: text
312 #ldap_company_admin_attribute_type = dn
313
314 # The attribute of the company which is listed in the
315 # ldap_company_admin_attribute
316 # Empty default, using ldap_user_unique_attribute
317 #ldap_company_admin_relation_attribute =
318
319 # The attribute which indicates which user is the system administrator
320 # for the specified company.
321 #ldap_company_system_admin_attribute = kopanoSystemAdmin
322
323 # Optional, default = text
324 # Active directory: dn
325 # LDAP: text
326 #ldap_company_system_admin_attribute_type = dn
327
328 # The attribute of the company which is listed in the
329 # ldap_company_system_admin attribute
330 # Empty default, using ldap_user_unique_attribute
331 #ldap_company_system_admin_relation_attribute =
332
333
334 ##########
335 # Addresslist settings
336
337 # Add a filter to the addresslist search
338 # Hint: Use the kopanoAccount attribute in the filter to differentiate
339 # between non-kopano and kopano addresslists.
340 # Optional, default = empty (match everything)
341 #ldap_addresslist_search_filter =
342
343 # This is the unique attribute of a addresslist which is never going
344 # to change, unless the addresslist is removed from LDAP. When this
345 # value changes, Kopano will remove the previous addresslist from the
346 # database, and create a new addresslist with this unique value
347 #ldap_addresslist_unique_attribute = cn
348
349 # This value can be "text" or "binary". For OpenLDAP, only text is used.
350 #ldap_addresslist_unique_attribute_type = text
351
352 # This is the name of the attribute on the addresslist object that
353 # specifies the filter to be applied for this addresslist. All users
354 # matching this filter AND matching the default
355 # ldap_user_search_filter will be included in the addresslist
356 #ldap_addresslist_filter_attribute = kopanoFilter
357
358 # This is the name of the attribute on the addresslist object that
359 # specifies the search base to be applied for this addresslist.
360 #ldap_addresslist_search_base_attribute = kopanoBase
361
362 # The attribute containing the name of the addresslist
363 #ldap_addresslist_name_attribute = cn
364
365
366 ##########
367 # Dynamicgroup settings
368
369 # Add a filter to the dynamicgroup search
370 # Hint: Use the kopanoAccount attribute in the filter to differentiate
371 # between non-kopano and kopano dynamic groups.
372 # Optional, default = empty (match everything)
373 #ldap_dynamicgroup_search_filter =
374
375 # This is the unique attribute of a dynamicgroup which is never going
376 # to change, unless the dynamicgroup is removed from LDAP. When this
377 # value changes, Kopano will remove the previous dynamicgroup from the
378 # database, and create a new dynamicgroup with this unique value
379 #ldap_dynamicgroup_unique_attribute = cn
380
381 # This value can be "text" or "binary". For OpenLDAP, only text is used.
382 #ldap_dynamicgroup_unique_attribute_type = text
383
384 # This is the name of the attribute on the dynamicgroup object that
385 # specifies the filter to be applied for this dynamicgroup. All users
386 # matching this filter AND matching the default
387 # ldap_user_search_filter will be included in the dynamicgroup
388 #ldap_dynamicgroup_filter_attribute = kopanoFilter
389
390 # This is the name of the attribute on the dynamicgroup object that
391 # specifies the search base to be applied for this dynamicgroup.
392 #ldap_dynamicgroup_search_base_attribute = kopanoBase
393
394 # The attribute containing the name of the dynamicgroup
395 #ldap_dynamicgroup_name_attribute = cn
396
397
398 ##########
399 # Quota settings
400
401 # Optional
402 # The attribute which indicates which users (besides the user who exceeds his quota)
403 # should also receive a warning mail when a user exceeds his quota.
404 #ldap_quota_userwarning_recipients_attribute = kopanoQuotaUserWarningRecipients
405
406 # Optional, default = text
407 # Active directory: dn
408 # LDAP: text
409 #ldap_quota_userwarning_recipients_attribute_type = text
410
411 # Optional, default empty
412 #ldap_quota_userwarning_recipients_relation_attribute =
413
414 # Optional
415 # The attribute which indicates which users should receive a warning mail
416 # when a company exceeds his quota.
417 #ldap_quota_companywarning_recipients_attribute = kopanoQuotaCompanyWarningRecipients
418
419 # Optional, default = text
420 # Active directory: dn
421 # LDAP: text
422 #ldap_quota_companywarning_recipients_attribute_type = text
423
424 # Optional, default empty
425 #ldap_quota_companywarning_recipients_relation_attribute =
426
427 # Whether to override the system wide quota settings
428 #ldap_quotaoverride_attribute = kopanoQuotaOverride
429
430 #ldap_warnquota_attribute = kopanoQuotaWarn
431 #ldap_softquota_attribute = kopanoQuotaSoft
432 #ldap_hardquota_attribute = kopanoQuotaHard
433
434 # Whether to override the system wide quota settings for all users within the company
435 #ldap_userdefault_quotaoverride_attribute = kopanoUserDefaultQuotaOverride
436
437 #ldap_userdefault_warnquota_attribute = kopanoUserDefaultQuotaWarn
438 #ldap_userdefault_softquota_attribute = kopanoUserDefaultQuotaSoft
439 #ldap_userdefault_hardquota_attribute = kopanoUserDefaultQuotaHard
440
441 # Mapping from the quota attributes to a number of bytes. Qmail-LDAP
442 # schema uses bytes (1), ADS uses kilobytes (1024*1024).
443 #ldap_quota_multiplier = 1048576
444
445 ##########
446 # Misc. settings
447
448 # Attribute which indicates if the user should be hidden from addressbook
449 #ldap_addressbook_hide_attribute = kopanoHidden
450
451 # LDAP object search filter. %s in this filter will be replaced with
452 # the object being searched.
453 # Hint: Use the kopanoAccount attribute in the filter to differentiate
454 # between non-kopano and kopano objects.
455 # Default: empty
456 # ADS recommended: (anr=%s)
457 # OpenLDAP optional: (|(mail=%s*)(uid=%s*)(cn=*%s*)(fullname=*%s*)(givenname=*%s*)(lastname=*%s*)(sn=*%s*))
458 #ldap_object_search_filter = (anr=%s)
459
460 # If a request want more objects than this value, it will download the
461 # full ldap tree (from the base with the search filter) and discard
462 # wat was not required. This is faster for large requests.
463 # Default: 1000
464 #ldap_filter_cutoff_elements = 1000
465
466 ##########
467 # Multi-server settings
468
469 # Users will be created on this named server
470 # Optional, default kopanoUserServer
471 #ldap_user_server_attribute = kopanoUserServer
472
473 # The public store of the company will be created on this named server
474 # Optional, default kopanoCompanyServer
475 #ldap_company_server_attribute = kopanoCompanyServer
476
477 # Optional
478 # Active directory: kopanoHostAddress
479 # LDAP: ipHostNumber
480 #ldap_server_address_attribute = kopanoHostAddress
481
482 # Optional, default = kopanoHttpPort
483 # Active directory: kopanoHttpPort
484 # LDAP: kopanoHttpPort
485 #ldap_server_http_port_attribute = kopanoHttpPort
486
487 # Optional, default = kopanoSslPort
488 # Active directory: kopanoSslPort
489 # LDAP: kopanoSslPort
490 #ldap_server_ssl_port_attribute = kopanoSslPort
491
492 # Optional, default = kopanoFilePath
493 # Active directory: kopanoFilePath
494 #LDAP: kopanoFilePath
495 #ldap_server_file_path_attribute = kopanoFilePath
496
497 # Determines if a server contains the public store of a non-hosted
498 # environment. Only one server is allowed to host the public store.
499 # Optional, default = kopanoContainsPublic
500 # Active directory: kopanoContainsPublic
501 # LDAP: kopanoContainsPublic
502 #ldap_server_contains_public_attribute = kopanoContainsPublic
503
504 # The Proxy URL of the node; the node must be available to clients
505 # using this Proxy URL if the server detects that original connection
506 # was received via a proxy. See server.cfg(5)'s proxy_header setting
507 #ldap_server_proxy_path_attribute = kopanoProxyURL
508
509 # Search for servers using this LDAP filter. See ldap_search(3) or RFC
510 # 2254 for details on the filter syntax.
511 # Optional, default = empty (match everything)
512 # For active directory, use:
513 # (objectCategory=Computer)
514 # For LDAP with posix users, use:
515 #
516 #ldap_server_search_filter = (objectCategory=Computer)
517
518 # Unique user id to find the server
519 # Required
520 # For active directory, use:
521 # CN
522 # For LDAP with posixAccount, use:
523 # cn
524 #ldap_server_unique_attribute = cn
+0
-528
installer/linux/ldapms.openldap.cfg less more
0 ##############################################################
1 # LDAP/ACTIVE DIRECTORY USER PLUGIN SETTINGS
2 #
3 # Any of these directives that are required, are only required if the
4 # userplugin parameter is set to ldap.
5
6 # LDAP host name/IP address
7 # Optional, default = localhost
8 #ldap_host = localhost
9
10 # LDAP port
11 # Optional, default = 389
12 # Use 636 for ldaps
13 #ldap_port = 389
14
15 # LDAP protocol
16 # Optional, default = ldap
17 # use 'ldaps' for SSL encryption. Make sure /etc/ldap/ldap.conf is
18 # configured correctly with TLS_CACERT
19 #ldap_protocol = ldap
20
21 # LDAP URI
22 # Optional, override ldap_host, ldap_port and ldap_protocol if set
23 # e.g. ldaps://servername:port. You may also specify multiple space-separated
24 # URI's
25 #ldap_uri =
26
27 # The charset that strings are stored in on the LDAP server. Normally this
28 # is utf-8, but this can differ according to your setup. The charset specified
29 # here must be supported by your iconv(1) setup. See iconv -l for all charset
30 #ldap_server_charset = utf-8
31
32 # The DN of the user to bind as for normal operations (not used for
33 # authentication if ldap_authentication_method is set to "bind"
34 # Optional, default = empty (anonymous bind)
35 # The userPassword attribute must be readable for this user if the
36 # ldap_authentication_method option is set to password.
37 #ldap_bind_user = cn=admin,cn=users,dc=kopano,dc=com
38
39 # LDAP bind password
40 # Optional, default = empty (no password)
41 #ldap_bind_passwd =
42
43 # The timeout for network operations in seconds
44 #ldap_network_timeout = 30
45
46 # When an object (user/group/company) is changed, this attribute will also change:
47 # Active directory: uSNChanged
48 # LDAP: modifyTimestamp
49 #ldap_last_modification_attribute = modifyTimestamp
50
51 # ldap_page_size limits the number of results from a query that will be downloaded at a time.
52 # Default ADS MaxPageSize is 1000.
53 #ldap_page_size = 1000
54
55 ##########
56 # Object settings
57
58 # Top level search base, every object should be available under this tree
59 #ldap_search_base = dc=kopano,dc=com
60
61 # attribute name which is/(should: was) used in ldap_user_search_filter
62 #ldap_object_type_attribute = objectClass
63 #ldap_user_type_attribute_value = posixAccount
64 #ldap_group_type_attribute_value = posixGroup
65 #ldap_contact_type_attribute_value = kopano-contact
66 #ldap_company_type_attribute_value = organizationalUnit
67 #ldap_addresslist_type_attribute_value = kopano-addresslist
68 #ldap_dynamicgroup_type_attribute_value = kopano-dynamicgroup
69 #ldap_server_type_attribute_value = ipHost
70
71 ##########
72 # There should be no need to edit any values below this line
73 ##########
74
75 ##########
76 # User settings
77
78 # Extra search for users using this LDAP filter. See ldap_search(3) or RFC
79 # 2254 for details on the filter syntax.
80 #
81 # Hint: Use the kopanoAccount attribute in the filter to differentiate
82 # between non-kopano and kopano users.
83 #
84 # Note: This filter should include contacts.
85 #
86 # Optional, default = empty (match everything)
87 # For active directory, use:
88 # (objectCategory=Person)
89 # For LDAP with posix users:
90 # no need to use the search filter.
91 #ldap_user_search_filter =
92
93 # unique user id for find the user
94 # Required
95 # For active directory, use:
96 # objectGuid ** WARNING: This WAS: objectSid ** Updates *WILL* fail! **
97 # For LDAP with posixAccount, use:
98 # uidNumber
99 # Note: contacts also use this field for uniqueness. If you change this,
100 # you might need to update the kopano.schema file too, and change
101 # the MUST uidNumber to whatever you set here.dnl
102 #ldap_user_unique_attribute = uidNumber
103
104 # Type of unique user id
105 # default: text
106 # For active directory, use:
107 # binary
108 # For LDAP with posix user, use:
109 # text
110 #ldap_user_unique_attribute_type = text
111
112 # Optional, default = cn
113 # For active directory, use:
114 # cn or displayName
115 # For LDAP with posix user, use:
116 # cn
117 #ldap_fullname_attribute = cn
118
119 # Optional, default = uid
120 # Active directory: sAMAccountName
121 # LDAP: uid
122 #ldap_loginname_attribute = uid
123
124 # Optional, default = userPassword
125 # Active directory: unicodePwd
126 # LDAP: userPassword
127 #ldap_password_attribute = userPassword
128
129 # If set to bind, users are authenticated by trying to bind to the
130 # LDAP tree using their username + password. Otherwise, the
131 # ldap_password_attribute is requested and checked.
132 # Optional, default = bind
133 # Choices: bind, password
134 # Active directory: bind
135 # LDAP: bind
136 #ldap_authentication_method = bind
137
138 # Optional, default = mail
139 # Active directory: mail
140 # LDAP: mail
141 #ldap_emailaddress_attribute = mail
142
143 # Optional, default = kopanoAliases
144 # Active directory: kopanoAliases
145 # LDAP: kopanoAliases
146 #ldap_emailaliases_attribute = kopanoAliases
147
148 # Whether the user is an admin. The field is interpreted as a
149 # boolean, 0 and false (case insensitive) meaning no, all other values
150 # yes.
151 # Optional, default = kopanoAdmin
152 # Active directory: kopanoAdmin
153 # LDAP: kopanoAdmin
154 #ldap_isadmin_attribute = kopanoAdmin
155
156 # Whether a user is a non-active user. This means that the user will
157 # not count towards your user count, but the user will also not be
158 # able to log in
159 # Optional, default = kopanoSharedStoreOnly
160 # Active directory: kopanoSharedStoreOnly
161 # LDAP: kopanoSharedStoreOnly
162 #ldap_nonactive_attribute = kopanoSharedStoreOnly
163
164 # A nonactive store, or resource, can be specified to be a user, room or equipment.
165 # Set it to 'room' or 'equipment' to make such types. If set to empty,
166 # or wrong word, or 'user' it will be a nonactive user.
167 # Optional, default = kopanoResourceType
168 # Active directory: kopanoResourceType
169 # LDAP: kopanoResourceType
170 #ldap_resource_type_attribute = kopanoResourceType
171
172 # Numeric resource capacity
173 # Optional, default = kopanoResourceCapacity
174 # Active directory: kopanoResourceCapacity
175 # LDAP: kopanoResourceCapacity
176 #ldap_resource_capacity_attribute = kopanoResourceCapacity
177
178 # Optional
179 # The attribute which indicates which users are allowed
180 # to send on behalf of the selected user
181 #ldap_sendas_attribute = kopanoSendAsPrivilege
182
183 # Optional, default = text
184 # Active directory: dn
185 # LDAP: text
186 #ldap_sendas_attribute_type = text
187
188 # The attribute of the user and group which is listed in
189 # the ldap_sendas_attribute
190 # Empty default, using ldap_user_unique_attribute
191 #ldap_sendas_relation_attribute =
192
193 # Optional, default = userCertificate
194 # Active directory: userCertificate
195 # LDAP: userCertificate;binary
196 #ldap_user_certificate_attribute = userCertificate;binary
197
198 # Load extra user properties from the propmap file
199 !propmap /etc/kopano/ldap.propmap.cfg
200
201 ##########
202 # Group settings
203
204 # Search for groups using this LDAP filter. See ldap_search(3) for
205 # details on the filter syntax.
206 # Hint: Use the kopanoAccount attribute in the filter to differentiate
207 # between non-kopano and kopano groups.
208 # Optional, default = empty (match everything)
209 # For active directory, use:
210 # (objectCategory=Group)
211 # For LDAP with posix groups, use:
212 # no need to set the search filter
213 #ldap_group_search_filter =
214
215 # unique group id for find the group
216 # Required
217 # For active directory, use:
218 # objectSid
219 # For LDAP with posix group, use:
220 # gidNumber
221 #ldap_group_unique_attribute = gidNumber
222
223 # Type of unique group id
224 # default: text
225 # For active directory, use:
226 # binary
227 # For LDAP with posix group, use:
228 # text
229 #ldap_group_unique_attribute_type = text
230
231 # Optional, default = cn
232 # Active directory: cn
233 # LDAP: cn
234 #ldap_groupname_attribute = cn
235
236 # Optional, default = member
237 # Active directory: member
238 # LDAP: memberUid
239 #ldap_groupmembers_attribute = memberUid
240
241 # Optional, default = text
242 # Active directory: dn
243 # LDAP: text
244 #ldap_groupmembers_attribute_type = text
245
246 # The attribute of the user which is listed in ldap_groupmember_attribute
247 # Active directory: empty, matching dn's
248 # LDAP: uid, matching users in ldap_loginname_attribute
249 #ldap_groupmembers_relation_attribute = uid
250
251 # A group can also be used for security, eg. setting permissions on folders.
252 # This makes a group a security group. The kopanoSecurityGroup value is boolean.
253 # Optional, default = kopanoSecurityGroup
254 # Active directory = groupType
255 # LDAP: kopanoSecurityGroup
256 #ldap_group_security_attribute = kopanoSecurityGroup
257
258 # In ADS servers, a special bitmask action is required on the groupType field.
259 # This is actived by setting the ldap_group_security_attribute_type to `''ads`''
260 # Otherwise, just the presence of the field will make the group security enabled.
261 # Optional, default = boolean
262 # Active directory = ads
263 # LDAP: boolean
264 #ldap_group_security_attribute_type = boolean
265
266 ##########
267 # Company settings
268
269 # Search for companies using this LDAP filter.
270 # Hint: Use the kopanoAccount attribute in the filter to differentiate
271 # between non-kopano and kopano companies.
272 # Optional, default = empty (match everything)
273 # For active directory, use:
274 # (objectCategory=Company)
275 # For LDAP with posix users, use:
276 # no need to set the filter
277 #ldap_company_search_filter =
278
279 # unique company id for find the company
280 # Active directory: objectGUID
281 # LDAP: ou
282 #ldap_company_unique_attribute = ou
283
284 # Optional, default = text
285 # Active directory: binary
286 # LDAP: text
287 #ldap_company_unique_attribute_type = text
288
289 # Optional, default = ou
290 # Active directory: ou
291 # LDAP: ou
292 #ldap_companyname_attribute = ou
293
294 # Optional
295 # The attribute which indicates which companies are allowed
296 # to view the members of the selected company
297 #ldap_company_view_attribute = kopanoViewPrivilege
298
299 # Optional, default = text
300 #ldap_company_view_attribute_type = text
301
302 # The attribute of the company which is listed in the
303 # ldap_company_view_attribute
304 # Empty default, using ldap_company_unique_attribute
305 #ldap_company_view_relation_attribute =
306
307 # Optional
308 # The attribute which indicates which users from different companies
309 # are administrator over the selected company.
310 #ldap_company_admin_attribute = kopanoAdminPrivilege
311
312 # Optional, default = text
313 # Active directory: dn
314 # LDAP: text
315 #ldap_company_admin_attribute_type = text
316
317 # The attribute of the company which is listed in the
318 # ldap_company_admin_attribute
319 # Empty default, using ldap_user_unique_attribute
320 #ldap_company_admin_relation_attribute =
321
322 # The attribute which indicates which user is the system administrator
323 # for the specified company.
324 #ldap_company_system_admin_attribute = kopanoSystemAdmin
325
326 # Optional, default = text
327 # Active directory: dn
328 # LDAP: text
329 #ldap_company_system_admin_attribute_type = text
330
331 # The attribute of the company which is listed in the
332 # ldap_company_system_admin attribute
333 # Empty default, using ldap_user_unique_attribute
334 #ldap_company_system_admin_relation_attribute =
335
336
337 ##########
338 # Addresslist settings
339
340 # Add a filter to the addresslist search
341 # Hint: Use the kopanoAccount attribute in the filter to differentiate
342 # between non-kopano and kopano addresslists.
343 # Optional, default = empty (match everything)
344 #ldap_addresslist_search_filter =
345
346 # This is the unique attribute of a addresslist which is never going
347 # to change, unless the addresslist is removed from LDAP. When this
348 # value changes, Kopano will remove the previous addresslist from the
349 # database, and create a new addresslist with this unique value
350 #ldap_addresslist_unique_attribute = cn
351
352 # This value can be 'text' or 'binary'. For OpenLDAP, only text is used.
353 #ldap_addresslist_unique_attribute_type = text
354
355 # This is the name of the attribute on the addresslist object that
356 # specifies the filter to be applied for this addresslist. All users
357 # matching this filter AND matching the default
358 # ldap_user_search_filter will be included in the addresslist
359 #ldap_addresslist_filter_attribute = kopanoFilter
360
361 # This is the name of the attribute on the addresslist object that
362 # specifies the search base to be applied for this addresslist.
363 #ldap_addresslist_search_base_attribute = kopanoBase
364
365 # The attribute containing the name of the addresslist
366 #ldap_addresslist_name_attribute = cn
367
368
369 ##########
370 # Dynamicgroup settings
371
372 # Add a filter to the dynamicgroup search
373 # Hint: Use the kopanoAccount attribute in the filter to differentiate
374 # between non-kopano and kopano dynamic groups.
375 # Optional, default = empty (match everything)
376 #ldap_dynamicgroup_search_filter =
377
378 # This is the unique attribute of a dynamicgroup which is never going
379 # to change, unless the dynamicgroup is removed from LDAP. When this
380 # value changes, Kopano will remove the previous dynamicgroup from the
381 # database, and create a new dynamicgroup with this unique value
382 #ldap_dynamicgroup_unique_attribute = cn
383
384 # This value can be 'text' or 'binary'. For OpenLDAP, only text is used.
385 #ldap_dynamicgroup_unique_attribute_type = text
386
387 # This is the name of the attribute on the dynamicgroup object that
388 # specifies the filter to be applied for this dynamicgroup. All users
389 # matching this filter AND matching the default
390 # ldap_user_search_filter will be included in the dynamicgroup
391 #ldap_dynamicgroup_filter_attribute = kopanoFilter
392
393 # This is the name of the attribute on the dynamicgroup object that
394 # specifies the search base to be applied for this dynamicgroup.
395 #ldap_dynamicgroup_search_base_attribute = kopanoBase
396
397 # The attribute containing the name of the dynamicgroup
398 #ldap_dynamicgroup_name_attribute = cn
399
400
401 ##########
402 # Quota settings
403
404 # Optional
405 # The attribute which indicates which users (besides the user who exceeds his quota)
406 # should also receive a warning mail when a user exceeds his quota.
407 #ldap_quota_userwarning_recipients_attribute = kopanoQuotaUserWarningRecipients
408
409 # Optional, default = text
410 # Active directory: dn
411 # LDAP: text
412 #ldap_quota_userwarning_recipients_attribute_type = text
413
414 # Optional, default empty
415 #ldap_quota_userwarning_recipients_relation_attribute =
416
417 # Optional
418 # The attribute which indicates which users should receive a warning mail
419 # when a company exceeds his quota.
420 #ldap_quota_companywarning_recipients_attribute = kopanoQuotaCompanyWarningRecipients
421
422 # Optional, default = text
423 # Active directory: dn
424 # LDAP: text
425 #ldap_quota_companywarning_recipients_attribute_type = text
426
427 # Optional, default empty
428 #ldap_quota_companywarning_recipients_relation_attribute =
429
430 # Whether to override the system wide quota settings
431 #ldap_quotaoverride_attribute = kopanoQuotaOverride
432
433 #ldap_warnquota_attribute = kopanoQuotaWarn
434 #ldap_softquota_attribute = kopanoQuotaSoft
435 #ldap_hardquota_attribute = kopanoQuotaHard
436
437 # Whether to override the system wide quota settings for all users within the company
438 #ldap_userdefault_quotaoverride_attribute = kopanoUserDefaultQuotaOverride
439
440 #ldap_userdefault_warnquota_attribute = kopanoUserDefaultQuotaWarn
441 #ldap_userdefault_softquota_attribute = kopanoUserDefaultQuotaSoft
442 #ldap_userdefault_hardquota_attribute = kopanoUserDefaultQuotaHard
443
444 # Mapping from the quota attributes to a number of bytes. Qmail-LDAP
445 # schema uses bytes (1), ADS uses kilobytes (1024*1024).
446 #ldap_quota_multiplier = 1
447
448 ##########
449 # Misc. settings
450
451 # Attribute which indicates if the user should be hidden from addressbook
452 #ldap_addressbook_hide_attribute = kopanoHidden
453
454 # LDAP object search filter. %s in this filter will be replaced with
455 # the object being searched.
456 # Hint: Use the kopanoAccount attribute in the filter to differentiate
457 # between non-kopano and kopano objects.
458 # Default: empty
459 # ADS recommended: (anr=%s)
460 # OpenLDAP optional: (|(mail=%s*)(uid=%s*)(cn=*%s*)(fullname=*%s*)(givenname=*%s*)(lastname=*%s*)(sn=*%s*))
461 #ldap_object_search_filter =
462
463 # If a request want more objects than this value, it will download the
464 # full ldap tree (from the base with the search filter) and discard
465 # wat was not required. This is faster for large requests.
466 # Default: 1000
467 #ldap_filter_cutoff_elements = 1000
468
469 ##########
470 # Multi-server settings
471
472 # Users will be created on this named server
473 # Optional, default kopanoUserServer
474 #ldap_user_server_attribute = kopanoUserServer
475
476 # The public store of the company will be created on this named server
477 # Optional, default kopanoCompanyServer
478 #ldap_company_server_attribute = kopanoCompanyServer
479
480 # Optional
481 # Active directory: kopanoHostAddress
482 # LDAP: ipHostNumber
483 #ldap_server_address_attribute = ipHostNumber
484
485 # Optional, default = kopanoHttpPort
486 # Active directory: kopanoHttpPort
487 # LDAP: kopanoHttpPort
488 #ldap_server_http_port_attribute = kopanoHttpPort
489
490 # Optional, default = kopanoSslPort
491 # Active directory: kopanoSslPort
492 # LDAP: kopanoSslPort
493 #ldap_server_ssl_port_attribute = kopanoSslPort
494
495 # Optional, default = kopanoFilePath
496 # Active directory: kopanoFilePath
497 #LDAP: kopanoFilePath
498 #ldap_server_file_path_attribute = kopanoFilePath
499
500 # Determines if a server contains the public store of a non-hosted
501 # environment. Only one server is allowed to host the public store.
502 # Optional, default = kopanoContainsPublic
503 # Active directory: kopanoContainsPublic
504 # LDAP: kopanoContainsPublic
505 #ldap_server_contains_public_attribute = kopanoContainsPublic
506
507 # The Proxy URL of the node; the node must be available to clients
508 # using this Proxy URL if the server detects that original connection
509 # was received via a proxy. See server.cfg(5)'s proxy_header setting
510 #ldap_server_proxy_path_attribute = kopanoProxyURL
511
512 # Search for servers using this LDAP filter. See ldap_search(3) or RFC
513 # 2254 for details on the filter syntax.
514 # Optional, default = empty (match everything)
515 # For active directory, use:
516 # (objectCategory=Computer)
517 # For LDAP with posix users, use:
518 #
519 #ldap_server_search_filter =
520
521 # Unique user id to find the server
522 # Required
523 # For active directory, use:
524 # CN
525 # For LDAP with posixAccount, use:
526 # cn
527 #ldap_server_unique_attribute = cn
5555
5656 # run server in this path (when not using the -F switch)
5757 #running_path = /var/lib/kopano
58
59 # Use given allocator library. Values like libtcmalloc.so.4,
60 # libtcmalloc_minimal.so.4 and libjemalloc.so.2 would work.
61 #allocator_library = default
5862
5963 # create memory coredumps upon crash in the running_path directory
6064 coredump_enabled = yes
00 SUBDIRS = createcompany.d creategroup.d createuser.d deletecompany.d deletegroup.d deleteuser.d
11 dist_bin_SCRIPTS = createcompany creategroup createuser deletecompany deletegroup deleteuser
2 bindir = $(USERSCRIPTDIR)
2 bindir = ${dcprefix}${USERSCRIPTDIR}
33 dist_data_DATA = users_common.sh groups_common.sh companies_common.sh
4 datadir = $(USERSCRIPTDIR)
4 datadir = ${dcprefix}${USERSCRIPTDIR}
55
66 install-data-hook:
77 for dir in $(SUBDIRS); do \
8 mkdir -p $(DESTDIR)/$(USERSCRIPTDIR)/$$dir; \
8 mkdir -p ${DESTDIR}/${dcprefix}${USERSCRIPTDIR}/$$dir; \
99 done
00 dist_bin_SCRIPTS = 00createpublic
1 bindir = $(USERSCRIPTDIR)/createcompany.d
1 bindir = ${dcprefix}${USERSCRIPTDIR}/createcompany.d
0 bindir = $(USERSCRIPTDIR)/creategroup.d
0 bindir = ${dcprefix}${USERSCRIPTDIR}/creategroup.d
00 dist_bin_SCRIPTS = 00createstore
1 bindir = $(USERSCRIPTDIR)/createuser.d
1 bindir = ${dcprefix}${USERSCRIPTDIR}/createuser.d
0 bindir = $(USERSCRIPTDIR)/deletecompany.d
0 bindir = ${dcprefix}${USERSCRIPTDIR}/deletecompany.d
0 bindir = $(USERSCRIPTDIR)/deletegroup.d
0 bindir = ${dcprefix}${USERSCRIPTDIR}/deletegroup.d
00 dist_bin_SCRIPTS =
1 bindir = $(USERSCRIPTDIR)/deleteuser.d
1 bindir = ${dcprefix}${USERSCRIPTDIR}/deleteuser.d
22 if [ -z "$1" ]; then
33 exit 0
44 fi
5 input="$1"
6 output="$2"
5 libtool="$1"; shift
6 input="$1"; shift
7 output="$1"; shift
78
89 case "$input" in #((
910 *.la)
1718 fi
1819 ;;
1920 *)
20 if libtool --mode=execute ldd -r "$input" | c++filt | \
21 if "${libtool}" --mode=execute ldd -r "$input" | c++filt | \
2122 grep "undefined symbol"; then
2223 exit 1
2324 fi
1919 #include "freebusyutil.h"
2020 #include <kopano/stringutil.h>
2121
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
25
2622 /**
27 * Constructor
28 *
2923 * @param[in] lpFBBlock Pointer to a list of free/busy blocks
3024 */
3125 ECEnumFBBlock::ECEnumFBBlock(ECFBBlockList* lpFBBlock)
4337 *
4438 * @param[in] lpFBBlock Pointer to a list of free/busy blocks
4539 * @param[out] lppEnumFBBlock Address of the pointer that receives the object ECEnumFBBlock pointer
46 *
47 * @return HRESULT
4840 */
4941 HRESULT ECEnumFBBlock::Create(ECFBBlockList* lpFBBlock, ECEnumFBBlock **lppEnumFBBlock)
5042 {
1616
1717 #include <kopano/platform.h>
1818 #include "ECFBBlockList.h"
19
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #endif
2319
2420 ECFBBlockList::ECFBBlockList(void)
2521 {
1818 #include "ECFreeBusyData.h"
1919
2020 #include "ECEnumFBBlock.h"
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
2521
2622 ECFreeBusyData::ECFreeBusyData(void)
2723 {
2626 #include "freebusyutil.h"
2727 #include <kopano/mapi_ptr.h>
2828
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
32
3329 ECFreeBusySupport::ECFreeBusySupport(void)
3430 {
3531 m_lpSession = NULL;
108104 }
109105 #endif
110106
111
112107 // Hold the mapisession, the session will be released by function 'close' or
113108 // on delete the class
114109 hr = lpMAPISession->QueryInterface(IID_IMAPISession, (void**)&m_lpSession);
137132
138133 return hr;
139134 }
140
141135
142136 HRESULT ECFreeBusySupport::Close()
143137 {
278272 if(lpMessage)
279273 lpMessage->Release();
280274
281
282275 return hr;
283276 }
284277
3232 #include <mapi.h>
3333 #include <mapidefs.h>
3434 #include <mapix.h>
35
36 #include "freebusy.h"
37 #include "freebusyguid.h"
3835
3936 #include <kopano/ECUnknown.h>
4037 #include <kopano/Trace.h>
2020
2121 #include "freebusyutil.h"
2222
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
2723 ECFreeBusyUpdate::ECFreeBusyUpdate(IMessage* lpMessage)
2824 {
2925 m_lpMessage = lpMessage;
5248
5349 return hr;
5450 }
55
5651
5752 HRESULT ECFreeBusyUpdate::QueryInterface(REFIID refiid, void** lppInterface)
5853 {
118113 }
119114 };
120115
121
122116 FileTimeToRTime(&ftStart, &rtmStart);
123117 FileTimeToRTime(&ftEnd, &rtmEnd);
124118
55
66 lib_LTLIBRARIES = libkcfreebusy.la
77 noinst_DATA = libkcfreebusy.ldd
8 CLEANFILES = ${noinst_DATA}
89
910 libkcfreebusy_la_includedir = $(includedir)/libfreebusy
1011
3434
3535 #define START_TIME 0
3636 #define END_TIME 1
37
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #endif
4137
4238 /**
4339 * Publish free/busy information from the default calendar
334334 * use of Outlook and are subject to change. Free/busy providers must implement them only
335335 * as specified, returning only the specified return values.
336336 */
337 #ifndef LINUX
338 MIDL_INTERFACE("00067066-0000-0000-C000-000000000046")
339 #else
340 class
341 #endif
342 IFreeBusyData : public IUnknown
343 {
344
337 class IFreeBusyData : public IUnknown {
345338 public:
346339
347340 /**
444437 * only as specified, returning only the specified return values.
445438 *
446439 */
447 #ifndef LINUX
448 MIDL_INTERFACE("00067067-0000-0000-C000-000000000046")
449 #else
450 class
451 #endif
452 IFreeBusySupport : public IUnknown
453 {
440 class IFreeBusySupport : public IUnknown {
454441 public:
455442
456443 /**
669656 * Missing call is CleanTombstone. This is not support in outlook 2000
670657 *
671658 */
672 #ifndef LINUX
673 MIDL_INTERFACE("00067067-0000-0000-C000-000000000046")
674 #else
675 class
676 #endif
677 IFreeBusySupportOutlook2000 : public IUnknown
678 {
659 class IFreeBusySupportOutlook2000 : public IUnknown {
679660 public:
680661
681662 /*! @copydoc IFreeBusySupport::Open */
2727 #include "freebusytags.h"
2828 #include <kopano/mapiext.h>
2929 #include <edkmdb.h>
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
3430
3531 BOOL leapyear(short year)
3632 {
9591
9692 enum eFreeBusyPos{ FBPOS_FREE_BUSY_FOR_LOCAL_SITE_ENTRYID};
9793
98
9994 // Get freebusy properies
10095 hr = lpPublicStore->GetProps((LPSPropTagArray)&sPropsFreeBusy, 0, &cValuesFreeBusy, &lpPropArrayFreeBusy);
10196 if (FAILED(hr))
173168 hr = MAPI_E_INVALID_ENTRYID;
174169 goto exit;
175170 }
176
177
178171
179172 // GetFreeBusyFolder
180173 hr = GetFreeBusyFolder(lpPublicStore, &lpFreeBusyFolder);
509502 if(FAILED(hr))
510503 goto exit;
511504
512
513505 // Get busy data
514506 if(lpPropArrayFBData[FBDATA_BUSY_EVENTS].ulPropTag == PR_FREEBUSY_BUSY_EVENTS &&
515507 lpPropArrayFBData[FBDATA_BUSY_MONTHS].ulPropTag == PR_FREEBUSY_BUSY_MONTHS)
552544 MAPIFreeBuffer(lpPropArrayFBData);
553545 return hr;
554546 }
555
556547
557548 unsigned int DiffYearMonthToMonth( struct tm *tm1, struct tm *tm2)
558549 {
3131 #include <algorithm>
3232 using namespace std;
3333
34 #ifdef _DEBUG
35 #define new DEBUG_NEW
36 #endif
37
3834 recurrence::recurrence() {
3935 m_ulMonth = 0x0;
4036 }
297293 return hr;
298294 }
299295
300
301296 time_t recurrence::getEndDateTime()
302297 {
303298 time_t tStart;
305300 RTimeToUnixTime(m_sRecState.ulEndDate, &tStart);
306301 return tStart + (m_sRecState.ulEndTimeOffset*60);
307302 }
308
309303
310304 HRESULT recurrence::setEndDateTime(time_t t)
311305 {
317311
318312 return hr;
319313 }
320
321314
322315 ULONG recurrence::getCount()
323316 {
459452 return hrSuccess;
460453 }
461454
462
463455 // only valid in monthly type 0x3 and 0xb
464456 UCHAR recurrence::getWeekNumber()
465457 {
500492 std::vector<unsigned int> lstDeletedInstanceDates;
501493 std::vector<unsigned int>::iterator d;
502494 std::vector<RecurrenceState::Exception>::const_iterator iExceptions;
503
504495
505496 // make copy of struct info
506497 lstDeletedInstanceDates = m_sRecState.lstDeletedInstanceDates;
11091100 // Go the the correct month day
11101101 tStart += (m_sRecState.ulDayOfMonth-1) * 24*60*60;
11111102
1112
11131103 // If the previous calculation gave us a start date *before* the original start date, then we need to skip to the next occurrence
11141104 if (m_sRecState.ulRecurFrequency == RF_MONTHLY &&
11151105 static_cast<int>(m_sRecState.ulDayOfMonth) < tm.tm_mday) {
12421232
12431233 if (m_sRecState.ulEndType != ET_NUMBER)
12441234 return getEndDateTime();
1245
12461235
12471236 tStart = getStartDateTime();
12481237 tEnd = tStart;
19281917 return false;
19291918 }
19301919
1931
19321920 ULONG recurrence::countDaysOfMonth(time_t tsDate)
19331921 {
19341922 ULONG ulYear = 0;
154154 if (hr != hrSuccess)
155155 goto exit;
156156
157 if (stricmp(lpMessageClass->Value.lpszA, "IPM.Task") == 0) {
157 if (strcasecmp(lpMessageClass->Value.lpszA, "IPM.Task") == 0) {
158158 hr = HrGetTzStruct(strSrvTZ, &ttTZinfo);
159159 if(hr == hrSuccess)
160160 m_tzMap[strSrvTZ] = ttTZinfo; // keep timezone pointer for tasks
161161 }
162162
163 if (stricmp(lpMessageClass->Value.lpszA, "IPM.Task") == 0) {
163 if (strcasecmp(lpMessageClass->Value.lpszA, "IPM.Task") == 0) {
164164 lpVEC = new VTodoConverter(m_lpAdrBook, &m_tzMap, m_lpNamedProps, m_strCharset, blCensor, false, NULL);
165 } else if (stricmp(lpMessageClass->Value.lpszA, "IPM.Appointment") == 0 || strnicmp(lpMessageClass->Value.lpszA, "IPM.Schedule", strlen("IPM.Schedule")) == 0) {
165 } else if (strcasecmp(lpMessageClass->Value.lpszA, "IPM.Appointment") == 0 || strncasecmp(lpMessageClass->Value.lpszA, "IPM.Schedule", strlen("IPM.Schedule")) == 0) {
166166 lpVEC = new VEventConverter(m_lpAdrBook, &m_tzMap, m_lpNamedProps, m_strCharset, blCensor, false, NULL);
167167 } else {
168168 hr = MAPI_E_TYPE_NO_SUPPORT;
11
22 lib_LTLIBRARIES = libkcicalmapi.la
33 noinst_DATA = libkcicalmapi.ldd
4 CLEANFILES = ${noinst_DATA}
45
56 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) $(BOOST_CPPFLAGS) \
67 $(ICAL_CFLAGS) \
910 -I$(top_srcdir)/libfreebusy
1011
1112 libkcicalmapi_la_LDFLAGS = ${AM_LDFLAGS} \
12 -version-info 0:0:0 \
13 -no-undefined -version-info 0:0:0 \
1314 -Wl,--version-script=${top_builddir}/default.sym
1415 EXTRA_libkcicalmapi_la_DEPENDENCIES = ${top_builddir}/default.sym
1516
240240 UnixTimeToFileTime(dtUTCUntil, &sPropVal.Value.ft);
241241 sPropVal.ulPropTag = CHANGE_PROP_TYPE(lpNamedProps->aulPropTag[PROP_RECURRENCE_END], PT_SYSTIME);
242242 lpIcalItem->lstMsgProps.push_back(sPropVal);
243
244243
245244 // find EXDATE properties, add to delete exceptions
246245 lpicProp = icalcomponent_get_first_property(lpicEvent, ICAL_EXDATE_PROPERTY);
808807
809808 icalcomponent_add_property(lpicEvent, icalproperty_new_rrule(icRRule));
810809
811
812810 // all delete exceptions are in the delete list,
813811 lstExceptions = lpRecurrence->getDeletedExceptions();
814812 if (!lstExceptions.empty()) {
2929 #include <kopano/CommonUtil.h>
3030 #include <kopano/Util.h>
3131 #include <kopano/stringutil.h>
32
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #endif
3632
3733 /**
3834 * Generates ical VALARM component from reminderbefore minutes.
104100 time_t ttReminderTime = 0;
105101 bool bReminderSet = false;
106102
107
108103 lpTrigger = icalcomponent_get_first_property(lpicAlarm, ICAL_TRIGGER_PROPERTY);
109104 lpAction = icalcomponent_get_first_property(lpicAlarm, ICAL_ACTION_PROPERTY);
110105
8080 }
8181
8282 /**
83 * Default constructor
8483 * @param[in] lpAdrBook Mapi addresss book
8584 * @param[in] mapTimeZones std::map containing timezone names and corresponding timezone structures
8685 * @param[in] lpNamedProps Named property tag array
307306 // Caller sets .ulPropTag
308307 sPropValue.Value.bin.cb = strBinUid.size();
309308 if ((hr = MAPIAllocateMore(sPropValue.Value.bin.cb, base, (void**)&sPropValue.Value.bin.lpb)) != hrSuccess)
310 goto exit;
309 return hr;
311310 memcpy(sPropValue.Value.bin.lpb, strBinUid.data(), sPropValue.Value.bin.cb);
312311
313312 // set return value
314 *lpPropValue = sPropValue;
315
316 exit:
317 return hr;
313 lpPropValue->Value.bin.cb = sPropValue.Value.bin.cb;
314 lpPropValue->Value.bin.lpb = sPropValue.Value.bin.lpb;
315 return hrSuccess;
318316 }
319317
320318 /**
24382436 icalcomponent_add_property(lpEvent, lpProp);
24392437 icalvalue_free(lpicValue);
24402438
2441
24422439 lpPropVal = PpropFindProp(lpMsgProps, ulMsgProps, PR_RTF_COMPRESSED);
24432440 if (lpPropVal && Util::GetBestBody(lpMsgProps, ulMsgProps, fMapiUnicode) == PR_RTF_COMPRESSED) {
24442441 string rtf;
24602457 lpStream ->Release();
24612458 }
24622459 }
2463
24642460
24652461 return hrSuccess;
24662462 }
28142810 goto exit;
28152811
28162812 if ((PROP_TYPE(lpSpropArray[0].ulPropTag) != PT_ERROR)
2817 && (stricmp(lpSpropArray[0].Value.lpszA, "IPM.Task") == 0)) {
2813 && (strcasecmp(lpSpropArray[0].Value.lpszA, "IPM.Task") == 0)) {
28182814 ulRecurrenceStateTag = CHANGE_PROP_TYPE(m_lpNamedProps->aulPropTag[PROP_TASK_RECURRSTATE], PT_BINARY);
28192815 lpSPropRecVal = &lpSpropArray[5];
28202816 ulFlag = RECURRENCE_STATE_TASKS;
218218 sPropVal.ulPropTag = PR_MESSAGE_CLASS_W;
219219 lstMsgProps->push_back(sPropVal);
220220 }
221
222221
223222 if (icMethod == ICAL_METHOD_CANCEL || icMethod == ICAL_METHOD_REQUEST)
224223 {
5858 lpicProp = icalcomponent_get_first_property(lpFbcomp, ICAL_ATTENDEE_PROPERTY);
5959 while (lpicProp) {
6060 strEmail = icalproperty_get_attendee(lpicProp);
61 if (strnicmp(strEmail.c_str(), "mailto:", 7) == 0) {
61 if (strncasecmp(strEmail.c_str(), "mailto:", 7) == 0) {
6262 strEmail.erase(0, 7);
6363 }
6464 lstUsers->push_back(strEmail);
9494 time_t tEnd = 0;
9595 std::string strEmail;
9696
97
9897 lpFbComp = icalcomponent_new(ICAL_VFREEBUSY_COMPONENT);
9998 if (!lpFbComp) {
10099 hr = MAPI_E_INVALID_PARAMETER;
143143 sPropVal.Value.ul = ulStatus;
144144 lplstMsgProps->push_back(sPropVal);
145145
146
147146 sPropVal.ulPropTag = PR_ICON_INDEX;
148147 // 1280: task
149148 // 1281: recurring task
286285 {
287286 HRESULT hr = hrSuccess;
288287 LPSPropValue lpPropVal = NULL;
289
290288
291289 hr = VConverter::HrSetTimeProperties(lpMsgProps, ulMsgProps, lpicTZinfo, strTZid, lpEvent);
292290 if (hr != hrSuccess)
2727 #include <edkmdb.h>
2828
2929 #include <list>
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
3430
3531 static inline bool operator==(const ECENTRYID& lhs, const ECENTRYID& rhs)
3632 {
2828 {
2929 return m_map.erase(array_type(sbinSourceKey.lpb, sbinSourceKey.lpb + sbinSourceKey.cb)) == 1;
3030 }
31
3231
3332 ECResyncSetIterator::ECResyncSetIterator(ECResyncSet &resyncSet)
3433 : m_lpResyncSet(&resyncSet)
7776 ++m_iterator;
7877 }
7978
80 const FILETIME ECResyncSetIterator::s_nullTime = {0, 0};
79 const FILETIME ECResyncSetIterator::s_nullTime = {0, 0};
4545 typedef mapi_object_ptr<IECChangeAdviseSink, IID_IECChangeAdviseSink> ECChangeAdviseSinkPtr;
4646 //DEFINEMAPIPTR(ECChangeAdviseSink);
4747
48 #ifdef _DEBUG
49 #define new DEBUG_NEW
50 #endif
51
5248 #define EC_SYNC_STATUS_VERSION 1
53
5449
5550 #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
5651 class ECChangeAdviseSink _zcp_final : public ECUnknown
5853 public:
5954 typedef ULONG(ECSyncContext::*NOTIFYCALLBACK)(ULONG,LPENTRYLIST);
6055
61 // Constructor
6256 ECChangeAdviseSink(ECSyncContext *lpsSyncContext, NOTIFYCALLBACK fnCallback)
6357 : m_lpsSyncContext(lpsSyncContext)
6458 , m_fnCallback(fnCallback)
144138 return hr;
145139 }
146140
147
148
149141 ECSyncContext::ECSyncContext(LPMDB lpStore, ECLogger *lpLogger)
150142 : m_lpStore(lpStore)
151143 , m_lpLogger(lpLogger)
177169 pthread_mutex_destroy(&m_hMutex);
178170 }
179171
180
181172 HRESULT ECSyncContext::HrGetMsgStore(LPMDB *lppMsgStore)
182173 {
183174 HRESULT hr = hrSuccess;
197188 exit:
198189 return hr;
199190 }
200
201191
202192 HRESULT ECSyncContext::HrGetReceiveFolder(LPMAPIFOLDER *lppInboxFolder)
203193 {
224214 return hr;
225215 }
226216
227
228217 HRESULT ECSyncContext::HrGetChangeAdvisor(IECChangeAdvisor **lppChangeAdvisor)
229218 {
230219 HRESULT hr = hrSuccess;
306295 return hr;
307296 }
308297
309
310298 HRESULT ECSyncContext::HrGetChangeAdviseSink(IECChangeAdviseSink **lppChangeAdviseSink)
311299 {
312300 ASSERT(m_lpChangeAdviseSink != NULL);
313301 return m_lpChangeAdviseSink->QueryInterface(IID_IECChangeAdviseSink, (void**)lppChangeAdviseSink);
314302 }
315
316303
317304 HRESULT ECSyncContext::HrQueryHierarchyTable(LPSPropTagArray lpsPropTags, LPSRowSet *lppRows)
318305 {
345332 return hr;
346333 }
347334
348
349335 HRESULT ECSyncContext::HrOpenRootFolder(LPMAPIFOLDER *lppRootFolder, LPMDB *lppMsgStore)
350336 {
351337 HRESULT hr = hrSuccess;
374360 return hr;
375361 }
376362
377
378363 HRESULT ECSyncContext::HrOpenFolder(SBinary *lpsEntryID, LPMAPIFOLDER *lppFolder)
379364 {
380365 HRESULT hr = hrSuccess;
398383 return hr;
399384 }
400385
401
402386 HRESULT ECSyncContext::HrNotifyNewMail(LPNOTIFICATION lpNotification)
403387 {
404388 return m_lpStore->NotifyNewMail(lpNotification);
405389 }
406
407390
408391 HRESULT ECSyncContext::HrGetSteps(SBinary *lpEntryID, SBinary *lpSourceKey, ULONG ulSyncFlags, ULONG *lpulSteps)
409392 {
526509 return hr;
527510 }
528511
529
530512 HRESULT ECSyncContext::HrUpdateChangeId(LPSTREAM lpStream)
531513 {
532514 HRESULT hr = hrSuccess;
540522 if (hr != hrSuccess)
541523 goto exit;
542524
543
544525 pthread_mutex_lock(&m_hMutex);
545526
546527 if (m_mapNotifiedSyncIds[ulSyncId] <= ulChangeId)
564545 exit:
565546 return hr;
566547 }
567
568548
569549 HRESULT ECSyncContext::HrGetSyncStateFromSourceKey(SBinary *lpSourceKey, SSyncState *lpsSyncState)
570550 {
582562 goto exit;
583563 }
584564
585
586565 // Try to get the information from the status stream.
587566 hr = HrGetSyncStatusStream(lpSourceKey, &lpStream);
588567 if (FAILED(hr))
613592 return !m_mapSyncStatus.empty();
614593 }
615594
616
617595 HRESULT ECSyncContext::HrClearSyncStatus()
618596 {
619597 m_mapSyncStatus.clear();
620598 return hrSuccess;
621599 }
622
623600
624601 HRESULT ECSyncContext::HrLoadSyncStatus(SBinary *lpsSyncState)
625602 {
687664 exit:
688665 return hr;
689666 }
690
691667
692668 HRESULT ECSyncContext::HrSaveSyncStatus(LPSPropValue *lppSyncStatusProp)
693669 {
758734 return hr;
759735 }
760736
761
762737 HRESULT ECSyncContext::HrGetSyncStatusStream(LPMAPIFOLDER lpFolder, LPSTREAM *lppStream)
763738 {
764739 HRESULT hr = hrSuccess;
776751 MAPIFreeBuffer(lpPropVal);
777752 return hr;
778753 }
779
780754
781755 HRESULT ECSyncContext::HrGetSyncStatusStream(SBinary *lpsSourceKey, LPSTREAM *lppStream)
782756 {
808782
809783 return hr;
810784 }
811
812785
813786 HRESULT ECSyncContext::GetResyncID(ULONG *lpulResyncID)
814787 {
6767 * Pointer to a IMsgStore pointer, which will contain
6868 * a pointer to the requested messages store upon successful
6969 * completion.
70 * @return HRESULT
7170 */
7271 HRESULT HrGetMsgStore(LPMDB *lppMsgStore);
7372
7978 * @param[out] lppInboxFolder
8079 * Pointer to a IMAPIFolder pointer, which will contain a
8180 * pointer to the requested folder upon successful completion.
82 * @return HRESULT
8381 */
8482 HRESULT HrGetReceiveFolder(LPMAPIFOLDER *lppInboxFolder);
8583
109107 * @param[out] lppChangeAdviseSink
110108 * Pointer to a IECChangeAdviseSInk pointer, which will contain a
111109 * pointer to the change advise sink upon successful completion.
112 * @return HRESULT.
113110 */
114111 HRESULT HrGetChangeAdviseSink(IECChangeAdviseSink **lppChangeAdviseSink);
115112
123120 * Pointer to a SRowSet pointer, which will be populated with
124121 * the rows from the hierarchy table. Needs to be freed with
125122 * FreePRows by the caller.
126 * @return HRESULT
127123 */
128124 HRESULT HrQueryHierarchyTable(LPSPropTagArray lpsPropTags, LPSRowSet *lppRows);
129125
137133 * Pointer to a IMsgStore pointer that will contain a pointer to
138134 * the message store upon successful completion. Passing NULL will
139135 * cause no MsgStore pointer to be returned.
140 * @return HRESULT
141136 */
142137 HRESULT HrOpenRootFolder(LPMAPIFOLDER *lppRootFolder, LPMDB *lppMsgStore = NULL);
143138
150145 * @param[out] lppFolder
151146 * Pointer to a IMAPIFolder pointer that will contain a pointer to
152147 * the requested folder upon successful completion.
153 * @return HRESULT
154148 */
155149 HRESULT HrOpenFolder(SBinary *lpsEntryID, LPMAPIFOLDER *lppFolder);
156150
160154 * @Param[in] lpNotification
161155 * Pointer to a NOTIFICATION structure that will be send as the
162156 * new mail notification.
163 * @return HRESULT
164157 */
165158 HRESULT HrNotifyNewMail(LPNOTIFICATION lpNotification);
166159
179172 * Pointer to a ULONG variable that will contain the number of steps
180173 * to complete a synchronization on the selected folder upon successful
181174 * completion.
182 * @return HRESULT
183175 */
184176 HRESULT HrGetSteps(SBinary *lpEntryID, SBinary *lpSourceKey, ULONG ulSyncFlags, ULONG *lpulSteps);
185177
192184 * @param[in] lpStream
193185 * The state stream from which the sync id and change id will be
194186 * extracted.
195 * @return HRESULT
196187 */
197188 HRESULT HrUpdateChangeId(LPSTREAM lpStream);
198189
205196
206197 /**
207198 * Clear the sync status streams.
208 *
209 * @return HRESULT
210199 */
211200 HRESULT HrClearSyncStatus();
212201
215204 *
216205 * @param[in] lpsSyncState
217206 * The SBinary structure containing the data to be decoded.
218 * @return HRESULT
219207 */
220208 HRESULT HrLoadSyncStatus(SBinary *lpsSyncState);
221209
225213 * @param[in] lppSyncStatusProp
226214 * Pointer to a SPropValue pointer that will be populated with
227215 * the binary data that's made out of the status streams.
228 * @return HRESULT
229216 */
230217 HRESULT HrSaveSyncStatus(LPSPropValue *lppSyncStatusProp);
231218
237224 * @param[out] lppStream
238225 * Pointer to a IStream pointer that will contain the
239226 * sync status stream on successful completion.
240 * @return HRESULT
241227 */
242228 HRESULT HrGetSyncStatusStream(LPMAPIFOLDER lpFolder, LPSTREAM *lppStream);
243229
250236 * @param[out] lppStream
251237 * Pointer to a IStream pointer that will contain the
252238 * sync status stream on successful completion.
253 * @return HRESULT
254239 */
255240 HRESULT HrGetSyncStatusStream(SBinary *lpsSourceKey, LPSTREAM *lppStream);
256241
311296 * @param[out] lpsSyncState
312297 * Pointer to a SSyncState structure that will be populated
313298 * with the retrieved sync state.
314 * @return HRESULT
315299 */
316300 HRESULT HrGetSyncStateFromSourceKey(SBinary *lpSourceKey, SSyncState *lpsSyncState);
317301
2525 #include <cstdlib>
2626 #include <mapidefs.h>
2727
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
31
3228 // for LOG_MAIL
3329 #include <syslog.h>
3430
4642 if (lpSettings->SyncLogEnabled()) {
4743 char dummy[MAX_PATH + 1] = { 0 };
4844
49 if (GetTempPathA(sizeof dummy, dummy) >= sizeof dummy)
45 if (GetTempPath(sizeof dummy, dummy) >= sizeof dummy)
5046 dummy[0] = 0x00;
5147
5248 std::string strPath = dummy + std::string("/");
109105 pthread_mutex_t ECSyncLog::s_hMutex;
110106 ECLogger *ECSyncLog::s_lpLogger = NULL;
111107
112
113108 ECSyncLog::__initializer::__initializer() {
114109 pthread_mutex_init(&ECSyncLog::s_hMutex, NULL);
115110 }
2121 #include <mapix.h>
2222
2323 #include <kopano/ECLogger.h>
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
2924
3025 ECSyncSettings* ECSyncSettings::GetInstance()
3126 {
188183 return ulPrev;
189184 }
190185
191
192
193186 pthread_mutex_t ECSyncSettings::s_hMutex;
194187 ECSyncSettings* ECSyncSettings::s_lpInstance = NULL;
195
196188
197189 ECSyncSettings::__initializer::__initializer() {
198190 pthread_mutex_init(&ECSyncSettings::s_hMutex, NULL);
1919 #include <kopano/mapi_ptr.h>
2020
2121 #include <mapix.h>
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
2622
2723 HRESULT HrDecodeSyncStateStream(LPSTREAM lpStream, ULONG *lpulSyncId, ULONG *lpulChangeId, PROCESSEDCHANGESSET *lpSetProcessChanged)
2824 {
66
77 lib_LTLIBRARIES = libkcsync.la
88 noinst_DATA = libkcsync.ldd
9 CLEANFILES = ${noinst_DATA}
910
1011 libkcsync_la_LIBADD = \
1112 ${top_builddir}/common/libkcmapi.la \
5959 #include <netdb.h>
6060
6161 using namespace std;
62
63 #ifdef _DEBUG
64 #define new DEBUG_NEW
65 #endif
6662
6763 #define PROFILEPREFIX "ec-adm-"
6864
731727 hr = lpMsgServiceAdmin->AdminProviders((MAPIUID *)lpProviderUID->Value.bin.lpb, 0, lppProviderAdmin);
732728 if(hr != hrSuccess)
733729 goto exit;
734
735730
736731 exit:
737732 if(lpServiceTable)
28212816 return hr;
28222817 }
28232818
2824
28252819 /**
28262820 * Converts a wrapped message store's entry identifier to a message store entry identifier.
28272821 *
30743068
30753069 return hr;
30763070 }
3077
30783071
30793072 /*
30803073 * Get local free/busy message to get delegate information
32463239 return hr;
32473240 }
32483241
3249
32503242 /**
32513243 * Set proccessing meeting request options of a user
32523244 *
3131 bool isFeature(const char* feature)
3232 {
3333 for (size_t i = 0; i < arraySize(kopano_features); ++i)
34 if (stricmp(feature, kopano_features[i]) == 0)
34 if (strcasecmp(feature, kopano_features[i]) == 0)
3535 return true;
3636 return false;
3737 }
5050 return MAPI_E_INVALID_PARAMETER;
5151
5252 for (ULONG i = 0; i < lpProps->Value.MVszA.cValues; ++i)
53 if (stricmp(lpProps->Value.MVszA.lppszA[i], feature) == 0)
53 if (strcasecmp(lpProps->Value.MVszA.lppszA[i], feature) == 0)
5454 return hrSuccess;
5555 return MAPI_E_NOT_FOUND;
5656 }
144144 return hr == hrSuccess;
145145 }
146146
147 bool isFeatureEnabled(const char* feature, IAddrBook *lpAddrBook, IMsgStore *lpStore)
148 {
149 return checkFeature(feature, lpAddrBook, lpStore, PR_EC_ENABLED_FEATURES_A);
150 }
151
152147 bool isFeatureDisabled(const char* feature, IAddrBook *lpAddrBook, IMsgStore *lpStore)
153148 {
154149 return checkFeature(feature, lpAddrBook, lpStore, PR_EC_DISABLED_FEATURES_A);
2929 HRESULT hasFeature(const WCHAR* feature, LPSPropValue lpProps);
3030 std::set<std::string> getFeatures();
3131
32 bool isFeatureEnabled(const char* feature, IAddrBook *lpAddrBook, IMsgStore *lpUser);
3332 bool isFeatureDisabled(const char* feature, IAddrBook *lpAddrBook, IMsgStore *lpUser);
3433
3534 #endif
1919 #include <kopano/ECRestriction.h>
2020 #include "HrException.h"
2121
22 /**
23 * ECHierarchyIteratorBase implementation
24 */
2522 ECHierarchyIteratorBase::ECHierarchyIteratorBase(LPMAPICONTAINER lpContainer, ULONG ulFlags, ULONG ulDepth)
2623 : m_ptrContainer(lpContainer, true)
2724 , m_ulFlags(ulFlags)
10299 throw HrException(hr); // @todo: Fix this
103100 }
104101
105
106 /**
107 * ECContentsIteratorBase implementation
108 */
109102 ECContentsIteratorBase::ECContentsIteratorBase(LPMAPICONTAINER lpContainer, LPSRestriction lpRestriction, ULONG ulFlags, bool bOwnRestriction)
110103 : m_ptrContainer(lpContainer, true)
111104 , m_ulFlags(ulFlags)
3333
3434 #include <kopano/ECDebug.h>
3535 #include <algorithm>
36
37 #ifdef LINUX
3836 // needed for htons()
3937 #include <netdb.h>
40 #endif
41
42 #ifdef _DEBUG
43 #define new DEBUG_NEW
44 #endif
4538
4639 using namespace std;
4740
48 SSortOrderSet sSortDefault = {0, 0};
41 static SSortOrderSet sSortDefault = {0, 0};
4942
5043 class FixStringType _zcp_final {
5144 public:
270263
271264 map<unsigned int, ECTableEntry>::iterator iterRows;
272265 map<unsigned int, ECTableEntry>::iterator iterNext;
273
274266
275267 pthread_mutex_lock(&m_hDataMutex);
276268
745737 return hr;
746738 }
747739
748
749740 HRESULT ECMemTableView::SetColumns(LPSPropTagArray lpPropTagArray, ULONG ulFlags)
750741 {
751742 HRESULT hr = hrSuccess;
851842 return hr;
852843 }
853844
854
855845 HRESULT ECMemTableView::SeekRow(BOOKMARK bkOrigin, LONG lRowCount, LONG *lplRowsSought)
856846 {
857847 HRESULT hr = hrSuccess;
869859 exit:
870860 return hr;
871861 }
872
873862
874863 HRESULT ECMemTableView::SeekRowApprox(ULONG ulNumerator, ULONG ulDenominator)
875864 {
890879 return hr;
891880 }
892881
893
894882 HRESULT ECMemTableView::QueryPosition(ULONG *lpulRow, ULONG *lpulNumerator, ULONG *lpulDenominator)
895883 {
896884 HRESULT hr = hrSuccess;
916904 exit:
917905 return hr;
918906 }
919
920907
921908 HRESULT ECMemTableView::FindRow(LPSRestriction lpRestriction, BOOKMARK bkOrigin, ULONG ulFlags)
922909 {
10281015 exit:
10291016 return hr;
10301017 }
1031
10321018
10331019 HRESULT ECMemTableView::FreeBookmark(BOOKMARK bkPosition)
10341020 {
11361122 return hr;
11371123 }
11381124
1139
11401125 HRESULT ECMemTableView::SortTable(LPSSortOrderSet lpSortCriteria, ULONG ulFlags)
11411126 {
11421127 HRESULT hr = hrSuccess;
12221207 }
12231208 }
12241209
1225
12261210 // Get all the sort columns and package them as binary keys
12271211 for (j = 0; j < lpsSortOrderSet->cSorts; ++j) {
12281212 lpsSortID = PpropFindProp(iterData->second.lpsPropVal, iterData->second.cValues, lpsSortOrderSet->aSort[j].ulPropTag);
12621246
12631247 memcpy(lpSortCriteria, lpsSortOrderSet, CbSSortOrderSet(lpsSortOrderSet));
12641248
1265
12661249 *lppSortCriteria = lpSortCriteria;
12671250 exit:
12681251 return hr;
13111294 if(hr != hrSuccess)
13121295 goto exit;
13131296
1314
13151297 hr = QueryRowData(&sRowList, lppRows);
13161298 if (hr != hrSuccess)
13171299 goto exit;
13181300 exit:
1319
13201301
13211302 return hr;
13221303 }
13331314 ECObjectTableList::const_iterator iterRowList;
13341315
13351316 convert_context converter;
1336
13371317
13381318 if (lpsRowList == NULL || lppRows == NULL) {
13391319 hr = MAPI_E_INVALID_PARAMETER;
2222 #include <mapicode.h>
2323 #include <mapix.h>
2424
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
2925 /**
3026 * Allocate and populate a MAPI SRestriction structure based on the current
3127 * ECRestriction object.
180176
181177 inline void ECRestriction::DummyFree(LPVOID) {}
182178
183
184179 /**
185180 * ECAndRestriction
186181 */
227222 return lpNew;
228223 }
229224
230
231225 /**
232226 * ECOrRestriction
233227 */
274268 return lpNew;
275269 }
276270
277
278271 /**
279272 * ECNotRestriction
280273 */
307300 ECRestriction *ECNotRestriction::Clone() const {
308301 return new ECNotRestriction(m_ptrRestriction);
309302 }
310
311303
312304 /**
313305 * ECContentRestriction
366358 return new ECContentRestriction(m_ulFuzzyLevel, m_ulPropTag, m_ptrProp);
367359 }
368360
369
370361 /**
371362 * ECBitMaskRestriction
372363 */
390381 ECRestriction *ECBitMaskRestriction::Clone() const {
391382 return new ECBitMaskRestriction(m_relBMR, m_ulPropTag, m_ulMask);
392383 }
393
394384
395385 /**
396386 * ECPropertyRestriction
449439 return new ECPropertyRestriction(m_relop, m_ulPropTag, m_ptrProp);
450440 }
451441
452
453442 /**
454443 * ECComparePropsRestriction
455444 */
474463 return new ECComparePropsRestriction(m_relop, m_ulPropTag1, m_ulPropTag2);
475464 }
476465
477
478466 /**
479467 * ECSizeRestriction
480468 */
499487 return new ECSizeRestriction(m_relop, m_ulPropTag, m_cb);
500488 }
501489
502
503490 /**
504491 * ECExistRestriction
505492 */
521508 ECRestriction *ECExistRestriction::Clone() const {
522509 return new ECExistRestriction(m_ulPropTag);
523510 }
524
525511
526512 /**
527513 * ECSubRestriction
560546 ECRestriction *ECSubRestriction::Clone() const {
561547 return new ECSubRestriction(m_ulSubObject, m_ptrRestriction);
562548 }
563
564549
565550 /**
566551 * ECCommentRestriction
583568 , m_ptrProp(ptrProp)
584569 { }
585570
586
587571 HRESULT ECCommentRestriction::GetMAPIRestriction(LPVOID lpBase, LPSRestriction lpRestriction, ULONG ulFlags) const {
588572 HRESULT hr = hrSuccess;
589573 SRestriction restriction = {0};
627611 return new ECCommentRestriction(m_ptrRestriction, m_cValues, m_ptrProp);
628612 }
629613
630
631614 /**
632615 * ECRawRestriction
633616 */
4040 * @param[in] ulFlags
4141 * - SYNC_CATCHUP Update the internal state, but don't perform any operations
4242 * on the server.
43 * @return HRESULT
4443 */
4544 virtual HRESULT __stdcall Config(LPSTREAM lpStream, LPGUID lpGUID, IECChangeAdviseSink *lpAdviseSink, ULONG ulFlags) = 0;
4645
4948 *
5049 * @param[in] lpStream
5150 * The stream in which the current state will be stored.
52 * @return HRESULT
5351 */
5452 virtual HRESULT __stdcall UpdateState(LPSTREAM lpStream) = 0;
5553
6159 * block of data. The first 4 bytes specify the sync id of the folder to
6260 * monitor. The second 4 bytes apecify the change id of the folder to monitor.
6361 * Use the SSyncState structure to easily create and access this data.
64 * @return HRESULT
6562 */
6663 virtual HRESULT __stdcall AddKeys(LPENTRYLIST lpEntryList) = 0;
6764
7168 * @param[in] lpEntryList
7269 * A list of keys specifying the folders to monitor. See AddKeys for
7370 * information about the key format.
74 * @return HRESULT
7571 */
7672 virtual HRESULT __stdcall RemoveKeys(LPENTRYLIST lpEntryList) = 0;
7773
9490 * The syncid for which to update the changeid.
9591 * @param[in] ulChangeId
9692 * The new changeid for the specified syncid.
97 *
98 * @return HRESULT
9993 */
10094 virtual HRESULT __stdcall UpdateSyncState(ULONG ulSyncId, ULONG ulChangeId) = 0;
10195 };
3737 #endif
3838 #else
3939 // Testing for both WIN32 && LINUX makes no f sense
40 #ifdef LINUX
4140 #define DEBUGPRINT(...)
42 #else
43 #define DEBUGPRINT __noop
44 #endif
45 #endif
46
47 #ifdef _DEBUG
48 #define new DEBUG_NEW
4941 #endif
5042
5143 class BinReader _zcp_final {
5353
5454 #include <kopano/ECGetText.h>
5555
56 #ifdef _DEBUG
57 #define new DEBUG_NEW
58 #endif
59
6056 // HACK: prototypes may differ depending on the compiler and/or system (the
6157 // second parameter may or may not be 'const'). This redeclaration is a hack
6258 // to have a common prototype "iconv_cast".
7167 private:
7268 const char** m_ptr;
7369 };
74
7570
7671 class PropTagCompare _zcp_final {
7772 public:
8479 };
8580
8681 typedef std::set<ULONG,PropTagCompare> PropTagSet;
87
8882
8983 /**
9084 * Add or replaces a prop value in a an SPropValue array
12611255 if (lpProp1->Value.MVszA.cValues == lpProp2->Value.MVszA.cValues) {
12621256 for (i = 0; i < lpProp1->Value.MVszA.cValues; ++i) {
12631257 if (lpProp1->Value.MVszA.lppszA[i] && lpProp2->Value.MVszA.lppszA[i])
1264 nCompareResult = stricmp(lpProp1->Value.MVszA.lppszA[i], lpProp2->Value.MVszA.lppszA[i]);
1258 nCompareResult = strcasecmp(lpProp1->Value.MVszA.lppszA[i], lpProp2->Value.MVszA.lppszA[i]);
12651259 else
12661260 nCompareResult = lpProp1->Value.MVszA.lppszA[i] != lpProp2->Value.MVszA.lppszA[i];
12671261
17111705
17121706 return -1;
17131707 }
1714
17151708
17161709 /**
17171710 * Return a human readable string for a specified HRESULT code. You
24402433 if (hr != hrSuccess)
24412434 goto exit;
24422435
2443
24442436 hr = hex2bin(input, len, buffer);
24452437 if(hr != hrSuccess)
24462438 goto exit;
24532445 exit:
24542446 return hr;
24552447 }
2456
24572448
24582449 /**
24592450 * Converts a string containing hexidecimal numbers into binary
24832474 exit:
24842475 return hr;
24852476 }
2486
24872477
24882478 /**
24892479 * Return the original body property tag of a message, or PR_NULL when unknown.
29872977 if (hr != hrSuccess)
29882978 goto exit;
29892979
2990
29912980 hr = lpSrc->GetHierarchyTable(MAPI_UNICODE, &lpTable);
29922981 if (hr != hrSuccess)
29932982 goto exit;
30923081 ULONG ulObj;
30933082 LPMESSAGE lpSrcMessage = NULL, lpDestMessage = NULL;
30943083 LPENTRYLIST lpDeleteEntries = NULL;
3095
30963084
30973085 hr = lpSrc->GetContentsTable(MAPI_UNICODE | ulWhat, &lpTable);
30983086 if (hr != hrSuccess)
33463334 goto exit;
33473335 }
33483336
3349
33503337 hr = FindInterface(&IID_IMAPIProp, ciidExclude, rgiidExclude);
33513338 if (hr == hrSuccess) {
33523339 hr = MAPI_E_INTERFACE_NOT_SUPPORTED;
33543341 }
33553342
33563343 // end sanity checks
3357
33583344
33593345 // check message, folder, attach, recipients, stream, mapitable, ... ?
33603346
33883374 if (hr != hrSuccess)
33893375 bPartial = true;
33903376 }
3391
33923377
33933378 } else if (*lpSrcInterface == IID_IMessage) {
33943379 // recipients & attachments
38413826 }
38423827 }
38433828
3844
38453829 hr = lpSrcProp->GetProps(lpIncludeProps, 0, &cValues, &lpProps);
38463830 if (FAILED(hr))
38473831 goto exit;
2929 #include <string>
3030 using namespace std;
3131
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #endif
35
36
37 SizedSPropTagArray(SHORTCUT_NUM, sPropsShortcuts) = {SHORTCUT_NUM, { PR_INSTANCE_KEY, PR_FAV_PUBLIC_SOURCE_KEY, PR_FAV_PARENT_SOURCE_KEY, PR_FAV_DISPLAY_NAME, PR_FAV_DISPLAY_ALIAS, PR_FAV_LEVEL_MASK, PR_FAV_CONTAINER_CLASS}};
38
32 static SizedSPropTagArray(SHORTCUT_NUM, sPropsShortcuts) = {SHORTCUT_NUM, {
33 PR_INSTANCE_KEY, PR_FAV_PUBLIC_SOURCE_KEY, PR_FAV_PARENT_SOURCE_KEY,
34 PR_FAV_DISPLAY_NAME, PR_FAV_DISPLAY_ALIAS, PR_FAV_LEVEL_MASK,
35 PR_FAV_CONTAINER_CLASS}};
3936
4037 LPSPropTagArray GetShortCutTagArray() {
4138 return (LPSPropTagArray)&sPropsShortcuts;
225222
226223 if (lpRows->cRows == 0)
227224 goto exit; // Folder already removed
228
229225
230226 hr = MAPIAllocateBuffer(sizeof(ENTRYLIST), (void**)&lpsMsgList);
231227 if (hr != hrSuccess)
528524 MAPIFreeBuffer(lpsPropArray);
529525 return hr;
530526 }
531
532 /**
533 * Check if the favorite is exist. If the favorite is exist, it will returns the favorite data
534 * @param ulFlags unicode flag (unused, since SetColumns always sets the correct tags)
535 */
536 HRESULT GetFavorite(IMAPIFolder *lpShortcutFolder, ULONG ulFlags, IMAPIFolder *lpMapiFolder, ULONG *lpcValues, LPSPropValue *lppShortCutPropValues)
537 {
538 HRESULT hr = hrSuccess;
539 LPSPropValue lpPropSourceKey = NULL;
540
541 LPMAPITABLE lpTable = NULL;
542
543 LPSPropValue lpShortCutPropValues = NULL;
544 ULONG cShortCutValues = 0;
545
546 LPSRestriction lpRestriction = NULL;
547
548 SRowSet *lpRows = NULL;
549
550 if (lpShortcutFolder == NULL || lpMapiFolder == NULL) {
551 hr = MAPI_E_INVALID_PARAMETER;
552 goto exit;
553 }
554
555 hr = HrGetOneProp(lpMapiFolder, PR_SOURCE_KEY, &lpPropSourceKey);
556 if (hr != hrSuccess) {
557 hr = MAPI_E_CORRUPT_DATA;
558 goto exit;
559 }
560
561 // Check for duplicates
562 hr = lpShortcutFolder->GetContentsTable(ulFlags, &lpTable);
563 if (hr != hrSuccess)
564 goto exit;
565
566 hr = lpTable->SetColumns(GetShortCutTagArray(), 0);
567 if(hr != hrSuccess)
568 goto exit;
569
570 // build restriction
571 CREATE_RESTRICTION(lpRestriction);
572 CREATE_RES_AND(lpRestriction, lpRestriction, 1);
573 DATA_RES_PROPERTY(lpRestriction, lpRestriction->res.resAnd.lpRes[0], RELOP_EQ, PR_FAV_PUBLIC_SOURCE_KEY, lpPropSourceKey);
574
575 hr = lpTable->FindRow(lpRestriction, BOOKMARK_BEGINNING, 0);
576 if (hr != hrSuccess)
577 goto exit;
578
579 // Favorite is exist, get the information
580
581 hr = lpTable->QueryRows (1, 0, &lpRows);
582 if (hr != hrSuccess)
583 goto exit;
584
585 if (lpRows->cRows == 0) {
586 hr = MAPI_E_NOT_FOUND;
587 goto exit; // Folder gone?
588 }
589
590 cShortCutValues = 0;
591 hr = Util::HrCopyPropertyArray(lpRows->aRow[0].lpProps, lpRows->aRow[0].cValues, &lpShortCutPropValues, &cShortCutValues, true);
592 if (hr != hrSuccess)
593 goto exit;
594
595
596 *lppShortCutPropValues = lpShortCutPropValues;
597 *lpcValues = cShortCutValues;
598 exit:
599 if (hr != hrSuccess)
600 MAPIFreeBuffer(lpShortCutPropValues);
601 MAPIFreeBuffer(lpPropSourceKey);
602 if (lpTable)
603 lpTable->Release();
604
605 FREE_RESTRICTION(lpRestriction);
606
607 return hr;
608 }
4242 HRESULT AddToFavorite(IMAPIFolder *lpShortcutFolder, ULONG ulLevel, LPCTSTR lpszAliasName, ULONG ulFlags, ULONG cValues, LPSPropValue lpPropArray);
4343 HRESULT GetShortcutFolder(LPMAPISESSION lpSession, LPTSTR lpszFolderName, LPTSTR lpszFolderComment, ULONG ulFlags, LPMAPIFOLDER* lppShortcutFolder);
4444 HRESULT CreateShortcutFolder(IMsgStore *lpMsgStore, LPTSTR lpszFolderName, LPTSTR lpszFolderComment, ULONG ulFlags, LPMAPIFOLDER* lppShortcutFolder);
45 HRESULT GetFavorite(IMAPIFolder *lpShortcutFolder, ULONG ulFlags, IMAPIFolder *lpMapiFolder, ULONG *lpcValues, LPSPropValue *lppShortCutPropValues);
46
4745 HRESULT DelFavoriteFolder(IMAPIFolder *lpShortcutFolder, LPSPropValue lpPropSourceKey);
4846 HRESULT AddFavoriteFolder(IMAPIFolder *lpShortcutFolder, LPMAPIFOLDER lpFolder, LPCTSTR lpszAliasName, ULONG ulFlags);
4947
4343 const char *GetServerUnixSocket(const char *szPreferred = NULL);
4444 std::string GetServerFQDN();
4545
46 HRESULT HrOpenECAdminSession(ECLogger *const lpLogger, IMAPISession **lppSession, const char *const app_version, const char *const app_misc, const char *szPath = NULL, ULONG ulProfileFlags = 0, const char *sslkey_file = NULL, const char *sslkey_password = NULL);
46 HRESULT __attribute__((nonnull(1))) HrOpenECAdminSession(ECLogger *const lpLogger, IMAPISession **lppSession, const char *const app_version, const char *const app_misc, const char *szPath = NULL, ULONG ulProfileFlags = 0, const char *sslkey_file = NULL, const char *sslkey_password = NULL);
4747
48 HRESULT HrOpenECSession(ECLogger *const lpLogger, IMAPISession **lppSession, const char *const app_version, const char *const app_misc, const WCHAR *szUsername, const WCHAR *szPassword, const char *szPath = NULL, ULONG ulProfileFlags = 0, const char *sslkey_file = NULL, const char *sslkey_password = NULL, const char *profname = NULL);
48 HRESULT __attribute__((nonnull(1))) HrOpenECSession(ECLogger *const lpLogger, IMAPISession **lppSession, const char *const app_version, const char *const app_misc, const WCHAR *szUsername, const WCHAR *szPassword, const char *szPath = NULL, ULONG ulProfileFlags = 0, const char *sslkey_file = NULL, const char *sslkey_password = NULL, const char *profname = NULL);
4949
5050 HRESULT HrSearchECStoreEntryId(IMAPISession *lpMAPISession, BOOL bPublic, ULONG *lpcbEntryID, LPENTRYID *lppEntryID);
5151
7575
7676 HRESULT GetClientVersion(unsigned int* ulVersion);
7777
78 HRESULT CreateProfileTemp(ECLogger *const lpLogger, const WCHAR *username, const WCHAR *password, const char *path, const char* szProfName, ULONG ulProfileFlags, const char *sslkey_file, const char *sslkey_password, const char *app_version, const char *app_misc);
78 HRESULT __attribute__((nonnull(1))) CreateProfileTemp(ECLogger *const lpLogger, const WCHAR *username, const WCHAR *password, const char *path, const char* szProfName, ULONG ulProfileFlags, const char *sslkey_file, const char *sslkey_password, const char *app_version, const char *app_misc);
7979 HRESULT DeleteProfileTemp(char *szProfName);
8080
8181 HRESULT OpenSubFolder(LPMDB lpMDB, const WCHAR *folder, WCHAR psep, ECLogger *lpLogger, bool bIsPublic, bool bCreateFolder, LPMAPIFOLDER *lppSubFolder);
4848
4949 enum { element_size = sizeof(_T) };
5050
51 // Constructors
5251 mapi_array_ptr() : m_lpObject(NULL) {}
5352
5453 mapi_array_ptr(pointer lpObject) : m_lpObject(lpObject) {}
55
56
57 // Destructor
5854 ~mapi_array_ptr() {
5955 MAPIFreeBuffer(m_lpObject);
6056 m_lpObject = NULL;
6157 }
6258
63
64 // Assignment
6559 mapi_array_ptr& operator=(pointer lpObject) {
6660 if (m_lpObject != lpObject) {
6761 mapi_array_ptr tmp(lpObject);
7064 return *this;
7165 }
7266
73
74 // Dereference
7567 reference operator*() { return *m_lpObject; }
7668 const_reference operator*() const { return *m_lpObject; }
7769
78
7970 // Utility
8071 void swap(mapi_array_ptr &other) {
8172 std::swap(m_lpObject, other.m_lpObject);
4949 typedef const _T& const_reference;
5050 typedef mapi_memory_proxy<_T> proxy;
5151
52
53 // Constructors
5452 mapi_memory_ptr() : m_lpMemory(NULL) {}
5553
5654 mapi_memory_ptr(pointer lpObject) : m_lpMemory(lpObject) {}
57
58
59 // Destructor
6055 ~mapi_memory_ptr() {
6156 MAPIFreeBuffer(m_lpMemory);
6257 m_lpMemory = NULL;
6358 }
6459
65
66 // Assignment
6760 mapi_memory_ptr& operator=(pointer lpObject) {
6861 if (m_lpMemory != lpObject) {
6962 mapi_memory_ptr tmp(lpObject);
7265 return *this;
7366 }
7467
75
76 // Dereference
7768 pointer operator->() { return m_lpMemory; }
7869 const_pointer operator->() const { return m_lpMemory; }
7970
5656 typedef const _T& const_reference;
5757 typedef mapi_object_proxy<_T,_R> proxy;
5858
59 // Constructors
6059 mapi_object_ptr() : m_lpObject(NULL) {}
6160
6261 explicit mapi_object_ptr(pointer lpObject, bool bAddRef = true) : m_lpObject(lpObject) {
6968 m_lpObject->AddRef();
7069 }
7170
72
73 // Destructor
7471 ~mapi_object_ptr() {
7572 if (m_lpObject) {
7673 m_lpObject->Release();
7875 }
7976 }
8077
81
82 // Assignment
8378 mapi_object_ptr& operator=(const mapi_object_ptr &other) {
8479 if (this != &other) {
8580 mapi_object_ptr tmp(other);
2525 #include <mapix.h>
2626 class ECLogger;
2727
28 HRESULT ValidateArchivedUserCount(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, unsigned int *lpulArchivedUsers, unsigned int *lpulMaxUsers);
29 HRESULT GetArchivedUserCount(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, unsigned int *lpulArchivedUsers);
30
3128 HRESULT GetArchivedUserList(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, std::list<std::string> *lplstUsers, bool bLocalOnly = false);
3229 HRESULT GetArchivedUserList(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, std::list<std::wstring> *lplstUsers, bool bLocalOnly = false);
3330
6767 static HRESULT GetMailboxDataPerServer(ECLogger *lpLogger, IMAPISession *lpSession, const char *lpszPath, DataCollector *lpCollector);
6868 static HRESULT UpdateServerList(ECLogger *lpLogger, IABContainer *lpContainer, std::set<servername> &listServers);
6969
70
7170 class UserCountCollector _zcp_final : public DataCollector
7271 {
7372 public:
9695 std::list<string_type> m_lstUsers;
9796 MAPISessionPtr m_ptrSession;
9897 };
99
10098
10199 HRESULT DataCollector::GetRequiredPropTags(LPMAPIPROP /*lpProp*/, LPSPropTagArray *lppPropTagArray) const {
102100 static SizedSPropTagArray(1, sptaDefaultProps) = {1, {PR_DISPLAY_NAME}};
131129 return hr;
132130 }
133131
134
135
136132 UserCountCollector::UserCountCollector(): m_ulUserCount(0) {}
137133
138134 HRESULT UserCountCollector::CollectData(LPMAPITABLE lpStoreTable) {
152148 inline unsigned int UserCountCollector::result() const {
153149 return m_ulUserCount;
154150 }
155
156151
157152 template<typename string_type, ULONG prAccount>
158153 UserListCollector<string_type, prAccount>::UserListCollector(IMAPISession *lpSession): m_ptrSession(lpSession, true) {}
213208 template<>
214209 void UserListCollector<std::wstring, PR_ACCOUNT_W>::push_back(LPSPropValue lpPropAccount) {
215210 m_lstUsers.push_back(lpPropAccount->Value.lpszW);
216 }
217
218
219
220 HRESULT ValidateArchivedUserCount(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, unsigned int *lpulArchivedUsers, unsigned int *lpulMaxUsers)
221 {
222 HRESULT hr = S_OK;
223 unsigned int ulArchivedUsers = 0;
224 unsigned int ulMaxUsers = 0;
225 MsgStorePtr ptrStore;
226 ECLicensePtr ptrLicense;
227
228 hr = GetArchivedUserCount(lpLogger, lpMapiSession, lpSSLKey, lpSSLPass, &ulArchivedUsers);
229 if (hr != hrSuccess)
230 goto exit;
231
232 //@todo use PR_EC_OBJECT property
233 hr = HrOpenDefaultStore(lpMapiSession, &ptrStore);
234 if(hr != hrSuccess) {
235 lpLogger->Log(EC_LOGLEVEL_CRIT, "Unable to open default store: 0x%08X", hr);
236 goto exit;
237 }
238
239 hr = ptrStore->QueryInterface(IID_IECLicense, &ptrLicense);
240 if(hr != hrSuccess)
241 goto exit;
242
243 // Do no check the return value, possible the license server isn't running!
244 ptrLicense->LicenseUsers(1/*SERVICE_TYPE_ARCHIVE*/, &ulMaxUsers);
245
246
247 *lpulArchivedUsers = ulArchivedUsers;
248 *lpulMaxUsers = ulMaxUsers;
249
250 exit:
251 return hr;
252 }
253
254 /**
255 * Get the archived users
256 *
257 * @param[out] lpulArchivedUsers Get archived user count
258 *
259 * @return MAPI error codes
260 */
261 HRESULT GetArchivedUserCount(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, unsigned int *lpulArchivedUsers)
262 {
263 HRESULT hr = hrSuccess;
264 UserCountCollector collector;
265
266 hr = GetMailboxData(lpLogger, lpMapiSession, lpSSLKey, lpSSLPass, false, &collector);
267 if (hr != hrSuccess)
268 goto exit;
269
270 *lpulArchivedUsers = collector.result();
271
272 exit:
273 return hr;
274211 }
275212
276213 HRESULT GetArchivedUserList(ECLogger *lpLogger, IMAPISession *lpMapiSession, const char *lpSSLKey, const char *lpSSLPass, std::list<std::string> *lplstUsers, bool bLocalOnly)
88
99 lib_LTLIBRARIES = libmapi.la libkchl.la
1010 noinst_DATA = libmapi.ldd libkchl.ldd
11 CLEANFILES = ${noinst_DATA}
1112
1213 libmapi_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info 1:0:0 \
1314 -Wl,--version-script=libmapi.sym ${BOOST_FILESYSTEM_LDFLAGS}
2829
2930 libkchl_la_SOURCES = hl.cpp
3031 libkchl_la_LIBADD = libmapi.la
32 libkchl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info 0:0:0 \
33 -Wl,--version-script=${top_builddir}/default.sym
34 EXTRA_libkchl_la_DEPENDENCIES = ${top_builddir}/default.sym
35
3136
3237 check-syntax:
3338 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
2020 #include <mapidefs.h>
2121 #include <mapiguid.h>
2222
23 // IUnknown implementation
2423 M4LUnknown::M4LUnknown() {
2524 ref = 0;
2625 pthread_mutex_init(&mutex, NULL);
9999 #ifdef DEBUG
100100 #define ORIG_TRACE_MAPILIB TraceMapiLib
101101 #else
102 #ifdef LINUX
103102 #define ORIG_TRACE_MAPILIB(...)
104 #else
105 #define ORIG_TRACE_MAPILIB __noop
106 #endif
107103 #endif
108104 #undef TRACE_MAPILIB
109105
231231 HRESULT hr;
232232 SPropValue sProp;
233233
234 memset(&sProp, 0, sizeof(sProp));
234235 sProp.ulPropTag = DefinitionFromString(strTag, true);
235236 switch (PROP_TYPE(sProp.ulPropTag)) {
236237 case PT_LONG:
317318 {
318319 HRESULT hr;
319320 inf_section::const_iterator iSection;
320 vector<string> prop;
321321
322322 hr = MAPIAllocateBuffer(sizeof(SPropValue) * infProvider->size(), (void**)&m_lpProps);
323323 if (hr != hrSuccess)
330330 ++m_cValues;
331331 return hrSuccess;
332332 }
333
334333
335334 SVCService::SVCService()
336335 {
352352 return hr;
353353 }
354354
355
356355 // ---
357356 // IProfSect
358357 // ---
360359 M4LProfSect::M4LProfSect(BOOL bGlobalProf) {
361360 this->bGlobalProf = bGlobalProf;
362361 }
363
364362
365363 HRESULT M4LProfSect::ValidateState(ULONG ulUIParam, ULONG ulFlags) {
366364 TRACE_MAPILIB(TRACE_ENTRY, "M4LProfSect::ValidateState", "");
456454 TRACE_MAPILIB1(TRACE_RETURN, "M4LProfSect::QueryInterface", "0x%08x", hr);
457455 return hr;
458456 }
459
460457
461458 // ---
462459 // IMAPITable
928925 return hr;
929926 }
930927
931
932928 //
933929 // IMAPIAdviseSink
934930 //
941937 ULONG M4LMAPIAdviseSink::OnNotify(ULONG cNotif, LPNOTIFICATION lpNotifications) {
942938 return this->lpFn(this->lpContext, cNotif, lpNotifications);
943939 }
944
945940
946941 // iunknown passthru
947942 ULONG M4LMAPIAdviseSink::AddRef() {
333333 LPENTRYLIST lpDeleteEntries = NULL;
334334 bool bPartial = false;
335335 ULONG i;
336
337336
338337 if (!lpSrcInterface || !lpSrcFolder || !lpDestFolder || !lpMsgList) {
339338 hr = MAPI_E_INVALID_PARAMETER;
603602 if (_tcscmp(lpAddrType->Value.LPSZ, _T("MAPIPDL")))
604603 continue;
605604
606
607605 lpDLEntryID = PpropFindProp(ptrRow[0].lpProps, ptrRow[0].cValues, PR_ENTRYID);
608606 if (!lpDLEntryID)
609607 continue;
355355 return hr;
356356 }
357357
358
359358 //--- php-ext used functions
360359 HRESULT __stdcall HrQueryAllRows(LPMAPITABLE lpTable, LPSPropTagArray lpPropTags, LPSRestriction lpRestriction, LPSSortOrderSet lpSortOrderSet, LONG crowsMax, LPSRowSet *lppRows) {
361360 TRACE_MAPILIB1(TRACE_ENTRY, "HrQueryAllRows", "%s", PropNameFromPropTagArray(lpPropTags).c_str());
447446 return (hr == hrSuccess);
448447 }
449448
450
451449 /* Actually not part of MAPI */
452 #ifdef LINUX
453450 HRESULT __stdcall CreateStreamOnHGlobal(void *hGlobal, BOOL fDeleteOnRelease, IStream **lppStream)
454451 {
455452 HRESULT hr = hrSuccess;
473470
474471 return hr;
475472 }
476 #endif
477473
478474 HRESULT __stdcall OpenStreamOnFile(LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags,
479475 LPTSTR lpszFileName, LPTSTR lpszPrefix, LPSTREAM FAR * lppStream)
518518 return *i;
519519 return NULL;
520520 }
521
522521
523522 HRESULT M4LMsgServiceAdmin::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR* lppMAPIError) {
524523 TRACE_MAPILIB(TRACE_ENTRY, "M4LMsgServiceAdmin::GetLastError", "");
976975 PR_DISPLAY_NAME_A, PR_OBJECT_TYPE, PR_PROVIDER_UID, PR_RESOURCE_TYPE,
977976 PR_PROVIDER_DISPLAY_A, PR_SERVICE_UID}};
978977
979
980978 pthread_mutex_lock(&m_mutexserviceadmin);
981979
982980 for (j = services.begin(); j != services.end(); ++j) {
10821080 TRACE_MAPILIB1(TRACE_RETURN, "M4LMsgServiceAdmin::QueryInterface", "0x%08x", hr);
10831081 return hr;
10841082 }
1085
10861083
10871084 // ---
10881085 // M4LMAPISession
18871884 return hr;
18881885 }
18891886
1890
18911887 // ---
18921888 // M4LAddrBook
18931889 // ---
20062002
20072003 return hr;
20082004 }
2009
20102005
20112006 //
20122007 // How it works:
27132708 return hr;
27142709 }
27152710
2716
27172711 // imapiprop passthru
27182712 // maybe not all functions should be passed though?
27192713 HRESULT M4LAddrBook::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR* lppMAPIError) {
27992793 return hr;
28002794 }
28012795
2802
28032796 // iunknown passthru
28042797 ULONG M4LAddrBook::AddRef() {
28052798 TRACE_MAPILIB(TRACE_ENTRY, "M4LAddrBook::AddRef", "");
28282821 TRACE_MAPILIB1(TRACE_RETURN, "M4LAddrBook::QueryInterface", "0x%08x", hr);
28292822 return hr;
28302823 }
2831
2832
28332824
28342825 // ---------------------------------------
28352826
3636 #include "ext/standard/php_string.h"
3737 }
3838
39
40
4139 // A very, very nice PHP #define that causes link errors in MAPI when you have multiple
4240 // files referencing MAPI....
4341 #undef inline
3636 #include "ext/standard/php_string.h"
3737 }
3838
39
40
4139 // A very, very nice PHP #define that causes link errors in MAPI when you have multiple
4240 // files referencing MAPI....
4341 #undef inline
2424
2525 #include <mapix.h>
2626
27
2827 /* conversion from unicode to string8 for rules table data */
2928 static HRESULT ConvertUnicodeToString8(LPSRestriction lpRes, void *base, convert_context &converter);
3029 static HRESULT ConvertUnicodeToString8(const ACTIONS *lpActions, void *base, convert_context &converter);
31
3230
3331 ECRulesTableProxy::ECRulesTableProxy(LPMAPITABLE lpTable)
3432 : m_lpTable(lpTable)
6361 exit:
6462 return hr;
6563 }
66
6764
6865 HRESULT ECRulesTableProxy::QueryInterface(REFIID refiid, void **lppInterface)
6966 {
230227 METHOD_PROLOGUE_(ECRulesTableProxy, MAPITable);
231228 return pThis->Release();
232229 }
233
234230
235231 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, QueryInterface, (REFIID, refiid), (void **, lppInterface))
236232 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, GetLastError, (HRESULT, hResult), (ULONG, ulFlags), (LPMAPIERROR *, lppMAPIError))
257253 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, GetCollapseState, (ULONG, ulFlags), (ULONG, cbInstanceKey, LPBYTE, lpbInstanceKey), (ULONG *, lpcbCollapseState, LPBYTE *, lppbCollapseState))
258254 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, SetCollapseState, (ULONG, ulFlags), (ULONG, cbCollapseState, LPBYTE, pbCollapseState), (BOOKMARK *, lpbkLocation))
259255
260
261
262256 static HRESULT ConvertUnicodeToString8(const WCHAR *lpszW, char **lppszA,
263257 void *base, convert_context &converter)
264258 {
77 $(PHP_INCLUDES)
88 AM_CXXFLAGS = ${ZCXXFLAGS} ${ZPHPCXXFLAGS}
99
10 lib_LTLIBRARIES = mapi.la
10 phplib_LTLIBRARIES = mapi.la
1111
12 libdir=$(PHP_EXTENSION_DIR)
12 phplibdir = ${dcprefix}${PHP_EXTENSION_DIR}
1313
1414 mapi_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version \
1515 $(PHP_LDFLAGS)
3636 # If we install our config file into that location, it will only be available
3737 # to only apache2-mod_php5 and not php-cli, php-fpm, etc.
3838 #
39 sysconfdir = ${PHP_SYSCONF_DIR}
39 sysconfdir = ${dcprefix}${PHP_SYSCONF_DIR}
4040 dist_sysconf_DATA = mapi.ini
4141
4242 sampleconfdir = ${docdir}/example-config
9595 }
9696
9797 /**
98 * @return string returns file name and line number combined where exception occured.
98 * @return string returns file name and line number combined where exception occurred.
9999 */
100100 public function getFileLine()
101101 {
135135 }
136136
137137 /**
138 * @return string returns base path of the file where exception occured.
138 * @return string returns base path of the file where exception occurred.
139139 */
140140 public function getBaseFile()
141141 {
191191
192192 // @TODO getTrace and getTraceAsString
193193 }
194 ?>
194 ?>
5555 var $tz;
5656
5757 /**
58 * Constructor
5958 * @param resource $store MAPI Message Store Object
6059 * @param resource $message the MAPI (appointment) message
6160 * @param array $properties the list of MAPI properties the message has.
3131 var $proptags;
3232
3333 /**
34 * Constuctor
35 *
3634 * @param mapi_session $session MAPI Session
3735 * @param mapi_folder $calendar Calendar to publish
3836 * @param string $entryid AddressBook Entry ID for the user we're publishing for
105105 var $errorSetResource;
106106
107107 /**
108 * Constructor
109 *
110108 * Takes a store and a message. The message is an appointment item
111109 * that should be converted into a meeting request or an incoming
112110 * e-mail message that is a meeting request.
841839
842840 if ($move) {
843841 // All we have to do is open the default calendar,
844 // set the mesage class correctly to be an appointment item
842 // set the message class correctly to be an appointment item
845843 // and move it to the calendar folder
846844 $sourcefolder = $this->openParentFolder();
847845
23592357 $this->includesResources = true;
23602358 }else{
23612359 /**
2362 * If no other errors occured and you have no access to the
2360 * If no other errors occurred and you have no access to the
23632361 * folder of the resource, throw an error=1.
23642362 */
23652363 if(!$this->errorSetResource){
28452843 $result = true;
28462844 }
28472845 } else {
2848 // we are not able to find exception, could mean that a significant change has occured on series
2846 // we are not able to find exception, could mean that a significant change has occurred on series
28492847 // and it deleted all exceptions, so compare with series
28502848 if ((isset($calendarItemProps[$this->proptags['updatecounter']]) && $props[$this->proptags['updatecounter']] < $calendarItemProps[$this->proptags['updatecounter']])
28512849 || (isset($calendarItemProps[$this->proptags['owner_critical_change']]) && $props[$this->proptags['owner_critical_change']] < $calendarItemProps[$this->proptags['owner_critical_change']])) {
5959 );
6060
6161 /**
62 * Constructor
6362 * @param resource $store MAPI Message Store Object
6463 * @param resource $message the MAPI (appointment) message
6564 */
174174 $this->action['startdate'] = $props[$this->proptags['startdate']] = $nextOccurrence[$this->proptags['startdate']];
175175 $this->action['commonstart'] = $props[$this->proptags['commonstart']] = $nextOccurrence[$this->proptags['startdate']];
176176
177 // If current task as been mark as 'Complete' then next occurrence should be uncomplete.
177 // If current task as been mark as 'Complete' then next occurrence should be incomplete.
178178 if (isset($this->action['complete']) && $this->action['complete'] == 1) {
179179 $this->action['status'] = $props[$this->proptags["status"]] = olTaskNotStarted;
180180 $this->action['complete'] = $props[$this->proptags["complete"]] = false;
8686 // All recipient properties
8787 var $recipprops = Array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID, PR_SEARCH_KEY);
8888
89 /* Constructor
90 *
89 /*
9190 * Constructs a TaskRequest object for the specified message. This can be either the task request
9291 * message itself (in the inbox) or the task in the tasks folder, depending on the action to be performed.
9392 *
3636 */
3737 function makeGuid($guid)
3838 {
39 // remove the { and } from the string and explode it into an array
40 $guidArray = explode('-', substr($guid, 1,strlen($guid)-2));
41
42 // convert to hex!
43 $data1[0] = intval(substr($guidArray[0], 0, 4),16); // we need to split the unsigned long
44 $data1[1] = intval(substr($guidArray[0], 4, 4),16);
45 $data2 = intval($guidArray[1], 16);
46 $data3 = intval($guidArray[2], 16);
47
48 $data4[0] = intval(substr($guidArray[3], 0, 2),16);
49 $data4[1] = intval(substr($guidArray[3], 2, 2),16);
50
51 for($i=0; $i < 6; $i++)
52 {
53 $data4[] = intval(substr($guidArray[4], $i*2, 2),16);
54 }
55
56 return pack("vvvvCCCCCCCC", $data1[1], $data1[0], $data2, $data3, $data4[0],$data4[1],$data4[2],$data4[3],$data4[4],$data4[5],$data4[6],$data4[7]);
39 return pack("vvvv", hexdec(substr($guid, 5, 4)), hexdec(substr($guid, 1, 4)), hexdec(substr($guid, 10, 4)), hexdec(substr($guid, 15, 4))) . hex2bin(substr($guid, 20, 4)) . hex2bin(substr($guid, 25, 12));
5740 }
5841
5942 /**
115115 #include "php_globals.h"
116116 #include "php_ini.h"
117117
118 #if PHP_MAJOR_VERSION >= 5
119 #define SUPPORT_EXCEPTIONS 1
120 #else
121 #define SUPPORT_EXCEPTIONS 0
122 #endif
123
124 #if SUPPORT_EXCEPTIONS
125118 #include "zend_exceptions.h"
126 #endif
127119 #include "ext/standard/info.h"
128120 #include "ext/standard/php_string.h"
129121 }
143135 ZEND_END_ARG_INFO()
144136 #endif
145137
146
147138 #define LOG_BEGIN() { \
148139 if (mapi_debug & 1) { \
149140 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "[IN] %s", __FUNCTION__); \
198189 #include "util.h"
199190 #include "rtfutil.h"
200191 #include <kopano/CommonUtil.h>
201 #include <kopano/ECLogger.h>
202192
203193 #include "ECImportContentsChangesProxy.h"
204194 #include "ECImportHierarchyChangesProxy.h"
453443 ZEND_FE(mapi_inetmapi_imtoinet, NULL)
454444 ZEND_FE(mapi_inetmapi_imtomapi, NULL)
455445
456 #if SUPPORT_EXCEPTIONS
457446 ZEND_FE(mapi_enable_exceptions, NULL)
458 #endif
459447
460448 ZEND_FE(mapi_feature, NULL)
461449
524512
525513 static int LoadSettingsFile(void)
526514 {
527 #ifdef LINUX
528515 const char *const cfg_file = ECConfig::GetDefaultPath("php-mapi.cfg");
529 #else
530 const char *const cfg_file = "php-mapi.cfg";
531 #endif
532
533516 struct stat st;
534517 if (stat(cfg_file, &st) == 0) {
535518 static const configsetting_t settings[] = {
554537 const char *temp = cfg->GetSetting(CE_PHP_MAPI_PERFORMANCE_TRACE_FILE);
555538 if (temp != NULL) {
556539 perf_measure_file = strdup(temp);
557 lpLogger->Log(EC_LOGLEVEL_INFO, "Performance measuring enabled");
540 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-MAPI Performance measuring enabled");
558541 }
559542
560543 temp = cfg->GetSetting(CE_PHP_MAPI_DEBUG);
569552 if (lpLogger == NULL)
570553 return FAILURE;
571554
572 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-Mapi instantiated " PROJECT_VERSION_EXT_STR);
555 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-MAPI instantiated " PROJECT_VERSION_EXT_STR);
573556
574557 ec_log_set(lpLogger);
575558 if (mapi_debug)
625608 }
626609
627610 // Used at the end of each MAPI call to throw exceptions if mapi_enable_exceptions() has been called
628 #if SUPPORT_EXCEPTIONS
629611 #define THROW_ON_ERROR() \
630612 if (FAILED(MAPI_G(hr))) { \
631613 if (lpLogger) \
634616 if (MAPI_G(exceptions_enabled)) \
635617 zend_throw_exception(MAPI_G(exception_ce), "MAPI error ", MAPI_G(hr) TSRMLS_CC); \
636618 }
637 #else
638 #define THROW_ON_ERROR() \
639 if (FAILED(MAPI_G(hr)) && lpLogger) \
640 lpLogger->Log(EC_LOGLEVEL_ERROR, "MAPI error: %s (%x) (method: %s, line: %d)", GetMAPIErrorMessage(MAPI_G(hr)), MAPI_G(hr), __FUNCTION__, __LINE__);
641 #endif
642619
643620 /**
644621 *
652629 perf_measure_file = NULL;
653630
654631 if (lpLogger)
655 lpLogger->Log(EC_LOGLEVEL_INFO, "php-mapi shutdown");
632 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-MAPI shutdown");
656633
657634 MAPIUninitialize();
658635 lpLogger->Release();
719696 LPUNKNOWN lpObj = (LPUNKNOWN)rsrc->ptr;
720697 if (lpObj) lpObj->Release();
721698 }
722
723699
724700 static HRESULT GetECObject(LPMAPIPROP lpMapiProp,
725701 IECUnknown **lppIECUnknown TSRMLS_DC)
11471123 LPADRBOOK lpAddrBook;
11481124 // local
11491125
1150
11511126 RETVAL_FALSE;
11521127 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
11531128
12901265 THROW_ON_ERROR();
12911266 }
12921267
1293
12941268 /**
12951269 * mapi_getstores
12961270 * Gets the table with the messagestores available
17431717 THROW_ON_ERROR();
17441718 }
17451719
1746
17471720 ZEND_FUNCTION(mapi_folder_emptyfolder)
17481721 {
17491722 PMEASURE_FUNC;
18171790 LOG_END();
18181791 THROW_ON_ERROR();
18191792 }
1820
18211793
18221794 /**
18231795 * mapi_msgstore_createentryid
18681840 LOG_END();
18691841 THROW_ON_ERROR();
18701842 }
1871
18721843
18731844 /**
18741845 * mapi_msgstore_getearchiveentryid
19201891 THROW_ON_ERROR();
19211892 }
19221893
1923
19241894 /**
19251895 * mapi_openentry
19261896 * Opens the msgstore to get the root folder.
22592229 }
22602230 }
22612231
2262
22632232 MAPI_G(hr) = lpTable->QueryRows(lRowCount, 0, &pRowSet);
22642233
22652234 if (FAILED(MAPI_G(hr)))
28632832 THROW_ON_ERROR();
28642833 }
28652834
2866
28672835 ZEND_FUNCTION(mapi_message_createattach)
28682836 {
28692837 PMEASURE_FUNC;
30953063 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) return;
30963064
30973065 ZEND_FETCH_RESOURCE_C(pStream, LPSTREAM, &res, -1, name_istream, le_istream);
3098
30993066
31003067 MAPI_G(hr) = pStream->Stat(&stg,STATFLAG_NONAME);
31013068 if(MAPI_G(hr) != hrSuccess)
33403307
33413308 if(guidArray)
33423309 guidHash = Z_ARRVAL_P(guidArray);
3343
33443310
33453311 // get the number of items in the array
33463312 hashTotal = zend_hash_num_elements(targetHash);
35573523 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown resource type");
35583524 goto exit;
35593525 }
3560
35613526
35623527 MAPI_G(hr) = lpSrcObj->CopyTo(cExcludeIIDs, lpExcludeIIDs, lpExcludeProps, 0, NULL, lpInterface, lpDstObj, flags, NULL);
35633528
43244289 THROW_ON_ERROR();
43254290 }
43264291
4327
43284292 ZEND_FUNCTION(mapi_zarafa_setuser)
43294293 {
43304294 PMEASURE_FUNC;
44244388
44254389 ZEND_FETCH_RESOURCE_C(lpMsgStore, LPMDB, &res, -1, name_mapi_msgstore, le_mapi_msgstore);
44264390
4427
44284391 MAPI_G(hr) = GetECObject(lpMsgStore, &lpUnknown TSRMLS_CC);
44294392 if(MAPI_G(hr) != hrSuccess) {
44304393 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Specified object is not a kopano store");
47384701 THROW_ON_ERROR();
47394702 }
47404703
4741
47424704 /**
47434705 * Retrieve user information
47444706 * @param logged on msgstore
52755237 if(MAPI_G(hr) != hrSuccess)
52765238 goto exit;
52775239
5278
52795240 array_init(return_value);
52805241 for (i = 0; i < ulGroups; ++i) {
52815242 MAKE_STD_ZVAL(zval_data_value);
53705331 IECUnknown *lpUnknown = NULL;
53715332 IECServiceAdmin *lpServiceAdmin = NULL;
53725333 ULONG ulUsers;
5373 ECUSER *lpsUsers;
5334 ECUSER *lpsUsers = NULL;
53745335 unsigned int i;
53755336
53765337 RETVAL_FALSE;
68526813 THROW_ON_ERROR();
68536814 }
68546815
6855
68566816 ZEND_FUNCTION(mapi_freebusyenumblock_skip)
68576817 {
68586818 PMEASURE_FUNC;
69776937
69786938 zend_hash_move_forward(target_hash);
69796939 }
6980
69816940
69826941 MAPI_G(hr) = lpFBUpdate->PublishFreeBusy(lpBlocks, cBlocks);
69836942 if(MAPI_G(hr) != hrSuccess)
75887547 THROW_ON_ERROR();
75897548 }
75907549
7591
75927550 ZEND_FUNCTION(mapi_importhierarchychanges_importfolderdeletion)
75937551 {
75947552 PMEASURE_FUNC;
76247582 LOG_END();
76257583 THROW_ON_ERROR();
76267584 }
7627
7628
76297585
76307586 /*
76317587 * This function needs some explanation as it is not just a one-to-one MAPI function. This function
77947750 return;
77957751 }
77967752
7797 #if SUPPORT_EXCEPTIONS
77987753 ZEND_FUNCTION(mapi_enable_exceptions)
77997754 {
78007755 PMEASURE_FUNC;
78167771 LOG_END();
78177772 return;
78187773 }
7819 #endif
78207774
78217775 // Can be queried by client applications to check whether certain API features are supported or not.
78227776 ZEND_FUNCTION(mapi_feature)
78337787 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &szFeature, &cbFeature) == FAILURE) return;
78347788
78357789 for (unsigned int i = 0; i < arraySize(features); ++i)
7836 if(stricmp(features[i], szFeature) == 0) {
7790 if(strcasecmp(features[i], szFeature) == 0) {
78377791 RETVAL_TRUE;
78387792 break;
78397793 }
296296 ZEND_FUNCTION(mapi_inetmapi_imtoinet);
297297 ZEND_FUNCTION(mapi_inetmapi_imtomapi);
298298
299 #if SUPPORT_EXCEPTIONS
300299 ZEND_FUNCTION(mapi_enable_exceptions);
301 #endif
302300
303301 ZEND_FUNCTION(mapi_feature);
304302
6767 PHPTag = (LONG)ulPropTag;
6868 return PHPTag;
6969 }
70
7170
7271 /*
7372 * Converts a PHP Array into a SBinaryArray. This is the same as an ENTRYLIST which
292291 exit:
293292 return MAPI_G(hr);
294293 }
295
296294
297295 /*
298296 * Converts an PHP property value array to a MAPI property value structure
460458 lpPropValue[cvalues].Value.mapimvmember.mapilpmember[j] = dataEntry[0]->value.phpmember; \
461459 zend_hash_move_forward(dataHash); \
462460 }
463
464461
465462 case PT_MV_I2:
466463 COPY_MV_PROPS(long, MVi, lpi, lval);
15271524 add_assoc_zval(ret, "1", array);
15281525 break;
15291526
1530
15311527 case RES_CONTENT:
15321528 MAPI_G(hr) = PropValueArraytoPHPArray(1, lpRes->res.resContent.lpProp, &props TSRMLS_CC);
15331529 if (MAPI_G(hr) != hrSuccess)
17131709 char pulproptag[16];
17141710
17151711 pPropValue = &pPropValueArray[col];
1716
17171712
17181713 /*
17191714 * PHP wants a string as array key. PHP will transform this to zval integer when possible.
20011996 return MAPI_G(hr);
20021997 }
20031998
2004
20051999 /*
20062000 * Convert from READSTATE array to PHP. Returns a list of arrays, each containing "sourcekey" and "flags" per entry
20072001 */
21112105 int i = 0;
21122106 zval **ppentry = NULL;
21132107 zval *pentry = NULL;
2114
21152108
21162109 MAPI_G(hr) = hrSuccess;
21172110
3838 #include "ext/standard/php_string.h"
3939 }
4040
41
42
4341 // A very, very nice PHP #define that causes link errors in MAPI when you have multiple
4442 // files referencing MAPI....
4543 #undef inline
3838 #include "ext/standard/php_string.h"
3939 }
4040
41
4241 // A very, very nice PHP #define that causes link errors in MAPI when you have multiple
4342 // files referencing MAPI....
4443 #undef inline
2424
2525 #include <mapix.h>
2626
27
2827 /* conversion from unicode to string8 for rules table data */
2928 static HRESULT ConvertUnicodeToString8(LPSRestriction lpRes, void *base, convert_context &converter);
3029 static HRESULT ConvertUnicodeToString8(const ACTIONS *lpActions, void *base, convert_context &converter);
31
3230
3331 ECRulesTableProxy::ECRulesTableProxy(LPMAPITABLE lpTable)
3432 : m_lpTable(lpTable)
6361 exit:
6462 return hr;
6563 }
66
6764
6865 HRESULT ECRulesTableProxy::QueryInterface(REFIID refiid, void **lppInterface)
6966 {
230227 METHOD_PROLOGUE_(ECRulesTableProxy, MAPITable);
231228 return pThis->Release();
232229 }
233
234230
235231 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, QueryInterface, (REFIID, refiid), (void **, lppInterface))
236232 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, GetLastError, (HRESULT, hResult), (ULONG, ulFlags), (LPMAPIERROR *, lppMAPIError))
257253 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, GetCollapseState, (ULONG, ulFlags), (ULONG, cbInstanceKey, LPBYTE, lpbInstanceKey), (ULONG *, lpcbCollapseState, LPBYTE *, lppbCollapseState))
258254 DEF_HRMETHOD(TRACE_MAPI, ECRulesTableProxy, MAPITable, SetCollapseState, (ULONG, ulFlags), (ULONG, cbCollapseState, LPBYTE, pbCollapseState), (BOOKMARK *, lpbkLocation))
259255
260
261
262256 static HRESULT ConvertUnicodeToString8(const WCHAR *lpszW, char **lppszA,
263257 void *base, convert_context &converter)
264258 {
77 $(PHP_INCLUDES)
88 AM_CXXFLAGS = ${ZCXXFLAGS} ${ZPHPCXXFLAGS}
99
10 lib_LTLIBRARIES = mapi.la
10 phplib_LTLIBRARIES = mapi.la
1111
12 libdir=$(PHP_EXTENSION_DIR)
12 phplibdir = ${dcprefix}${PHP_EXTENSION_DIR}
1313
1414 mapi_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version \
1515 $(PHP_LDFLAGS)
3636 # If we install our config file into that location, it will only be available
3737 # to only apache2-mod_php5 and not php-cli, php-fpm, etc.
3838 #
39 sysconfdir = ${PHP_SYSCONF_DIR}
40 dist_sysconf_DATA = mapi.ini
39 phpconfdir = ${dcprefix}${PHP_SYSCONF_DIR}
40 dist_phpconf_DATA = mapi.ini
4141
4242 sampleconfdir = ${docdir}/example-config
4343 sampleconf_DATA = mapi.ini
5555 var $tz;
5656
5757 /**
58 * Constructor
5958 * @param resource $store MAPI Message Store Object
6059 * @param resource $message the MAPI (appointment) message
6160 * @param array $properties the list of MAPI properties the message has.
3131 var $proptags;
3232
3333 /**
34 * Constuctor
35 *
3634 * @param mapi_session $session MAPI Session
3735 * @param mapi_folder $calendar Calendar to publish
3836 * @param string $entryid AddressBook Entry ID for the user we're publishing for
105105 var $errorSetResource;
106106
107107 /**
108 * Constructor
109 *
110108 * Takes a store and a message. The message is an appointment item
111109 * that should be converted into a meeting request or an incoming
112110 * e-mail message that is a meeting request.
841839
842840 if ($move) {
843841 // All we have to do is open the default calendar,
844 // set the mesage class correctly to be an appointment item
842 // set the message class correctly to be an appointment item
845843 // and move it to the calendar folder
846844 $sourcefolder = $this->openParentFolder();
847845
5959 );
6060
6161 /**
62 * Constructor
6362 * @param resource $store MAPI Message Store Object
6463 * @param resource $message the MAPI (appointment) message
6564 */
174174 $this->action['startdate'] = $props[$this->proptags['startdate']] = $nextOccurrence[$this->proptags['startdate']];
175175 $this->action['commonstart'] = $props[$this->proptags['commonstart']] = $nextOccurrence[$this->proptags['startdate']];
176176
177 // If current task as been mark as 'Complete' then next occurrence should be uncomplete.
177 // If current task as been mark as 'Complete' then next occurrence should be incomplete.
178178 if (isset($this->action['complete']) && $this->action['complete'] == 1) {
179179 $this->action['status'] = $props[$this->proptags["status"]] = olTaskNotStarted;
180180 $this->action['complete'] = $props[$this->proptags["complete"]] = false;
8686 // All recipient properties
8787 var $recipprops = Array(PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_RECIPIENT_ENTRYID, PR_RECIPIENT_TYPE, PR_SEND_INTERNET_ENCODING, PR_SEND_RICH_INFO, PR_RECIPIENT_DISPLAY_NAME, PR_ADDRTYPE, PR_DISPLAY_TYPE, PR_RECIPIENT_TRACKSTATUS, PR_RECIPIENT_TRACKSTATUS_TIME, PR_RECIPIENT_FLAGS, PR_ROWID, PR_SEARCH_KEY);
8888
89 /* Constructor
90 *
89 /*
9190 * Constructs a TaskRequest object for the specified message. This can be either the task request
9291 * message itself (in the inbox) or the task in the tasks folder, depending on the action to be performed.
9392 *
3636 */
3737 function makeGuid($guid)
3838 {
39 // remove the { and } from the string and explode it into an array
40 $guidArray = explode('-', substr($guid, 1,strlen($guid)-2));
41
42 // convert to hex!
43 $data1[0] = intval(substr($guidArray[0], 0, 4),16); // we need to split the unsigned long
44 $data1[1] = intval(substr($guidArray[0], 4, 4),16);
45 $data2 = intval($guidArray[1], 16);
46 $data3 = intval($guidArray[2], 16);
47
48 $data4[0] = intval(substr($guidArray[3], 0, 2),16);
49 $data4[1] = intval(substr($guidArray[3], 2, 2),16);
50
51 for($i=0; $i < 6; $i++)
52 {
53 $data4[] = intval(substr($guidArray[4], $i*2, 2),16);
54 }
55
56 return pack("vvvvCCCCCCCC", $data1[1], $data1[0], $data2, $data3, $data4[0],$data4[1],$data4[2],$data4[3],$data4[4],$data4[5],$data4[6],$data4[7]);
39 return pack("vvvv", hexdec(substr($guid, 5, 4)), hexdec(substr($guid, 1, 4)), hexdec(substr($guid, 10, 4)), hexdec(substr($guid, 15, 4))) . hex2bin(substr($guid, 20, 4)) . hex2bin(substr($guid, 25, 12));
5740 }
5841
5942 /**
117117 #include "php_globals.h"
118118 #include "php_ini.h"
119119
120 #if PHP_MAJOR_VERSION >= 5
121 #define SUPPORT_EXCEPTIONS 1
122 #else
123 #define SUPPORT_EXCEPTIONS 0
124 #endif
125
126 #if SUPPORT_EXCEPTIONS
127120 #include "zend_exceptions.h"
128 #endif
129121 #include "ext/standard/info.h"
130122 #include "ext/standard/php_string.h"
131123 }
145137 ZEND_END_ARG_INFO()
146138 #endif
147139
148
149140 #define LOG_BEGIN() { \
150141 if (mapi_debug & 1) { \
151142 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "[IN] %s", __FUNCTION__); \
204195 #include "util.h"
205196 #include "rtfutil.h"
206197 #include <kopano/CommonUtil.h>
207 #include <kopano/ECLogger.h>
208198
209199 #include "ECImportContentsChangesProxy.h"
210200 #include "ECImportHierarchyChangesProxy.h"
459449 ZEND_FE(mapi_inetmapi_imtoinet, NULL)
460450 ZEND_FE(mapi_inetmapi_imtomapi, NULL)
461451
462 #if SUPPORT_EXCEPTIONS
463452 ZEND_FE(mapi_enable_exceptions, NULL)
464 #endif
465453
466454 ZEND_FE(mapi_feature, NULL)
467455
530518
531519 static int LoadSettingsFile(void)
532520 {
533 #ifdef LINUX
534521 const char *const cfg_file = ECConfig::GetDefaultPath("php-mapi.cfg");
535 #else
536 const char *const cfg_file = "php-mapi.cfg";
537 #endif
538
539522 struct stat st;
540523 if (stat(cfg_file, &st) == 0) {
541524 static const configsetting_t settings[] = {
575558 if (lpLogger == NULL)
576559 return FAILURE;
577560
578 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-Mapi instantiated " PROJECT_VERSION_EXT_STR);
561 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-MAPI instantiated " PROJECT_VERSION_EXT_STR);
579562
580563 ec_log_set(lpLogger);
581564 if (mapi_debug)
631614 }
632615
633616 // Used at the end of each MAPI call to throw exceptions if mapi_enable_exceptions() has been called
634 #if SUPPORT_EXCEPTIONS
635617 #define THROW_ON_ERROR() \
636618 if (FAILED(MAPI_G(hr))) { \
637619 if (lpLogger) \
640622 if (MAPI_G(exceptions_enabled)) \
641623 zend_throw_exception(MAPI_G(exception_ce), "MAPI error ", MAPI_G(hr) TSRMLS_CC); \
642624 }
643 #else
644 #define THROW_ON_ERROR() \
645 if (FAILED(MAPI_G(hr)) && lpLogger) \
646 lpLogger->Log(EC_LOGLEVEL_ERROR, "MAPI error: %s (%x) (method: %s, line: %d)", GetMAPIErrorMessage(MAPI_G(hr)), MAPI_G(hr), __FUNCTION__, __LINE__);
647 #endif
648625
649626 /**
650627 *
658635 perf_measure_file = NULL;
659636
660637 if (lpLogger)
661 lpLogger->Log(EC_LOGLEVEL_INFO, "php-mapi shutdown");
638 lpLogger->Log(EC_LOGLEVEL_INFO, "PHP-MAPI shutdown");
662639
663640 MAPIUninitialize();
664641 lpLogger->Release();
725702 LPUNKNOWN lpObj = (LPUNKNOWN)rsrc->ptr;
726703 if (lpObj) lpObj->Release();
727704 }
728
729705
730706 static HRESULT GetECObject(LPMAPIPROP lpMapiProp,
731707 IECUnknown **lppIECUnknown TSRMLS_DC)
11531129 LPADRBOOK lpAddrBook;
11541130 // local
11551131
1156
11571132 RETVAL_FALSE;
11581133 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
11591134
13011276 THROW_ON_ERROR();
13021277 }
13031278
1304
13051279 /**
13061280 * mapi_getstores
13071281 * Gets the table with the messagestores available
17541728 THROW_ON_ERROR();
17551729 }
17561730
1757
17581731 ZEND_FUNCTION(mapi_folder_emptyfolder)
17591732 {
17601733 PMEASURE_FUNC;
18281801 LOG_END();
18291802 THROW_ON_ERROR();
18301803 }
1831
18321804
18331805 /**
18341806 * mapi_msgstore_createentryid
18791851 LOG_END();
18801852 THROW_ON_ERROR();
18811853 }
1882
18831854
18841855 /**
18851856 * mapi_msgstore_getearchiveentryid
19311902 THROW_ON_ERROR();
19321903 }
19331904
1934
19351905 /**
19361906 * mapi_openentry
19371907 * Opens the msgstore to get the root folder.
22682238 }
22692239 }
22702240
2271
22722241 MAPI_G(hr) = lpTable->QueryRows(lRowCount, 0, &pRowSet);
22732242
22742243 if (FAILED(MAPI_G(hr)))
28712840 THROW_ON_ERROR();
28722841 }
28732842
2874
28752843 ZEND_FUNCTION(mapi_message_createattach)
28762844 {
28772845 PMEASURE_FUNC;
31033071 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &res) == FAILURE) return;
31043072
31053073 ZEND_FETCH_RESOURCE_C(pStream, LPSTREAM, &res, -1, name_istream, le_istream);
3106
31073074
31083075 MAPI_G(hr) = pStream->Stat(&stg,STATFLAG_NONAME);
31093076 if(MAPI_G(hr) != hrSuccess)
33483315
33493316 if(guidArray)
33503317 guidHash = Z_ARRVAL_P(guidArray);
3351
33523318
33533319 // get the number of items in the array
33543320 hashTotal = zend_hash_num_elements(targetHash);
35653531 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown resource type");
35663532 goto exit;
35673533 }
3568
35693534
35703535 MAPI_G(hr) = lpSrcObj->CopyTo(cExcludeIIDs, lpExcludeIIDs, lpExcludeProps, 0, NULL, lpInterface, lpDstObj, flags, NULL);
35713536
43314296 THROW_ON_ERROR();
43324297 }
43334298
4334
43354299 ZEND_FUNCTION(mapi_zarafa_setuser)
43364300 {
43374301 PMEASURE_FUNC;
44314395
44324396 ZEND_FETCH_RESOURCE_C(lpMsgStore, LPMDB, &res, -1, name_mapi_msgstore, le_mapi_msgstore);
44334397
4434
44354398 MAPI_G(hr) = GetECObject(lpMsgStore, &lpUnknown TSRMLS_CC);
44364399 if(MAPI_G(hr) != hrSuccess) {
44374400 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Specified object is not an zarafa store");
47084671 if (MAPI_G(hr) != hrSuccess)
47094672 goto exit;
47104673
4674 ZVAL_DEREF(array);
47114675 data = HASH_OF(array);
47124676 zend_hash_internal_pointer_reset(data);
47134677
47544718 LOG_END();
47554719 THROW_ON_ERROR();
47564720 }
4757
47584721
47594722 /**
47604723 * Retrieve user information from zarafa
52925255 if(MAPI_G(hr) != hrSuccess)
52935256 goto exit;
52945257
5295
52965258 array_init(return_value);
52975259 for (i = 0; i < ulGroups; ++i) {
52985260 array_init(&zval_data_value);
53855347 IECUnknown *lpUnknown = NULL;
53865348 IECServiceAdmin *lpServiceAdmin = NULL;
53875349 ULONG ulUsers;
5388 ECUSER *lpsUsers;
5350 ECUSER *lpsUsers = NULL;
53895351 unsigned int i;
53905352
53915353 RETVAL_FALSE;
63806342 goto exit;
63816343 }
63826344
6345 ZVAL_DEREF(perms);
63836346 target_hash = HASH_OF(perms);
63846347 if (!target_hash) {
63856348 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
63986361 j = 0;
63996362 ZEND_HASH_FOREACH_VAL(target_hash, entry) {
64006363 // null pointer returned if perms was not array(array()).
6364 ZVAL_DEREF(entry);
64016365 data = HASH_OF(entry);
64026366 zend_hash_internal_pointer_reset(data);
64036367
65526516
65536517 ZEND_FETCH_RESOURCE_C(lpFBSupport, IFreeBusySupport*, &resFBSupport, -1, name_fb_support, le_freebusy_support);
65546518
6519 ZVAL_DEREF(resUsers);
65556520 target_hash = HASH_OF(resUsers);
65566521 if (!target_hash) {
65576522 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
66326597
66336598 ZEND_FETCH_RESOURCE_C(lpFBSupport, IFreeBusySupport*, &resFBSupport, -1, name_fb_support, le_freebusy_support);
66346599
6600 ZVAL_DEREF(resUsers);
66356601 target_hash = HASH_OF(resUsers);
66366602 if (!target_hash) {
66376603 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
68656831 THROW_ON_ERROR();
68666832 }
68676833
6868
68696834 ZEND_FUNCTION(mapi_freebusyenumblock_skip)
68706835 {
68716836 PMEASURE_FUNC;
69526917
69536918 ZEND_FETCH_RESOURCE_C(lpFBUpdate, IFreeBusyUpdate*, &resFBUpdate, -1, name_fb_update, le_freebusy_update);
69546919
6920 ZVAL_DEREF(aBlocks);
69556921 target_hash = HASH_OF(aBlocks);
69566922 if (!target_hash) {
69576923 MAPI_G(hr) = MAPI_E_INVALID_PARAMETER;
69586924 goto exit;
69596925 }
69606926
6927 cBlocks = zend_hash_num_elements(target_hash);
69616928 MAPI_G(hr) = MAPIAllocateBuffer(sizeof(FBBlock_1)*cBlocks, (void**)&lpBlocks);
69626929 if(MAPI_G(hr) != hrSuccess)
69636930 goto exit;
69646931
6965 i = 0;
6966 ZEND_HASH_FOREACH_VAL(target_hash, entry) {
6932 i = 0;
6933 ZEND_HASH_FOREACH_VAL(target_hash, entry) {
6934 ZVAL_DEREF(entry);
69676935 data = HASH_OF(entry);
69686936 zend_hash_internal_pointer_reset(data);
69696937
69896957 }
69906958 ++i;
69916959
6992 } ZEND_HASH_FOREACH_END();
6993
6994 cBlocks = zend_hash_num_elements(target_hash);
6960 } ZEND_HASH_FOREACH_END();
69956961 MAPI_G(hr) = lpFBUpdate->PublishFreeBusy(lpBlocks, cBlocks);
69966962 if(MAPI_G(hr) != hrSuccess)
69976963 goto exit;
76047570 THROW_ON_ERROR();
76057571 }
76067572
7607
76087573 ZEND_FUNCTION(mapi_importhierarchychanges_importfolderdeletion)
76097574 {
76107575 PMEASURE_FUNC;
76407605 LOG_END();
76417606 THROW_ON_ERROR();
76427607 }
7643
7644
76457608
76467609 /*
76477610 * This function needs some explanation as it is not just a one-to-one MAPI function. This function
78107773 return;
78117774 }
78127775
7813 #if SUPPORT_EXCEPTIONS
78147776 ZEND_FUNCTION(mapi_enable_exceptions)
78157777 {
78167778 PMEASURE_FUNC;
78317793 LOG_END();
78327794 return;
78337795 }
7834 #endif
78357796
78367797 // Can be queried by client applications to check whether certain API features are supported or not.
78377798 ZEND_FUNCTION(mapi_feature)
78487809 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &szFeature, &cbFeature) == FAILURE) return;
78497810
78507811 for (unsigned int i = 0; i < arraySize(features); ++i)
7851 if(stricmp(features[i], szFeature) == 0) {
7812 if(strcasecmp(features[i], szFeature) == 0) {
78527813 RETVAL_TRUE;
78537814 break;
78547815 }
296296 ZEND_FUNCTION(mapi_inetmapi_imtoinet);
297297 ZEND_FUNCTION(mapi_inetmapi_imtomapi);
298298
299 #if SUPPORT_EXCEPTIONS
300299 ZEND_FUNCTION(mapi_enable_exceptions);
301 #endif
302300
303301 ZEND_FUNCTION(mapi_feature);
304302
6969 PHPTag = (LONG)ulPropTag;
7070 return PHPTag;
7171 }
72
7372
7473 /*
7574 * Converts a PHP Array into a SBinaryArray. This is the same as an ENTRYLIST which
287286 exit:
288287 return MAPI_G(hr);
289288 }
290
291289
292290 /*
293291 * Converts an PHP property value array to a MAPI property value structure
467465 lpPropValue[cvalues].Value.mapimvmember.mapilpmember[j] = dataEntry->value.phpmember; \
468466 zend_hash_move_forward(dataHash); \
469467 }
470
471468
472469 case PT_MV_I2:
473470 COPY_MV_PROPS(long, MVi, lpi, lval);
15481545 add_assoc_zval(ret, "1", &array);
15491546 break;
15501547
1551
15521548 case RES_CONTENT:
15531549 MAPI_G(hr) = PropValueArraytoPHPArray(1, lpRes->res.resContent.lpProp, &props TSRMLS_CC);
15541550 if (MAPI_G(hr) != hrSuccess)
17161712 char pulproptag[16];
17171713
17181714 pPropValue = &pPropValueArray[col];
1719
17201715
17211716 /*
17221717 * PHP wants a string as array key. PHP will transform this to zval integer when possible.
19861981 return MAPI_G(hr);
19871982 }
19881983
1989
19901984 /*
19911985 * Convert from READSTATE array to PHP. Returns a list of arrays, each containing "sourcekey" and "flags" per entry
19921986 */
20932087 int n = 0;
20942088 int i = 0;
20952089 zval *pentry = NULL;
2096
20972090
20982091 MAPI_G(hr) = hrSuccess;
20992092
1010 mkdir -p $$sub; \
1111 msgfmt -f -v -o $$sub/kopano.mo ${top_srcdir}/po/$$po; \
1212 done
13
14 uninstall-local:
15 for po in ${EXTRA_DIST}; do \
16 rm -f "${DESTDIR}${datadir}/$${po%.po}/LC_MESSAGES/kopano.mo"; \
17 done
0 SUBDIRS = include soap common libserver server client plugins contacts
0 # -*- Makefile -*-
1
2 SUBDIRS = include
3
4 AM_CPPFLAGS = ${ZCPPFLAGS} ${DEBUGFLAGS} \
5 -DLDAP_THREAD_SAFE -DWITH_MULTISERVER -DPKGLIBDIR='"${pkglibdir}"' \
6 -Isoap \
7 -I${top_srcdir}/common \
8 -I${top_srcdir}/libfreebusy \
9 -I${top_srcdir}/libsync \
10 -I${top_srcdir}/m4lcommon \
11 -I${top_srcdir}/mapi4linux/include \
12 -I${top_srcdir}/provider/client \
13 -I${top_srcdir}/provider/common \
14 -I${top_srcdir}/provider/include \
15 -I${top_srcdir}/provider/libserver \
16 -I${top_srcdir}/provider/plugins \
17 ${BOOST_CPPFLAGS} ${GSOAP_CFLAGS} ${KRB5_CFLAGS} ${LDAP_FLAGS} \
18 ${MYSQL_INCLUDES} ${SSL_CFLAGS} ${s3_CFLAGS} ${TCMALLOC_CFLAGS}
19 AM_CXXFLAGS = ${ZCXXFLAGS} -Wno-sign-compare
20
21 sbin_PROGRAMS = kopano-server
22 noinst_LTLIBRARIES = libkccommon.la
23 lib_LTLIBRARIES = libkcsoapclient.la libkcsoapserver.la libkcserver.la
24 pkglib_LTLIBRARIES = libkcclient.la libkccontacts.la
25 pkginclude_HEADERS = \
26 common/include/kopano/pcuser.hpp \
27 libserver/include/kopano/ECPluginSharedData.h
28 noinst_DATA = kopano-server.ldx libkcclient.ldd libkccontacts.ldd
29 CLEANFILES = ${noinst_DATA}
30 #noinst_DATA += libkccommon.ldd libkcserver.ldd \
31 # libkcsoapclient.ldd libkcsoapserver.ldd
32 sysconf_configdir = ${MAPICONFIGDIR}
33 dist_sysconf_config_DATA = client/kopano.inf contacts/zcontacts.inf
34
35 sampleconfdir = ${docdir}/example-config
36 sampleconf_DATA = client/kopano.inf contacts/zcontacts.inf
37
38 # -E (-rdynamic) still needed because libkcserver.so references
39 # "searchfolder_restart_required", "_Z23kopano_get_server_statsPjPdS_S_"
40 # and "_Z18kopano_notify_doneP4soap"
41 #
42 kopano_server_LDFLAGS = ${AM_LDFLAGS} -Wl,-E ${BOOST_FILESYSTEM_LDFLAGS}
43 kopano_server_LDADD = \
44 libkcserver.la ${GSOAP_LIBS} libkcsoapserver.la libkccommon.la \
45 ${top_builddir}/common/libkcutil.la \
46 ${top_builddir}/common/libkcmapi.la \
47 ${top_builddir}/common/libkcssl.la \
48 ${PROG_LIBS} ${BOOST_FILESYSTEM_LIBS} ${BOOST_SYSTEM_LIBS} \
49 ${icu_uc_LIBS} ${icu_i18n_LIBS} ${DL_LIBS} \
50 ${MYSQL_LIBS} ${SSL_LIBS} ${PAM_LIBS} ${KRB5_LIBS} -lrt
51 kopano_server_SOURCES = \
52 server/ECServer.cpp \
53 server/ECSoapServerConnection.cpp server/ECSoapServerConnection.h \
54 server/ECClientUpdate.cpp server/ECClientUpdate.h \
55 server/ECThreadManager.cpp server/ECThreadManager.h
56
57 libkcclient_la_SOURCES = \
58 client/ClientUtil.cpp client/ClientUtil.h \
59 client/DLLGlobal.h \
60 client/ECABContainer.cpp client/ECABContainer.h \
61 client/ECABLogon.cpp client/ECABLogon.h \
62 client/ECABProp.cpp client/ECABProp.h \
63 client/ECABProvider.cpp client/ECABProvider.h \
64 client/ECABProviderOffline.cpp client/ECABProviderOffline.h \
65 client/ECABProviderSwitch.cpp client/ECABProviderSwitch.h \
66 client/ECArchiveAwareAttach.cpp client/ECArchiveAwareAttach.h \
67 client/ECArchiveAwareMessage.cpp client/ECArchiveAwareMessage.h \
68 client/ECArchiveAwareMsgStore.cpp client/ECArchiveAwareMsgStore.h \
69 client/ECAttach.cpp client/ECAttach.h \
70 client/ECChangeAdvisor.cpp client/ECChangeAdvisor.h \
71 client/ECDisplayTable.cpp client/ECDisplayTable.h \
72 client/ECDistList.cpp client/ECDistList.h \
73 client/ECExchangeExportChanges.cpp client/ECExchangeExportChanges.h \
74 client/ECExchangeImportContentsChanges.cpp \
75 client/ECExchangeImportContentsChanges.h \
76 client/ECExchangeImportHierarchyChanges.cpp \
77 client/ECExchangeImportHierarchyChanges.h \
78 client/ECExchangeModifyTable.cpp client/ECExchangeModifyTable.h \
79 client/ECExportAddressbookChanges.cpp \
80 client/ECExportAddressbookChanges.h \
81 client/ECGenericProp.cpp client/ECGenericProp.h \
82 client/ECICS.h \
83 client/ECMAPIContainer.cpp client/ECMAPIContainer.h \
84 client/ECMAPIFolder.cpp client/ECMAPIFolder.h \
85 client/ECMAPIFolderPublic.cpp client/ECMAPIFolderPublic.h \
86 client/ECMAPIProp.cpp client/ECMAPIProp.h \
87 client/ECMAPITable.cpp client/ECMAPITable.h \
88 client/ECMSProvider.cpp client/ECMSProvider.h \
89 client/ECMSProviderOffline.cpp client/ECMSProviderOffline.h \
90 client/ECMSProviderSwitch.cpp client/ECMSProviderSwitch.h \
91 client/ECMailUser.cpp client/ECMailUser.h \
92 client/ECMemTablePublic.cpp client/ECMemTablePublic.h \
93 client/ECMessage.cpp client/ECMessage.h \
94 client/ECMessageStreamImporterIStreamAdapter.cpp \
95 client/ECMessageStreamImporterIStreamAdapter.h \
96 client/ECMsgStore.cpp client/ECMsgStore.h \
97 client/ECMsgStorePublic.cpp client/ECMsgStorePublic.h \
98 client/ECNamedProp.cpp client/ECNamedProp.h \
99 client/ECNotifyClient.cpp client/ECNotifyClient.h \
100 client/ECNotifyMaster.cpp client/ECNotifyMaster.h \
101 client/ECParentStorage.cpp client/ECParentStorage.h \
102 client/ECPropertyEntry.cpp client/ECPropertyEntry.h \
103 client/ECSessionGroupManager.cpp client/ECSessionGroupManager.h \
104 client/ECXPLogon.cpp client/ECXPLogon.h \
105 client/ECXPProvider.cpp client/ECXPProvider.h \
106 client/EntryPoint.h \
107 client/IECPropStorage.h \
108 client/Mem.cpp client/Mem.h \
109 client/ProviderUtil.cpp client/ProviderUtil.h \
110 client/SessionGroupData.cpp client/SessionGroupData.h \
111 client/WSABPropStorage.cpp client/WSABPropStorage.h \
112 client/WSABTableView.cpp client/WSABTableView.h \
113 client/WSMAPIFolderOps.cpp client/WSMAPIFolderOps.h \
114 client/WSMAPIPropStorage.cpp client/WSMAPIPropStorage.h \
115 client/WSMessageStreamExporter.cpp client/WSMessageStreamExporter.h \
116 client/WSMessageStreamImporter.cpp client/WSMessageStreamImporter.h \
117 client/WSSerializedMessage.cpp client/WSSerializedMessage.h \
118 client/WSStoreTableView.cpp client/WSStoreTableView.h \
119 client/WSTableView.cpp client/WSTableView.h \
120 client/WSTransport.cpp client/WSTransport.h \
121 client/WSUtil.cpp client/WSUtil.h \
122 client/epclient.cpp \
123 client/resource.h
124 libkcclient_la_LDFLAGS = ${AM_LDFLAGS} -avoid-version -module
125 libkcclient_la_LIBADD = \
126 ${top_builddir}/common/libkcmapi.la \
127 ${top_builddir}/common/libkcssl.la \
128 ${top_builddir}/common/libkcutil.la \
129 ${top_builddir}/libfreebusy/libkcfreebusy.la \
130 ${top_builddir}/libsync/libkcsync.la \
131 ${top_builddir}/mapi4linux/src/libmapi.la \
132 libkccommon.la libkcsoapclient.la -lstdc++ \
133 ${GSOAP_LIBS} ${ICU_LIBS} ${SSL_LIBS} ${UUID_LIBS}
134
135 libkccommon_la_SOURCES = \
136 common/ECLicenseClient.h common/ECLicenseClient.cpp \
137 common/ECSearchClient.h common/ECSearchClient.cpp \
138 common/SOAPAlloc.h common/SOAPDebug.cpp common/SOAPDebug.h \
139 common/SOAPHelpers.cpp common/SOAPHelpers.h \
140 common/SOAPSock.cpp common/SOAPSock.h \
141 common/SOAPUtils.cpp common/SOAPUtils.h \
142 common/pcuser.cpp common/pcutil.cpp common/pcutil.hpp \
143 common/soapctor.cpp common/versions.h
144 libkccommon_la_LIBADD = \
145 ../common/libkcutil.la ../common/libkcmapi.la libkcsoapclient.la \
146 ../common/libkcssl.la ${GSOAP_LIBS} ${SSL_LIBS}
147 libkccommon_la_LDFLAGS = ${AM_LDFLAGS} \
148 -Wl,--version-script=${top_builddir}/default.sym
149 EXTRA_libkccommon_la_DEPENDENCIES = ${top_builddir}/default.sym
150
151 libkccontacts_la_SOURCES = \
152 contacts/epcontact.cpp contacts/ZCABData.h \
153 contacts/ZCABContainer.h contacts/ZCABContainer.cpp \
154 contacts/ZCABLogon.h contacts/ZCABLogon.cpp \
155 contacts/ZCABProvider.h contacts/ZCABProvider.cpp \
156 contacts/ZCMAPIProp.h contacts/ZCMAPIProp.cpp
157 libkccontacts_la_LDFLAGS = ${AM_LDFLAGS} -avoid-version -module
158 libkccontacts_la_LIBADD = \
159 ${top_builddir}/common/libkcutil.la \
160 ${top_builddir}/common/libkcmapi.la \
161 ${top_builddir}/mapi4linux/src/libmapi.la \
162 -lstdc++ $(UUID_LIBS) $(ICU_LIBS)
163
164 libkcserver_la_SOURCES = \
165 libserver/ECABObjectTable.cpp libserver/ECABObjectTable.h \
166 libserver/ECAttachmentStorage.cpp libserver/ECAttachmentStorage.h \
167 libserver/ECCacheManager.cpp libserver/ECCacheManager.h \
168 libserver/ECConvenientDepthABObjectTable.cpp \
169 libserver/ECConvenientDepthABObjectTable.h \
170 libserver/ECConvenientDepthObjectTable.cpp \
171 libserver/ECConvenientDepthObjectTable.h \
172 libserver/ECConversion.cpp libserver/ECConversion.h \
173 libserver/ECDBDef.h \
174 libserver/ECDatabase.h \
175 libserver/ECDatabaseFactory.cpp libserver/ECDatabaseFactory.h \
176 libserver/ECDatabaseMySQL.cpp libserver/ECDatabaseMySQL.h \
177 libserver/ECDatabaseUpdate.cpp libserver/ECDatabaseUpdate.h \
178 libserver/ECDatabaseUtils.cpp libserver/ECDatabaseUtils.h \
179 libserver/ECGenProps.cpp libserver/ECGenProps.h \
180 libserver/ECGenericObjectTable.cpp \
181 libserver/ECGenericObjectTable.h \
182 libserver/ECICS.cpp libserver/ECICS.h \
183 libserver/ECICSHelpers.cpp libserver/ECICSHelpers.h \
184 libserver/ECIndexer.cpp libserver/ECIndexer.h \
185 libserver/ECKrbAuth.cpp libserver/ECKrbAuth.h \
186 libserver/ECLockManager.cpp libserver/ECLockManager.h \
187 libserver/ECMAPI.h \
188 libserver/ECMailBoxTable.cpp libserver/ECMailBoxTable.h \
189 libserver/ECMultiStoreTable.cpp libserver/ECMultiStoreTable.h \
190 libserver/ECNotification.cpp libserver/ECNotification.h \
191 libserver/ECNotificationManager.cpp libserver/ECNotificationManager.h \
192 libserver/ECPamAuth.cpp libserver/ECPamAuth.h \
193 libserver/ECPluginFactory.cpp libserver/ECPluginFactory.h \
194 libserver/ECPluginSharedData.cpp \
195 libserver/ECS3Attachment.cpp libserver/ECS3Attachment.h \
196 libserver/ECSearchFolders.cpp libserver/ECSearchFolders.h \
197 libserver/ECSearchObjectTable.cpp libserver/ECSearchObjectTable.h \
198 libserver/ECSecurity.cpp libserver/ECSecurity.h \
199 libserver/ECSecurityOffline.cpp libserver/ECSecurityOffline.h \
200 libserver/ECServerEntrypoint.cpp libserver/ECServerEntrypoint.h \
201 libserver/ECSession.cpp libserver/ECSession.h \
202 libserver/ECSessionGroup.cpp libserver/ECSessionGroup.h \
203 libserver/ECSessionManager.cpp libserver/ECSessionManager.h \
204 libserver/ECSessionManagerOffline.cpp \
205 libserver/ECSessionManagerOffline.h \
206 libserver/ECStatsCollector.cpp libserver/ECStatsCollector.h \
207 libserver/ECStatsTables.cpp libserver/ECStatsTables.h \
208 libserver/ECStoreObjectTable.cpp libserver/ECStoreObjectTable.h \
209 libserver/ECStringCompat.cpp libserver/ECStringCompat.h \
210 libserver/ECSubRestriction.cpp libserver/ECSubRestriction.h \
211 libserver/ECTPropsPurge.cpp libserver/ECTPropsPurge.h \
212 libserver/ECTableManager.cpp libserver/ECTableManager.h \
213 libserver/ECTestProtocol.cpp libserver/ECTestProtocol.h \
214 libserver/ECUserManagement.cpp libserver/ECUserManagement.h \
215 libserver/ECUserManagementOffline.cpp \
216 libserver/ECUserManagementOffline.h \
217 libserver/ECUserStoreTable.cpp libserver/ECUserStoreTable.h \
218 libserver/StorageUtil.cpp libserver/StorageUtil.h \
219 libserver/StreamUtil.cpp libserver/StreamUtil.h \
220 libserver/cmd.cpp libserver/cmd.hpp \
221 libserver/cmdutil.cpp libserver/cmdutil.hpp \
222 libserver/logontime.cpp libserver/logontime.hpp
223 libkcserver_la_LIBADD = \
224 ../common/libkcutil.la libkccommon.la \
225 -lpthread ${icu_i18n_LIBS} ${icu_uc_LIBS} \
226 ${KRB5_LIBS} ${MYSQL_LIBS} ${PAM_LIBS} ${SSL_LIBS}
227 libkcserver_la_LDFLAGS = ${AM_LDFLAGS} \
228 -Wl,--version-script=${top_builddir}/default.sym
229 EXTRA_libkcserver_la_DEPENDENCIES = ${top_builddir}/default.sym
230
231 nodist_libkcsoapclient_la_SOURCES = soap/soapC.cpp soap/soapClient.cpp
232 libkcsoapclient_la_LIBADD = ${GSOAP_LIBS}
233 libkcsoapclient_la_LDFLAGS = ${AM_LDFLAGS} \
234 -Wl,--version-script=${top_builddir}/default.sym
235 EXTRA_libkcsoapclient_la_DEPENDENCIES = ${top_builddir}/default.sym
236
237 nodist_libkcsoapserver_la_SOURCES = soap/soapC.cpp soap/soapServer.cpp
238 libkcsoapserver_la_LIBADD = ${GSOAP_LIBS}
239 libkcsoapserver_la_LDFLAGS = ${AM_LDFLAGS} \
240 -Wl,--version-script=${top_builddir}/default.sym
241 EXTRA_libkcsoapserver_la_DEPENDENCIES = ${top_builddir}/default.sym
242
243 SOAPHEADER = include/proto.h
244 SOAP_NS = soap/KCmd.nsmap soap/KCmd.wsdl
245 SOAP_H_FILES = soap/soapH.h soap/soapStub.h
246 SOAP_CPP_CLIENT = soap/soapClient.cpp soap/soapC.cpp
247 SOAP_LIB_FILES = soap/soapClientLib.cpp soap/soapServerLib.cpp \
248 soap/soapKCmdObject.h
249 SOAP_CPP_SRC = ${SOAP_CPP_CLIENT} soap/soapServer.cpp ${SOAP_H_FILES} \
250 ${SOAP_NS} ${SOAP_LIB_FILES}
251
252 ${SOAP_CPP_SRC}: soap/ns.xsd
253 soap/ns.xsd: ${SOAPHEADER}
254 ${MKDIR_P} soap
255 soapcpp2 -z1 -x -Iinclude/ -d soap/ $<
256
257 BUILT_SOURCES = soap/ns.xsd ${SOAP_CPP_SRC}
258 CLEANFILES += ${SOAP_CPP_SRC} soap/*.req.xml soap/*.res.xml soap/*.wsdl \
259 soap/*.nsmap soap/*.xsd soap/*Proxy\.h soap/*~
260
261 COMMON_PLUGIN_FILES = plugins/plugin.h
262 COMMON_DBPLUGIN_FILES = plugins/DBBase.h plugins/DBBase.cpp
263
264 # default plugin
265 pkglib_LTLIBRARIES += dbplugin.la
266 #noinst_DATA += dbplugin.ldd
267 dbplugin_la_SOURCES = \
268 plugins/DBUserPlugin.cpp plugins/DBUserPlugin.h \
269 ${COMMON_PLUGIN_FILES} ${COMMON_DBPLUGIN_FILES}
270 dbplugin_la_LDFLAGS = -module -avoid-version
271 dbplugin_la_LIBADD = \
272 ${top_builddir}/common/libkcutil.la \
273 libkcserver.la ${MYSQL_LIBS}
274
275 if WITH_UNIX
276 pkglib_LTLIBRARIES += unixplugin.la
277 #noinst_DATA += unixplugin.ldd
278 unixplugin_la_SOURCES = \
279 plugins/UnixUserPlugin.cpp plugins/UnixUserPlugin.h \
280 ${COMMON_PLUGIN_FILES} ${COMMON_DBPLUGIN_FILES}
281 unixplugin_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version
282 unixplugin_la_LIBADD = \
283 ${top_builddir}/common/libkcutil.la \
284 libkcserver.la ${MYSQL_LIBS} ${CRYPT_LIBS}
285 endif
286
287 if WITH_LDAP
288 pkglib_LTLIBRARIES += ldapplugin.la
289 #noinst_DATA += ldapplugin.ldd
290 noinst_DATA += .libs/ldapmsplugin.so
291 ldapplugin_la_SOURCES = \
292 plugins/LDAPUserPlugin.cpp plugins/LDAPUserPlugin.h \
293 plugins/LDAPCache.cpp plugins/LDAPCache.h \
294 plugins/ldappasswords.cpp plugins/ldappasswords.h \
295 ${COMMON_PLUGIN_FILES}
296 ldapplugin_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version
297 ldapplugin_la_LIBADD = \
298 ${top_builddir}/common/libkcutil.la \
299 libkcserver.la ${CRYPTO_LIBS} ${LDAP_LIBS}
300
301 .libs/ldapmsplugin.so: ldapplugin.la
302 ${AM_V_GEN}ln -fs ldapplugin.so .libs/ldapmsplugin.so
303
304 install-exec-local:
305 ${MKDIR_P} ${DESTDIR}${pkglibdir}
306 ln -fs ldapplugin.so ${DESTDIR}${pkglibdir}/ldapmsplugin.so
307 endif
308
309 check-syntax:
310 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
311 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
312
313 include ../global.am
4242 #include <boost/algorithm/string/case_conv.hpp>
4343
4444 using namespace std;
45
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
4945
5046 HRESULT ClientUtil::HrInitializeStatusRow (const char * lpszProviderDisplay, ULONG ulResourceType, LPMAPISUP lpMAPISup, LPSPropValue lpspvIdentity, ULONG ulFlags)
5147 {
287283 PR_INTERNET_MESSAGE_ID, PR_DELIVER_TIME, PR_SENT_REPRESENTING_ADDRTYPE, PR_SENT_REPRESENTING_EMAIL_ADDRESS,
288284 PR_MDN_DISPOSITION_TYPE, PR_MDN_DISPOSITION_SENDINGMODE } };
289285
290
291286 // Check incoming parameters
292287 if(lpReadMessage == NULL || lppEmptyMessage == NULL || *lppEmptyMessage == NULL) {
293288 hr = MAPI_E_INVALID_OBJECT;
322317 goto exit;
323318 }
324319
325
326320 strBodyText = _("Your message");
327321 strBodyText+= _T("\r\n\r\n");
328322
365359 strBodyText+= _T("\r\n");
366360 }
367361
368
369362 strBodyText+= _T("\r\n");
370363 strBodyText+= lpReportText;
371364 strBodyText+= _T(" ");
379372
380373 strBodyText+= convert_to<tstring>(szTime, strlen(szTime), CHARSET_CHAR);
381374 strBodyText+= _T("\r\n");
382
383375
384376 ulMaxDestValues = cSrcValues + 4;//+ default properties
385377 hr = MAPIAllocateBuffer(sizeof(SPropValue)*ulMaxDestValues, (void**)&lpDestPropValue);
705697 goto exit;
706698 }
707699
708
709700 if((lpProp = PpropFindProp(lpsPropArray, cValues, PR_EC_PATH)) != NULL)
710701 lpsProfileProps->strServerPath = lpProp->Value.lpszA;
711702
826817 * Read registry key to discover the installation directory for the exchange redirector
827818 *
828819 * @param[out] lpConfigPath String containing full config path
829 * @return HRESULT Result
830820 */
831821 HRESULT ClientUtil::GetConfigPath(std::string *lpConfigPath)
832822 {
843833 * @param pValues[in] Incoming exchange properties (must contain PR_PROFILE_UNRESOLVED_{USER,SERVER})
844834 * @param lpcValues[out] Number of properties in lppProps
845835 * @param lppProps[out] New ZARAFA properties
846 * @return HRESULT Success result
847836 */
848837 HRESULT ClientUtil::ConvertMSEMSProps(ULONG cValues, LPSPropValue pValues, ULONG *lpcValues, LPSPropValue *lppProps)
849838 {
10531042
10541043 if (ulSize >= ulMaxSize)
10551044 return MAPI_E_NOT_FOUND;
1056 if (strnicmp(lpTmpServerName, "pseudo://", 9) == 0)
1045 if (strncasecmp(lpTmpServerName, "pseudo://", 9) == 0)
10571046 bIsPseudoUrl = true;
1058 else if (strnicmp(lpTmpServerName, "http://", 7) &&
1059 strnicmp(lpTmpServerName, "https://", 8) &&
1060 strnicmp(lpTmpServerName, "file://", 7))
1047 else if (strncasecmp(lpTmpServerName, "http://", 7) &&
1048 strncasecmp(lpTmpServerName, "https://", 8) &&
1049 strncasecmp(lpTmpServerName, "file://", 7))
10611050 return MAPI_E_NOT_FOUND;
10621051
10631052 rServerPath = lpTmpServerName;
11441133 return MAPI_E_INVALID_PARAMETER;
11451134 }
11461135
1147
11481136 if (lpcbEntryID == NULL || lppEntryID == NULL)
11491137 return MAPI_E_INVALID_PARAMETER;
11501138
2323 #include <kopano/ECGuid.h>
2424 #include <kopano/ECDebug.h>
2525
26
27 #include "ECMAPITable.h"
28
2926 #include "ECDisplayTable.h"
3027
3128 #include <kopano/CommonUtil.h>
3936
4037 #include <kopano/charset/convstring.h>
4138 #include <kopano/ECGetText.h>
42
43 #ifdef _DEBUG
44 #define new DEBUG_NEW
45 #endif
4639
4740 ECABContainer::ECABContainer(void *lpProvider, ULONG ulObjType, BOOL fModify,
4841 const char *szClassName) :
3232 #include <kopano/stringutil.h>
3333 #include "pcutil.hpp"
3434
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
38
3935 ECABLogon::ECABLogon(LPMAPISUP lpMAPISup, WSTransport* lpTransport, ULONG ulProfileFlags, GUID *lpGUID) : ECUnknown("IABLogon")
4036 {
4137 // The 'legacy' guid used normally (all AB entryIDs have this GUID)
414410 if(lpPropVal == NULL)
415411 lpPropVal = &lpPropArray[j];
416412
417
418413 hr = Util::HrCopyProperty(lpNewPropArray + j, lpPropVal, lpNewPropArray);
419414 if(hr != hrSuccess)
420415 goto exit;
462457 return hr;
463458 }
464459
465
466460 HRESULT ECABLogon::xABLogon::QueryInterface(REFIID refiid, void ** lppInterface)
467461 {
468462 TRACE_MAPI(TRACE_ENTRY, "IABLogon::QueryInterface", "%s", DBGGUIDToString(refiid).c_str());
2323 #include <kopano/ECDefs.h>
2424 #include <kopano/CommonUtil.h>
2525 #include <kopano/ECDebug.h>
26
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
3126
3227 ECABProp::ECABProp(void *lpProvider, ULONG ulObjType, BOOL fModify,
3328 const char *szClassName) :
2525
2626 #include <kopano/ECDebug.h>
2727
28
2928 #include <kopano/Util.h>
3029
3130 #include "WSTransport.h"
3938 #include <kopano/ECGetText.h>
4039
4140 using namespace std;
42
43 #ifdef _DEBUG
44 #define new DEBUG_NEW
45 #endif
4641
4742 ECABProvider::ECABProvider(ULONG ulFlags, const char *szClassName) :
4843 ECUnknown(szClassName)
125120 if(hr != hrSuccess)
126121 goto exit;
127122
128
129123 if (lpulcbSecurity)
130124 *lpulcbSecurity = 0;
131125
153147
154148 return hr;
155149 }
156
157150
158151 HRESULT __stdcall ECABProvider::xABProvider::QueryInterface(REFIID refiid, void ** lppInterface)
159152 {
2020 #include <mapiutil.h>
2121 #include <mapispi.h>
2222
23
2423 #include <kopano/ECGuid.h>
2524 #include <edkguid.h>
2625
3029 #include <kopano/ECTags.h>
3130
3231 #include "ECABProviderOffline.h"
33
34 #ifdef _DEBUG
35 #define new DEBUG_NEW
36 #endif
37
3832
3933 ECABProviderOffline::ECABProviderOffline(void) : ECABProvider(EC_PROVIDER_OFFLINE, "ECABProviderOffline")
4034 {
3737 #include "ProviderUtil.h"
3838
3939 #include <kopano/charset/convstring.h>
40
41 #ifdef _DEBUG
42 #define new DEBUG_NEW
43 #endif
4440
4541 ECABProviderSwitch::ECABProviderSwitch(void) : ECUnknown("ECABProviderSwitch")
4642 {
1818 #include "ECArchiveAwareAttach.h"
1919 #include "ECArchiveAwareMessage.h"
2020
21
2221 HRESULT ECArchiveAwareAttachFactory::Create(ECMsgStore *lpMsgStore, ULONG ulObjType, BOOL fModify, ULONG ulAttachNum, ECMAPIProp *lpRoot, ECAttach **lppAttach) const
2322 {
2423 return ECArchiveAwareAttach::Create(lpMsgStore, ulObjType, fModify, ulAttachNum, lpRoot, lppAttach);
2524 }
26
27
2825
2926 ECArchiveAwareAttach::ECArchiveAwareAttach(ECMsgStore *lpMsgStore, ULONG ulObjType, BOOL fModify, ULONG ulAttachNum, ECMAPIProp *lpRoot)
3027 : ECAttach(lpMsgStore, ulObjType, fModify, ulAttachNum, lpRoot)
3232 #include <sstream>
3333 #include <kopano/ECDebug.h>
3434 #include <kopano/charset/convert.h>
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
3835
3936 #define dispidStoreEntryIds "store-entryids"
4037 #define dispidItemEntryIds "item-entryids"
5047 ULONG m_ulPropTag;
5148 };
5249
53
5450 HRESULT ECArchiveAwareMessageFactory::Create(ECMsgStore *lpMsgStore, BOOL fNew, BOOL fModify, ULONG ulFlags, BOOL bEmbedded, ECMAPIProp* lpRoot, ECMessage **lppMessage) const
5551 {
5652 ECArchiveAwareMsgStore *lpArchiveAwareStore = dynamic_cast<ECArchiveAwareMsgStore*>(lpMsgStore);
6258
6359 return ECArchiveAwareMessage::Create(lpArchiveAwareStore, FALSE, fModify, ulFlags, lppMessage);
6460 }
65
6661
6762 ECArchiveAwareMessage::ECArchiveAwareMessage(ECArchiveAwareMsgStore *lpMsgStore, BOOL fNew, BOOL fModify, ULONG ulFlags)
6863 : ECMessage(lpMsgStore, fNew, fModify, ulFlags, FALSE, NULL)
3131 class ECArchiveAwareMessage _kc_final : public ECMessage {
3232 protected:
3333 /**
34 * \brief Constructor
35 *
3634 * \param lpMsgStore The store owning this message.
3735 * \param fNew Specifies whether the message is a new message.
3836 * \param fModify Specifies whether the message is writable.
2626 #include <kopano/ECDebug.h>
2727 #include <kopano/ECInterfaceDefs.h>
2828
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
32
33
3429 HRESULT ECAttachFactory::Create(ECMsgStore *lpMsgStore, ULONG ulObjType, BOOL fModify, ULONG ulAttachNum, ECMAPIProp *lpRoot, ECAttach **lppAttach) const
3530 {
3631 return ECAttach::Create(lpMsgStore, ulObjType, fModify, ulAttachNum, lpRoot, lppAttach);
3732 }
38
39
4033
4134 ECAttach::ECAttach(ECMsgStore *lpMsgStore, ULONG ulObjType, BOOL fModify, ULONG ulAttachNum, ECMAPIProp *lpRoot) : ECMAPIProp(lpMsgStore, ulObjType, fModify, lpRoot, "IAttach")
4235 {
2323
2424 #include "ECChangeAdvisor.h"
2525 #include "ECMsgStore.h"
26
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
3126
3227 ULONG ECChangeAdvisor::GetSyncId(const ConnectionMap::value_type &sConnection)
3328 {
157152
158153 return hr;
159154 }
160
161
162155
163156 HRESULT ECChangeAdvisor::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR *lppMAPIError)
164157 {
340333 lpStream->Write(&m_mapSyncStates[iterConnection->first], sizeof(SyncStateMap::key_type), NULL);
341334 }
342335
343
344336 exit:
345337 pthread_mutex_unlock(&m_hConnectionLock);
346338 return hr;
351343 HRESULT hr = hrSuccess;
352344 SSyncState *lpsSyncState = NULL;
353345 ECLISTCONNECTION listConnections;
354 ECLISTCONNECTION::const_iterator iterConnection;
355346 ECLISTSYNCSTATE listSyncStates;
356347
357348 if (m_lpChangeAdviseSink == NULL && !(m_ulFlags & SYNC_CATCHUP))
6363 * change notifications.
6464 * @param[out] lppChangeAdvisor
6565 * The new change advisor.
66 * @return HRESULT
6766 */
6867 static HRESULT Create(ECMsgStore *lpMsgStore, ECChangeAdvisor **lppChangeAdvisor);
6968
131130 * The parameter passed to AddSessionReloadCallback.
132131 * @param[in] newSessionId
133132 * The sessionid of the new session.
134 *
135 * @return HRESULT.
136133 */
137134 static HRESULT Reload(void *lpParam, ECSESSIONID newSessionId);
138135
139136 /**
140137 * Purge all unused connections from advisor.
141 * @return HRESULT
142138 */
143139 HRESULT PurgeStates();
144140
2323
2424 #include "Mem.h"
2525 #include <kopano/ECMemTable.h>
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #endif
2926
3027 // This function is NOT used, but is used as dummy for the xgettext parser so it
3128 // can find the translation strings. **DO NOT REMOVE THIS FUNCTION**
2525 #include <kopano/CommonUtil.h>
2626 #include <kopano/ECDebug.h>
2727
28
2928 #include "ECMAPITable.h"
3029
3130 #include "ECDisplayTable.h"
32
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #endif
3631
3732 ECDistList::ECDistList(void* lpProvider, BOOL fModify) : ECABContainer(lpProvider, MAPI_DISTLIST, fModify, "IDistList")
3833 {
4040 #include "ECSyncSettings.h"
4141 #include "EntryPoint.h"
4242 #include <kopano/CommonUtil.h>
43
44 #ifdef LINUX
4543 // We use ntohl/htonl for network-order conversion
4644 #include <arpa/inet.h>
47 #endif
48
4945 #include <kopano/charset/convert.h>
50
51 #ifdef _DEBUG
52 #define new DEBUG_NEW
53 #endif
5446
5547 ECExchangeExportChanges::ECExchangeExportChanges(ECMsgStore *lpStore, const std::string &sk, const wchar_t * szDisplay, unsigned int ulSyncType)
5648 : m_iidMessage(IID_IMessage)
492484 }
493485
494486 if (*lpulProgress == 0 && m_lpLogger->Log(EC_LOGLEVEL_DEBUG))
495 m_clkStart = z_times(&m_tmsStart);
487 m_clkStart = times(&m_tmsStart);
496488
497489 if(m_ulSyncType == ICS_SYNC_CONTENTS){
498490 hr = ExportMessageChanges();
555547
556548 if(m_ulChanges) {
557549 if (m_lpLogger->Log(EC_LOGLEVEL_DEBUG)) {
558 struct z_tms tmsEnd = {0};
559 clock_t clkEnd = z_times(&tmsEnd);
550 struct tms tmsEnd = {0};
551 clock_t clkEnd = times(&tmsEnd);
560552 double dblDuration = 0;
561553 char szDuration[64] = {0};
562554
563555 // Calculate diff
564556 dblDuration = (double)(clkEnd - m_clkStart) / TICKS_PER_SEC;
565557 if (dblDuration >= 60)
566 _snprintf(szDuration, sizeof(szDuration), "%u:%02u.%03u min.", (unsigned)(dblDuration / 60), (unsigned)dblDuration % 60, (unsigned)(dblDuration * 1000 + .5) % 1000);
558 snprintf(szDuration, sizeof(szDuration), "%u:%02u.%03u min.", (unsigned)(dblDuration / 60), (unsigned)dblDuration % 60, (unsigned)(dblDuration * 1000 + .5) % 1000);
567559 else
568 _snprintf(szDuration, sizeof(szDuration), "%u.%03u s.", (unsigned)dblDuration % 60, (unsigned)(dblDuration * 1000 + .5) % 1000);
560 snprintf(szDuration, sizeof(szDuration), "%u.%03u s.", (unsigned)dblDuration % 60, (unsigned)(dblDuration * 1000 + .5) % 1000);
569561
570562 m_lpLogger->Log(EC_LOGLEVEL_DEBUG, "folder changes synchronized in %s", szDuration);
571563 } else
804796 return pThis->SetLogger(lpLogger);
805797 }
806798
807
808799 HRESULT ECExchangeExportChanges::ExportMessageChanges() {
809800 ASSERT(m_lpImportContents != NULL);
810801 if (m_lpImportStreamedContents != NULL)
11011092 ZLOG_DEBUG(m_lpLogger, "SaveChanges failed for destination message");
11021093 goto exit;
11031094 }
1104
11051095
11061096 next:
11071097 // Mark this change as processed, even if we skipped it due to SYNC_E_IGNORE or because the item was deleted on the source server
126126
127127 ECLogger *m_lpLogger;
128128 clock_t m_clkStart;
129 struct z_tms m_tmsStart;
129 struct tms m_tmsStart;
130130
131131 HRESULT AddProcessedChanges(ChangeList &lstChanges);
132132
4242 #include "EntryPoint.h"
4343
4444 #include <list>
45
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
49
50 #ifdef _DEBUG
51 class NullStream _kc_final : public IStream
52 {
53 public:
54 NullStream() : m_cRef(1) {}
55
56 // IUnknown
57 ULONG __stdcall AddRef() { return ++m_cRef; }
58 ULONG __stdcall Release() {
59 ULONG cRef = --m_cRef;
60 if (!m_cRef)
61 delete this;
62 return cRef;
63 }
64 HRESULT __stdcall QueryInterface(REFIID refiid, void **lpvoid) {
65 if (refiid == IID_IUnknown || refiid == IID_IStream) {
66 AddRef();
67 *lpvoid = this;
68 return hrSuccess;
69 }
70 return MAPI_E_INTERFACE_NOT_SUPPORTED;
71 }
72
73 // ISequentialStream
74 HRESULT __stdcall Read(void *pv, ULONG cb, ULONG *pcbRead) {
75 if (pcbRead)
76 *pcbRead = cb;
77 return hrSuccess;
78 }
79 HRESULT __stdcall Write(const void *pv, ULONG cb, ULONG *pcbWritten) {
80 if (pcbWritten)
81 *pcbWritten = cb;
82 return hrSuccess;
83 }
84
85 // IStream
86 HRESULT __stdcall Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) { return MAPI_E_NO_SUPPORT; }
87 HRESULT __stdcall SetSize(ULARGE_INTEGER libNewSize) { return MAPI_E_NO_SUPPORT; }
88 HRESULT __stdcall CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) { return MAPI_E_NO_SUPPORT; }
89 HRESULT __stdcall Commit(DWORD grfCommitFlags) { return MAPI_E_NO_SUPPORT; }
90 HRESULT __stdcall Revert(void) { return MAPI_E_NO_SUPPORT; }
91 HRESULT __stdcall LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return MAPI_E_NO_SUPPORT; }
92 HRESULT __stdcall UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { return MAPI_E_NO_SUPPORT; }
93 HRESULT __stdcall Stat(STATSTG *pstatstg, DWORD grfStatFlag) { return MAPI_E_NO_SUPPORT; }
94 HRESULT __stdcall Clone(IStream **ppstm) { return MAPI_E_NO_SUPPORT; }
95
96 private:
97 ULONG m_cRef;
98 };
99 #endif
10045
10146 ECExchangeImportContentsChanges::ECExchangeImportContentsChanges(ECMAPIFolder *lpFolder)
10247 : m_iidMessage(IID_IMessage)
279224 return hrSuccess;
280225 }
281226
282
283227 HRESULT ECExchangeImportContentsChanges::ImportMessageChange(ULONG cValue, LPSPropValue lpPropArray, ULONG ulFlags, LPMESSAGE * lppMessage){
284228 HRESULT hr = hrSuccess;
285229
566510 return bConflict;
567511 }
568512
569
570513 HRESULT ECExchangeImportContentsChanges::CreateConflictMessage(LPMESSAGE lpMessage)
571514 {
572515 HRESULT hr = hrSuccess;
583526 hr = lpMessage->SaveChanges(KEEP_OPEN_READWRITE);
584527 if(hr != hrSuccess)
585528 goto exit;
586
587529
588530 exit:
589531 MAPIFreeBuffer(lpConflictItems);
704646 MAPIFreeBuffer(lpEntryIdProp);
705647 return hr;
706648 }
707
708649
709650 HRESULT ECExchangeImportContentsChanges::CreateConflictFolders(){
710651 HRESULT hr = hrSuccess;
10591000 m_iidMessage = refiid;
10601001 return hrSuccess;
10611002 }
1062
10631003
10641004 /**
10651005 * Check if the passed entryids can be found in the RES_PROPERTY restrictions with the proptag
3737 #include <kopano/charset/utf8string.h>
3838 #include <kopano/charset/convstring.h>
3939
40 #ifdef _DEBUG
41 #define new DEBUG_NEW
42 #endif
43
4440 ECExchangeImportHierarchyChanges::ECExchangeImportHierarchyChanges(ECMAPIFolder *lpFolder){
4541 m_lpFolder = lpFolder;
4642 m_lpStream = NULL;
209205
210206 return lpStream->Write(&m_ulChangeId, 4, &ulLen);
211207 }
212
213208
214209 HRESULT ECExchangeImportHierarchyChanges::ImportFolderChange(ULONG cValue, LPSPropValue lpPropArray){
215210 HRESULT hr = hrSuccess;
466461 hrTmp = ECExchangeImportContentsChanges::HrUpdateSearchReminders(ptrRoot, lpPropAdditionalREN);
467462 }
468463
469
470464 exit:
471465 MAPIFreeBuffer(lpPropVal);
472466 MAPIFreeBuffer(lpEntryId);
4141
4242 #include <kopano/ECInterfaceDefs.h>
4343
44 #ifdef _DEBUG
45 #define new DEBUG_NEW
46 #endif
47
4844 static LPWSTR WTF1252_to_WCHAR(LPCSTR szWTF1252, LPVOID lpBase, convert_context *lpConverter)
4945 {
5046 HRESULT hr = hrSuccess;
8076
8177 return lpszResult;
8278 }
83
8479
8580 ECExchangeModifyTable::ECExchangeModifyTable(ULONG ulUniqueTag, ECMemTable *table, ECMAPIProp *lpParent, ULONG ulStartUniqueId, ULONG ulFlags) {
8681 m_ecTable = table;
10297 if(m_lpParent)
10398 m_lpParent->Release();
10499 }
105
106100
107101 HRESULT __stdcall ECExchangeModifyTable::CreateACLTable(ECMAPIProp *lpParent, ULONG ulFlags, LPEXCHANGEMODIFYTABLE *lppObj) {
108102 HRESULT hr = hrSuccess;
333327 return hr;
334328 }
335329
336
337330 HRESULT ECExchangeModifyTable::OpenACLS(ECMAPIProp *lpecMapiProp, ULONG ulFlags, ECMemTable *lpTable, ULONG *lpulUniqueID)
338331 {
339332 HRESULT hr = hrSuccess;
550543 hr = ConvertString8ToUnicode(lpRowSet);
551544 if(hr != hrSuccess)
552545 goto exit;
553
554546
555547 // Convert to SOAP rows
556548 hr = CopyMAPIRowSetToSOAPRowSet(lpRowSet, &lpSOAPRowSet);
688680 return MAPI_E_NO_SUPPORT;
689681 }
690682
691
692683 // wrappers for ExchageRuleAction class
693684
694685 DEF_HRMETHOD(TRACE_MAPI, ECExchangeRuleAction, ExchangeRuleAction, QueryInterface, (REFIID, refiid), (void **, lppInterface))
3232 #include <kopano/Util.h>
3333
3434 #include <edkmdb.h>
35
36 #ifdef _DEBUG
37 #define new DEBUG_NEW
38 #endif
3935
4036 ECExportAddressbookChanges::ECExportAddressbookChanges(ECMsgStore *lpStore) {
4137 ECSyncLog::GetLogger(&m_lpLogger);
344340 return hrSuccess;
345341 }
346342
347
348343 /**
349344 * Compares two ICSCHANGE objects and determines which of the two should precede the other.
350345 * This function is supposed to be used as the predicate in std::stable_sort.
398393 return false;
399394 }
400395
401
402396 ULONG ECExportAddressbookChanges::xECExportAddressbookChanges::AddRef()
403397 {
404398 METHOD_PROLOGUE_(ECExportAddressbookChanges, ECExportAddressbookChanges);
3131 #include <kopano/charset/convert.h>
3232 #include "EntryPoint.h"
3333
34 #ifdef _DEBUG
35 #define new DEBUG_NEW
36 #endif
37
3834 ECGenericProp::ECGenericProp(void *lpProvider, ULONG ulObjType, BOOL fModify,
3935 const char *szClassName) :
4036 ECUnknown(szClassName)
458454 }
459455 return hr;
460456 }
461
462457
463458 HRESULT ECGenericProp::GetLastError(HRESULT hResult, ULONG ulFlags, LPMAPIERROR FAR * lppMAPIError)
464459 {
2121 #include <kopano/ECGuid.h>
2222 #include <kopano/ECDebug.h>
2323
24
2524 //#include <edkmdb.h>
2625 #include <kopano/mapiext.h>
2726 #include <mapiutil.h>
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3227
3328 ECMAPIContainer::ECMAPIContainer(ECMsgStore *lpMsgStore, ULONG ulObjType,
3429 BOOL fModify, const char *szClassName) :
9388 if(hr != hrSuccess)
9489 goto exit;
9590
96
9791 hr = this->GetMsgStore()->lpTransport->HrOpenTableOps(MAPI_MESSAGE, (ulFlags&(MAPI_UNICODE|SHOW_SOFT_DELETES|MAPI_ASSOCIATED|EC_TABLE_NOCAP)), m_cbEntryId, m_lpEntryId, this->GetMsgStore(), &lpTableOps);
9892
9993 if(hr != hrSuccess)
117111
118112 return hr;
119113 }
120
121114
122115 HRESULT ECMAPIContainer::GetHierarchyTable(ULONG ulFlags, LPMAPITABLE *lppTable)
123116 {
191184 return this->GetMsgStore()->OpenEntry(cbEntryID, lpEntryID, lpInterface, ulFlags, lpulObjType, lppUnk);
192185 }
193186
194
195187 // From IMAPIContainer
196188 HRESULT ECMAPIContainer::xMAPIContainer::GetContentsTable(ULONG ulFlags, LPMAPITABLE *lppTable)
197189 {
4747 #include <kopano/stringutil.h>
4848
4949 #include <kopano/charset/convstring.h>
50
51 #ifdef _DEBUG
52 #define new DEBUG_NEW
53 #endif
5450
5551 static LONG __stdcall AdviseECFolderCallback(void *lpContext, ULONG cNotif,
5652 LPNOTIFICATION lpNotif)
225221 return hr;
226222 }
227223
228
229224 HRESULT ECMAPIFolder::QueryInterface(REFIID refiid, void **lppInterface)
230225 {
231226 REGISTER_INTERFACE(IID_ECMAPIFolder, this);
447442 if(hr != hrSuccess)
448443 goto exit;
449444
450
451445 // Load an empty property set
452446 hr = lpMessage->HrLoadEmptyProps();
453447 if(hr != hrSuccess)
731725 hr = this->GetMsgStore()->lpSupport->CopyFolder(&IID_IMAPIFolder, &this->m_xMAPIFolder, cbEntryID, lpEntryID, lpInterface, lpDestFolder, lpszNewFolderName, ulUIParam, lpProgress, ulFlags);
732726 }
733727
734
735728 exit:
736729 if(lpMapiFolder)
737730 lpMapiFolder->Release();
10811074 return hr;
10821075 }
10831076
1084
10851077 HRESULT ECMAPIFolder::xMAPIFolder::CreateMessage(LPCIID lpInterface, ULONG ulFlags, LPMESSAGE *lppMessage)
10861078 {
10871079 TRACE_MAPI(TRACE_ENTRY, "IMAPIFolder::CreateMessage", "flags=%d", ulFlags);
4242
4343 #include <kopano/ECGetText.h>
4444
45 #ifdef _DEBUG
46 #define new DEBUG_NEW
47 #endif
48
49
5045 ECMAPIFolderPublic::ECMAPIFolderPublic(ECMsgStore *lpMsgStore, BOOL fModify, WSMAPIFolderOps *lpFolderOps, enumPublicEntryID ePublicEntryID) :
5146 ECMAPIFolder(lpMsgStore, fModify, lpFolderOps, "IMAPIFolderPublic")
5247 {
545540 hr = this->GetMsgStore()->lpSupport->CopyFolder(&IID_IMAPIFolder, &this->m_xMAPIFolder, cbEntryID, lpEntryID, lpInterface, lpDestFolder, lpszNewFolderName, ulUIParam, lpProgress, ulFlags);
546541 }
547542
548
549543 exit:
550544 if(lpMapiFolder)
551545 lpMapiFolder->Release();
4343
4444 #include <sstream>
4545
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
49
5046 static struct rights ECPermToRightsCheap(const ECPERMISSION &p)
5147 {
5248 struct rights r = {0, p.ulType, p.ulRights, p.ulState};
386382
387383 return hr;
388384 }
389
390385
391386 // FIXME openproperty on computed value is illegal
392387 HRESULT ECMAPIProp::OpenProperty(ULONG ulPropTag, LPCIID lpiid, ULONG ulInterfaceOptions, ULONG ulFlags, LPUNKNOWN FAR * lppUnk)
537532 exit:
538533 if(lpsPropValue)
539534 ECFreeBuffer(lpsPropValue);
540
541535
542536 return hr;
543537 }
748742 return hrSuccess;
749743 }
750744
751
752745 HRESULT ECMAPIProp::CopyTo(ULONG ciidExclude, LPCIID rgiidExclude, LPSPropTagArray lpExcludeProps, ULONG ulUIParam, LPMAPIPROGRESS lpProgress, LPCIID lpInterface, LPVOID lpDestObj, ULONG ulFlags, LPSPropProblemArray FAR * lppProblems)
753746 {
754747 return Util::DoCopyTo(&IID_IMAPIProp, &this->m_xMAPIProp, ciidExclude, rgiidExclude, lpExcludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
3131 #include <kopano/ECDebug.h>
3232 #include <kopano/ECInterfaceDefs.h>
3333
34
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
38
3934 ECMAPITable::ECMAPITable(std::string strName, ECNotifyClient *lpNotifyClient, ULONG ulFlags) : ECUnknown("IMAPITable")
4035 {
4136 TRACE_MAPI(TRACE_ENTRY, "ECMAPITable::ECMAPITable","");
238233 return hr;
239234 }
240235
241
242236 HRESULT ECMAPITable::SetColumns(LPSPropTagArray lpPropTagArray, ULONG ulFlags)
243237 {
244238 HRESULT hr = hrSuccess;
314308 return hr;
315309 }
316310
317
318311 HRESULT ECMAPITable::SeekRow(BOOKMARK bkOrigin, LONG lRowCount, LONG *lplRowsSought)
319312 {
320313 HRESULT hr = hrSuccess;
333326 return hr;
334327 }
335328
336
337329 HRESULT ECMAPITable::SeekRowApprox(ULONG ulNumerator, ULONG ulDenominator)
338330 {
339331 HRESULT hr = hrSuccess;
358350
359351 return hr;
360352 }
361
362353
363354 HRESULT ECMAPITable::QueryPosition(ULONG *lpulRow, ULONG *lpulNumerator, ULONG *lpulDenominator)
364355 {
387378 return hr;
388379 }
389380
390
391381 HRESULT ECMAPITable::FindRow(LPSRestriction lpRestriction, BOOKMARK bkOrigin, ULONG ulFlags)
392382 {
393383 HRESULT hr = hrSuccess;
409399
410400 return hr;
411401 }
412
413402
414403 HRESULT ECMAPITable::Restrict(LPSRestriction lpRestriction, ULONG ulFlags)
415404 {
442431 return hr;
443432 }
444433
445
446434 HRESULT ECMAPITable::CreateBookmark(BOOKMARK* lpbkPosition)
447435 {
448436 HRESULT hr = hrSuccess;
460448 return hr;
461449 }
462450
463
464451 HRESULT ECMAPITable::FreeBookmark(BOOKMARK bkPosition)
465452 {
466453 HRESULT hr = hrSuccess;
477464
478465 return hr;
479466 }
480
481467
482468 HRESULT ECMAPITable::SortTable(LPSSortOrderSet lpSortCriteria, ULONG ulFlags)
483469 {
511497 return hr;
512498 }
513499
514
515500 HRESULT ECMAPITable::QuerySortOrder(LPSSortOrderSet *lppSortCriteria)
516501 {
517502 HRESULT hr = hrSuccess;
561546 return hr;
562547 }
563548
564
565549 HRESULT ECMAPITable::ExpandRow(ULONG cbInstanceKey, LPBYTE pbInstanceKey, ULONG ulRowCount, ULONG ulFlags, LPSRowSet * lppRows, ULONG *lpulMoreRows)
566550 {
567551 HRESULT hr = hrSuccess;
577561 pthread_mutex_unlock(&m_hLock);
578562 return hr;
579563 }
580
581564
582565 HRESULT ECMAPITable::CollapseRow(ULONG cbInstanceKey, LPBYTE pbInstanceKey, ULONG ulFlags, ULONG *lpulRowCount)
583566 {
614597 return hr;
615598 }
616599
617
618600 HRESULT ECMAPITable::GetCollapseState(ULONG ulFlags, ULONG cbInstanceKey, LPBYTE lpbInstanceKey, ULONG *lpcbCollapseState, LPBYTE *lppbCollapseState)
619601 {
620602 HRESULT hr = hrSuccess;
631613
632614 return hr;
633615 }
634
635616
636617 HRESULT ECMAPITable::SetCollapseState(ULONG ulFlags, ULONG cbCollapseState, LPBYTE pbCollapseState, BOOKMARK *lpbkLocation)
637618 {
3333
3434 #include <kopano/ECDebug.h>
3535
36
3736 #include "ClientUtil.h"
3837 #include "EntryPoint.h"
3938
5251
5352 #include <kopano/mapi_ptr/mapi_memory_ptr.h>
5453 typedef mapi_memory_ptr<ECUSER> ECUserPtr;
55
56 #ifdef _DEBUG
57 #define new DEBUG_NEW
58 #endif
5954
6055 ECMSProvider::ECMSProvider(ULONG ulFlags, const char *szClassName) :
6156 ECUnknown(szClassName)
256251 sGlobalProfileProps sProfileProps;
257252 wchar_t *strSep = NULL;
258253
259
260254 if(lpEntryID == NULL) {
261255 hr = MAPI_E_UNCONFIGURED;
262256 goto exit;
298292 }
299293 }
300294
301
302295 if (cbSpoolSecurity % sizeof(wchar_t) != 0) {
303296 hr = MAPI_E_INVALID_PARAMETER;
304297 goto exit;
336329 &lpMsgStore);
337330 if(hr != hrSuccess)
338331 goto exit;
339
340332
341333 // Register ourselves with mapisupport
342334 //guidStore = lpMsgStore->GetStoreGuid();
2929 #include <kopano/Trace.h>
3030 #include <kopano/ECDebug.h>
3131
32
3332 #include <edkguid.h>
3433 #include "EntryPoint.h"
3534 #include "DLLGlobal.h"
4039 #include <kopano/stringutil.h>
4140
4241 #include "ProviderUtil.h"
43
44 #ifdef _DEBUG
45 #define new DEBUG_NEW
46 #endif
47
4842
4943 ECMSProviderOffline::ECMSProviderOffline(ULONG ulFlags) :
5044 ECMSProvider(ulFlags|EC_PROVIDER_OFFLINE, "ECMSProviderOffline")
4949 #undef swprintf
5050 #endif
5151
52 #ifdef _DEBUG
53 #define new DEBUG_NEW
54 #endif
55
5652 ECMSProviderSwitch::ECMSProviderSwitch(ULONG ulFlags) : ECUnknown("ECMSProviderSwitch")
5753 {
5854 m_ulFlags = ulFlags;
277273 swprintf((wchar_t*)*lppbSpoolSecurity, cbSpoolSecurity, L"%s%c%s", sProfileProps.strUserName.c_str(), 0, sProfileProps.strPassword.c_str());
278274 *lpcbSpoolSecurity = cbSpoolSecurity;
279275 }
280
281276
282277 exit:
283278 if (lppMAPIError)
340335 if (hr != hrSuccess)
341336 goto exit;
342337
343
344338 if (lppMSLogon) {
345339 hr = lpMSLogon->QueryInterface(IID_IMSLogon, (void **)lppMSLogon);
346340 if (hr != hrSuccess)
353347 goto exit;
354348 }
355349
356
357350 exit:
358351 if (lppMAPIError)
359352 *lppMAPIError = NULL;
2525
2626 #include "ECDisplayTable.h"
2727
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
31
3228 ECMailUser::ECMailUser(void* lpProvider, BOOL fModify) : ECABProp(lpProvider, MAPI_MAILUSER, fModify, "IMailUser")
3329 {
3430 // since we have no OpenProperty / abLoadProp, remove the 8k prop limit
3030 #include <kopano/restrictionutil.h>
3131 #include "favoritesutil.h"
3232
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #endif
36
37
3833 //FIXME: add the classname "ECMemTablePublic"
3934 ECMemTablePublic::ECMemTablePublic(ECMAPIFolderPublic *lpECParentFolder, SPropTagArray *lpsPropTags, ULONG ulRowPropTag) : ECMemTable(lpsPropTags, ulRowPropTag)
4035 {
6964 m_lpECParentFolder->Release();
7065
7166 }
72
7367
7468 HRESULT ECMemTablePublic::Create(ECMAPIFolderPublic *lpECParentFolder, ECMemTablePublic **lppECMemTable)
7569 {
235229 hr = lpShortcutTable->SetColumns(GetShortCutTagArray(), MAPI_DEFERRED_ERRORS);
236230 if(hr != hrSuccess)
237231 goto exit;
238
239232
240233 // build restriction
241234 CREATE_RESTRICTION(lpRestriction);
375368 lpEntryID = lpFolderID;
376369 }
377370
378
379371 cProps = 0;
380372
381373 hr = MAPIAllocateBuffer(sizeof(SPropValue) * 20, (void**)&lpProps);
3636 #include <kopano/ECDebug.h>
3737 #include "WSUtil.h"
3838
39
4039 #include "ClientUtil.h"
4140 #include "ECMemStream.h"
4241
4443 #include <kopano/charset/convert.h>
4544
4645 using namespace std;
47
48 #ifdef _DEBUG
49 #define new DEBUG_NEW
50 #endif
5146
5247 #define MAX_TABLE_PROPSIZE 8192
5348
9691
9792 // Workaround for support html in outlook 2000/xp need SetPropHandler
9893 this->HrAddPropHandlers(PR_HTML, GetPropHandler ,SetPropHandler, (void*) this, FALSE, FALSE);
99
10094
10195 // The property 0x10970003 is set by outlook when browsing in the 'unread mail' searchfolder. It is used to make sure
10296 // that a message that you just read is not removed directly from view. It is set for each message which should be in the view
548542 if (hr != hrSuccess)
549543 goto exit;
550544
551
552545 // Determine strategy based on RTF type.
553546 if (isrtfhtml(strRTF.c_str(), strRTF.size()))
554547 rtfType = RTFTypeFromHTML;
556549 rtfType = RTFTypeFromText;
557550 else
558551 rtfType = RTFTypeOther;
559
560552
561553 if (rtfType == RTFTypeOther) {
562554 BOOL bUpdated;
962954 } // !new == empty table
963955 }
964956
965
966957 if(this->lpAttachments == NULL) {
967958 hr = MAPI_E_CALL_FAILED;
968959 goto exit;
12671258 goto exit;
12681259 } // !fNew
12691260 }
1270
12711261
12721262 hr = lpRecips->HrGetView(createLocaleFromName(""), ulFlags & MAPI_UNICODE, &lpView);
12731263
21482138 goto exit;
21492139 }
21502140
2151
21522141 // Property change of a new item
21532142 if (fNew && this->GetMsgStore()->IsSpooler() == TRUE) {
21542143
26942683
26952684 hr = Util::DoCopyTo(&IID_IMessage, &this->m_xMessage, ciidExclude, rgiidExclude, lpExcludeProps, ulUIParam, lpProgress, lpInterface, lpDestObj, ulFlags, lppProblems);
26962685
2697
26982686 exit:
26992687 if(lpECMAPIProp)
27002688 lpECMAPIProp->Release();
27552743 if (lpsBodyProps[2].ulPropTag == PR_HTML || (lpsBodyProps[2].ulPropTag == PROP_TAG(PT_ERROR, PROP_ID(PR_HTML)) && lpsBodyProps[2].Value.err == MAPI_E_NOT_ENOUGH_MEMORY))
27562744 fHTMLOK = TRUE;
27572745
2758
27592746 if (fRTFOK) {
27602747 HRESULT hrTmp = hrSuccess;
27612748
28902877 goto exit;
28912878 }
28922879
2893
28942880 if (!m_sMapiObject) {
28952881 // when does this happen? .. just a simple precaution for now
28962882 ASSERT(m_sMapiObject != NULL);
31073093 return pThis->Release();
31083094 }
31093095
3110
31113096 HRESULT ECMessage::xMessage::GetLastError(HRESULT hError, ULONG ulFlags, LPMAPIERROR * lppMapiError)
31123097 {
31133098 TRACE_MAPI(TRACE_ENTRY, "IMessage::GetLastError", "");
32053190 return hr;
32063191 }
32073192
3208
32093193 HRESULT ECMessage::xMessage::GetAttachmentTable(ULONG ulFlags, LPMAPITABLE *lppTable)
32103194 {
32113195 TRACE_MAPI(TRACE_ENTRY, "IMessage::GetAttachmentTable", "");
4040 class ECMessage : public ECMAPIProp {
4141 protected:
4242 /**
43 * \brief Constructor
44 *
4543 * \param lpMsgStore The store owning this message.
4644 * \param fNew Specifies whether the message is a new message.
4745 * \param fModify Specifies whether the message is writable.
128128 return MAPI_E_NO_SUPPORT;
129129 }
130130
131
132131 ECMessageStreamImporterIStreamAdapter::ECMessageStreamImporterIStreamAdapter(WSMessageStreamImporter *lpStreamImporter)
133132 : m_ptrStreamImporter(lpStreamImporter, true)
134133 { }
137136 {
138137 Commit(0); // This causes us to wait for the async thread.
139138 }
140
141
142139
143140 // ISequentialStream proxies
144141 ULONG ECMessageStreamImporterIStreamAdapter::xSequentialStream::AddRef()
6363
6464 using namespace std;
6565
66 #ifdef _DEBUG
67 #define new DEBUG_NEW
68 #endif
69
7066 // FIXME: from libserver/ECMAPI.h
7167 #define MSGFLAG_DELETED ((ULONG) 0x00000400)
72
7368
7469 const static SizedSPropTagArray(NUM_RFT_PROPS, sPropRFTColumns) =
7570 {
158153 if(lpszProfname)
159154 this->m_strProfname = lpszProfname;
160155 }
161
162
163156
164157 ECMsgStore::~ECMsgStore() {
165158
754747 if(hr != hrSuccess)
755748 goto exit;
756749
757
758750 switch( ulObjType ) {
759751 case MAPI_FOLDER:
760752 hr = lpTransport->HrOpenFolderOps(cbEntryID, lpEntryID, &lpFolderOps);
17161708 // localfreebusy message
17171709 IMessage* lpFBMessage = NULL;
17181710
1719
17201711 // Freebusy mv propery
17211712 // This property will be fill in on another place
17221713 hr = ECAllocateBuffer(sizeof(SPropValue), (void**)&lpFBPropValue);
17321723 goto exit;
17331724
17341725 memset(lpFBPropValue->Value.MVbin.lpbin, 0, sizeof(SBinary)*lpFBPropValue->Value.MVbin.cValues);
1735
17361726
17371727 // Create Freebusy Data into the rootfolder
17381728 // Folder for "freebusy data" settings
17861776 lpPropValue[cCurValues].ulPropTag = PR_PROCESS_MEETING_REQUESTS;
17871777 lpPropValue[cCurValues++].Value.b = false;
17881778
1789
17901779 hr = lpFBMessage->SetProps(cCurValues, lpPropValue, NULL);
17911780 if(hr != hrSuccess)
17921781 goto exit;
18331822 lpPropValue[cCurValues].ulPropTag = PR_FREEBUSY_NUM_MONTHS;
18341823 lpPropValue[cCurValues++].Value.ul = ECFREEBUSY_DEFAULT_PUBLISH_MONTHS;
18351824
1836
18371825 hr = lpFBMessage->SetProps(cCurValues, lpPropValue, NULL);
18381826 if(hr != hrSuccess)
18391827 goto exit;
18591847
18601848 ECFreeBuffer(lpPropValue); lpPropValue = NULL;
18611849 lpFBMessage->Release(); lpFBMessage = NULL;
1862
18631850
18641851 // Add freebusy entryid on Inbox folder
18651852 hr = lpInboxFolder->SetProps(1, lpFBPropValue, NULL);
20192006 return hr;
20202007 }
20212008
2022
20232009 HRESULT ECMsgStore::CreateStore(ULONG ulStoreType, ULONG cbUserId, LPENTRYID lpUserId, ULONG* lpcbStoreId, LPENTRYID* lppStoreId, ULONG* lpcbRootId, LPENTRYID *lppRootId)
20242010 {
20252011 HRESULT hr = hrSuccess;
20362022 LPMAPIFOLDER lpInboxFolder = NULL;
20372023 LPMAPIFOLDER lpCalendarFolder = NULL;
20382024
2039
20402025 LPSPropValue lpPropValue = NULL;
20412026 ULONG cValues = 0;
20422027 ULONG ulObjType = 0;
20552040 LPENTRYID lpStoreId = NULL;
20562041 ULONG cbRootId = 0;
20572042 LPENTRYID lpRootId = NULL;
2058
20592043
20602044 hr = CreateEmptyStore(ulStoreType, cbUserId, lpUserId, 0, &cbStoreId, &lpStoreId, &cbRootId, &lpRootId);
20612045 if (hr != hrSuccess)
21472131 if(hr != hrSuccess)
21482132 goto exit;
21492133
2150
21512134 // Set acl's on the folder
21522135 sPermission.ulRights = ecRightsReadAny|ecRightsFolderVisible;
21532136 sPermission.ulState = RIGHT_NEW|RIGHT_AUTOUPDATE_DENIED;
21922175 lpECSecurity->Release();
21932176 lpECSecurity = NULL;
21942177
2195
21962178 // Set acl's on the IPM subtree folder
21972179 sPermission.ulRights = ecRightsReadAny| ecRightsCreate | ecRightsEditOwned| ecRightsDeleteOwned | ecRightsCreateSubfolder | ecRightsFolderVisible;
21982180 sPermission.ulState = RIGHT_NEW|RIGHT_AUTOUPDATE_DENIED;
22912273 if(hr != hrSuccess)
22922274 goto exit;
22932275
2294
22952276 // Create Outbox
22962277 hr = CreateSpecialFolder(lpFolderRootST, lpecMsgStore, _("Outbox"), _T(""), PR_IPM_OUTBOX_ENTRYID, 0, NULL, NULL);
22972278 if(hr != hrSuccess)
23892370
23902371 lpCalendarFolder->Release(); lpCalendarFolder = NULL;
23912372 lpECMapiFolderInbox->Release(); lpECMapiFolderInbox = NULL;
2392
23932373
23942374 // Create Outlook 2007/2010 Additional folders
23952375 hr = CreateAdditionalFolder(lpFolderRoot, lpInboxFolder, lpFolderRootST, RSF_PID_RSS_SUBSCRIPTION, _("RSS Feeds"), _("RSS Feed comment"), _T("IPF.Note.OutlookHomepage"), false);
25422522 goto exit;
25432523 }
25442524
2545
25462525 if (*lpcbStoreId == 0 || *lpcbRootId == 0) {
25472526 if (CoCreateGuid(&guidStore) != S_OK) {
25482527 hr = MAPI_E_CALL_FAILED;
32993278
33003279 // Check if the last part equals 'cn=Microsoft Private MDB'
33013280 riPart = parts.rbegin();
3302 if (stricmp(riPart->c_str(), "cn=Microsoft Private MDB") != 0)
3281 if (strcasecmp(riPart->c_str(), "cn=Microsoft Private MDB") != 0)
33033282 return MAPI_E_INVALID_PARAMETER;
33043283
33053284 // Check if the for last part starts with 'cn='
33063285 ++riPart;
3307 if (strnicmp(riPart->c_str(), "cn=", 3) != 0)
3286 if (strncasecmp(riPart->c_str(), "cn=", 3) != 0)
33083287 return MAPI_E_INVALID_PARAMETER;
33093288
33103289 // If the server has no home server information for a user, the servername will be set to 'Unknown'
33113290 // Return MAPI_E_NO_SUPPORT in that case.
3312 if (stricmp(riPart->c_str(), "cn=Unknown") == 0)
3291 if (strcasecmp(riPart->c_str(), "cn=Unknown") == 0)
33133292 return MAPI_E_NO_SUPPORT;
33143293
33153294 *lpstrPseudoUrl = utf8string::from_string("pseudo://" + riPart->substr(3));
3333
3434 using namespace std;
3535
36 #ifdef _DEBUG
37 #define new DEBUG_NEW
38 #endif
39
4036 ECMsgStorePublic::ECMsgStorePublic(char *lpszProfname, LPMAPISUP lpSupport, WSTransport *lpTransport, BOOL fModify, ULONG ulProfileFlags, BOOL fIsSpooler, BOOL bOfflineStore) :
4137 ECMsgStore(lpszProfname, lpSupport, lpTransport, fModify, ulProfileFlags, fIsSpooler, false, bOfflineStore)
4238 {
4642 HrAddPropHandlers(PR_IPM_PUBLIC_FOLDERS_ENTRYID, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
4743 HrAddPropHandlers(PR_IPM_FAVORITES_ENTRYID, GetPropHandler, DefaultSetPropComputed, (void*) this, FALSE, FALSE);
4844 HrAddPropHandlers(PR_EC_PUBLIC_IPM_SUBTREE_ENTRYID, GetPropHandler, SetPropHandler, (void*) this, FALSE, TRUE);
49
5045
5146 m_lpIPMSubTreeID = NULL;
5247 m_lpIPMFavoritesID = NULL;
239234 goto exit;
240235 }
241236
242
243237 switch( ulObjType ) {
244238 case MAPI_FOLDER:
245239
2525 #include "Mem.h"
2626 #include "ECNamedProp.h"
2727 #include "WSTransport.h"
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3228
3329 /*
3430 * How our named properties work
5955 * Exchange) due to the fact that we know which named properties are likely to be
6056 * requested. This means that we have
6157 */
62
6358
6459 /* Our local names
6560 *
236231
237232 lpsPropTagArray->cValues = cPropNames;
238233
239
240234 // Pass 1, resolve static (local) names (FAST)
241235 for (i = 0; i < cPropNames; ++i)
242236 if(lppPropNames[i] == NULL || ResolveLocal(lppPropNames[i], &lpsPropTagArray->aulPropTag[i]) != hrSuccess)
373367 exit:
374368 return hr;
375369 }
376
377370
378371 // Update the cache with the given data
379372 HRESULT ECNamedProp::UpdateCache(ULONG ulId, MAPINAMEID *lpName)
1313 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1414 */
1515 #include <kopano/platform.h>
16 #include <stdexcept>
1617 #include <mapispi.h>
1718 #include <mapix.h>
1819 #include <kopano/ECDebug.h>
2829
2930 #define MAX_NOTIFS_PER_CALL 64
3031
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
34
3532 static inline std::pair<ULONG,ULONG> SyncAdviseToConnection(const SSyncAdvise &sSyncAdvise) {
3633 return std::make_pair(sSyncAdvise.sSyncState.ulSyncId,sSyncAdvise.ulConnection);
3734 }
5653 else if(m_ulProviderType == MAPI_ADDRBOOK)
5754 m_lpTransport = ((ECABLogon*)m_lpProvider)->m_lpTransport;
5855 else
59 ASSERT(FALSE);
56 throw std::runtime_error("Unknown m_ulProviderType");
6057
6158 /* Get the sessiongroup ID of the provider that we will be handling notifications for */
6259 if (m_lpTransport->HrGetSessionId(&ecSessionId, &m_ecSessionGroupId) != hrSuccess)
63 ASSERT(FALSE);
60 throw std::runtime_error("ECNotifyClient/HrGetSessionId failed");
6461
6562 /* Get the session group that this session belongs to */
6663 if (g_ecSessionManager.GetSessionGroupData(m_ecSessionGroupId, m_lpTransport->GetProfileProps(), &m_lpSessionGroup) != hrSuccess)
67 ASSERT(FALSE);
64 throw std::runtime_error("ECNotifyClient/GetSessionGroupData failed");
6865
6966 if (m_lpSessionGroup->GetOrCreateNotifyMaster(&m_lpNotifyMaster) != hrSuccess)
70 ASSERT(FALSE);
67 throw std::runtime_error("ECNotifyClient/GetOrCreateNotifyMaster failed");
7168
7269 m_lpNotifyMaster->AddSession(this);
7370 }
528525 return hr;
529526 }
530527
531
532528 HRESULT ECNotifyClient::ReleaseAll()
533529 {
534530 HRESULT hr = hrSuccess;
566562
567563 notifications.push_back(&notif);
568564
569
570565 // The transport used for this notifyclient *may* have a broken session. Inform the
571566 // transport that the session may be broken and it should verify that all is well.
572567
582577
583578 return hr;
584579 }
585
586580
587581 HRESULT ECNotifyClient::Notify(ULONG ulConnection, const NOTIFYLIST &lNotifications)
588582 {
2626 #include <kopano/stringutil.h>
2727 #include "SOAPUtils.h"
2828 #include "WSTransport.h"
29
30 #ifdef LINUX
3129 #include <sys/signal.h>
3230 #include <sys/types.h>
33 #endif
34
35 #ifdef _DEBUG
36 #define new DEBUG_NEW
37 #endif
3831
3932 #define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))
4033
258251 /* Make thread joinable which we need during shutdown */
259252 pthread_attr_setdetachstate(&m_hAttrib, PTHREAD_CREATE_JOINABLE);
260253
261 #ifdef LINUX
262254 /* 1Mb of stack space per thread */
263255 if (pthread_attr_setstacksize(&m_hAttrib, 1024 * 1024)) {
264256 hr = MAPI_E_CALL_FAILED;
265257 goto exit;
266258 }
267 #endif
268
269259 if (pthread_create(&m_hThread, &m_hAttrib, NotifyWatch, (void *)this)) {
270260 hr = MAPI_E_CALL_FAILED;
271261 goto exit;
341331 notifyResponse notifications;
342332 bool bReconnect = false;
343333
344 #ifdef LINUX
345334 /* Ignore SIGPIPE which may be caused by HrGetNotify writing to the closed socket */
346335 signal(SIGPIPE, SIG_IGN);
347 #endif
348336
349337 while (!pNotifyMaster->m_bThreadExit) {
350338 memset(&notifications, 0, sizeof(notifications));
2525 #include "WSUtil.h"
2626 #include <kopano/Util.h>
2727
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
31
32 /*
33 * ECParentStorage implementation
34 */
35
3628 ECParentStorage::ECParentStorage(ECGenericProp *lpParentObject, ULONG ulUniqueId, ULONG ulObjId, IECPropStorage *lpServerStorage)
3729 {
3830 m_lpParentObject = lpParentObject;
10092
10193 HRESULT ECParentStorage::HrSaveObject(ULONG ulFlags, MAPIOBJECT *lpsMapiObject)
10294 {
103 ECMapiObjects::const_iterator iterSObj;
104
10595 if (m_lpParentObject == NULL)
10696 return MAPI_E_INVALID_OBJECT;
10797
2020 #include "Mem.h"
2121 #include <kopano/charset/convert.h>
2222
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
2723 //
2824 // ECPropertyEntry
2925 //
2323 #include "ECSessionGroupManager.h"
2424 #include "SessionGroupData.h"
2525 #include "SSLUtil.h"
26
27 #ifdef _DEBUG
28 #define new DEBUG_NEW
29 #endif
30
3126
3227 /* std::algorithm helper structures/functions */
3328 struct findSessionGroupId
3838 #include <kopano/ECRestriction.h>
3939 #include <kopano/mapi_ptr.h>
4040
41
42 #ifdef _DEBUG
43 #define new DEBUG_NEW
44 #endif
45
4641 static HRESULT HrGetECMsgStore(IMAPIProp *lpProp, ECMsgStore **lppECMsgStore)
4742 {
4843 HRESULT hr;
725720 return hResult;
726721 }
727722
728
729723 HRESULT ECXPLogon::xXPLogon::QueryInterface(REFIID refiid, void ** lppInterface)
730724 {
731725 TRACE_MAPI(TRACE_ENTRY, "IXPLogon::QueryInterface", "%s", DBGGUIDToString(refiid).c_str());
1818 #include <mapiutil.h>
1919 #include <kopano/ECGuid.h>
2020
21
2221 #include "kcore.hpp"
2322 #include "ECXPProvider.h"
2423 #include "ECXPLogon.h"
3534
3635 #include <kopano/charset/convstring.h>
3736 #include <kopano/ECGetText.h>
38
39 #ifdef _DEBUG
40 #define new DEBUG_NEW
41 #endif
4237
4338 ECXPProvider::ECXPProvider() : ECUnknown("IXPProvider")
4439 {
+0
-83
provider/client/Makefile.am less more
0 # -*- Makefile -*-
1
2 pkglib_LTLIBRARIES = libkcclient.la
3 noinst_DATA = libkcclient.ldd
4
5 sysconf_configdir = ${MAPICONFIGDIR}
6 dist_sysconf_config_DATA = kopano.inf
7
8 sampleconfdir = ${docdir}/example-config
9 sampleconf_DATA = kopano.inf
10
11 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) $(BOOST_CPPFLAGS) \
12 $(GSOAP_CFLAGS) $(SSL_CFLAGS) \
13 -I${top_srcdir}/provider/include \
14 -I${top_srcdir}/provider/common \
15 -I${top_builddir}/provider/soap \
16 -I${top_srcdir}/provider/soap \
17 -I${top_srcdir}/mapi4linux/include \
18 -I${top_srcdir}/libfreebusy \
19 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon \
20 -I${top_srcdir}/libsync
21
22 libkcclient_la_LDFLAGS = ${AM_LDFLAGS} -avoid-version -module
23 libkcclient_la_LIBADD = $(SSL_LIBS) \
24 ${GSOAP_LIBS} \
25 ${top_builddir}/provider/soap/libkcsoapclient.la \
26 ${top_builddir}/provider/common/libkccommon.la \
27 ${top_builddir}/common/libkcutil.la \
28 ${top_builddir}/common/libkcmapi.la \
29 ${top_builddir}/common/libkcssl.la \
30 ${top_builddir}/libfreebusy/libkcfreebusy.la \
31 ${top_builddir}/mapi4linux/src/libmapi.la \
32 ${top_builddir}/libsync/libkcsync.la \
33 -lstdc++ $(UUID_LIBS) $(ICU_LIBS)
34
35 libkcclient_la_SOURCES = ECABLogon.cpp ECABProvider.cpp \
36 ECAttach.cpp ECMAPIContainer.cpp ECMAPIFolder.cpp ECMAPIProp.cpp \
37 ECMAPITable.cpp ECMessage.cpp ECMsgStore.cpp \
38 ECMSProvider.cpp ECNamedProp.cpp ECNotifyClient.cpp ECNotifyMaster.cpp \
39 SessionGroupData.cpp ECSessionGroupManager.cpp ECXPLogon.cpp ECXPProvider.cpp epclient.cpp \
40 Mem.cpp WSTransport.cpp \
41 ECPropertyEntry.cpp ECGenericProp.cpp ECParentStorage.cpp \
42 ECABProp.cpp ECABContainer.cpp ECDistList.cpp ECMailUser.cpp \
43 WSMAPIPropStorage.cpp WSMAPIFolderOps.cpp WSTableView.cpp \
44 WSABPropStorage.cpp WSUtil.cpp \
45 WSABTableView.cpp WSStoreTableView.cpp \
46 DLLGlobal.h ECABLogon.h ECABProvider.h ECAttach.h ECMAPIContainer.h \
47 ECMAPIFolder.h ECMAPIProp.h ECMAPITable.h ECMessage.h \
48 ECMsgStore.h ECMSProvider.h ECNamedProp.h ECNotifyClient.h SessionGroupData.h ECSessionGroupManager.h \
49 ECXPLogon.h ECXPProvider.h EntryPoint.h Mem.h resource.h WSTransport.h \
50 IECPropStorage.h ECPropertyEntry.h ECGenericProp.h ECParentStorage.h \
51 ECABProp.h ECABContainer.h ECDistList.h ECMailUser.h \
52 WSMAPIPropStorage.h WSMAPIFolderOps.h WSTableView.h \
53 WSABPropStorage.h ECNotifyMaster.h WSUtil.h \
54 WSABTableView.h WSStoreTableView.h \
55 ClientUtil.h ClientUtil.cpp \
56 ECExchangeModifyTable.cpp ECExchangeModifyTable.h \
57 ECExchangeExportChanges.cpp ECExchangeExportChanges.h \
58 ECExchangeImportContentsChanges.cpp ECExchangeImportContentsChanges.h \
59 ECExchangeImportHierarchyChanges.cpp ECExchangeImportHierarchyChanges.h \
60 ECICS.h \
61 ECMSProviderSwitch.cpp ECMSProviderSwitch.h ECMSProviderOffline.h ECMSProviderOffline.cpp \
62 ECABProviderSwitch.cpp ECABProviderSwitch.h ECABProviderOffline.h ECABProviderOffline.cpp \
63 ProviderUtil.h ProviderUtil.cpp \
64 ECExportAddressbookChanges.h ECExportAddressbookChanges.cpp \
65 ECMAPIFolderPublic.h ECMAPIFolderPublic.cpp \
66 ECMemTablePublic.h ECMemTablePublic.cpp \
67 ECMsgStorePublic.h ECMsgStorePublic.cpp \
68 ECChangeAdvisor.h ECChangeAdvisor.cpp \
69 ECDisplayTable.h ECDisplayTable.cpp \
70 ECArchiveAwareMsgStore.h ECArchiveAwareMsgStore.cpp \
71 ECArchiveAwareMessage.h ECArchiveAwareMessage.cpp \
72 ECArchiveAwareAttach.h ECArchiveAwareAttach.cpp \
73 WSMessageStreamExporter.h WSMessageStreamExporter.cpp \
74 WSSerializedMessage.h WSSerializedMessage.cpp \
75 WSMessageStreamImporter.h WSMessageStreamImporter.cpp \
76 ECMessageStreamImporterIStreamAdapter.h ECMessageStreamImporterIStreamAdapter.cpp
77
78 check-syntax:
79 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
80 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
81
82 include ../../global.am
2121 #include <kopano/Trace.h>
2222 #include "Mem.h"
2323
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
27
2824 // We don't want that here
2925 #undef ECAllocateBuffer
3026
3329 LPALLOCATEMORE _pfnAllocMore;
3430 LPFREEBUFFER _pfnFreeBuf;
3531 HINSTANCE _hInstance;
36
37 LPALLOCATEBUFFER GetAllocateBuffer() { return _pfnAllocBuf; }
38 LPALLOCATEMORE GetAllocateMore() { return _pfnAllocMore; }
39 LPFREEBUFFER GetFreeBuffer() { return _pfnFreeBuf; }
40 HINSTANCE GetInstance() { return _hInstance; }
41 LPMALLOC GetMalloc(){ return _pmalloc; }
4232
4333 // This is the same as client-side MAPIFreeBuffer, but uses
4434 // the linked memory routines passed in during MSProviderInit()
7565 return MAPI_E_CALL_FAILED;
7666 else return _pfnAllocMore(cbSize, lpBase, lpvoid);
7767 }
78
79 // Use these functions for internal memory management
80
81 /* Use new() and delete() instead !
82 HRESULT HrAlloc(ULONG cbSize, void **lpvoid) {
83 if(_pmalloc == NULL)
84 return MAPI_E_CALL_FAILED;
85 else {
86 *lpvoid = _pmalloc->Alloc(cbSize);
87 if(*lpvoid == NULL)
88 return MAPI_E_NOT_ENOUGH_MEMORY;
89 else
90 return hrSuccess;
91 }
92 }
93
94 HRESULT HrRealloc(ULONG cbSize, void *lpBase, void **lpvoid) {
95 if(_pmalloc == NULL)
96 return MAPI_E_CALL_FAILED;
97 else {
98 *lpvoid = _pmalloc->Realloc(lpBase, cbSize);
99 if(*lpvoid == NULL)
100 return MAPI_E_NOT_ENOUGH_MEMORY;
101 else
102 return hrSuccess;
103 }
104 }
105
106 HRESULT HrFree(void *lpvoid) {
107 if(lpvoid == NULL)
108 return MAPI_E_CALL_FAILED;
109
110 if(_pmalloc == NULL)
111 return MAPI_E_CALL_FAILED;
112 else {
113 _pmalloc->Free(lpvoid);
114 return hrSuccess;
115 }
116 }
117
118 */
11968
12069 HRESULT AllocNewMapiObject(ULONG ulUniqueId, ULONG ulObjId, ULONG ulObjType, MAPIOBJECT **lppMapiObject)
12170 {
2525 HRESULT ECAllocateBufferDbg(ULONG cbSize, void **lpvoid, char *szFile, int line);
2626 HRESULT ECAllocateMore(ULONG cbSize, void *lpBase, void **lpvoid);
2727
28 LPALLOCATEBUFFER GetAllocateBuffer();
29 LPALLOCATEMORE GetAllocateMore();
30 LPFREEBUFFER GetFreeBuffer();
31
32 HINSTANCE GetInstance();
33 LPMALLOC GetMalloc();
34
35 // Standard memory management
36 /* DEPRECATED - do not use
37 HRESULT HrAlloc(ULONG cbSize, void **lpvoid);
38 HRESULT HrRealloc(ULONG cbSize, void *lpBase, void **lpvoid);
39 HRESULT HrFree(void *lpvoid); */
40
41 // debug tracing
42 #ifdef _DEBUG
43 #define ECAllocateBuffer(cbSize, lpvoid) ECAllocateBufferDbg(cbSize, lpvoid, __FILE__, __LINE__)
44 #endif
45
46
4728 HRESULT AllocNewMapiObject(ULONG ulUniqueId, ULONG ulObjId, ULONG ulObjType, MAPIOBJECT **lppMapiObject);
4829 HRESULT FreeMapiObject(MAPIOBJECT *lpsObject);
4930
5454
5555 using namespace std;
5656
57 #ifdef _DEBUG
58 #define new DEBUG_NEW
59 #endif
60
61
6257 HRESULT CompareStoreIDs(ULONG cbEntryID1, LPENTRYID lpEntryID1, ULONG cbEntryID2, LPENTRYID lpEntryID2, ULONG ulFlags, ULONG *lpulResult)
6358 {
6459 HRESULT hr = hrSuccess;
110105 return hr;
111106 }
112107
113 // Get MAPI unique guid, guaranteed by MAPI to be unique for all profiles.
114 HRESULT GetMAPIUniqueProfileId(LPMAPISUP lpMAPISup, tstring* lpstrUniqueId)
115 {
116 HRESULT hr = hrSuccess;
117 LPPROFSECT lpProfSect = NULL;
118 LPSPropValue lpsPropValue = NULL;
119
120 hr = lpMAPISup->OpenProfileSection((LPMAPIUID)&MUID_PROFILE_INSTANCE, 0, &lpProfSect);
121 if(hr != hrSuccess)
122 goto exit;
123
124 hr = HrGetOneProp(lpProfSect, PR_SEARCH_KEY, &lpsPropValue);
125 if(hr != hrSuccess)
126 goto exit;
127
128 *lpstrUniqueId = bin2hext(lpsPropValue->Value.bin.cb, lpsPropValue->Value.bin.lpb);
129 exit:
130 MAPIFreeBuffer(lpsPropValue);
131 if(lpProfSect)
132 lpProfSect->Release();
133
134 return hr;
135 }
136
137108 HRESULT RemoveAllProviders(ECMapProvider* lpmapProvider)
138109 {
139110 ECMapProvider::const_iterator iterProvider;
154125
155126 HRESULT SetProviderMode(IMAPISupport *lpMAPISup, ECMapProvider* lpmapProvider, LPCSTR lpszProfileName, ULONG ulConnectType)
156127 {
157 return hrSuccess;
158 }
159
160 HRESULT GetLastConnectionType(IMAPISupport *lpMAPISup, ULONG *lpulType) {
161 *lpulType = CT_ONLINE;
162128 return hrSuccess;
163129 }
164130
4343 HRESULT RemoveAllProviders(ECMapProvider *lpmapProvider);
4444 HRESULT SetProviderMode(IMAPISupport *lpMAPISup, ECMapProvider *lpmapProvider, LPCSTR lpszProfileName, ULONG ulConnectType);
4545 HRESULT GetProviders(ECMapProvider *lpmapProvider, IMAPISupport *lpMAPISup, LPCSTR lpszProfileName, ULONG ulFlags, PROVIDER_INFO *lpsProviderInfo);
46 HRESULT GetLastConnectionType(IMAPISupport *lpMAPISup, ULONG *lpulType);
4746
48 HRESULT GetMAPIUniqueProfileId(LPMAPISUP lpMAPISup, tstring *lpstrUniqueId);
4947 HRESULT GetTransportToNamedServer(WSTransport *lpTransport, LPCTSTR lpszServerName, ULONG ulFlags, WSTransport **lppTransport);
5048
5149 #endif // #ifndef PROVIDERUTIL_H
0 Kopano basic tech. information
1 ===============================
2
3 The Kopano Message store provider works with the following components (layered top-to-bottom):
4
5 Client side:
6 - Full MAPI implementation to the client
7 - Local client handling of data structures, formats, and anything needing caching or local processing
8 - Abstract 'storage' classes for doing the actual transport of data to and from the server
9 - Currently only the WS (WebService) Transport is implemented, using gSOAP for serialization
10
11 Network:
12 - HTTP / SOAP network transport
13
14 Server side:
15 - Server deserialisation and RPC with gSOAP (through either Apache or standalone server)
16 - Storage layer for database communication
17 - MySQL database storage
2424 #include "ECSessionGroupManager.h"
2525 #include "SessionGroupData.h"
2626 #include "WSTransport.h"
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
31
3227
3328 SessionGroupData::SessionGroupData(ECSESSIONGROUPID ecSessionGroupId, ECSessionGroupInfo *lpInfo, const sGlobalProfileProps &sProfileProps)
3429 {
7166
7267 return hr;
7368 }
74
7569
7670 HRESULT SessionGroupData::GetOrCreateNotifyMaster(ECNotifyMaster **lppMaster)
7771 {
2020 #include "WSUtil.h"
2121 #include <kopano/charset/convert.h>
2222
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
2723 #define START_SOAP_CALL retry:
2824 #define END_SOAP_CALL \
2925 if(er == KCERR_END_OF_SESSION) { if(this->m_lpTransport->HrReLogon() == hrSuccess) goto retry; } \
2929 #include "SOAPUtils.h"
3030 #include "WSUtil.h"
3131
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #endif
35
3632 WSABTableView::WSABTableView(ULONG ulType, ULONG ulFlags, KCmd *lpCmd, pthread_mutex_t *lpDataLock, ECSESSIONID ecSessionId, ULONG cbEntryId, LPENTRYID lpEntryId, ECABLogon* lpABLogon, WSTransport *lpTransport) : WSTableView(ulType, ulFlags, lpCmd, lpDataLock, ecSessionId, cbEntryId, lpEntryId, lpTransport, "WSABTableView")
3733 {
3834 m_lpProvider = lpABLogon;
2626
2727 #include <kopano/charset/utf8string.h>
2828
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
32
3329 #define START_SOAP_CALL retry:
3430 #define END_SOAP_CALL \
3531 if(er == KCERR_END_OF_SESSION) { if(m_lpTransport->HrReLogon() == hrSuccess) goto retry; } \
157153 return hr;
158154 }
159155
160
161156 HRESULT WSMAPIFolderOps::HrEmptyFolder(ULONG ulFlags, ULONG ulSyncId)
162157 {
163158 ECRESULT er = erSuccess;
251246 exit:
252247 UnLockSoap();
253248
254
255249 if(lpsRestrict)
256250 FreeRestrictTable(lpsRestrict);
257251
2222 #include "pcutil.hpp"
2323 #include <kopano/charset/convert.h>
2424
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
28
2925 /*
3026 *
3127 * This is a PropStorage object for use with the WebServices storage platform
467463 struct loadObjectResponse sResponse;
468464 convert_context converter;
469465
470
471466 HrMapiObjectToSoapObject(lpsMapiObject, &sSaveObj, &converter);
472467
473468 LockSoap();
643638 return &this->m_xECPropStorage; // I am the server storage
644639 }
645640
646
647641 //FIXME: one lock/unlock function
648642 HRESULT WSMAPIPropStorage::LockSoap()
649643 {
2020 #include "WSTransport.h"
2121 #include <kopano/charset/convert.h>
2222 #include "WSUtil.h"
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
2723
2824 /**
2925 * Create a WSMessageStreamExporter instance.
1818 #include "WSMessageStreamImporter.h"
1919 #include "WSUtil.h"
2020 #include "ECSyncSettings.h"
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
25
26 // WSMessageStreamSink Implementation
2721
2822 /**
2923 * Create a new WSMessageStreamSink instance
7973 }
8074
8175 /**
82 * Constructor
8376 * @param[in] lpFifoBuffer The fifobuffer to write the data into.
8477 */
8578 WSMessageStreamSink::WSMessageStreamSink(ECFifoBuffer *lpFifoBuffer, ULONG ulTimeout, WSMessageStreamImporter *lpImporter)
1717 #include <kopano/platform.h>
1818 #include "WSSerializedMessage.h"
1919
20 #ifdef _DEBUG
21 #define new DEBUG_NEW
22 #endif
23
2420 /**
25 * Constructor
2621 * @param[in] lpSoap The gSoap object from which the MTOM attachments must be obtained.
2722 * @param[in] strStreamId The expected stream id. Used to validate the MTOM attachment obtained from gSoap.
2823 * @param[in] cbProps The amount of properties returned from the original soap call.
10398 return m_hr;
10499 }
105100
106
107
108
109101 void* WSSerializedMessage::StaticMTOMWriteOpen(struct soap *soap, void *handle, const char *id, const char *type, const char *description, enum soap_mime_encoding encoding)
110102 {
111103 WSSerializedMessage *lpMessage = reinterpret_cast<WSSerializedMessage*>(handle);
2020 #include "SOAPUtils.h"
2121 #include "WSUtil.h"
2222
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
2723 WSStoreTableView::WSStoreTableView(ULONG ulType, ULONG ulFlags, KCmd *lpCmd, pthread_mutex_t *lpDataLock, ECSESSIONID ecSessionId, ULONG cbEntryId, LPENTRYID lpEntryId, ECMsgStore *lpMsgStore, WSTransport *lpTransport) : WSTableView(ulType, ulFlags, lpCmd, lpDataLock, ecSessionId, cbEntryId, lpEntryId, lpTransport, "WSStoreTableView")
2824 {
2925
126122 return hr;
127123 }
128124
129
130125 HRESULT WSTableMultiStore::HrSetEntryIDs(LPENTRYLIST lpMsgList)
131126 {
132127 // Not really a transport function, but this is the best place for it for now
133128
134129 return CopyMAPIEntryListToSOAPEntryList(lpMsgList, &m_sEntryList);
135130 }
136
137131
138132 /*
139133 Miscellaneous tables are not really store tables, but the is the same, so it inherits from the store table
2020 #include "WSUtil.h"
2121 #include <kopano/charset/convert.h>
2222
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
26
2723 /*
2824 * TableView operations for WS transport
2925 */
130126 return hr;
131127 }
132128
133
134129 HRESULT WSTableView::HrSetColumns(LPSPropTagArray lpsPropTagArray)
135130 {
136131 ECRESULT er = erSuccess;
307302
308303 return hr;
309304 }
310
311305
312306 HRESULT WSTableView::HrGetRowCount(ULONG *lpulRowCount, ULONG *lpulCurrentRow)
313307 {
5858 #include "WSMessageStreamImporter.h"
5959
6060 using namespace std;
61
62 #ifdef _DEBUG
63 #define new DEBUG_NEW
64 #endif
65
6661
6762 /*
6863 *
334329 if (sResponse.sServerGuid.__ptr != NULL && sResponse.sServerGuid.__size == sizeof(m_sServerGuid))
335330 memcpy(&m_sServerGuid, sResponse.sServerGuid.__ptr, sizeof(m_sServerGuid));
336331
337
338332 // From here the login is ok
339333
340334 auth: // User have a logon
395389 this->m_lpCmd->soap->recv_timeout = ulSeconds;
396390 return hrSuccess;
397391 }
398
399392
400393 HRESULT WSTransport::CreateAndLogonAlternate(LPCSTR szServer, WSTransport **lppTransport) const
401394 {
709702 }
710703 END_SOAP_CALL
711704
712
713705 exit:
714706 UnLockSoap();
715707
775767 LPENTRYID lpUnWrapEntryID = NULL;
776768 ULONG cbUnWrapEntryID = 0;
777769
778
779770 if (lpParentEntryID) {
780771 hr = UnWrapServerClientStoreEntry(cbParentEntryID, lpParentEntryID, &cbUnWrapParentID, &lpUnWrapParentID);
781772 if(hr != hrSuccess)
830821
831822 LPENTRYID lpUnWrapStoreID = NULL;
832823 ULONG cbUnWrapStoreID = 0;
833
834824
835825 hr = UnWrapServerClientABEntry(cbEntryID, lpEntryID, &cbUnWrapStoreID, &lpUnWrapStoreID);
836826 if(hr != hrSuccess)
954944 if(hr != hrSuccess)
955945 goto exit;
956946
957
958947 START_SOAP_CALL
959948 {
960949 if(SOAP_OK != m_lpCmd->ns__deleteObjects(m_ecSessionId, ulFlags, &sEntryList, ulSyncId, &er))
961950 er = KCERR_NETWORK_ERROR;
962951 }
963952 END_SOAP_CALL
964
965953
966954 exit:
967955 UnLockSoap();
11111099
11121100 }
11131101 END_SOAP_CALL
1114
11151102
11161103 exit:
11171104 MAPIFreeBuffer(notSubscribeArray.__ptr);
14151402 sEntryId.__ptr = (unsigned char*)lpUnWrapStoreID;
14161403 sEntryId.__size = cbUnWrapStoreID;
14171404
1418
1419
14201405 // Get ReceiveFolder information from the server
14211406 START_SOAP_CALL
14221407 {
15081493 if(lpstrExplicitClass)
15091494 lpstrExplicitClass->clear();
15101495
1511
15121496 // Get ReceiveFolder information from the server
15131497 START_SOAP_CALL
15141498 {
15751559 sStoreId.__ptr = (unsigned char*)lpUnWrapStoreID;
15761560 sStoreId.__size = cbUnWrapStoreID;
15771561
1578
15791562 // Ignore error
15801563 CopyMAPIEntryIdToSOAPEntryId(cbEntryID, lpEntryID, &sEntryId, true);
1581
15821564
15831565 START_SOAP_CALL
15841566 {
17851767 hr = MAPI_E_INVALID_PARAMETER;
17861768 goto exit;
17871769 }
1788
17891770
17901771 START_SOAP_CALL
17911772 {
18731854
18741855 return hr;
18751856 }
1876
18771857
18781858 /**
18791859 * Create a new user.
20492029
20502030 }
20512031 END_SOAP_CALL
2052
20532032
20542033 exit:
20552034 UnLockSoap();
22782257 goto exit;
22792258 }
22802259
2281
22822260 *lpcUsers = 0;
22832261
22842262 START_SOAP_CALL
26422620 er = KCERR_NETWORK_ERROR;
26432621 }
26442622 END_SOAP_CALL
2645
26462623
26472624 hr = CopyUserClientUpdateStatusFromSOAP(sResponse, ulFlags, lppECUCUS);
26482625 if (hr != hrSuccess)
41464123 }
41474124 pthread_mutex_unlock(&m_ResolveResultCacheMutex);
41484125
4149
41504126 // Cache failed. Try the server
41514127 LockSoap();
41524128
42034179 hr = SvrNameListToSoapMvString8(lpServerNameList, ulFlags & MAPI_UNICODE, &lpsSvrNameList);
42044180 if (hr != hrSuccess)
42054181 goto exit;
4206
42074182
42084183 START_SOAP_CALL
42094184 {
44354410 HRESULT hr = hrSuccess;
44364411 WSTableMultiStore *lpMultiStoreTable = NULL;
44374412
4438
44394413 if (!lpMsgList || lpMsgList->cValues == 0) {
44404414 hr = MAPI_E_INVALID_PARAMETER;
44414415 goto exit;
44424416 }
4443
44444417
44454418 hr = WSTableMultiStore::Create(ulFlags, m_lpCmd, &m_hDataLock, m_ecSessionId, cbEntryID, lpEntryID, lpMsgStore, this, &lpMultiStoreTable);
44464419 if (hr != hrSuccess)
44584431
44594432 return hr;
44604433 }
4461
44624434
44634435 HRESULT WSTransport::HrOpenMiscTable(ULONG ulTableType, ULONG ulFlags, ULONG cbEntryID, LPENTRYID lpEntryID, ECMsgStore *lpMsgStore, WSTableView **lppTableView)
44644436 {
45084480 /* else: er is already set and good to use */
45094481 }
45104482 END_SOAP_CALL
4511
45124483
45134484 exit:
45144485 UnLockSoap();
46154586 er = sResponse.er;
46164587 }
46174588 END_SOAP_CALL
4618
46194589
46204590 *lpulUsers = sResponse.ulUsers;
46214591
48614831 {
48624832 if (!m_strAppName.empty())
48634833 return m_strAppName;
4864 #ifdef LINUX
48654834 std::string procpath = "/proc/" + stringify(getpid()) + "/cmdline";
48664835 std::string s;
48674836
48714840 m_strAppName = "<unknown>";
48724841 else
48734842 m_strAppName = basename((char *)s.c_str());
4874 #else
4875 char s[1024];
4876 GetModuleFileNameA(0, s, sizeof(s));
4877
4878 s[sizeof(s)-1] = 0;
4879
4880 m_strAppName = basename(s);
4881 #endif
48824843 return m_strAppName;
48834844 }
48844845
1515 */
1616
1717 #include <kopano/platform.h>
18 #ifdef LINUX
1918 #include <sys/un.h>
20 #endif
2119 #include "WSUtil.h"
2220 #include <kopano/ECIConv.h>
2321 #include <kopano/ECGuid.h>
4846 #include "SOAPSock.h"
4947
5048 using namespace std;
51
52 #ifdef _DEBUG
53 #define new DEBUG_NEW
54 #endif
55
5649
5750 #define CONVERT_TO(_context, _charset, ...) ((_context) ? (_context)->convert_to<_charset>(__VA_ARGS__) : convert_to<_charset>(__VA_ARGS__))
5851
15411534 convert_context converter;
15421535 ULONG ulConvFlags;
15431536
1544
15451537 if (lpPropmap && lpPropmap->cEntries) {
15461538 hr = ECAllocateBuffer(sizeof *soapPropmap, (void**)&soapPropmap);
15471539 if (hr != hrSuccess)
22232215 CopySOAPEntryIdToMAPIEntryId(lpSrc->newmail->pParentId, &lpNotification->info.newmail.cbParentID, &lpNotification->info.newmail.lpParentID, (void **)lpNotification);
22242216 }
22252217
2226
22272218 if(lpSrc->newmail->lpszMessageClass != NULL) {
22282219 nLen = strlen(lpSrc->newmail->lpszMessageClass)+1;
22292220 ECAllocateMore(nLen, lpNotification, (void**)&lpNotification->info.newmail.lpszMessageClass);
22812272 if(lpSrc->tab->propPrior.Value.bin){
22822273 lpNotification->info.tab.propPrior.Value.bin.cb = lpSrc->tab->propPrior.Value.bin->__size;
22832274 ECAllocateMore(lpNotification->info.tab.propPrior.Value.bin.cb, lpNotification, (void**)&lpNotification->info.tab.propPrior.Value.bin.lpb);
2284
22852275
22862276 memcpy(lpNotification->info.tab.propPrior.Value.bin.lpb, lpSrc->tab->propPrior.Value.bin->__ptr, lpSrc->tab->propPrior.Value.bin->__size);
22872277 }
24422432
24432433 if (hr != hrSuccess)
24442434 goto exit;
2445
24462435
24472436 *lppECUCUS = lpECUCUS;
24482437 lpECUCUS = NULL;
6868
6969 HRESULT SvrNameListToSoapMvString8(ECSVRNAMELIST *lpSvrNameList, ULONG ulFLags, struct mv_string8 **lppsSvrNameList);
7070 HRESULT SoapServerListToServerList(const struct serverList *lpsServerList, ULONG ulFLags, ECSERVERLIST **lppServerList);
71
72 #ifdef LINUX
7371 int gsoap_connect_unixsocket(struct soap *soap, const char *endpoint, const char *host, int port);
74 #else
75 int gsoap_win_fsend(struct soap *soap, const char *s, size_t n);
76 size_t gsoap_win_frecv(struct soap *soap, char *s, size_t n);
77 int gsoap_win_fclose(struct soap *soap);
78 int gsoap_connect_namedpipe(struct soap *soap, const char *endpoint, const char *host, int port);
79 #endif
80
8172 HRESULT CreateSoapTransport(ULONG ulUIFlags, const sGlobalProfileProps &sProfileProps, KCmd **const lppCmd);
8273
8374 HRESULT WrapServerClientStoreEntry(const char* lpszServerName, entryId* lpsStoreId, ULONG* lpcbStoreID, LPENTRYID* lppStoreID);
3434 #include "ECMSProviderSwitch.h"
3535 #include "ECXPProvider.h"
3636 #include "ECABProviderSwitch.h"
37 #ifdef LINUX
3837 #include <iostream>
39 #endif
40
4138 #include <kopano/ecversion.h>
4239
4340 #include <kopano/ECDebug.h>
6057 #include <kopano/charset/convstring.h>
6158
6259 using namespace std;
63
64 #ifdef _DEBUG
65 #define new DEBUG_NEW
66
67 #define DEBUG_WITH_MEMORY_DUMP 0 // Sure to dump memleaks before the dll is exit
68 #endif
6960
7061 class EPCDeleter {
7162 public:
174165 *
175166 * @param lpProviderAdmin[in] The ProviderAdmin object passed to MSGServiceEntry
176167 * @param lpServiceName[out] The name of the message service
177 * @return HRESULT Result status
178168 */
179169 static HRESULT GetServiceName(IProviderAdmin *lpProviderAdmin,
180170 std::string *lpServiceName)
441431 d.provadm = lpAdminProvider;
442432 d.profsect = lpProfSect;
443433 d.count = d.eid_size = 0;
434 d.transport = NULL;
444435
445436 if (d.provadm != NULL) {
446437 hr = GetServiceName(d.provadm, &strServiceName);
862853 }
863854 break;
864855 } // switch(ulContext)
865
866856
867857 exit:
868858 if (lppMapiError) {
925915 return hr;
926916 }
927917
928
929918 extern "C" HRESULT __cdecl XPProviderInit(HINSTANCE hInstance, LPMALLOC lpMalloc, LPALLOCATEBUFFER lpAllocateBuffer, LPALLOCATEMORE lpAllocateMore, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, ULONG ulMAPIVer, ULONG * lpulProviderVer, LPXPPROVIDER * lppXPProvider)
930919 {
931920 TRACE_MAPI(TRACE_ENTRY, "XPProviderInit", "");
958947 if(pXPProvider)
959948 pXPProvider->Release();
960949
961
962950 return hr;
963951 }
964
965952
966953 extern "C" HRESULT __cdecl ABProviderInit(HINSTANCE hInstance, LPMALLOC lpMalloc, LPALLOCATEBUFFER lpAllocateBuffer, LPALLOCATEMORE lpAllocateMore, LPFREEBUFFER lpFreeBuffer, ULONG ulFlags, ULONG ulMAPIVer, ULONG * lpulProviderVer, LPABPROVIDER * lppABProvider)
967954 {
994981 if(lpABProvider)
995982 lpABProvider->Release();
996983
997
998984 return hr;
999985 }
1818
1919 #include <string>
2020 #include <vector>
21
22 #ifdef LINUX
21 #include <cstdlib>
2322 #include <sys/un.h>
2423 #include <sys/socket.h>
25 #endif
26
2724 #include <kopano/ECDefs.h>
2825 #include <kopano/ECChannel.h>
2926 #include <kopano/base64.h>
128125 } LICENSERESPONSE;
129126
130127 ECRESULT ECLicenseClient::Auth(const unsigned char *lpData,
131 unsigned int ulSize, unsigned char **lppResponse,
132 unsigned int *lpulResponseSize)
128 unsigned int ulSize, void **lppResponse, unsigned int *lpulResponseSize)
133129 {
134 LICENSERESPONSE *lpResponse = new LICENSERESPONSE;
135 memset(lpResponse, 0, sizeof(LICENSERESPONSE));
136
137 *lppResponse = (unsigned char *)lpResponse;
130 *lppResponse = calloc(1, sizeof(LICENSERESPONSE));
138131 *lpulResponseSize = sizeof(LICENSERESPONSE);
139
140132 return erSuccess;
141133 }
142134
3232 ECRESULT QueryCapability(unsigned int ulServiceType, const std::string &strCapability, bool *lpbResult);
3333 ECRESULT GetSerial(unsigned int ulServiceType, std::string &lpstrSerial, std::vector<std::string> &lstCALs);
3434 ECRESULT GetInfo(unsigned int ulServiceType, unsigned int *lpulUserCount);
35 ECRESULT Auth(const unsigned char *lpData, unsigned int ulSize, unsigned char **lpResponse, unsigned int *lpulResponseSize);
35 ECRESULT Auth(const unsigned char *lpData, unsigned int ulSize, void **ret, unsigned int *retsize);
3636 ECRESULT SetSerial(unsigned int ulServiceType, const std::string &strSerial, const std::vector<std::string> &lstCALs);
3737
3838 private:
1515 */
1616
1717 #include <kopano/platform.h>
18
19 #ifdef LINUX
2018 #include <sys/un.h>
2119 #include <sys/socket.h>
22 #endif
23
2420 #include <kopano/base64.h>
2521 #include <kopano/ECChannel.h>
2622 #include <kopano/ECDefs.h>
+0
-36
provider/common/Makefile.am less more
0 # -*- Makefile -*-
1
2 AM_CPPFLAGS = ${ZCPPFLAGS} ${DEBUGFLAGS} ${GSOAP_CFLAGS} \
3 ${BOOST_CPPFLAGS} \
4 -I${top_srcdir}/mapi4linux/include -I${top_srcdir}/provider/include \
5 -I${top_builddir}/provider/soap -I${top_srcdir}/provider/soap \
6 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon
7
8 pkginclude_HEADERS = include/kopano/pcuser.hpp
9
10 noinst_LTLIBRARIES = libkccommon.la
11 #noinst_DATA = libkccommon.ldd
12
13 libkccommon_la_SOURCES = SOAPUtils.cpp SOAPUtils.h \
14 SOAPAlloc.h \
15 SOAPHelpers.cpp SOAPHelpers.h \
16 SOAPDebug.cpp SOAPDebug.h \
17 SOAPSock.cpp SOAPSock.h \
18 pcutil.cpp pcutil.hpp \
19 pcuser.cpp \
20 ECLicenseClient.h ECLicenseClient.cpp \
21 ECSearchClient.h ECSearchClient.cpp \
22 soapctor.cpp
23 libkccommon_la_LIBADD = \
24 ../../common/libkcutil.la ../../common/libkcmapi.la \
25 ../soap/libkcsoapclient.la ../../common/libkcssl.la \
26 ${GSOAP_LIBS} ${SSL_LIBS}
27 libkccommon_la_LDFLAGS = ${AM_LDFLAGS} \
28 -Wl,--version-script=${top_builddir}/default.sym
29 EXTRA_libkccommon_la_DEPENDENCIES = ${top_builddir}/default.sym
30
31 check-syntax:
32 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
33 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
34
35 include ../../global.am
2424 #include <kopano/stringutil.h>
2525
2626 using namespace std;
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
3127
3228 std::string RestrictionToString(const restrictTable *lpRestriction,
3329 unsigned int indent)
1515 */
1616
1717 #include "SOAPHelpers.h"
18
19 #ifdef _DEBUG
20 #define new DEBUG_NEW
21 #endif
2218
2319 void *mime_file_read_open(struct soap *soap, void *handle, const char *id, const char *type, const char *description)
2420 {
1616
1717 #include <kopano/platform.h>
1818 #include "SOAPSock.h"
19
20 #ifdef LINUX
2119 #include <sys/un.h>
22 #endif
23
2420 #include "SOAPUtils.h"
21 #include <kopano/stringutil.h>
2522 #include <kopano/threadutil.h>
2623 #include <kopano/CommonUtil.h>
2724 #include <string>
5855 return soap->fposthdr(soap, NULL, NULL);
5956 }
6057
61 #ifdef LINUX
62
6358 // This function wraps the GSOAP fopen call to support "file:///var/run/socket" unix-socket URI's
6459 static int gsoap_connect_pipe(struct soap *soap, const char *endpoint,
6560 const char *host, int port)
8883 // >= because there also needs to be room for the 0x00
8984 if (strlen(socket_name) >= sizeof(saddr.sun_path))
9085 return SOAP_EOF;
91
92 strncpy(saddr.sun_path, socket_name, sizeof(saddr.sun_path));
93
86 kc_strlcpy(saddr.sun_path, socket_name, sizeof(saddr.sun_path));
9487 connect(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_un));
9588
9689 soap->sendfd = soap->recvfd = SOAP_INVALID_SOCKET;
10699
107100 return SOAP_OK;
108101 }
109 #else
110 /* In windows, we support file: URI's with named pipes (ie file://\\server\pipe\kopano)
111 * Unfortunately, we can't use the standard fsend/frecv call with this, because gsoap
112 * uses winsock-style SOCKET handles for send and recv, so we also have to supply
113 * fsend,frecv, etc to use HANDLE-type connections
114 */
115
116 int gsoap_win_fsend(struct soap *soap, const char *s, size_t n)
117 {
118 int rc = SOAP_ERR;
119 DWORD ulWritten;
120 OVERLAPPED op = {0};
121
122 op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Will this ever fail?
123
124 if (WriteFile((HANDLE)soap->socket, s, n, &ulWritten, &op) == TRUE)
125 rc = SOAP_OK;
126
127 else if (GetLastError() == ERROR_IO_PENDING) {
128 if (WaitForSingleObject(op.hEvent, 70*1000) == WAIT_OBJECT_0) {
129 // We would normaly reset the event here, but we're not reusing it anyway.
130 if (GetOverlappedResult((HANDLE)soap->socket, &op, &ulWritten, TRUE) == TRUE)
131 rc = SOAP_OK;
132 } else
133 CancelIo((HANDLE)soap->socket);
134 }
135
136 CloseHandle(op.hEvent);
137 return rc;
138 }
139
140 size_t gsoap_win_frecv(struct soap *soap, char *s, size_t n)
141 {
142 size_t rc = 0;
143 DWORD ulRead;
144 OVERLAPPED op = {0};
145
146 op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Will this ever fail?
147
148 if (ReadFile((HANDLE)soap->socket, s, n, &ulRead, &op) == TRUE)
149 rc = ulRead;
150
151 else if (GetLastError() == ERROR_IO_PENDING) {
152 if (WaitForSingleObject(op.hEvent, 70*1000) == WAIT_OBJECT_0) {
153 // We would normaly reset the event here, but we're not reusing it anyway.
154 if (GetOverlappedResult((HANDLE)soap->socket, &op, &ulRead, TRUE) == TRUE)
155 rc = ulRead;
156 } else
157 CancelIo((HANDLE)soap->socket);
158 }
159
160 CloseHandle(op.hEvent);
161 return rc;
162 }
163
164 int gsoap_win_fclose(struct soap *soap)
165 {
166 if((HANDLE)soap->socket == INVALID_HANDLE_VALUE)
167 return SOAP_OK;
168
169 CloseHandle((HANDLE)soap->socket); // Ignore error
170 soap->socket = (int)INVALID_HANDLE_VALUE;
171
172 return SOAP_OK;
173 }
174
175 int gsoap_win_fpoll(struct soap *soap)
176 {
177 // Always a connection
178 return SOAP_OK;
179 }
180
181 // Override the soap function shutdown
182 // disable read/write actions
183 static int gsoap_win_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
184 {
185 // Normaly gsoap called shutdown, but the function isn't
186 // exist for named pipes, so return;
187 return SOAP_OK;
188 }
189
190 int gsoap_connect_pipe(struct soap *soap, const char *endpoint, const char *host, int port)
191 {
192 HANDLE hSocket = INVALID_HANDLE_VALUE;
193
194 #ifdef UNDER_CE
195 WCHAR x[1024];
196 #endif
197 // Check whether it is already a validated socket.
198 if ((HANDLE)soap->socket != INVALID_HANDLE_VALUE) // if (soap_valid_socket(soap->socket))
199 return SOAP_OK;
200
201 if (strncmp(endpoint, "file:", 5) || strlen(endpoint) < 7)
202 return SOAP_EOF;
203
204 #ifdef UNDER_CE
205 MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,endpoint+5+2,strlen(endpoint+5+2),x,1024);
206 #endif
207
208 for (int nRetry = 0; nRetry < 10; ++nRetry) {
209 #ifdef UNDER_CE
210 hSocket = CreateFileW(x, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
211 #else
212 hSocket = CreateFileA(endpoint+5+2, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
213 #endif
214 if (hSocket == INVALID_HANDLE_VALUE) {
215 if (GetLastError() != ERROR_PIPE_BUSY) {
216 return SOAP_EOF; // Could not open pipe
217 }
218
219 // All pipe instances are busy, so wait for 1 second.
220 if (!WaitNamedPipeA(endpoint+5+2, 1000)) {
221 if (GetLastError() != ERROR_PIPE_BUSY) {
222 return SOAP_EOF; // Could not open pipe
223 }
224 }
225 } else {
226 break;
227 }
228 }// for (...)
229
230 if (hSocket == INVALID_HANDLE_VALUE)
231 return SOAP_EOF;
232
233 #ifdef UNDER_CE
234 soap->sendfd = soap->recvfd = NULL;
235 #else
236 soap->sendfd = soap->recvfd = SOAP_INVALID_SOCKET;
237 #endif
238
239 soap->max_keep_alive = 0;
240 soap->socket = (int)hSocket;
241 soap->status = SOAP_POST;
242
243 //Override soap functions
244 soap->fpoll = gsoap_win_fpoll;
245 soap->fsend = gsoap_win_fsend;
246 soap->frecv = gsoap_win_frecv;
247 soap->fclose = gsoap_win_fclose;
248 soap->fshutdownsocket = gsoap_win_shutdownsocket;
249
250 // Unused
251 soap->faccept = NULL;
252 soap->fopen = NULL;
253
254 return SOAP_OK;
255 }
256 #endif
257102
258103 HRESULT CreateSoapTransport(ULONG ulUIFlags,
259104 const char *strServerPath,
1515 */
1616
1717 #include <kopano/platform.h>
18
18 #include <cstring>
1919 #include <mapidefs.h>
2020 #include <mapitags.h>
2121 #include <edkmdb.h>
2929 #include <kopano/base64.h>
3030
3131 using namespace std;
32
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #endif
3632
3733 /* See m4lcommon/Util.cpp for twcmp */
3834 template<typename T> static int twcmp(T a, T b)
659655 *lpCompareResult = nCompareResult;
660656 return er;
661657 }
662
663658
664659 /**
665660 * ulType is one of the RELOP_xx types. The result returned will indicate that at least one of the values in lpMVProp positively
12331228 return erSuccess;
12341229 }
12351230
1236
12371231 ECRESULT CopyRestrictTable(struct soap *soap,
12381232 const struct restrictTable *lpSrc, struct restrictTable **lppDst)
12391233 {
14421436 lpDst->__ptr[i].__ptr = s_alloc<unsigned char>(soap, lpSrc->__ptr[i].__size);
14431437 memcpy(lpDst->__ptr[i].__ptr, lpSrc->__ptr[i].__ptr, sizeof(unsigned char) * lpSrc->__ptr[i].__size);
14441438 }
1445
14461439
14471440 *lppDst = lpDst;
14481441 return erSuccess;
17581751 return KCERR_NOT_FOUND;
17591752
17601753 lpDst = new searchCriteria;
1754 memset(lpDst, '\0', sizeof(*lpDst));
17611755 if(lpSrc->lpRestrict) {
17621756 er = CopyRestrictTable(soap, lpSrc->lpRestrict, &lpDst->lpRestrict);
17631757 if (er != erSuccess)
17991793
18001794 return er;
18011795 }
1802
1803 ECRESULT CopyUserObjectDetailsToSoap(unsigned int ulId, entryId *lpUserEid, const objectdetails_t &details, struct soap *soap, struct userobject *lpObject)
1804 {
1805 ECRESULT er = erSuccess;
1806
1807 lpObject->ulId = ulId;
1808 lpObject->lpszName = s_strcpy(soap, details.GetPropString(OB_PROP_S_FULLNAME).c_str());
1809 lpObject->ulType = details.GetClass();
1810 lpObject->sId.__size = lpUserEid->__size;
1811 lpObject->sId.__ptr = s_alloc<unsigned char>(soap, lpUserEid->__size);
1812 memcpy(lpObject->sId.__ptr, lpUserEid->__ptr, lpUserEid->__size);
1813
1814 return er;
1815 }
1816
18171796
18181797 /**
18191798 * Copy extra user details into propmap, (only the string values)
8484 ECRESULT CopyRightsArrayToSoap(struct soap *soap, struct rightsArray *lpRightsArraySrc, struct rightsArray **lppRightsArrayDst);
8585
8686 // userobjects
87 ECRESULT CopyUserObjectDetailsToSoap(unsigned int ulId, entryId *lpUserEid, const objectdetails_t &details,
88 struct soap *soap, struct userobject *lpObject);
8987 ECRESULT CopyUserDetailsToSoap(unsigned int ulId, entryId *lpUserEid, const objectdetails_t &details, bool bCopyBinary,
9088 struct soap *soap, struct user *lpUser);
9189 ECRESULT CopyUserDetailsFromSoap(struct user *lpUser, std::string *lpstrExternId, objectdetails_t *details, struct soap *soap);
2020 #include <kopano/pcuser.hpp>
2121
2222 #include <sstream>
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
2723
2824 template<int(*fnCmp)(const char*, const char*)>
2925 class StringComparer {
228224 {
229225 const std::list<std::string> list = GetPropListString(propname);
230226 if (ignoreCase)
231 return std::find_if(list.begin(), list.end(), StringComparer<stricmp>(value)) != list.end();
227 return std::find_if(list.begin(), list.end(), StringComparer<strcasecmp>(value)) != list.end();
232228 return std::find_if(list.begin(), list.end(), StringComparer<strcmp>(value)) != list.end();
233229 }
234230
2424 #include <mapidefs.h>
2525 #include <kopano/ECGuid.h>
2626 #include "versions.h"
27
28 #ifdef _DEBUG
29 #define new DEBUG_NEW
30 #endif
3127
3228 bool IsKopanoEntryId(ULONG cb, LPBYTE lpEntryId)
3329 {
+0
-36
provider/contacts/Makefile.am less more
0 # -*- Makefile -*-
1
2 pkglib_LTLIBRARIES = libkccontacts.la
3 noinst_DATA = libkccontacts.ldd
4
5 sysconf_configdir = ${MAPICONFIGDIR}
6 dist_sysconf_config_DATA = zcontacts.inf
7
8 sampleconfdir = ${docdir}/example-config
9 sampleconf_DATA = zcontacts.inf
10
11 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) \
12 -I${top_srcdir}/provider/include \
13 -I${top_srcdir}/provider/common \
14 -I${top_srcdir}/provider/client \
15 -I${top_srcdir}/mapi4linux/include \
16 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon
17
18 libkccontacts_la_LDFLAGS = ${AM_LDFLAGS} -avoid-version -module
19 libkccontacts_la_LIBADD = \
20 ${top_builddir}/common/libkcutil.la \
21 ${top_builddir}/common/libkcmapi.la \
22 ${top_builddir}/mapi4linux/src/libmapi.la \
23 -lstdc++ $(UUID_LIBS) $(ICU_LIBS)
24
25 libkccontacts_la_SOURCES = epcontact.cpp ZCABData.h \
26 ZCMAPIProp.h ZCMAPIProp.cpp \
27 ZCABProvider.h ZCABProvider.cpp \
28 ZCABLogon.h ZCABLogon.cpp \
29 ZCABContainer.h ZCABContainer.cpp
30
31 check-syntax:
32 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
33 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
34
35 include ../../global.am
3838 #include <kopano/stringutil.h>
3939 using namespace std;
4040
41 #ifdef _DEBUG
42 #define new DEBUG_NEW
43 #endif
44
4541 ZCABContainer::ZCABContainer(std::vector<zcabFolderEntry> *lpFolders,
4642 IMAPIFolder *lpContacts, LPMAPISUP lpMAPISup, void *lpProvider,
4743 const char *szClassName) :
269265 {(LPGUID)&PSETID_Address, MNID_ID, {dispidABPArrayType}},
270266 };
271267
272
273268 ulFlags = ulFlags & MAPI_UNICODE;
274269
275270 hr = Util::HrCopyUnicodePropTagArray(ulFlags, (LPSPropTagArray)&inputCols, &ptrInputCols);
381376
382377 if (
383378 ((ulFlags & MAPI_UNICODE) && wcscasecmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszW, L"IPM.Contact") == 0) ||
384 ((ulFlags & MAPI_UNICODE) == 0 && stricmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszA, "IPM.Contact") == 0)
379 ((ulFlags & MAPI_UNICODE) == 0 && strcasecmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszA, "IPM.Contact") == 0)
385380 )
386381 {
387382 lpColData[O_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
394389 lpColData[O_ADDRTYPE].Value = ptrRows[i].lpProps[I_NAMEDSTART + ulOffset + 1].Value;
395390 } else if (
396391 ((ulFlags & MAPI_UNICODE) && wcscasecmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszW, L"IPM.DistList") == 0) ||
397 ((ulFlags & MAPI_UNICODE) == 0 && stricmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszA, "IPM.DistList") == 0)
392 ((ulFlags & MAPI_UNICODE) == 0 && strcasecmp(ptrRows[i].lpProps[I_MESSAGE_CLASS].Value.lpszA, "IPM.DistList") == 0)
398393 )
399394 {
400395 lpColData[O_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
547542 if (hr != hrSuccess)
548543 goto exit;
549544
550
551545 sKey.ulPropTag = PR_ROWID;
552546 sKey.Value.ul = 0;
553547 for (ULONG i = 0; i < ptrEntries->Value.MVbin.cValues; ++i) {
557551 // Wrapped entryid's:
558552 // Flags: (ULONG) 0
559553 // Provider: (GUID) 0xC091ADD3519DCF11A4A900AA0047FAA4
560 // Type: (BYTE) <value>, describes wrapped enrtyid
554 // Type: (BYTE) <value>, describes wrapped entryid
561555 // lower 4 bits:
562556 // 0x00 = OneOff (use addressbook)
563557 // 0x03 = Contact (use folder / session?)
648642 return hr;
649643 }
650644
651
652645 /**
653646 * Returns an addressbook contents table of the IPM.Contacts folder in m_lpContactFolder.
654647 *
11151108 ptrColumns->cValues = stProps.size();
11161109 std::copy(stProps.begin(), stProps.end(), ptrColumns->aulPropTag);
11171110
1118
11191111 hr = this->GetContentsTable(ulFlags & MAPI_UNICODE, &ptrContents);
11201112 if (hr != hrSuccess)
11211113 goto exit;
2525 #include "kcore.hpp"
2626 #include <mapix.h>
2727 #include <edkmdb.h>
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3228
3329 ZCABLogon::ZCABLogon(LPMAPISUP lpMAPISup, ULONG ulProfileFlags, GUID *lpGUID) : ECUnknown("IABLogon")
3430 {
333329 return hr;
334330 }
335331
336
337332 HRESULT ZCABLogon::xABLogon::QueryInterface(REFIID refiid, void ** lppInterface)
338333 {
339334 TRACE_MAPI(TRACE_ENTRY, "IABLogon::QueryInterface", "%s", DBGGUIDToString(refiid).c_str());
2929 #include <kopano/namedprops.h>
3030 #include <kopano/mapiguidext.h>
3131
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #endif
35
3632 ZCMAPIProp::ZCMAPIProp(ULONG ulObjType, const char *szClassName) :
3733 ECUnknown(szClassName), m_ulObject(ulObjType)
3834 {
391387 return hr;
392388 }
393389
394
395390 /**
396391 * return property data of this object
397392 *
2121 #include <kopano/Trace.h>
2222
2323 #include "ZCABProvider.h"
24
25 #ifdef _DEBUG
26 #define new DEBUG_NEW
27 #endif
2824
2925 extern "C" MSGSERVICEENTRY __stdcall MSGServiceEntry;
3026
6460 if (lppMapiError)
6561 *lppMapiError = NULL;
6662
67
6863 TRACE_MAPI(TRACE_RETURN, "MSGServiceEntry", "%s", GetMAPIErrorDescription(hr).c_str());
6964 return hr;
7065 }
3232 #include "ECSession.h"
3333 #include "ECSessionManager.h"
3434 #include <kopano/stringutil.h>
35
36 #ifdef _DEBUG
37 #define new DEBUG_NEW
38 #endif
3935
4036 ECABObjectTable::ECABObjectTable(ECSession *lpSession, unsigned int ulABId, unsigned int ulABType, unsigned int ulABParentId, unsigned int ulABParentType, unsigned int ulFlags, const ECLocale &locale) : ECGenericObjectTable(lpSession, ulABType, ulFlags, locale)
4137 {
138134
139135 pthread_mutex_unlock(&m_hLock);
140136
141
142137 return er;
143138 }
144139
145140 ECRESULT ECABObjectTable::ReloadTableMVData(ECObjectTableList* lplistRows, ECListInt* lplistMVPropTag)
146141 {
147142 ECRESULT er = erSuccess;
148 ECListIntIterator iterListMVPropTag;
149
150 ECObjectTableList::const_iterator iterListRows;
151143
152144 ASSERT(lplistMVPropTag->size() <2); //FIXME: Limit of one 1 MV column
153145
158150 return er;
159151 }
160152
161
162153 ECRESULT ECABObjectTable::GetMVRowCount(unsigned int ulObjId, unsigned int *lpulCount)
163154 {
164155 ECRESULT er = erSuccess;
165 ECObjectTableList listRows;
166 ECObjectTableList::const_iterator iterListRows;
167 ECObjectTableMap::const_iterator iterIDs;
168
169 ECListInt::const_iterator iterListMVPropTag;
170156
171157 pthread_mutex_lock(&m_hLock);
172158
122122 }
123123 if (ans != NULL && strcmp(ans, "files") == 0) {
124124 const char *const sync_files_par = lpConfig->GetSetting("attachment_files_fsync");
125 bool sync_files = sync_files_par == NULL || strcmp_ci(sync_files_par, "yes") == 0;
125 bool sync_files = sync_files_par == NULL || strcasecmp(sync_files_par, "yes") == 0;
126126 const char *comp = lpConfig->GetSetting("attachment_compression");
127127 unsigned int complvl = (comp == NULL) ? 0 : strtoul(comp, NULL, 0);
128128
129129 lpAttachmentStorage = new ECFileAttachment(lpDatabase, dir, complvl, sync_files);
130130 #ifdef HAVE_LIBS3_H
131131 } else if (ans != NULL && strcmp(ans, "s3") == 0) {
132 lpAttachmentStorage = new ECS3Attachment(lpDatabase,
132 try {
133 lpAttachmentStorage = new ECS3Attachment(lpDatabase,
133134 lpConfig->GetSetting("attachment_s3_protocol"),
134135 lpConfig->GetSetting("attachment_s3_uristyle"),
135136 lpConfig->GetSetting("attachment_s3_accesskeyid"),
137138 lpConfig->GetSetting("attachment_s3_bucketname"),
138139 lpConfig->GetSetting("attachment_path"),
139140 strtol(lpConfig->GetSetting("attachment_compression"), NULL, 0));
141 } catch (std::runtime_error &e) {
142 ec_log_warn("Cannot instantiate ECS3Attachment: %s", e.what());
143 return KCERR_DATABASE_ERROR;
144 }
140145 #endif
141146 } else {
142147 lpAttachmentStorage = new ECDatabaseAttachment(lpDatabase);
11891194 return erSuccess;
11901195 }
11911196
1192
11931197 // Attachment storage is in separate files
11941198 ECFileAttachment::ECFileAttachment(ECDatabase *lpDatabase,
11951199 const std::string &basepath, unsigned int ulCompressionLevel,
3030 #include <kopano/stringutil.h>
3131 #include "ECGenericObjectTable.h"
3232 #include <kopano/threadutil.h>
33
34 #ifdef _DEBUG
35 #define new DEBUG_NEW
36 #endif
3733
3834 #include <algorithm>
3935
652648 memcpy(&guid, lpDBRow[1], sizeof(GUID));
653649 ulType = atoi(lpDBRow[2]);
654650
655
656651 } else {
657652 // We have a parent, get the store for our parent by recursively calling ourselves
658653 er = GetStoreAndType(ulSubObjId, &ulStore, &guid, &ulType, maxdepth-1);
980975 return m_UserObjectCache.AddCacheItem(ulUserId, sData);
981976 }
982977
983
984978 ECRESULT ECCacheManager::_GetUserObject(unsigned int ulUserId, objectclass_t* lpulClass, unsigned int *lpulCompanyId,
985979 std::string* lpstrExternId, std::string* lpstrSignature)
986980 {
13331327
13341328 void ECCacheManager::ForEachCacheItem(void(callback)(const std::string &, const std::string &, const std::string &, void*), void *obj)
13351329 {
1336 string value;
1337
13381330 pthread_mutex_lock(&m_hCacheMutex);
13391331
13401332 m_ObjectsCache.RequestStats(callback, obj);
13491341
13501342 pthread_mutex_unlock(&m_hCacheMutex);
13511343
1352
13531344 pthread_mutex_lock(&m_hCacheCellsMutex);
13541345
13551346 m_CellCache.RequestStats(callback, obj);
13561347
13571348 pthread_mutex_unlock(&m_hCacheCellsMutex);
1358
13591349
13601350 pthread_mutex_lock(&m_hCacheIndPropMutex);
13611351
13811371 m_ServerDetailsCache.DumpStats();
13821372 pthread_mutex_unlock(&m_hCacheMutex);
13831373
1384
13851374 pthread_mutex_lock(&m_hCacheCellsMutex);
13861375 m_CellCache.DumpStats();
13871376 pthread_mutex_unlock(&m_hCacheCellsMutex);
1388
13891377
13901378 pthread_mutex_lock(&m_hCacheIndPropMutex);
13911379 m_PropToObjectCache.DumpStats();
16071595 {
16081596 ECRESULT er = erSuccess;
16091597 ECsIndexObject sObjectKeyLower, sObjectKeyUpper;
1610 ECMapObjectToProp::const_iterator iter, iDel;
16111598 ECMapPropToObject::const_iterator iterPropToObj;
16121599
16131600 std::list<ECMapObjectToProp::value_type> lstItems;
16291616
16301617 return er;
16311618 }
1632
16331619
16341620 ECRESULT ECCacheManager::RemoveIndexData(unsigned int ulPropTag, unsigned int cbData, unsigned char *lpData)
16351621 {
20292015 if(bPartialCompletion)
20302016 er = KCWARN_PARTIAL_COMPLETION;
20312017
2032
20332018 return er;
20342019 }
20352020
2626 #include "ECSession.h"
2727 #include "ECMAPI.h"
2828 #include <kopano/stringutil.h>
29
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
3329
3430 ECConvenientDepthABObjectTable::ECConvenientDepthABObjectTable(ECSession *lpSession, unsigned int ulABId, unsigned int ulABType, unsigned int ulABParentId, unsigned int ulABParentType, unsigned int ulFlags, const ECLocale &locale) : ECABObjectTable(lpSession, ulABId, ulABType, ulABParentId, ulABParentType, ulFlags, locale) {
3531 m_lpfnQueryRowData = ECConvenientDepthABObjectTable::QueryRowData;
8379 }
8480 return erSuccess;
8581 }
86
8782
8883 /*
8984 * Loads an entire multi-depth hierarchy table recursively.
2727 #include <kopano/stringutil.h>
2828
2929 #include <list>
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
3430
3531 ECConvenientDepthObjectTable::ECConvenientDepthObjectTable(ECSession *lpSession, unsigned int ulStoreId, LPGUID lpGuid, unsigned int ulFolderId, unsigned int ulObjType, unsigned int ulFlags, const ECLocale &locale) : ECStoreObjectTable(lpSession, ulStoreId, lpGuid, 0, ulObjType, ulFlags, 0, locale) {
3632 m_ulFolderId = ulFolderId;
2727
2828 using namespace std;
2929
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
33
3430 // Convert search criteria from zarafa-5.2x to zarafa-6 format
3531 ECRESULT ConvertSearchCriteria52XTo6XX(ECDatabase *lpDatabase, char* lpData, struct searchCriteria **lppNewSearchCriteria)
3632 {
110106 er = lpDatabase->DoSelect(strQuery, &lpDBResult);
111107 if(er != erSuccess)
112108 goto exit;
113
114109
115110 while ((lpDBRow = lpDatabase->FetchRow(lpDBResult)))
116111 {
2121
2222 #include "ECServerEntrypoint.h"
2323
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
27
2824 // The ECDatabaseFactory creates database objects connected to the server database. Which
2925 // database is returned is chosen by the database_engine configuration setting.
3026
3733 {
3834 const char *szEngine = m_lpConfig->GetSetting("database_engine");
3935
40 if(stricmp(szEngine, "mysql") == 0) {
36 if(strcasecmp(szEngine, "mysql") == 0) {
4137 *lppDatabase = new ECDatabaseMySQL(m_lpConfig);
4238 } else {
4339 ec_log_crit("ECDatabaseFactory::GetDatabaseFactory(): database not mysql");
4343
4444 using namespace std;
4545
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
4946 #ifdef DEBUG
5047 #define DEBUG_SQL 0
5148 #define DEBUG_TRANSACTION 0
252249 " FROM mvproperties JOIN hierarchy ON mvproperties.hierarchyid=hierarchy.id LEFT JOIN names ON (mvproperties.tag-0x8501)=names.id WHERE hierarchy.parent=hid AND (tag <= 0x8500 OR names.id IS NOT NULL) GROUP BY tag, mvproperties.type; \n"
253250 "END;\n";
254251
255
256252 static const char szGetBestBody[] =
257253 "CREATE PROCEDURE GetBestBody(hid integer, OUT bestbody integer)\n"
258254 "DETERMINISTIC\n"
11561152 cbFields = mysql_field_count(&m_lpMySQL);
11571153
11581154 for (unsigned int i = 0; i < cbFields && ulIndex == (unsigned int)-1; ++i)
1159 if (stricmp(lpFields[i].name, strFieldname.c_str()) == 0)
1155 if (strcasecmp(lpFields[i].name, strFieldname.c_str()) == 0)
11601156 ulIndex = i;
11611157
11621158 return ulIndex;
13741370 }
13751371
13761372 while ((lpDBRow = FetchRow(lpResult)) != NULL) {
1377 if (stricmp(lpDBRow[0], "InnoDB") != 0)
1373 if (strcasecmp(lpDBRow[0], "InnoDB") != 0)
13781374 continue;
13791375
1380 if (stricmp(lpDBRow[1], "DISABLED") == 0) {
1376 if (strcasecmp(lpDBRow[1], "DISABLED") == 0) {
13811377 // mysql has run with innodb enabled once, but disabled this.. so check your log.
13821378 ec_log_crit("INNODB engine is disabled. Please re-enable the INNODB engine. Check your MySQL log for more information or comment out skip-innodb in the mysql configuration file.");
13831379 er = KCERR_DATABASE_ERROR;
13841380 goto exit;
1385 } else if (stricmp(lpDBRow[1], "YES") != 0 && stricmp(lpDBRow[1], "DEFAULT") != 0) {
1381 } else if (strcasecmp(lpDBRow[1], "YES") != 0 && strcasecmp(lpDBRow[1], "DEFAULT") != 0) {
13861382 // mysql is incorrectly configured or compiled.
13871383 ec_log_crit("INNODB engine is not supported. Please enable the INNODB engine in the mysql configuration file.");
13881384 er = KCERR_DATABASE_ERROR;
15851581 er = KCERR_UNKNOWN_DATABASE;
15861582
15871583 while (lpDBRow != NULL) {
1588 if (lpDBRow[0] != NULL && stricmp(lpDBRow[0], "storeid") == 0) {
1584 if (lpDBRow[0] != NULL && strcasecmp(lpDBRow[0], "storeid") == 0) {
15891585 dbv->v_major = 5;
15901586 dbv->v_minor = 0;
15911587 dbv->v_rev = 0;
16621658 *lpulDatabaseRevision = 0;
16631659 }else
16641660 *lpulDatabaseRevision = atoui(lpDBRow[0]);
1665
16661661
16671662 exit:
16681663 if (lpResult != NULL)
273273 DB_RESULT lpResult = NULL;
274274 DB_ROW lpDBRow = NULL;
275275 DB_LENGTHS lpDBLenths = NULL;
276
277276
278277 strQuery = "SELECT `value` FROM `settings` WHERE `name` = 'server_guid'";
279278 er = lpDatabase->DoSelect(strQuery, &lpResult);
875874 lpResult = NULL;
876875 }
877876
878
879877 exit:
880878 if(lpResult)
881879 lpDatabase->FreeResult(lpResult);
920918 if (er != erSuccess)
921919 goto exit;
922920
923
924921 // Create the new objectproperty table.
925922 strQuery = Z_TABLEDEF_OBJECT_PROPERTY;
926923 strQuery.replace(strQuery.find("objectproperty"), 14, "objectproperty_temp");
928925 if (er != erSuccess)
929926 goto exit;
930927
931
932928 // Create the new objectrelation table.
933929 strQuery = Z_TABLEDEF_OBJECT_RELATION;
934930 strQuery.replace(strQuery.find("objectrelation"), 14, "objectrelation_temp");
936932 if (er != erSuccess)
937933 goto exit;
938934
939
940935 // Create a list of all current objects from the object table.
941936 strQuery = "SELECT id, objecttype FROM object ORDER BY objecttype";
942937 er = lpDatabase->DoSelect(strQuery, &lpResult);
955950
956951 lpDatabase->FreeResult(lpResult);
957952 lpResult = NULL;
958
959953
960954 // Recreate the objects in the object_temp table and on the fly create the queries to regenerate
961955 // their properties in the objectpropert_temp table.
10211015 if (er != erSuccess)
10221016 goto exit;
10231017 }
1024
10251018
10261019 // Now repopulate the objectrelation table.
10271020 strQuery = "SELECT objectid, parentobjectid, relationtype FROM objectrelation";
11071100 goto exit;
11081101 }
11091102
1110
1111
11121103 // Now delete the old tables and rename the new ones
11131104 er = lpDatabase->DoDelete("DROP TABLE object, objectproperty, objectrelation");
11141105 if (er != erSuccess)
12231214 if (er != erSuccess)
12241215 goto exit;
12251216 }
1226
12271217
12281218 // Remove the extracted changes from the changes table
12291219 strQuery = "DELETE FROM changes WHERE id IN (";
15231513 if (lpDBRow[0] == NULL || lpDBRow[1] == NULL || lpDBRow[2] == NULL)
15241514 continue;
15251515
1526 if(stricmp(lpDBRow[2], "hi") == 0) {
1516 if(strcasecmp(lpDBRow[2], "hi") == 0) {
15271517 bUpdate = true;
15281518 break;
15291519 }
20542044 ECRESULT UpdateDatabaseCreateDeferred(ECDatabase *lpDatabase)
20552045 {
20562046 ECRESULT er = erSuccess;
2057 std::string strQuery;
20582047 // Create the deferred table
20592048 er = lpDatabase->DoInsert(Z_TABLEDEF_DELAYEDUPDATE);
20602049 return er;
3131 #include <pthread.h>
3232 #include <string>
3333
34 #ifdef _DEBUG
35 #define new DEBUG_NEW
36 #endif
37
3834 ECRESULT GetPropSize(DB_ROW lpRow, DB_LENGTHS lpLen, unsigned int *lpulSize)
3935 {
4036 ECRESULT er = erSuccess;
7369 return er;
7470 }
7571
76
7772 // Case insensitive find
7873 static size_t
7974 ci_find_substr(const std::string &first, const std::string &second)
364359 default:
365360 return KCERR_INVALID_TYPE;
366361 }
367 return erSuccess;
368 }
369 // by table
370
371 ECRESULT ParseMVPropCount(const char *lpRowData, ULONG ulSize,
372 unsigned int *lpulLastPos, int *lpnItemCount)
373 {
374 ULONG ulPos = *lpulLastPos;
375 ULONG ulIter = ulPos;
376 std::string strSize;
377
378 ASSERT(ulPos < ulSize);
379
380 while(ulIter < ulSize && lpRowData[ulIter] != ':')
381 ++ulIter;
382
383 strSize.insert(0, lpRowData+ulPos, ulIter - ulPos);
384
385 *lpnItemCount = atoi(strSize.c_str());
386 *lpulLastPos = (ulIter+1);
387
388362 return erSuccess;
389363 }
390364
569543 goto exit;
570544 }
571545 lpPropVal->__union = SOAP_UNION_propValData_li;
572 lpPropVal->Value.li = _atoi64(lpRow[FIELD_NR_LONGINT]);
546 lpPropVal->Value.li = atoll(lpRow[FIELD_NR_LONGINT]);
573547 break;
574548 case PT_STRING8:
575549 case PT_UNICODE:
734708 ulLastPos = 0;
735709 for (gsoap_size_t i = 0; i < lpPropVal->Value.mvli.__size; ++i) {
736710 ParseMVProp(lpRow[FIELD_NR_LONGINT], lpLen[FIELD_NR_LONGINT], &ulLastPos, &strData);
737 lpPropVal->Value.mvli.__ptr[i] = _atoi64(strData.c_str());
711 lpPropVal->Value.mvli.__ptr[i] = atoll(strData.c_str());
738712 }
739713 break;
740714 default:
748722 freelocale(loc);
749723 return er;
750724 }
751
752725
753726 unsigned int NormalizeDBPropTag(unsigned int ulPropTag)
754727 {
7979 ECRESULT CopySOAPPropValToDatabaseMVPropVal(struct propVal *lpPropVal, int nItem, std::string &strColName, std::string &strColData, ECDatabase *lpDatabase);
8080
8181 ECRESULT ParseMVProp(const char *lpRowData, ULONG ulSize, unsigned int *lpulLastPos, std::string *lpstrData);
82 ECRESULT ParseMVPropCount(const char *lpRowData, ULONG ulSize, unsigned int *lpulLastPos, int *lpnItemCount);
8382
8483 unsigned int NormalizeDBPropTag(unsigned int ulPropTag);
8584 bool CompareDBPropTag(unsigned int ulPropTag1, unsigned int ulPropTag2);
3737
3838 #include <edkmdb.h>
3939 #include <kopano/mapiext.h>
40
41 #ifdef _DEBUG
42 #define new DEBUG_NEW
43 #endif
4440
4541 #define _(string) dcgettext("kopano", string, LC_MESSAGES)
4642
294290 ECRESULT ECGenProps::GetPropComputed(struct soap *soap, unsigned int ulObjType, unsigned int ulPropTagRequested, unsigned int ulObjId, struct propVal *lpPropVal)
295291 {
296292 ECRESULT er = erSuccess;
297 char* lpszColon = NULL;
298293
299294 switch(PROP_ID(ulPropTagRequested)) {
300295 case PROP_ID(PR_MSG_STATUS):
334329 } else {
335330 lpPropVal->ulPropTag = ulPropTagRequested;
336331 // Check for RE, FWD and similar muck at the start of the subject line
337 lpszColon = strchr(lpPropVal->Value.lpszA, ':');
332 const char *lpszColon = strchr(lpPropVal->Value.lpszA, ':');
338333 if (lpszColon != NULL && (lpszColon - lpPropVal->Value.lpszA) > 1 && (lpszColon - lpPropVal->Value.lpszA) < 4)
339334 {
340335 char* c = lpPropVal->Value.lpszA;
859854 if (lpDatabase->GetNumRows(lpDBResult) == 0)
860855 bIsOrphan = true;
861856
862
863857 *lpbIsOrphan = bIsOrphan;
864858
865859 exit:
4646 #include <kopano/mapiext.h>
4747
4848 #include <sys/types.h>
49 #ifdef LINUX
49 #if 1 /* change to HAVE_REGEX_H */
5050 #include <regex.h>
5151 #endif
5252
6767
6868 #include "ECSession.h"
6969
70 struct sortOrderArray sDefaultSortOrder{__gszeroinit};
71
72 #ifdef _DEBUG
73 #define new DEBUG_NEW
74 #endif
75
76 ULONG sANRProps[] = { PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_ACCOUNT, PR_DEPARTMENT_NAME, PR_OFFICE_TELEPHONE_NUMBER, PR_OFFICE_LOCATION, PR_PRIMARY_FAX_NUMBER, PR_SURNAME};
70 static struct sortOrderArray sDefaultSortOrder{__gszeroinit};
71 static const ULONG sANRProps[] = {
72 PR_DISPLAY_NAME, PR_SMTP_ADDRESS, PR_ACCOUNT, PR_DEPARTMENT_NAME,
73 PR_OFFICE_TELEPHONE_NUMBER, PR_OFFICE_LOCATION, PR_PRIMARY_FAX_NUMBER,
74 PR_SURNAME
75 };
7776
7877 #define ISMINMAX(x) ((x) == EC_TABLE_SORT_CATEG_MIN || (x) == EC_TABLE_SORT_CATEG_MAX)
7978
117116
118117 return fMatch;
119118 }
120
121
122119
123120 /**
124121 * Constructor of the Generic Object Table
631628 ECObjectTableMap::const_iterator iterObjects;
632629
633630 pthread_mutex_lock(&m_hLock);
634
635631
636632 if(ulFlags & TBL_ALL_COLUMNS) {
637633 // All columns were requested. Simply get a unique list of all the proptags used in all the objects in this table
19811977 unsigned int ulSearchStringSize;
19821978 ULONG ulPropType;
19831979 ULONG ulFuzzyLevel;
1984 unsigned int ulScan, ulPos;
19851980 unsigned int ulSubRestrict = 0;
19861981 SUBRESTRICTIONRESULT::const_iterator iterSubResult;
19871982 entryId sEntryId;
20762071 fMatch = false;
20772072 break;
20782073 } else {
2079 ulScan = 1;
2074 unsigned int ulScan = 1;
20802075 if(ulPropTagRestrict & MV_FLAG)
20812076 {
20822077 if(PROP_TYPE(ulPropTagRestrict) == PT_MV_TSTRING)
20992094 // Default match is false
21002095 fMatch = false;
21012096
2102 for (ulPos = 0; ulPos < ulScan; ++ulPos) {
2097 for (unsigned int ulPos = 0; ulPos < ulScan; ++ulPos) {
21032098 if(ulPropTagRestrict & MV_FLAG)
21042099 {
21052100 if(PROP_TYPE(ulPropTagRestrict) == PT_MV_TSTRING) {
21572152
21582153 if(fMatch)
21592154 break;
2160 } // for (ulPos = 0; ulPos < ulScan; ++ulPos)
2155 }
21612156 }
21622157 break;
21632158
21812176 if((PROP_TYPE(ulPropTagRestrict) & ~MV_FLAG) != PROP_TYPE(ulPropTagValue))
21822177 // cannot compare two different types, except mvprop -> prop
21832178 return KCERR_INVALID_TYPE;
2184 #ifdef LINUX
2179 #if 1 /* HAVE_REGEX_H */
21852180 if(lpsRestrict->lpProp->ulType == RELOP_RE) {
21862181 regex_t reg;
21872182
34123407 return erSuccess;
34133408 }
34143409
3415
34163410 void ECCategory::DecUnread() {
34173411 --m_ulUnread;
34183412 }
34293423 size_t ECCategory::GetObjectSize(void) const
34303424 {
34313425 size_t ulSize = 0;
3432 unsigned int i;
34333426
34343427 if (m_cProps > 0) {
34353428 ulSize += sizeof(struct propVal) * m_cProps;
3436
3437 for (i = 0; i < m_cProps; ++i)
3429 for (unsigned int i = 0; i < m_cProps; ++i)
34383430 ulSize += PropSize(&m_lpProps[i]);
34393431 }
34403432
3535 #include "soapH.h"
3636 #include "SOAPUtils.h"
3737
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #endif
41
4238 extern ECSessionManager* g_lpSessionManager;
4339
4440 struct ABChangeRecord {
5753 , change_type(_change_type)
5854 { }
5955
60
6156 typedef std::list<ABChangeRecord> ABChangeRecordList;
62
6357
6458 static bool isICSChange(unsigned int ulChange)
6559 {
618612 // CHeck if the client understands the new ABEID.
619613 if ((lpSession->GetCapabilities() & KOPANO_CAP_MULTI_SERVER) == KOPANO_CAP_MULTI_SERVER)
620614 bAcceptABEID = true;
621
622615
623616 if(ulChangeType != ICS_SYNC_AB) {
624617 // You must first register your sync via setSyncStatus()
127127 * The source key of the message.
128128 * @param[in] sParentSourceKey
129129 * THe source key of the folder containing the message.
130 *
131 * @return HRESULT
132130 */
133131 ECRESULT AddToLastSyncedMessagesSet(ECDatabase *lpDatabase, unsigned int ulSyncId, const SOURCEKEY &sSourceKey, const SOURCEKEY &sParentSourceKey);
134132
3434 #include <kopano/ECLogger.h>
3535 extern ECLogger* g_lpLogger;
3636
37 #ifdef _DEBUG
38 #define new DEBUG_NEW
39 #endif
40
4137 extern ECSessionManager* g_lpSessionManager;
42
43
4438
4539 /**
4640 * IDbQueryCreator: Interface to the database query creators
5145 virtual ~IDbQueryCreator() {};
5246 virtual std::string CreateQuery() = 0;
5347 };
54
5548
5649 /**
5750 * CommonQueryCreator: Abstract implementation of IDBQueryCreator that handles the
9487
9588 return strQuery;
9689 }
97
9890
9991 /**
10092 * IncrementalQueryCreator: Creates an incremental query. In other words only messages
161153 return " ORDER BY changes.id";
162154 }
163155
164
165156 /**
166157 * FullQueryCreator: Create a query that will return all messages for a sync id. The
167158 * messages need to be processed afterwards to see what needs to be
214205 return " ORDER BY hierarchy.id DESC";
215206 }
216207
217
218208 /**
219209 * NullQueryCreator: Returns no query at all. This is only used for SYNC_CATCHUP syncs that
220210 * do not have a restriction set. (When a restriction is set, we still need to generate the message set
254244 virtual ECRESULT GetResidualMessages(LPMESSAGESET lpsetResiduals) = 0;
255245 virtual unsigned int GetMaxChangeId() const = 0;
256246 };
257
258247
259248 /**
260249 * NonLegacyIncrementalProcessor: Processes accepted and rejected messages without the burden of tracking
912901 if (m_lpsRestrict && m_setNewMessages.empty())
913902 m_setNewMessages.insert(MESSAGESET::value_type(SOURCEKEY(1, "\x00"), SAuxMessageData(m_sFolderSourceKey, 0, 0)));
914903
915
916904 if (!m_setNewMessages.empty()) {
917905 std::set<unsigned int> setChangeIds;
918906
2020 #include <kopano/threadutil.h>
2121
2222 #include <boost/utility.hpp>
23
24 #ifdef _DEBUG
25 #define new DEBUG_NEW
26 #endif
2723
2824 using namespace std;
2925
2727 #include <kopano/stringutil.h>
2828
2929 #include "ECMailBoxTable.h"
30
31 #ifdef _DEBUG
32 #define new DEBUG_NEW
33 #endif
3430
3531 ECMailBoxTable::ECMailBoxTable(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale) :
3632 ECStoreObjectTable(lpSession, 0, NULL, 0, MAPI_STORE, ulFlags, TABLE_FLAG_OVERRIDE_HOME_MDB, locale)
2525 #include "ECSession.h"
2626 #include "ECMAPI.h"
2727 #include <kopano/stringutil.h>
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3228
3329 ECMultiStoreTable::ECMultiStoreTable(ECSession *lpSession, unsigned int ulObjType, unsigned int ulFlags, const ECLocale &locale) : ECStoreObjectTable(lpSession, 0, NULL, 0, ulObjType, ulFlags, 0, locale) {
3430 }
1717 #include "ECNotification.h"
1818 #include "ECMAPI.h"
1919 #include "SOAPUtils.h"
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
2420
2521 ECNotification::ECNotification()
2622 {
162162
163163 return hrSuccess;
164164 }
165
166165
167166 void * ECNotificationManager::Thread(void *lpParam)
168167 {
2626 #include <kopano/ECLogger.h>
2727 #include <kopano/ecversion.h>
2828
29 #ifdef EMBEDDED_USERPLUGIN
30 #include "DBUserPlugin.h"
31 #endif
32
33 #ifdef _DEBUG
34 #define new DEBUG_NEW
35 #endif
36
3729 ECPluginFactory::ECPluginFactory(ECConfig *config, ECStatsCollector *lpStatsCollector,
3830 bool bHosted, bool bDistributed)
3931 {
5951 ECRESULT ECPluginFactory::CreateUserPlugin(UserPlugin **lppPlugin) {
6052 UserPlugin *lpPlugin = NULL;
6153
62 #ifdef EMBEDDED_USERPLUGIN
63 m_getUserPluginInstance = (UserPlugin* (*)(pthread_mutex_t*, ECPluginSharedData *)) getUserPluginInstance;
64 #else
6554 if(m_dl == NULL) {
6655 const char *pluginpath = m_config->GetSetting("plugin_path");
6756 const char *pluginname = m_config->GetSetting("user_plugin");
11099 goto out;
111100 }
112101 }
113 #endif
114102 try {
115103 lpPlugin = m_getUserPluginInstance(&m_plugin_lock, m_shareddata);
116104 lpPlugin->InitPlugin();
137137
138138 void ECPluginSharedData::Signal(int signal)
139139 {
140 #ifdef LINUX
141140 if (!m_lpConfig)
142141 return;
143142
154153 default:
155154 break;
156155 }
157 #endif
158156 }
159157
11 #ifdef HAVE_LIBS3_H
22 #include <kopano/platform.h>
33 #include <algorithm>
4 #include <mutex>
5 #include <stdexcept>
46 #include <cerrno>
57 #include <pthread.h>
68 #include <unistd.h>
3840 void *cbdata;
3941 };
4042
43 static void *ec_libs3_handle;
44 #define W(n) static decltype(S3_ ## n) *DY_ ## n;
45 W(put_object)
46 W(initialize)
47 W(status_is_retryable)
48 W(deinitialize)
49 W(get_status_name)
50 W(head_object)
51 W(delete_object)
52 W(get_object)
53 #undef W
54
4155 /**
4256 * Static function used to forward the response properties callback to the
4357 * right object.
100114 ECRESULT ECS3Attachment::StaticInit(ECConfig *cf)
101115 {
102116 ec_log_info("Initializing S3 Attachment Storage");
103 S3Status status = S3_initialize("Kopano Mail", S3_INIT_ALL, cf->GetSetting("attachment_s3_hostname"));
117
118 /*
119 * Do a dlopen of libs3.so.2 so that the implicit pull-in of
120 * libldap-2.4.so.2 symbols does not pollute our namespace of
121 * libldap_r-2.4.so.2 symbols.
122 */
123 void *h = ec_libs3_handle = dlopen("libs3.so.2", RTLD_LAZY | RTLD_LOCAL);
124 const char *err;
125 if (ec_libs3_handle == NULL) {
126 ec_log_warn("dlopen libs3.so.2: %s", (err = dlerror()) ? err : "<none>");
127 return KCERR_DATABASE_ERROR;
128 }
129 #define W(n) do { \
130 DY_ ## n = reinterpret_cast<decltype(DY_ ## n)>(dlsym(h, "S3_" #n)); \
131 if (DY_ ## n == NULL) { \
132 ec_log_warn("dlsym S3_" #n ": %s", (err = dlerror()) ? err : "<none>"); \
133 dlclose(h); \
134 ec_libs3_handle = NULL; \
135 return KCERR_DATABASE_ERROR; \
136 } \
137 } while (false)
138
139 W(put_object);
140 W(initialize);
141 W(status_is_retryable);
142 W(deinitialize);
143 W(get_status_name);
144 W(head_object);
145 W(delete_object);
146 W(get_object);
147 #undef W
148
149 S3Status status = DY_initialize("Kopano Mail", S3_INIT_ALL, cf->GetSetting("attachment_s3_hostname"));
104150 if (status != S3StatusOK) {
105 ec_log_err("Error while initializing S3 Attachment Storage, error type: %s", S3_get_status_name(status));
151 ec_log_err("Error while initializing S3 Attachment Storage, error type: %s",
152 DY_get_status_name(status));
106153 return KCERR_NETWORK_ERROR;
107154 }
108155 return erSuccess;
112159 {
113160 ec_log_info("Deinitializing S3 Attachment Storage");
114161 /* Deinitialize the S3 storage environment */
115 S3_deinitialize();
162 if (ec_libs3_handle != NULL) {
163 DY_deinitialize();
164 dlclose(ec_libs3_handle);
165 }
116166 return erSuccess;
117167 }
118168
136186 * simply request the dagent to resend the attachment and to obtain a new
137187 * attachment id.
138188 */
139
140189
141190 /**
142191 * The ECS3Attachment Storage engine is used to store attachments as separate
239288 struct s3_cd *data = reinterpret_cast<struct s3_cd *>(cbdata);
240289 data->status = status;
241290
242 ec_log_debug("Response completed: %s.", S3_get_status_name(status));
291 ec_log_debug("Response completed: %s.", DY_get_status_name(status));
243292 if (status == S3StatusOK)
244293 return;
245294 if (error == 0) {
246 ec_log_err("Amazon S3 return status %s", S3_get_status_name(status));
295 ec_log_err("Amazon S3 return status %s", DY_get_status_name(status));
247296 return;
248297 }
249298 ec_log_err("Amazon S3 return status %s, error: %s, resource: \"%s\"",
250 S3_get_status_name(status),
299 DY_get_status_name(status),
251300 error->message ? error->message : "<unknown>",
252301 error->resource ? error->resource : "<none>");
253302 if (error->furtherDetails != NULL)
374423 */
375424 cdp->retries = S3_RETRIES;
376425 do {
377 S3_head_object(&m_bucket_ctx, filename.c_str(), 0,
426 DY_head_object(&m_bucket_ctx, filename.c_str(), 0,
378427 &m_response_handler, &cwdata);
379 if (S3_status_is_retryable(cdp->status))
380 ec_log_debug("Existence check result in while: %s", S3_get_status_name(cdp->status));
381 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
382
383 ec_log_debug("Result of the existence check: %s", S3_get_status_name(cdp->status));
428 if (DY_status_is_retryable(cdp->status))
429 ec_log_debug("Existence check result in while: %s",
430 DY_get_status_name(cdp->status));
431 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
432
433 ec_log_debug("Result of the existence check: %s",
434 DY_get_status_name(cdp->status));
384435 return cdp->status == S3StatusOK;
385436 }
386437
422473 */
423474 cdp->retries = S3_RETRIES;
424475 do {
425 S3_get_object(&m_bucket_ctx, filename.c_str(),
476 DY_get_object(&m_bucket_ctx, filename.c_str(),
426477 &m_get_conditions, /*startByte*/ 0, /*byteCount*/ 0, 0,
427478 &m_get_obj_handler, &cwdata);
428 if (S3_status_is_retryable(cdp->status))
479 if (DY_status_is_retryable(cdp->status))
429480 ec_log_debug("Load instance result in while: %s",
430 S3_get_status_name(cdp->status));
431 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
481 DY_get_status_name(cdp->status));
482 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
432483
433484 ec_log_debug("Result of the load instance: %s",
434 S3_get_status_name(cdp->status));
485 DY_get_status_name(cdp->status));
435486
436487 if (cdp->size != cdp->processed) {
437488 ec_log_err("Short read while reading attachment data, key: %s", filename.c_str());
495546 */
496547 cdp->retries = S3_RETRIES;
497548 do {
498 S3_get_object(&m_bucket_ctx, filename.c_str(),
549 DY_get_object(&m_bucket_ctx, filename.c_str(),
499550 &m_get_conditions, /*startByte*/ 0, /*byteCount*/ 0, 0,
500551 &m_get_obj_handler, &cwdata);
501 if (S3_status_is_retryable(cdp->status))
502 ec_log_debug("Load instance result in while: %s", S3_get_status_name(cdp->status));
503 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
504
505 ec_log_debug("Result of the load instance: %s", S3_get_status_name(cdp->status));
552 if (DY_status_is_retryable(cdp->status))
553 ec_log_debug("Load instance result in while: %s",
554 DY_get_status_name(cdp->status));
555 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
556
557 ec_log_debug("Result of the load instance: %s",
558 DY_get_status_name(cdp->status));
506559 if (cdp->size != cdp->processed) {
507560 ec_log_err("Short read while reading attachment data from S3, key: %s", filename.c_str());
508561 ret = KCERR_DATABASE_ERROR;
557610 */
558611 cdp->retries = S3_RETRIES;
559612 do {
560 S3_put_object(&m_bucket_ctx, filename.c_str(), size, NULL,
613 DY_put_object(&m_bucket_ctx, filename.c_str(), size, NULL,
561614 NULL, &m_put_obj_handler, &cwdata);
562 if (S3_status_is_retryable(cdp->status))
615 if (DY_status_is_retryable(cdp->status))
563616 ec_log_debug("Save attachment result in while: %s",
564 S3_get_status_name(cdp->status));
565 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
566
567 ec_log_debug("Result of the save attachment: %s", S3_get_status_name(cdp->status));
617 DY_get_status_name(cdp->status));
618 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
619
620 ec_log_debug("Result of the save attachment: %s",
621 DY_get_status_name(cdp->status));
568622 /* set in transaction before disk full check to remove empty file */
569623 if (m_transact)
570624 m_new_att.insert(ins_id);
615669 */
616670 cdp->retries = S3_RETRIES;
617671 do {
618 S3_put_object(&m_bucket_ctx, filename.c_str(), size, NULL,
672 DY_put_object(&m_bucket_ctx, filename.c_str(), size, NULL,
619673 NULL, &m_put_obj_handler, &cwdata);
620 if (S3_status_is_retryable(cdp->status))
674 if (DY_status_is_retryable(cdp->status))
621675 ec_log_debug("Save attachment result in while: %s",
622 S3_get_status_name(cdp->status));
623 }
624 while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
676 DY_get_status_name(cdp->status));
677 }
678 while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
625679
626680 ec_log_debug("Result of the save attachment: %s",
627 S3_get_status_name(cdp->status));
681 DY_get_status_name(cdp->status));
628682 /* set in transaction before disk full check to remove empty file */
629683 if (m_transact)
630684 m_new_att.insert(ins_id);
715769 */
716770 cdp->retries = S3_RETRIES;
717771 do {
718 S3_delete_object(&m_bucket_ctx, filename.c_str(), 0,
772 DY_delete_object(&m_bucket_ctx, filename.c_str(), 0,
719773 &m_response_handler, &cwdata);
720
721 if (S3_status_is_retryable(cdp->status))
722 ec_log_debug("Delete marked attachment result in while: %s", S3_get_status_name(cdp->status));
723 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
724
725 ec_log_debug("Result of the delete marked attachment: %s", S3_get_status_name(cdp->status));
774 if (DY_status_is_retryable(cdp->status))
775 ec_log_debug("Delete marked attachment result in while: %s",
776 DY_get_status_name(cdp->status));
777 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
778
779 ec_log_debug("Result of the delete marked attachment: %s",
780 DY_get_status_name(cdp->status));
726781 if (cdp->status == S3StatusOK)
727782 return erSuccess;
728783 return KCERR_NOT_FOUND;
831886 */
832887 cdp->retries = S3_RETRIES;
833888 do {
834 S3_head_object(&m_bucket_ctx, filename.c_str(), 0,
889 DY_head_object(&m_bucket_ctx, filename.c_str(), 0,
835890 &m_response_handler, &cwdata);
836 if (S3_status_is_retryable(cdp->status))
891 if (DY_status_is_retryable(cdp->status))
837892 ec_log_debug("Get size attachment result in while: %s",
838 S3_get_status_name(cdp->status));
839 } while (S3_status_is_retryable(cdp->status) && should_retry(cdp));
893 DY_get_status_name(cdp->status));
894 } while (DY_status_is_retryable(cdp->status) && should_retry(cdp));
840895
841896 ec_log_debug("Get size of attachment: %s -> %d",
842 S3_get_status_name(cdp->status), cdp->size);
897 DY_get_status_name(cdp->status), cdp->size);
843898
844899 if (cdp->status == S3StatusOK) {
845900 *size_p = cdp->size;
3434 #include <kopano/stringutil.h>
3535
3636 #include "ECSearchClient.h"
37
38 #ifdef _DEBUG
39 #define new DEBUG_NEW
40 #endif
4137
4238 typedef struct {
4339 SEARCHFOLDER *lpFolder;
311307 pthread_attr_t attr;
312308 pthread_attr_init(&attr);
313309 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
314 #ifdef LINUX
315310 pthread_attr_setstacksize(&attr, 512*1024); // 512KB stack space for search threads
316 #endif
317311 int err = 0;
318312
319313 if((err = pthread_create(&lpSearchFolder->sThreadId, &attr, ECSearchFolders::SearchThread, (void *)ti)) != 0) {
10601054 return er;
10611055 }
10621056
1063
10641057 // Does an actual search of a specific search Criteria in store ulStoreId, search folder ulFolderId. Will cancel if *lpbCancel
10651058 // is TRUE. We check after each message row set to see if the cancel has been requested.
10661059 ECRESULT ECSearchFolders::Search(unsigned int ulStoreId, unsigned int ulFolderId, struct searchCriteria *lpSearchCrit, bool *lpbCancel, bool bNotify)
11591152 strQuery = "SELECT hierarchy.id from hierarchy WHERE hierarchy.parent = " + stringify(*iterFolders) + " AND hierarchy.type=3 AND hierarchy.flags & " + stringify(MSGFLAG_DELETED|MSGFLAG_ASSOCIATED) + " = 0 ORDER by hierarchy.id DESC";
11601153
11611154 er = lpDatabase->DoSelect(strQuery, &lpDBResult);
1162 if(er != erSuccess)
1163 continue; // Try to continue if the query failed ..
1164
1165 while((lpDBRow = lpDatabase->FetchRow(lpDBResult)) != NULL) {
1166 if(lpDBRow && lpDBRow[0])
1167 lstFolders.push_back(atoi(lpDBRow[0]));
1155 if(er == erSuccess) {
1156 while((lpDBRow = lpDatabase->FetchRow(lpDBResult)) != NULL) {
1157 if(lpDBRow && lpDBRow[0])
1158 lstFolders.push_back(atoi(lpDBRow[0]));
1159 }
1160 } else
1161 ec_log_crit("ECSearchFolders::Search() could not expand target folders: 0x%x", er);
1162
1163 if(lpDBResult) {
1164 lpDatabase->FreeResult(lpDBResult);
1165 lpDBResult = NULL;
11681166 }
11691167
1170 if(lpDBResult){ lpDatabase->FreeResult(lpDBResult); lpDBResult = NULL; }
11711168 ++iterFolders;
11721169 }
11731170 }
15831580 return erSuccess;
15841581 }
15851582
1586
15871583 // Remove a single search result (so one message in a search folder). Returns NOT_FOUND if the item wasn't in the database in the first place
15881584 ECRESULT ECSearchFolders::DeleteResults(unsigned int ulStoreId, unsigned int ulFolderId, unsigned int ulObjId, unsigned int *lpulOldFlags)
15891585 {
18341830 struct soap xmlsoap;
18351831 struct searchCriteria sSearchCriteria;
18361832 std::ostringstream xml;
1837
18381833
18391834 // We use the soap serializer / deserializer to store the data
18401835 soap_set_mode(&xmlsoap, SOAP_XML_TREE | SOAP_C_UTFSTRING);
2222 #include "ECSessionManager.h"
2323 #include "ECSearchObjectTable.h"
2424 #include "ECSession.h"
25
26 #ifdef _DEBUG
27 #define new DEBUG_NEW
28 #endif
2925
3026 ECSearchObjectTable::ECSearchObjectTable(ECSession *lpSession, unsigned int ulStoreId, LPGUID lpGuid, unsigned int ulFolderId, unsigned int ulObjType, unsigned int ulFlags, const ECLocale &locale) : ECStoreObjectTable(lpSession, ulStoreId, lpGuid, 0, ulObjType, ulFlags, 0, locale) {
3127 // We don't pass ulFolderId to ECStoreObjectTable (see constructor above passing '0'), because
1313 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1414 */
1515 #include <kopano/platform.h>
16 #ifdef LINUX
1716 #include <sys/types.h>
1817 #include <sys/stat.h>
1918 #include <pwd.h>
2019 #include <dirent.h>
21 #endif
22
2320 #include "ECDatabaseUtils.h"
2421 #include "ECDatabase.h"
2522 #include "ECSessionManager.h"
3330 #include "kcore.hpp"
3431 #include <kopano/md5.h>
3532
36 #include <kopano/ECDefs.h>
3733 #include <mapidefs.h>
3834 #include <mapicode.h>
3935 #include <mapitags.h>
5652 #include "ECDBDef.h"
5753 #include "cmdutil.hpp"
5854
59 #ifdef _DEBUG
60 #define new DEBUG_NEW
61 #endif
62
6355 #define MAX_PARENT_LIMIT 64
6456
6557 /**
66 * ECSecurity constructor
67 *
6858 * @param[in] lpSession user session
6959 * @param[in] lpConfig config object
7060 * @param[in] lpLogger log object for normal logging
197187 cSeenGroups.m_seen.insert(*iterGroups);
198188
199189 std::list<localobjectdetails_t> *lpGroupInGroups = NULL;
200 std::list<localobjectdetails_t>::const_iterator li;
201190
202191 er = m_lpSession->GetUserManagement()->GetParentObjectsOfObjectAndSync(OBJECTRELATION_GROUP_MEMBER,
203192 iterGroups->ulId, &lpGroupInGroups, USERMANAGEMENT_IDS_ONLY);
687676 ECRESULT ECSecurity::SetRights(unsigned int objid, struct rightsArray *lpsRightsArray)
688677 {
689678 ECRESULT er;
690 std::string strQueryNew, strQueryDeniedNew;
691 std::string strQueryModify, strQueryDeniedModify;
692 std::string strQueryDelete, strQueryDeniedDelete;
679 std::string strQueryNew, strQueryDelete;
693680 unsigned int ulDeniedRights=0;
694681 ECDatabase *lpDatabase = NULL;
695682 unsigned int ulUserId = 0;
12591246 goto exit;
12601247 }
12611248
1262 *lpllStoreSize = _atoi64(lpDBRow[0]);
1249 *lpllStoreSize = atoll(lpDBRow[0]);
12631250
12641251 exit:
12651252 if(lpDBResult)
13181305 if (lpDBRow[0] == NULL)
13191306 llUserSize = 0;
13201307 else
1321 llUserSize = _atoi64(lpDBRow[0]);
1308 llUserSize = atoll(lpDBRow[0]);
13221309
13231310 *lpllUserSize = llUserSize;
13241311
14671454 quotadetails.bUseDefaultQuota = true;
14681455 quotadetails.bIsUserDefaultQuota = false;
14691456 if (lpszWarnQuota)
1470 quotadetails.llWarnSize = _atoi64(lpszWarnQuota) * 1024 * 1024;
1457 quotadetails.llWarnSize = atoll(lpszWarnQuota) * 1024 * 1024;
14711458 if (lpszSoftQuota)
1472 quotadetails.llSoftSize = _atoi64(lpszSoftQuota) * 1024 * 1024;
1459 quotadetails.llSoftSize = atoll(lpszSoftQuota) * 1024 * 1024;
14731460 if (lpszHardQuota)
1474 quotadetails.llHardSize = _atoi64(lpszHardQuota) * 1024 * 1024;
1461 quotadetails.llHardSize = atoll(lpszHardQuota) * 1024 * 1024;
14751462
14761463 exit:
14771464 if (er == erSuccess)
1818
1919 #include <kopano/ECDefs.h>
2020 #include "ECSecurityOffline.h"
21
22 #ifdef _DEBUG
23 #define new DEBUG_NEW
24 #endif
2521
2622 ECSecurityOffline::ECSecurityOffline(ECSession *lpSession, ECConfig *lpConfig) :
2723 ECSecurity(lpSession, lpConfig, NULL)
2727 #include "ECSessionManagerOffline.h"
2828 #include "ECS3Attachment.h"
2929
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
33
3430 pthread_key_t database_key;
3531 pthread_key_t plugin_key;
3632
37 ULONG g_ulServerInitFlags = 0; // Libary init flags
3833 ECSessionManager* g_lpSessionManager = NULL;
3934 ECStatsCollector* g_lpStatsCollector = NULL;
40 std::set<ECDatabase*> g_lpDBObjectList;
41 pthread_mutex_t g_hMutexDBObjectList;
42 bool g_bInitLib = false;
35 static std::set<ECDatabase *> g_lpDBObjectList;
36 static pthread_mutex_t g_hMutexDBObjectList;
37 static bool g_bInitLib = false;
4338
4439 void AddDatabaseObject(ECDatabase* lpDatabase)
4540 {
191186 return erSuccess;
192187 }
193188
194 #if 0
195 static void kopano_resetstats(void)
196 {
197 if (g_lpStatsCollector)
198 g_lpStatsCollector->Reset();
199 }
200 #endif
201
202189 /**
203190 * Called for each HTTP header in a request, handles the proxy header
204191 * and marks the connection as using the proxy if it is found. The value
218205 const char *val)
219206 {
220207 const char *szProxy = g_lpSessionManager->GetConfig()->GetSetting("proxy_header");
221 if(strlen(szProxy) > 0 && stricmp(key, szProxy) == 0) {
208 if(strlen(szProxy) > 0 && strcasecmp(key, szProxy) == 0) {
222209 ((SOAPINFO *)soap->user)->bProxy = true;
223210 }
224211
1616
1717 #include <kopano/platform.h>
1818 #include <new>
19 #ifdef LINUX
2019 #include <sys/types.h>
2120 #include <sys/stat.h>
2221 #include <pwd.h>
2322 #include <dirent.h>
24 #endif
25
2623 #include <mapidefs.h>
2724 #include <mapitags.h>
2825
5148
5249 #include <boost/filesystem.hpp>
5350 namespace bfs = boost::filesystem;
54
55 #ifdef _DEBUG
56 #define new DEBUG_NEW
57 #endif
5851
5952 #if defined LINUX || !defined UNICODE
6053 #define WHITESPACE " \t\n\r"
183176 return this->m_lpDatabaseFactory->CreateDatabaseObject(lppDatabase, str);
184177 }
185178
186
187179 ECRESULT BTSession::GetServerGUID(GUID* lpServerGuid){
188180 return m_lpSessionManager->GetServerGUID(lpServerGuid);
189181 }
305297 pthread_mutex_init(&m_hStateLock, NULL);
306298 pthread_mutex_init(&m_hLocksLock, NULL);
307299 }
308
309300
310301 ECSession::~ECSession()
311302 {
674665 if (m_lpEcSecurity)
675666 ulSize += m_lpEcSecurity->GetObjectSize();
676667
677
678668 // The Table manager size is not callculated here
679669 // ulSize += GetTableManager()->GetObjectSize();
680670 return ulSize;
694684
695685 m_ulConnectingPid = 0;
696686
697 #ifdef LINUX
698687 m_NTLM_pid = -1;
699688 #ifdef HAVE_GSSAPI
700689 m_gssServerCreds = GSS_C_NO_CREDENTIAL;
701690 m_gssContext = GSS_C_NO_CONTEXT;
702691 #endif
703 #else
704 SecInvalidateHandle(&m_hCredentials);
705 SecInvalidateHandle(&m_hContext);
706 m_cPackages = 0;
707 m_ulPid = 0;
708 m_lpPackageInfo = NULL;
709 #endif
710692 }
711693
712694 ECAuthSession::~ECAuthSession()
727709 pthread_cond_wait(&m_hThreadReleased, &m_hThreadReleasedMutex);
728710 pthread_mutex_unlock(&m_hThreadReleasedMutex);
729711
730 #ifdef LINUX
731712 if (m_NTLM_pid != -1) {
732713 int status;
733714
758739 #endif
759740 }
760741 }
761 #else // LINUX
762 if (m_lpPackageInfo)
763 FreeContextBuffer(m_lpPackageInfo);
764
765 if (SecIsValidHandle(&m_hCredentials))
766 FreeCredentialHandle(&m_hCredentials);
767
768 if (SecIsValidHandle(&m_hContext))
769 DeleteSecurityContext(&m_hContext);
770 #endif
771
772742 delete m_lpUserManagement;
773743 }
774
775744
776745 ECRESULT ECAuthSession::CreateECSession(ECSESSIONGROUPID ecSessionGroupId,
777746 const std::string &cl_ver, const std::string &cl_app,
831800 }
832801
833802 // SYSTEM can't login with user/pass
834 if (stricmp(lpszName, KOPANO_ACCOUNT_SYSTEM) == 0)
803 if (strcasecmp(lpszName, KOPANO_ACCOUNT_SYSTEM) == 0)
835804 return KCERR_NO_ACCESS;
836805 er = m_lpUserManagement->AuthUserAndSync(lpszName, lpszPassword, &m_ulUserID);
837806 if(er != erSuccess)
870839 goto exit;
871840 }
872841 p = m_lpSessionManager->GetConfig()->GetSetting("allow_local_users");
873 if (p && !stricmp(p, "yes")) {
842 if (p && !strcasecmp(p, "yes")) {
874843 allowLocalUsers = true;
875844 }
876845
877846 // Authentication stage
878 #ifdef LINUX
879847 localAdminUsers = strdup(m_lpSessionManager->GetConfig()->GetSetting("local_admin_users"));
880848
881849 struct passwd pwbuf;
943911 }
944912 p = strtok_r(NULL, WHITESPACE, &ptr);
945913 }
946
947 #else // LINUX
948
949 localAdminUsers = _tcsdup(GetConfigSetting(m_lpSessionManager->GetConfig(), "local_admin_users"));
950
951 dwSize = arraySize(szUsernameServer);
952
953 if (!GetNamedPipeHandleState((HANDLE)socket, NULL, NULL, NULL, NULL, szUsernameClient, arraySize(szUsernameClient)) ||
954 !GetUserName(szUsernameServer, &dwSize))
955 {
956 //GetLastError();
957 er = KCERR_LOGON_FAILED;
958 goto exit;
959 }
960
961 if (_tcscmp(szUsernameServer, szUsernameClient) == 0)
962 goto userok;
963
964 pt = _tcstok(localAdminUsers, WHITESPACE);
965
966 while (pt) {
967 if (_tcscmp(szUsernameClient, pt) == 0)
968 goto userok;
969
970 pt = _tcstok(NULL, WHITESPACE);
971 }
972
973 #endif // LINUX
974
975914 er = KCERR_LOGON_FAILED;
976915 goto exit;
977916
11141053 return er;
11151054 }
11161055
1117 #ifdef LINUX
11181056 #define NTLMBUFFER 8192
11191057 ECRESULT ECAuthSession::ValidateSSOData(struct soap* soap, const char* lpszName, const char* lpszImpersonateUser, const char* szClientVersion, const char *szClientApp, const char *szClientAppVersion, const char *szClientAppMisc, const struct xsd__base64Binary* lpInput, struct xsd__base64Binary **lppOutput)
11201058 {
13251263 if (pos != string::npos)
13261264 strUsername.erase(pos);
13271265
1328 if (stricmp(strUsername.c_str(), lpszName) == 0) {
1266 if (strcasecmp(strUsername.c_str(), lpszName) == 0) {
13291267 er = m_lpUserManagement->ResolveObjectAndSync(ACTIVE_USER, lpszName, &m_ulUserID);
13301268 // don't check NONACTIVE, since those shouldn't be able to login
13311269 if(er != erSuccess)
15811519 if(er != erSuccess)
15821520 return er;
15831521
1584 if (stricmp(lpszName, strAnswer.c_str()) != 0) {
1522 if (strcasecmp(lpszName, strAnswer.c_str()) != 0) {
15851523 // cannot open another user without password
15861524 // or should we check permissions ?
15871525 ec_log_warn("Single Sign-On: User \"%s\" authenticated, but user \"%s\" requested.", strAnswer.c_str(), lpszName);
16131551 return er;
16141552 }
16151553 #undef NTLMBUFFER
1616 #endif
16171554
16181555 ECRESULT ECAuthSession::ProcessImpersonation(const char* lpszImpersonateUser)
16191556 {
16331570
16341571 return ulSize;
16351572 }
1636
16371573
16381574 ECAuthSessionOffline::ECAuthSessionOffline(const char *src_addr,
16391575 ECSESSIONID sessionID, ECDatabaseFactory *lpDatabaseFactory,
240240
241241 ECRESULT ProcessImpersonation(const char* lpszImpersonateUser);
242242
243 #ifdef LINUX
244243 /* NTLM */
245244 pid_t m_NTLM_pid;
246245 int m_NTLM_stdin[2], m_NTLM_stdout[2], m_NTLM_stderr[2];
251250 gss_cred_id_t m_gssServerCreds;
252251 gss_ctx_id_t m_gssContext;
253252 #endif
254 #endif
255253 };
256254
257255 /*
2525 #include "ECSessionGroup.h"
2626 #include "ECSessionManager.h"
2727 #include "SOAPUtils.h"
28
29 #ifdef _DEBUG
30 #define new DEBUG_NEW
31 #endif
3228
3329 class FindChangeAdvise
3430 {
309305 lpNotify->ulEventType = fnevTableModified;
310306 lpNotify->tab->ulTableEvent = ulType;
311307
312
313308 if(lpsChildRow && (lpsChildRow->ulObjId > 0 || lpsChildRow->ulOrderId > 0)) {
314309 lpNotify->tab->propIndex.ulPropTag = PR_INSTANCE_KEY;
315310 lpNotify->tab->propIndex.__union = SOAP_UNION_propValData_bin;
374369 SESSIONINFOMAP::const_iterator iterSessions;
375370
376371 std::map<ECSESSIONID,unsigned int> mapInserted;
377 std::map<ECSESSIONID,unsigned int>::const_iterator iterInserted;
378372 std::set<unsigned int>::const_iterator iterSyncId;
379373 CHANGESUBSCRIBEMAP::const_iterator iterItem;
380374 std::pair<CHANGESUBSCRIBEMAP::const_iterator, CHANGESUBSCRIBEMAP::const_iterator> iterRange;
3434 #include <edkmdb.h>
3535 #include "logontime.hpp"
3636
37 #ifdef _DEBUG
38 #define new DEBUG_NEW
39 #endif
40
4137 ECSessionManager::ECSessionManager(ECConfig *lpConfig, ECLogger *lpAudit,
4238 bool bHostedKopano, bool bDistributedKopano)
4339 {
612608 g_lpStatsCollector->Increment(SCN_LOGIN_DENIED);
613609 goto exit;
614610
615
616611 authenticated:
617612 ec_log_debug("User \"%s\" from \"%s\" authenticated through \"%s\" using program %s", szName, from.c_str(), method, szClientApp ? szClientApp : "<unknown>");
618613 if (strcmp(KOPANO_SYSTEM_USER, szName) != 0) {
840835 struct timeval now;
841836 struct timespec timeout;
842837 list<BTSession*> lstSessions;
843
844838
845839 if(lpSessionManager == NULL) {
846840 return 0;
10421036 return er;
10431037 }
10441038
1045
10461039 ECRESULT ECSessionManager::NotificationModified(unsigned int ulObjType, unsigned int ulObjId, unsigned int ulParentId)
10471040 {
10481041 ECRESULT er = erSuccess;
13771370 {
13781371 ECRESULT er = erSuccess;
13791372 unsigned int ulLicensedUsers = 0;
1380
1381 #ifdef LINUX
13821373 ECLicenseClient *lpLicenseClient = NULL;
13831374 lpLicenseClient = new ECLicenseClient();
13841375
13901381 }
13911382
13921383 delete lpLicenseClient;
1393 #else
1394 ulLicensedUsers = 0;
1395 #endif
1396
13971384 *lpulLicensedUsers = ulLicensedUsers;
13981385
13991386 return er;
1919
2020 #include "ECSecurity.h"
2121 #include "ECSessionManagerOffline.h"
22
23 #ifdef _DEBUG
24 #define new DEBUG_NEW
25 #endif
2622
2723 ECSessionManagerOffline::ECSessionManagerOffline(ECConfig *lpConfig,
2824 bool bHostedKopano, bool bDistributedKopano) :
225225 pthread_mutex_unlock(&iSD->second.lock);
226226 }
227227
228
229228 void ECStatsCollector::Max(SCName name, float max)
230229 {
231230 SCMap::iterator iSD = m_StatData.find(name);
267266 iSD->second.data.ts = max;
268267 pthread_mutex_unlock(&iSD->second.lock);
269268 }
270
271269
272270 void ECStatsCollector::Avg(SCName name, float add)
273271 {
316314 iSD->second.avginc = 1;
317315 pthread_mutex_unlock(&iSD->second.lock);
318316 }
319
320
321317
322318 void ECStatsCollector::Set(const std::string &name, const std::string &description, const std::string &value)
323319 {
3434 #include "ECStatsCollector.h"
3535
3636 #if defined(HAVE_GPERFTOOLS_MALLOC_EXTENSION_H)
37 # include <gperftools/malloc_extension.h>
37 # include <gperftools/malloc_extension_c.h>
3838 #elif defined(HAVE_GOOGLE_MALLOC_EXTENSION_H)
39 # include <google/malloc_extension.h>
39 # include <google/malloc_extension_c.h>
40 #endif
41 #ifdef HAVE_MALLOC_H
42 # include <malloc.h>
4043 #endif
4144
4245 /*
104107
105108 #ifdef HAVE_TCMALLOC
106109 size_t value = 0;
107 MallocExtension::instance()->GetNumericProperty("generic.current_allocated_bytes", &value);
108 GetStatsCollectorData("tc_allocated", "Current allocated memory by TCMalloc", stringify_int64(value), this); // Bytes in use by application
109
110 value = 0;
111 MallocExtension::instance()->GetNumericProperty("generic.heap_size", &value);
112 GetStatsCollectorData("tc_reserved", "Bytes of system memory reserved by TCMalloc", stringify_int64(value), this);
113
114 value = 0;
115 MallocExtension::instance()->GetNumericProperty("tcmalloc.pageheap_free_bytes", &value);
116 GetStatsCollectorData("tc_page_map_free", "Number of bytes in free, mapped pages in page heap", stringify_int64(value), this);
117
118 value = 0;
119 MallocExtension::instance()->GetNumericProperty("tcmalloc.pageheap_unmapped_bytes", &value);
120 GetStatsCollectorData("tc_page_unmap_free", "Number of bytes in free, unmapped pages in page heap (released to OS)", stringify_int64(value), this);
121
122 value = 0;
123 MallocExtension::instance()->GetNumericProperty("tcmalloc.max_total_thread_cache_bytes", &value);
124 GetStatsCollectorData("tc_threadcache_max", "A limit to how much memory TCMalloc dedicates for small objects", stringify_int64(value), this);
125
126 value = 0;
127 MallocExtension::instance()->GetNumericProperty("tcmalloc.current_total_thread_cache_bytes", &value);
128 GetStatsCollectorData("tc_threadcache_cur", "Current allocated memory in bytes for thread cache", stringify_int64(value), this);
110 auto gnp = reinterpret_cast<decltype(MallocExtension_GetNumericProperty) *>(dlsym(NULL, "MallocExtension_GetNumericProperty"));
111 if (gnp != NULL) {
112 gnp("generic.current_allocated_bytes", &value);
113 GetStatsCollectorData("tc_allocated", "Current allocated memory by TCMalloc", stringify_int64(value), this); // Bytes in use by application
114
115 value = 0;
116 gnp("generic.heap_size", &value);
117 GetStatsCollectorData("tc_reserved", "Bytes of system memory reserved by TCMalloc", stringify_int64(value), this);
118
119 value = 0;
120 gnp("tcmalloc.pageheap_free_bytes", &value);
121 GetStatsCollectorData("tc_page_map_free", "Number of bytes in free, mapped pages in page heap", stringify_int64(value), this);
122
123 value = 0;
124 gnp("tcmalloc.pageheap_unmapped_bytes", &value);
125 GetStatsCollectorData("tc_page_unmap_free", "Number of bytes in free, unmapped pages in page heap (released to OS)", stringify_int64(value), this);
126
127 value = 0;
128 gnp("tcmalloc.max_total_thread_cache_bytes", &value);
129 GetStatsCollectorData("tc_threadcache_max", "A limit to how much memory TCMalloc dedicates for small objects", stringify_int64(value), this);
130
131 value = 0;
132 gnp("tcmalloc.current_total_thread_cache_bytes", &value);
133 GetStatsCollectorData("tc_threadcache_cur", "Current allocated memory in bytes for thread cache", stringify_int64(value), this);
134 }
135 #ifdef HAVE_MALLINFO
136 /* parallel threaded allocator */
137 struct mallinfo malloc_info = mallinfo();
138 GetStatsCollectorData("pt_allocated", "Current allocated memory by libc ptmalloc, in bytes", stringify_int64(malloc_info.uordblks), this);
139 #endif
129140
130141 #ifdef DEBUG
131142 char test[2048] = {0};
132 MallocExtension::instance()->GetStats(test, sizeof(test));
133 GetStatsCollectorData("tc_stats_string", "TCMalloc memory debug data", test, this);
143 auto getstat = reinterpret_cast<decltype(MallocExtension_GetStats) *>(dlsym(NULL, "MallocExtension_GetStats"));
144 if (getstat != NULL) {
145 getstat(test, sizeof(test));
146 GetStatsCollectorData("tc_stats_string", "TCMalloc memory debug data", test, this);
147 }
134148 #endif
135149
136150 #endif
234248 *lppRowSet = lpsRowSet;
235249 return erSuccess;
236250 }
237
238251
239252 /*
240253 Session stats
489502
490503 for (j = 0, iterBS = iterSD->second.busystates.begin();
491504 iterBS != iterSD->second.busystates.end(); ++j, ++iterBS) {
492 const char *szState;
505 const char *szState = "";
493506 if(iterBS->state == SESSION_STATE_PROCESSING)
494507 szState = "P";
495508 else if(iterBS->state == SESSION_STATE_SENDING)
521534 *lppRowSet = lpsRowSet;
522535 return erSuccess;
523536 }
524
525537
526538 /*
527539 User stats
603615 delete lpObjects;
604616 return er;
605617 }
606
607618
608619 ECRESULT ECUserStatsTable::QueryRowData(ECGenericObjectTable *lpThis, struct soap *soap, ECSession *lpSession, ECObjectTableList *lpRowList, struct propTagArray *lpsPropTagArray, void *lpObjectData, struct rowSet **lppRowSet, bool bCacheTableData, bool bTableLimit)
609620 {
815826 return er;
816827 }
817828
818
819829 ECCompanyStatsTable::ECCompanyStatsTable(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale) : ECGenericObjectTable(lpSession, MAPI_STATUS, ulFlags, locale)
820830 {
821831 m_lpfnQueryRowData = QueryRowData;
849859 delete lpCompanies;
850860 return er;
851861 }
852
853862
854863 ECRESULT ECCompanyStatsTable::QueryRowData(ECGenericObjectTable *lpThis, struct soap *soap, ECSession *lpSession, ECObjectTableList* lpRowList, struct propTagArray *lpsPropTagArray, void* lpObjectData, struct rowSet **lppRowSet, bool bCacheTableData, bool bTableLimit)
855864 {
905914 // company gone missing since last call, all quota props should be set to ignore
906915 bNoQuotaDetails = true;
907916
908
909917 if (lpSession->GetSecurity()->GetUserSize(iterRowList->ulObjId, &llStoreSize) != erSuccess)
910918 llStoreSize = 0;
911919
10281036 return erSuccess;
10291037 }
10301038
1031
10321039 ECRESULT ECServerStatsTable::QueryRowData(ECGenericObjectTable *lpThis, struct soap *soap, ECSession *lpSession, ECObjectTableList* lpRowList, struct propTagArray *lpsPropTagArray, void* lpObjectData, struct rowSet **lppRowSet, bool bCacheTableData, bool bTableLimit)
10331040 {
10341041 gsoap_size_t i;
6767 #include "ECSession.h"
6868
6969 #include <map>
70
71 #ifdef _DEBUG
72 #define new DEBUG_NEW
73 #endif
7470
7571 extern ECStatsCollector* g_lpStatsCollector;
7672
780776 memset(&lpsRowSet->__ptr[ulRowNum].__ptr[iterColumns->second], 0, sizeof(lpsRowSet->__ptr[ulRowNum].__ptr[iterColumns->second]));
781777 }
782778
783
784779 if(CopyDatabasePropValToSOAPPropVal(soap, lpDBRow, lpDBLen, &lpsRowSet->__ptr[ulRowNum].__ptr[iterColumns->second]) != erSuccess) {
785780 // This can happen if a subquery returned a NULL field or if your database contains bad data (eg a NULL field where there shouldn't be)
786781 ++iterColumns;
806801 if(lpDBResult) lpDatabase->FreeResult(lpDBResult);
807802 lpDBResult = NULL;
808803 }
809
810804
811805 for (iterColumns = mapColumns.begin(); iterColumns != mapColumns.end(); ++iterColumns) {
812806 ASSERT(lpsRowSet->__ptr[ulRowNum].__ptr[iterColumns->second].ulPropTag == 0);
10411035 return er;
10421036 }
10431037
1044
10451038 ECRESULT ECStoreObjectTable::GetMVRowCount(unsigned int ulObjId, unsigned int *lpulCount)
10461039 {
10471040 ECRESULT er = erSuccess;
13051298
13061299 }
13071300
1308
13091301 /**
13101302 * Get all deferred changes for a specific folder
13111303 */
101101 // deleting a NULL ptr is allowed.
102102 delete m_lpConverter;
103103 }
104
105104
106105 ECRESULT FixPropEncoding(struct soap *soap, const ECStringCompat &stringCompat, enum EncodingFixDirection type, struct propVal *lpProp, bool bNoTagUpdate)
107106 {
2828 #include "SOAPUtils.h"
2929
3030 #include "ECSessionManager.h"
31
32 #ifdef _DEBUG
33 #define new DEBUG_NEW
34 #endif
3531
3632 static ECRESULT GetSubRestrictionRecursive(struct restrictTable *lpRestrict,
3733 unsigned int *lpulCount, unsigned int ulSubRestriction,
4747 #include <kopano/mapiext.h>
4848 #include <edkmdb.h>
4949
50 #ifdef _DEBUG
51 #define new DEBUG_NEW
52 #endif
53
5450 void FreeRowSet(struct rowSet *lpRowSet, bool bBasePointerDel);
5551
5652 unsigned int sContentsProps[] = { PR_ENTRYID, PR_DISPLAY_NAME, PR_MESSAGE_FLAGS, PR_SUBJECT, PR_STORE_ENTRYID, PR_STORE_RECORD_KEY, PR_STORE_SUPPORT_MASK, PR_INSTANCE_KEY, PR_RECORD_KEY, PR_ACCESS, PR_ACCESS_LEVEL };
149145 pthread_mutex_unlock(&hListMutex);
150146
151147 }
152
153148
154149 ECRESULT ECTableManager::OpenOutgoingQueueTable(unsigned int ulStoreId, unsigned int *lpulTableId)
155150 {
650645 {
651646 ECRESULT er = erSuccess;
652647 std::map<unsigned int, TABLE_ENTRY *>::const_iterator iterTables;
653 std::map<unsigned int, unsigned int>::const_iterator iterFolders;
654648
655649 sObjectTableKey sRow;
656650
3030 {
3131 ECRESULT er = erSuccess;
3232
33 if(stricmp(szCommand, "purge_deferred") == 0) {
33 if(strcasecmp(szCommand, "purge_deferred") == 0) {
3434 while (1) {
3535 unsigned int ulFolderId = 0;
3636 ECDatabase *lpDatabase = NULL;
5050 return er;
5151 }
5252
53 } else if (stricmp(szCommand, "indexer_syncrun") == 0) {
53 } else if (strcasecmp(szCommand, "indexer_syncrun") == 0) {
5454 if (parseBool(g_lpSessionManager->GetConfig()->GetSetting("search_enabled"))) {
5555 er = ECSearchClient(
5656 g_lpSessionManager->GetConfig()->GetSetting("search_socket"),
5757 60 * 10 /* 10 minutes should be enough for everyone */
5858 ).SyncRun();
5959 }
60 } else if (stricmp(szCommand, "run_searchfolders") == 0) {
60 } else if (strcasecmp(szCommand, "run_searchfolders") == 0) {
6161 lpSession->GetSessionManager()->GetSearchFolders()->FlushAndWait();
62 } else if (stricmp(szCommand, "kill_sessions") == 0) {
62 } else if (strcasecmp(szCommand, "kill_sessions") == 0) {
6363 ECSESSIONID id = lpSession->GetSessionId();
6464
6565 // Remove all sessions except our own
6666 er = lpSession->GetSessionManager()->CancelAllSessions(id);
67 } else if(stricmp(szCommand, "sleep") == 0) {
67 } else if(strcasecmp(szCommand, "sleep") == 0) {
6868 if(ulArgs == 1 && args[0])
6969 Sleep(atoui(args[0]) * 1000);
7070 }
7575 {
7676 ECRESULT er = erSuccess;
7777
78 if(stricmp(szVarName, "cell_cache_disabled") == 0) {
78 if(strcasecmp(szVarName, "cell_cache_disabled") == 0) {
7979 if(atoi(szValue) > 0)
8080 g_lpSessionManager->GetCacheManager()->DisableCellCache();
8181 else
8282 g_lpSessionManager->GetCacheManager()->EnableCellCache();
8383
84 } else if (stricmp(szVarName, "search_enabled") == 0) {
84 } else if (strcasecmp(szVarName, "search_enabled") == 0) {
8585 // Since there's no object that represents the indexer, it's probably cleanest to
8686 // update the configuration.
8787 if (atoi(szValue) > 0)
9797 {
9898 ECRESULT er = erSuccess;
9999
100 if(!stricmp(szVarName, "ping")) {
100 if(!strcasecmp(szVarName, "ping")) {
101101 *szValue = s_strcpy(soap, "pong");
102102 } else {
103103 er = KCERR_NOT_FOUND;
3434 #include "SymmetricCrypt.h"
3535 #include "ECPamAuth.h"
3636 #include "ECKrbAuth.h"
37 #ifdef LINUX
3837 #include <kopano/UnixUtil.h>
39 #else
40 #include "WinUtil.h"
41 #endif
42
4338 #include <kopano/base64.h>
4439
4540 #include "ECICS.h"
5752 #include <boost/algorithm/string.hpp>
5853 namespace ba = boost::algorithm;
5954
60 #ifdef _DEBUG
61 #define new DEBUG_NEW
62 #endif
6355 #ifndef AB_UNICODE_OK
6456 #define AB_UNICODE_OK ((ULONG) 0x00000040)
6557 #endif
9890 for (i = lstEnv.begin(); i != lstEnv.end(); ++i)
9991 env[n++] = i->c_str();
10092 env[n] = NULL;
101
102 #ifdef LINUX
10393 return unix_system(scriptname, scriptname, env);
104 #else
105 return win_system(scriptname, scriptname, env);
106 #endif
107 }
108
109 #if 0
110 static std::string HostnameFromSoap(struct soap *soap)
111 {
112 /*
113 * Is the client connecting using an IP address or fully qualified hostname?
114 * SOAP knows... SOAP is all-knowing.
115 */
116 if (soap->host[0] == '\0') {
117 /* Use the endpoint which is something like: http://<ip>:<port>/<path>*/
118 std::string ip = soap->endpoint;
119 size_t pos;
120
121 pos = ip.find("://");
122 if (pos != std::string::npos)
123 ip.erase(0, ip.find_first_not_of(":/", pos));
124
125 pos = ip.find_first_of(":/");
126 if (pos != std::string::npos)
127 ip.erase(pos, std::string::npos);
128
129 return ip;
130 }
131 return std::string(soap->host);
132 }
133 #endif
94 }
13495
13596 static const char *ObjectClassToName(objectclass_t objclass)
13697 {
12301191 if ((OBJECTCLASS_TYPE(objclass) == OBJECTTYPE_UNKNOWN ||
12311192 objclass == OBJECTCLASS_USER ||
12321193 objclass == ACTIVE_USER) &&
1233 stricmp(szName, KOPANO_ACCOUNT_SYSTEM) == 0)
1194 strcasecmp(szName, KOPANO_ACCOUNT_SYSTEM) == 0)
12341195 {
12351196 *lpulObjectId = KOPANO_UID_SYSTEM;
12361197 return er;
12371198 } else if ((OBJECTCLASS_TYPE(objclass) == OBJECTTYPE_UNKNOWN ||
12381199 objclass == OBJECTCLASS_DISTLIST ||
12391200 objclass == DISTLIST_SECURITY) &&
1240 stricmp(szName, KOPANO_FULLNAME_EVERYONE) == 0)
1201 strcasecmp(szName, KOPANO_FULLNAME_EVERYONE) == 0)
12411202 {
12421203 *lpulObjectId = KOPANO_UID_EVERYONE;
12431204 return er;
17311692 return er;
17321693
17331694 // Special case: SYSTEM
1734 if (stricmp(szSearchString, KOPANO_ACCOUNT_SYSTEM) == 0) {
1695 if (strcasecmp(szSearchString, KOPANO_ACCOUNT_SYSTEM) == 0) {
17351696 // Hide user SYSTEM when requested
17361697 if (lpSecurity->GetUserId() != KOPANO_UID_SYSTEM) {
17371698 szHideSystem = m_lpConfig->GetSetting("hide_system");
17411702
17421703 *lpulID = KOPANO_UID_SYSTEM;
17431704 return erSuccess;
1744 } else if (stricmp(szSearchString, KOPANO_ACCOUNT_EVERYONE) == 0) {
1705 } else if (strcasecmp(szSearchString, KOPANO_ACCOUNT_EVERYONE) == 0) {
17451706 // Hide group everyone when requested
17461707 if (lpSecurity->GetUserId() != KOPANO_UID_SYSTEM) {
17471708 szHideEveryone = m_lpConfig->GetSetting("hide_everyone");
23182279 list<objectid_t> lstExternIDs;
23192280 map<objectid_t, unsigned int> mapLocalIDs;
23202281 std::map<objectid_t, unsigned int>::const_iterator iterLocalIDs;
2321 string strQuery;
23222282 objectid_t sExternID;
23232283 unsigned int ulLocalID = 0;
23242284
25582518 ECRESULT ECUserManagement::CheckUserLicense(unsigned int *lpulLicenseStatus)
25592519 {
25602520 ECRESULT er;
2561 std::string strQuery;
25622521 unsigned int ulTotalUsers = 0;
25632522 unsigned int ulActive = 0;
25642523 unsigned int ulNonActive = 0;
27282687 case NONACTIVE_ROOM:
27292688 case NONACTIVE_EQUIPMENT:
27302689 strUserServer = details.GetPropString(OB_PROP_S_SERVERNAME);
2731 if (!bDistributed || stricmp(strUserServer.c_str(), strThisServer.c_str()) == 0) {
2690 if (!bDistributed || strcasecmp(strUserServer.c_str(), strThisServer.c_str()) == 0) {
27322691 execute_script(m_lpConfig->GetSetting("createuser_script"),
27332692 "KOPANO_USER", details.GetPropString(OB_PROP_S_LOGIN).c_str(),
27342693 NULL);
27422701 break;
27432702 case CONTAINER_COMPANY:
27442703 strUserServer = details.GetPropString(OB_PROP_S_SERVERNAME);
2745 if (!bDistributed || stricmp(strUserServer.c_str(), strThisServer.c_str()) == 0) {
2704 if (!bDistributed || strcasecmp(strUserServer.c_str(), strThisServer.c_str()) == 0) {
27462705 execute_script(m_lpConfig->GetSetting("createcompany_script"),
27472706 "KOPANO_COMPANY", details.GetPropString(OB_PROP_S_FULLNAME).c_str(),
27482707 NULL);
32623221 if(er != erSuccess)
32633222 goto exit;
32643223
3265 // Object didn't exist locally, so no delete has occured
3224 // Object didn't exist locally, so no delete has occurred
32663225 if (ulDeletedRows == 0) {
32673226 er = lpDatabase->Commit();
32683227 if (er != erSuccess)
35163475 struct propVal *lpPropVal;
35173476 unsigned int ulOrder = 0;
35183477 ECSecurity *lpSecurity = NULL;
3519 std::string strEncExId;
35203478 struct propValArray sPropVals{__gszeroinit};
35213479 struct propValArray *lpPropVals = &sPropVals;
35223480 ULONG ulMapiType = 0;
40854043 struct propVal *lpPropVal;
40864044 unsigned int ulOrder = 0;
40874045 ECSecurity *lpSecurity = NULL;
4088 std::string strEncExId;
40894046 ULONG ulMapiType = 0;
40904047
40914048 er = GetSecurity(&lpSecurity);
44114368 if(lpSession)
44124369 lpSession->GetClientApp(&strApp);
44134370
4414 if(strnicmp(strApp.c_str(), "blackberry", 10) == 0) {
4371 if(strncasecmp(strApp.c_str(), "blackberry", 10) == 0) {
44154372 // For blackberry, we pose as being the Exchange AddressList. We have to do this
44164373 // since it searches for the GAB by restricting by this GUID, otherwise the Lookup
44174374 // function will not function properly.
46844641 ECRESULT ECUserManagement::ProcessModification(unsigned int ulId, const std::string &newsignature)
46854642 {
46864643 ECRESULT er;
4687 std::string strQuery;
46884644 ECDatabase *lpDatabase = NULL;
46894645 ABEID eid(MAPI_ABCONT, MUIDECSAB, 1);
46904646 SOURCEKEY sSourceKey;
48494805 return erSuccess;
48504806 }
48514807
4852 ECRESULT ECUserManagement::RemoveAllObjectsAndSync(unsigned int ulObjId)
4853 {
4854 ECRESULT er;
4855 UserPlugin *lpPlugin = NULL;
4856 objectid_t id;
4857
4858 er = GetThreadLocalPlugin(m_lpPluginFactory, &lpPlugin);
4859 if(er != erSuccess)
4860 return er;
4861 er = GetExternalId(ulObjId, &id);
4862 if(er != erSuccess)
4863 return er;
4864 lpPlugin->removeAllObjects(id);
4865 return SyncAllObjects();
4866 }
4867
48684808 ECRESULT ECUserManagement::SyncAllObjects()
48694809 {
48704810 ECRESULT er = erSuccess;
212212 /* Create an ABEID in version 1 or version 0 */
213213 ECRESULT CreateABEntryID(struct soap *soap, unsigned int ulVersion, unsigned int ulObjId, unsigned int ulType, objectid_t *sExternId, gsoap_size_t *lpcbEID, ABEID **lppEid);
214214
215 /* Completely remove all users, groups, etc except for the passed object */
216 ECRESULT RemoveAllObjectsAndSync(unsigned int ulObjId);
217
218215 /* Resync all objects from the plugin. */
219216 ECRESULT SyncAllObjects();
220217
1717 #include <kopano/platform.h>
1818
1919 #include "ECUserManagementOffline.h"
20
21 #ifdef _DEBUG
22 #define new DEBUG_NEW
23 #endif
2420
2521 ECUserManagementOffline::ECUserManagementOffline(ECSession *lpSession,
2622 ECPluginFactory *lpPluginFactory, ECConfig *lpConfig) :
7470
7571 lpUsers->push_back(localuserdetails_t(m_ulUserId, details));
7672
77
7873 *lppUsers = lpUsers;
7974 return erSuccess;
8075 }
2626 #include "ECGenProps.h"
2727 #include "ECSession.h"
2828 #include <kopano/stringutil.h>
29
30 #ifdef _DEBUG
31 #define new DEBUG_NEW
32 #endif
3329
3430 // 1 == MAPI_STORE.. does it even matter?
3531 ECUserStoreTable::ECUserStoreTable(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale) :
+0
-90
provider/libserver/Makefile.am less more
0 # -*- Makefile -*-
1
2 AM_CPPFLAGS = ${ZCPPFLAGS} ${DEBUGFLAGS} ${BOOST_CPPFLAGS} \
3 -I${top_srcdir}/mapi4linux/include \
4 -I${top_srcdir}/provider/libserver -I${top_srcdir}/provider/plugins \
5 -I${top_srcdir}/provider/include -I${top_srcdir}/provider/common \
6 -I${top_srcdir}/provider/client -I${top_builddir}/provider/soap \
7 -I${top_srcdir}/provider/soap \
8 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon \
9 -DPKGLIBDIR='"${pkglibdir}"' \
10 ${MYSQL_INCLUDES} ${GSOAP_CFLAGS} ${SSL_CFLAGS} \
11 ${SSL_HAS_EVP_PKEY_CMP} ${KRB5_CFLAGS} ${TCMALLOC_CFLAGS}
12
13 # We are not actually using any linked symbols from tcmalloc's header files,
14 # so linking to tcmalloc is not done, not here at least. It is done in
15 # provider/*/Makefile.am. Probably such that other components including
16 # libkcserver.la (provider/plugins/) _don't_ get tcmalloc.
17
18 pkginclude_HEADERS = include/kopano/ECPluginSharedData.h
19
20 lib_LTLIBRARIES = libkcserver.la
21 #noinst_DATA = libkcserver.ldd
22
23 libkcserver_la_SOURCES = \
24 cmd.cpp cmd.hpp \
25 ECABObjectTable.cpp ECABObjectTable.h \
26 ECCacheManager.cpp ECCacheManager.h \
27 ECDBDef.h ECDatabase.h \
28 ECDatabaseFactory.cpp ECDatabaseFactory.h \
29 ECDatabaseMySQL.cpp ECDatabaseMySQL.h \
30 ECDatabaseUtils.cpp ECDatabaseUtils.h \
31 ECDatabaseUpdate.cpp ECDatabaseUpdate.h \
32 ECGenProps.cpp ECGenProps.h \
33 ECGenericObjectTable.cpp ECGenericObjectTable.h \
34 ECICS.cpp ECICS.h \
35 ECICSHelpers.cpp ECICSHelpers.h \
36 ECMAPI.h \
37 ECNotification.cpp ECNotification.h \
38 ECPluginFactory.cpp ECPluginFactory.h \
39 ECPluginSharedData.cpp ECPluginSharedData.h \
40 ECPamAuth.cpp ECPamAuth.h \
41 ECKrbAuth.cpp ECKrbAuth.h \
42 ECSecurity.cpp ECSecurity.h \
43 ECServerEntrypoint.cpp ECServerEntrypoint.h \
44 ECSession.cpp ECSession.h \
45 ECSessionGroup.cpp ECSessionGroup.h \
46 ECSessionManager.cpp ECSessionManager.h \
47 ECStoreObjectTable.cpp ECStoreObjectTable.h \
48 ECStringCompat.cpp ECStringCompat.h \
49 ECSubRestriction.cpp ECSubRestriction.h \
50 ECTableManager.cpp ECTableManager.h \
51 ECUserManagement.cpp ECUserManagement.h \
52 ECSessionManagerOffline.cpp ECSessionManagerOffline.h \
53 ECUserManagementOffline.cpp ECUserManagementOffline.h \
54 ECSecurityOffline.cpp ECSecurityOffline.h \
55 ECSearchFolders.cpp ECSearchFolders.h \
56 ECSearchObjectTable.cpp ECSearchObjectTable.h \
57 ECConvenientDepthObjectTable.cpp ECConvenientDepthObjectTable.h \
58 ECConvenientDepthABObjectTable.cpp ECConvenientDepthABObjectTable.h \
59 ECMultiStoreTable.cpp ECMultiStoreTable.h \
60 ECUserStoreTable.cpp ECUserStoreTable.h \
61 ECConversion.cpp ECConversion.h \
62 ECS3Attachment.cpp ECS3Attachment.h \
63 ECAttachmentStorage.cpp ECAttachmentStorage.h \
64 ECStatsCollector.cpp ECStatsCollector.h \
65 ECStatsTables.cpp ECStatsTables.h \
66 ECNotificationManager.cpp ECNotificationManager.h \
67 ECIndexer.cpp ECIndexer.h \
68 StreamUtil.cpp StreamUtil.h \
69 StorageUtil.cpp StorageUtil.h \
70 ECTPropsPurge.cpp ECTPropsPurge.h \
71 ECMailBoxTable.cpp ECMailBoxTable.h \
72 ECTestProtocol.cpp ECTestProtocol.h \
73 cmdutil.cpp cmdutil.hpp logontime.cpp logontime.hpp \
74 ECLockManager.cpp ECLockManager.h
75 libkcserver_la_LIBADD = \
76 ../../common/libkcutil.la ../common/libkccommon.la \
77 -lpthread ${icu_i18n_LIBS} ${icu_uc_LIBS} \
78 ${KRB5_LIBS} ${MYSQL_LIBS} ${PAM_LIBS} ${SSL_LIBS} \
79 ${TCMALLOC_LIBS} ${s3_LIBS}
80 libkcserver_la_LDFLAGS = ${AM_LDFLAGS} \
81 -Wl,--version-script=${top_builddir}/default.sym
82 EXTRA_libkcserver_la_DEPENDENCIES = ${top_builddir}/default.sym
83
84
85 check-syntax:
86 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
87 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
88
89 include ../../global.am
0 Libserver
1 =========
2
3 Libserver is splitted for historical reasons in libserver/server.
4 There is no reason to keep this code in different places.
5
6
7 ECCacheManager
8 --------------
9
10 The ECCacheManager caches some specific MySQL table items in a hash map.
11 For example for the hierarchtable it is stored as <id, (hierarchyid, parentid, fooid>.
12 When the cache limit is hit, we randomly remove 5% of the items.
13
14 The sort() operation on unordered hashmaps is very expensive
15 so you might notice cache spikes everytime the cache is cleaned.
16 A possible solution is randomly removing the cache entries.
17
18 +-------------------------------------------------------------+
19 | |
20 | |
21 cache --+| xxxxxxxx xxxxxxxx xxxxxxxxxx xxxxxxxxxxxxxx|
22 limit | xxx x x x x x x |
23 | xxxx x x x |
24 | xxxx |
25 | xx |
26 | xxx |
27 | xxxx |
28 |xxx |
29 xx------------------------------------------------------------+
2727 // External objects
2828 extern ECSessionManager *g_lpSessionManager; // ECServerEntrypoint.cpp
2929
30
3130 ECRESULT CreateAttachmentStorage(ECDatabase *lpDatabase, ECAttachmentStorage **lppAttachmentStorage)
3231 {
3332 return ECAttachmentStorage::CreateAttachmentStorage(lpDatabase, g_lpSessionManager->GetConfig(), lppAttachmentStorage);
3433 }
35
3634
3735 ECRESULT CreateObject(ECSession *lpecSession, ECDatabase *lpDatabase, unsigned int ulParentObjId, unsigned int ulParentType, unsigned int ulObjType, unsigned int ulFlags, unsigned int *lpulObjId)
3836 {
7876 return erSuccess;
7977 }
8078
81
8279 /* Get the size of an object, PR_MESSAGE_SIZE or PR_ATTACH_SIZE */
8380 ECRESULT GetObjectSize(ECDatabase* lpDatabase, unsigned int ulObjId, unsigned int* lpulSize)
8481 {
117114
118115 return er;
119116 }
120
121117
122118 ECRESULT CalculateObjectSize(ECDatabase* lpDatabase, unsigned int objid, unsigned int ulObjType, unsigned int* lpulSize)
123119 {
201197
202198 return er;
203199 }
204
205200
206201 ECRESULT UpdateObjectSize(ECDatabase* lpDatabase, unsigned int ulObjId, unsigned int ulObjType, eSizeUpdateAction updateAction, long long llSize)
207202 {
4343 #include <map>
4444 #include <string>
4545
46 #ifdef _DEBUG
47 #define new DEBUG_NEW
48 #endif
49
5046 /*
5147 streams are as follows:
5248 <version>
5854 <# of sub objects>:32bit
5955 <subobject>
6056
61
6257 properties are as follows:
6358 <prop tag>:32bit
6459 [<length in bytes>:32bit]
6560 <data bytes>
6661 [<guid, kind, [id|bytes+string>]
67
6862
6963 subobjects are as follows:
7064 <type>:32bit
114108 nameidmap_t m_mapNameIds;
115109 namestringmap_t m_mapNameStrings;
116110 };
117
118111
119112 NamedPropertyMapper::NamedPropertyMapper(ECDatabase *lpDatabase)
120113 : m_lpDatabase(lpDatabase)
172165 // *lpulId now contains the local propid, update the cache
173166 m_mapNameIds.insert(nameidmap_t::value_type(key, *lpulId));
174167
175
176168 exit:
177169 if (lpResult)
178170 m_lpDatabase->FreeResult(lpResult);
230222 // *lpulId now contains the local propid, update the cache
231223 m_mapNameStrings.insert(namestringmap_t::value_type(key, *lpulId));
232224
233
234225 exit:
235226 if (lpResult)
236227 m_lpDatabase->FreeResult(lpResult);
237228
238229 return er;
239230 }
240
241231
242232 // Utility Functions
243233 ECRESULT SerializeDatabasePropVal(LPCSTREAMCAPS lpStreamCaps, DB_ROW lpRow, DB_LENGTHS lpLen, ECSerializer *lpSink)
338328 er = KCERR_NOT_FOUND;
339329 goto exit;
340330 }
341 li = _atoi64(lpRow[FIELD_NR_LONGINT]);
331 li = atoll(lpRow[FIELD_NR_LONGINT]);
342332 er = lpSink->Write(&li, sizeof(li), 1);
343333 break;
344334 case PT_STRING8:
505495 ulLastPos = 0;
506496 for (unsigned int x = 0; er == erSuccess && x < ulCount; ++x) {
507497 ParseMVProp(lpRow[FIELD_NR_LONGINT], lpLen[FIELD_NR_LONGINT], &ulLastPos, &strData);
508 li = _atoi64(strData.c_str());
498 li = atoll(strData.c_str());
509499 er = lpSink->Write(&li, sizeof(li), 1);
510500 }
511501 break;
553543 unsigned int ulLen;
554544 unsigned char b;
555545 unsigned int ulPropTag = sPropVal.ulPropTag;
556 std::string strData;
557546 convert_context converter;
558547 NamedPropDefMap::const_iterator iNamedPropDef;
559548
14191408 CopyPropVal(lpsPropval, lpPropValArray->__ptr + lpPropValArray->__size++);
14201409 }
14211410
1422
14231411 // Make sure we dont have a colliding PR_SOURCE_KEY. This can happen if a user imports an exported message for example.
14241412 if (lpsPropval->ulPropTag == PR_SOURCE_KEY) {
14251413 // don't use the sourcekey if found.
14401428 // We can't use lpDBRow here except for checking if it was NULL.
14411429 if (lpDBRow != NULL)
14421430 continue;
1443
14441431
14451432 strQuery = "REPLACE INTO indexedproperties(hierarchyid,tag,val_binary) VALUES (" + stringify(ulObjId) + "," + stringify(PROP_ID(PR_SOURCE_KEY)) + "," + lpDatabase->EscapeBinary(lpsPropval->Value.bin->__ptr, lpsPropval->Value.bin->__size) + ")";
14461433 er = lpDatabase->DoInsert(strQuery);
16481635 if (er != erSuccess)
16491636 goto exit;
16501637
1651
1652
16531638 if (ulParentType == MAPI_FOLDER) {
16541639 sObjectTableKey key(ulObjId, 0);
16551640 propVal sProp;
16761661 if (er != erSuccess)
16771662 goto exit;
16781663 }
1679
1680
16811664
16821665 if (ulRealObjType == MAPI_MESSAGE || ulRealObjType == MAPI_ATTACH) {
16831666 unsigned int ulSubObjCount = 0;
17961779 return er;
17971780 }
17981781
1799
18001782 ECRESULT GetValidatedPropType(DB_ROW lpRow, unsigned int *lpulType)
18011783 {
18021784 ECRESULT er = KCERR_DATABASE_ERROR;
18891871 *lpulType = ulType;
18901872 return erSuccess;
18911873 }
1892
1893 ECRESULT GetValidatedPropCount(ECDatabase *lpDatabase, DB_RESULT lpDBResult, unsigned int *lpulCount)
1894 {
1895 ECRESULT er;
1896 unsigned int ulCount = 0;
1897 DB_ROW lpRow;
1898
1899 if (lpDatabase == NULL || lpDBResult == NULL || lpulCount == 0)
1900 return KCERR_INVALID_PARAMETER;
1901
1902 while ((lpRow = lpDatabase->FetchRow(lpDBResult)) != NULL) {
1903 unsigned int ulType;
1904 er = GetValidatedPropType(lpRow, &ulType); // Ignore ulType, we just need the validation
1905 if (er == KCERR_DATABASE_ERROR) {
1906 ec_log_err("GetValidatedPropCount(): GetValidatedPropType failed");
1907 continue;
1908 } else if (er != erSuccess)
1909 return er;
1910 ++ulCount;
1911 }
1912
1913 lpDatabase->ResetResult(lpDBResult);
1914 *lpulCount = ulCount;
1915 return erSuccess;
1916 }
4949 ECRESULT DeserializeObject(ECSession *lpecSession, ECDatabase *lpDatabase, ECAttachmentStorage *lpAttachmentStorage, LPCSTREAMCAPS lpStreamInfo, unsigned int ulObjId, unsigned int ulStoreId, GUID *lpsGuid, bool bNewItem, unsigned long long ullIMAP, ECSerializer *lpSource, struct propValArray **lppPropValArray);
5050
5151 ECRESULT GetValidatedPropType(DB_ROW lpRow, unsigned int *lpulType);
52 ECRESULT GetValidatedPropCount(ECDatabase *lpDatabase, DB_RESULT lpDBResult, unsigned int *lpulCount);
5352
5453 #endif // ndef STREAMUTIL_H
7272 #include "ECTPropsPurge.h"
7373 #include "versions.h"
7474 #include "ECTestProtocol.h"
75 #include "ECTPropsPurge.h"
7675
7776 #include <kopano/ECDefs.h>
7877 #include <kopano/EMSAbTag.h>
8887 #include "logontime.hpp"
8988
9089 #if defined(HAVE_GPERFTOOLS_MALLOC_EXTENSION_H)
91 # include <gperftools/malloc_extension.h>
90 # include <gperftools/malloc_extension_c.h>
9291 #elif defined(HAVE_GOOGLE_MALLOC_EXTENSION_H)
93 # include <google/malloc_extension.h>
92 # include <google/malloc_extension_c.h>
9493 #endif
9594
9695 #define STRIN_FIX(s) (bSupportUnicode ? (s) : ECStringCompat::WTF1252_to_UTF8(soap, (s)))
9998
10099 #define LOG_SOAP_DEBUG(_msg, ...) \
101100 ec_log(EC_LOGLEVEL_DEBUG | EC_LOGLEVEL_SOAP, "soap: " _msg, ##__VA_ARGS__)
102
103 #ifdef _DEBUG
104 #define new DEBUG_NEW
105 #endif
106101
107102 extern ECSessionManager* g_lpSessionManager;
108103 extern ECStatsCollector* g_lpStatsCollector;
242237 if (ulUserId == 2) // Everyone, public in single tennant
243238 *lpbHasLocalStore = true;
244239 else
245 *lpbHasLocalStore = (stricmp(sDetails.GetPropString(OB_PROP_S_SERVERNAME).c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0);
240 *lpbHasLocalStore = (strcasecmp(sDetails.GetPropString(OB_PROP_S_SERVERNAME).c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0);
246241 } else // Archive store
247242 *lpbHasLocalStore = sDetails.PropListStringContains((property_key_t)PR_EC_ARCHIVE_SERVERS_A, g_lpSessionManager->GetConfig()->GetSetting("server_name"), true);
248243 } else // Single tennant
289284
290285 // First check if we're connecting through unix-socket/named-pipe and if the request url matches this server
291286 if (SOAP_CONNECTION_TYPE_NAMED_PIPE(soap) &&
292 stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0)
287 strcasecmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0)
293288 bResult = true;
294289
295290 else
587582 goto exit;
588583
589584 lpszEnabled = g_lpSessionManager->GetConfig()->GetSetting("enable_sso");
590 if (!(lpszEnabled && stricmp(lpszEnabled, "yes") == 0))
585 if (!(lpszEnabled && strcasecmp(lpszEnabled, "yes") == 0))
591586 goto nosso;
592587
593588 lpsResponse->lpszVersion = const_cast<char *>("0," PROJECT_VERSION_SERVER_STR);
784779 } \
785780 return SOAP_OK;
786781
787
788782 // This is the variadic macro we would like to use. Unfortunately, the win32 vc++ compiler
789783 // doesn't understand variadic macro's, so we have to split them into the cases below...
790784 #define SOAP_ENTRY_START(fname,resultvar,...) \
795789 #define SOAP_ENTRY_END() \
796790 SOAP_ENTRY_FUNCTION_FOOTER \
797791 }
798
799792
800793 #define ALLOC_DBRESULT() \
801794 DB_ROW UNUSED_VAR lpDBRow = NULL; \
823816 #define ROLLBACK_ON_ERROR() \
824817 if (lpDatabase && FAILED(er)) \
825818 lpDatabase->Rollback(); \
826
827819
828820 static ECRESULT PurgeSoftDelete(ECSession *lpecSession,
829821 unsigned int ulLifetime, unsigned int *lpulMessages,
10831075 }
10841076
10851077 /* Do we own the store? */
1086 if (stricmp(strThisServer.c_str(), strStoreServer.c_str()) != 0)
1078 if (strcasecmp(strThisServer.c_str(), strStoreServer.c_str()) != 0)
10871079 {
10881080 if ((ulFlags & EC_OVERRIDE_HOMESERVER) == 0) {
10891081 er = GetBestServerPath(soap, lpecSession, strStoreServer, &strServerPath);
11771169 er = KCERR_NOT_FOUND;
11781170 goto exit;
11791171 }
1180 if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
1172 if (strcasecmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
11811173 er = GetBestServerPath(soap, lpecSession, strServerName, &strServerPath);
11821174 if (er != erSuccess)
11831175 goto exit;
15191511 if(er != erSuccess)
15201512 goto exit;
15211513
1522
15231514 exit:
15241515 FREE_DBRESULT();
15251516
16491640 if(lpDBRow == NULL || lpDBRow[0] == NULL)
16501641 llSize = 0;
16511642 else
1652 llSize = _atoi64(lpDBRow[0]);
1643 llSize = atoll(lpDBRow[0]);
16531644
16541645 // Free results
16551646 if(lpDBResult) { lpDatabase->FreeResult(lpDBResult); lpDBResult = NULL; }
20252016
20262017 if (lpfHaveChangeKey && lpPropValArray->__ptr[i].ulPropTag == PR_CHANGE_KEY)
20272018 *lpfHaveChangeKey = true;
2028
20292019
20302020 if((PROP_TYPE(lpPropValArray->__ptr[i].ulPropTag) & MV_FLAG) == MV_FLAG) {
20312021 // Make sure string prop_types become PT_MV_STRING8
23032293
23042294 g_lpSessionManager->GetCacheManager()->SetObjectProp(PROP_ID(PR_SOURCE_KEY), sSourceKey.size(), sSourceKey, ulObjId);
23052295 }
2306
23072296
23082297 if(ulParentType == MAPI_FOLDER) {
23092298 // Add a PR_EC_IMAP_ID to the newly created message
27062695 ++n;
27072696 }
27082697
2709
27102698 // set actual array size
27112699 lpsReturnObj->delProps.__size = n;
27122700 lpsReturnObj->modProps.__size = n;
31933181 goto exit;
31943182 }
31953183
3196 if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
3184 if (strcasecmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
31973185 er = KCERR_UNABLE_TO_COMPLETE; // Reason 2
31983186 goto exit;
31993187 }
32323220 ulParentObjType = MAPI_FOLDER;
32333221 } else if(ulObjType == MAPI_FOLDER) {
32343222
3235
32363223 // Disable searchfolder for delegate stores without admin permissions
32373224 if ( (ulObjFlags&FOLDER_SEARCH) && lpecSession->GetSecurity()->GetAdminLevel() == 0 &&
32383225 lpecSession->GetSecurity()->IsStoreOwner(ulObjId) != erSuccess)
33343321 if(er != erSuccess)
33353322 goto exit;
33363323
3337
33383324 while (!bExist && (lpDBRow = lpDatabase->FetchRow(lpDBResult)) != NULL) {
33393325 if (lpDBRow[0] == NULL || lpDBRow[1] == NULL) {
33403326 er = KCERR_DATABASE_ERROR;
33423328 goto exit;
33433329 }
33443330
3345 if (stricmp(lpDBRow[1], name) == 0)
3331 if (strcasecmp(lpDBRow[1], name) == 0)
33463332 bExist = true;
33473333 }
3348
33493334
33503335 if(bExist && !ulSyncId) {
33513336 // Check folder read access
34993484
35003485 // Update all tables viewing this folder
35013486 g_lpSessionManager->UpdateTables(ECKeyTable::TABLE_ROW_ADD, 0, ulParentId, ulFolderId, MAPI_FOLDER);
3502
35033487
35043488 // Update notification, grandparent of the mainfolder
35053489 g_lpSessionManager->UpdateTables(ECKeyTable::TABLE_ROW_MODIFY, 0, ulGrandParent, ulParentId, MAPI_FOLDER);
41624146 ECMultiStoreTable *lpMultiStoreTable = NULL;
41634147 ECListInt lObjectList;
41644148
4165
41664149 if(lpEntryList == NULL) {
41674150 er = KCERR_INVALID_PARAMETER;
41684151 goto exit;
48264809 er = KCERR_NOT_FOUND;
48274810 }
48284811
4829
48304812 exit:
48314813 FREE_DBRESULT();
48324814 }
49154897 FREE_DBRESULT();
49164898 }
49174899
4918
49194900 strQuery = "SELECT objid, id FROM receivefolder WHERE storeid="+stringify(ulStoreid)+" AND messageclass='"+lpDatabase->Escape(lpszMessageClass)+"'";
49204901 er = lpDatabase->DoSelect(strQuery, &lpDBResult);
49214902 if(er != erSuccess)
49524933 er = lpecSession->GetSecurity()->CheckPermission(ulStoreid, ecSecurityCreate);
49534934 if(er != erSuccess)
49544935 goto exit;
4955
49564936
49574937 if(bIsUpdate) {
49584938 strQuery = "UPDATE receivefolder SET objid="+stringify(ulId);
51505130 if(er != erSuccess)
51515131 goto exit;
51525132
5153
51545133 while( (lpDBRow = lpDatabase->FetchRow(lpDBResult)) )
51555134 {
51565135 if(lpDBRow[0] == NULL || lpDBRow[1] == NULL){
51935172 er = lpDatabase->DoUpdate(strQuery);
51945173 if(er != erSuccess)
51955174 goto exit;
5196
51975175
51985176 er = UpdateTProp(lpDatabase, PR_MESSAGE_FLAGS, ulParent, &lHierarchyIDs); // FIXME ulParent is not constant for all lHierarchyIDs
51995177 if(er != erSuccess)
57275705 er = g_lpSessionManager->GetCacheManager()->PurgeCache(ulFlags);
57285706
57295707 #ifdef HAVE_TCMALLOC
5730 MallocExtension::instance()->ReleaseFreeMemory();
5708 {
5709 auto rfm = reinterpret_cast<decltype(MallocExtension_ReleaseFreeMemory) *>
5710 (dlsym(NULL, "MallocExtension_ReleaseFreeMemory"));
5711 if (rfm != NULL)
5712 rfm();
5713 }
57315714 #endif
57325715
57335716 g_lpStatsCollector->SetTime(SCN_SERVER_LAST_CACHECLEARED, time(NULL));
59165899 if(er != erSuccess)
59175900 goto exit;
59185901
5919
59205902 // Set ACL's on public store
59215903 if(ulStoreType == ECSTORE_TYPE_PUBLIC) {
59225904 // ulUserId == a group
71507132 if(er != erSuccess)
71517133 goto exit;
71527134
7153
71547135 // Remove messge from the outgoing queue
71557136 g_lpSessionManager->UpdateOutgoingTables(ECKeyTable::TABLE_ROW_DELETE, ulStoreId, ulObjId, ulFlags, MAPI_MESSAGE);
71567137
72657246 g_lpSessionManager->NotificationModified(MAPI_MESSAGE, ulObjId, ulParentId);
72667247 g_lpSessionManager->GetCacheManager()->Update(fnevObjectModified, ulParentId);
72677248 g_lpSessionManager->NotificationModified(MAPI_FOLDER, ulParentId);
7268
72697249
72707250 g_lpSessionManager->UpdateTables(ECKeyTable::TABLE_ROW_MODIFY, 0, ulParentId, ulObjId, MAPI_MESSAGE);
72717251 if(g_lpSessionManager->GetCacheManager()->GetParent(ulParentId, &ulGrandParentId) == erSuccess) {
74287408 goto exit;
74297409 }
74307410
7431 if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
7411 if (strcasecmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
74327412 if ((ulFlags & OPENSTORE_OVERRIDE_HOME_MDB) == 0) {
74337413 string strServerPath;
74347414
76957675 // Check whether it is a move to the same parent, and if so, skip them.
76967676 if(iterCopyItems->ulParent == ulDestFolderId && (iterCopyItems->ulFlags&MSGFLAG_DELETED) == 0)
76977677 continue;
7698
76997678
77007679 er = g_lpSessionManager->GetCacheManager()->GetEntryIdFromObject(iterCopyItems->ulId, NULL, 0, &lpsOldEntryId);
77017680 if(er != erSuccess) {
79037882 }
79047883 }
79057884
7906
79077885 lstParent.sort();
79087886 lstParent.unique();
79097887
81758153 lpsNewEntryId = NULL;
81768154 }
81778155
8178
81798156 // Get child items of the message like , attachment, recipient...
81808157 strQuery = "SELECT id FROM hierarchy WHERE parent="+stringify(ulObjId);
81818158 er = lpDatabase->DoSelect(strQuery, &lpDBResult);
81828159 if (er != erSuccess) {
8183 ec_log_err("CopyObject: failed retriving child items of mesage: %s (%x)", GetMAPIErrorMessage(er), er);
8160 ec_log_err("CopyObject: failed retrieving child items of message: %s (%x)", GetMAPIErrorMessage(er), er);
81848161 goto exit;
81858162 }
81868163
83208297 }
83218298 }
83228299
8323
83248300 g_lpSessionManager->GetCacheManager()->Update(fnevObjectModified, ulDestFolderId);
83258301
83268302 if(bDoNotification){
84988474 GetSourceKey(ulNewDestFolderId, &sSourceKey);
84998475
85008476 AddChange(lpecSession, ulSyncId, sSourceKey, sParentSourceKey, ICS_FOLDER_CHANGE);
8501
85028477
85038478 //Select all Messages of the home folder
85048479 // Skip deleted and associated items
91039078 er = lpDatabase->DoSelect(strQuery, &lpDBResult);
91049079 if(er != erSuccess)
91059080 goto exit;
9106
91079081
91089082 ulRows = lpDatabase->GetNumRows(lpDBResult);
91099083
1046510439
1046610440 SOAP_ENTRY_START(getLicenseAuth, lpsResponse->er, struct xsd__base64Binary sAuthData, struct getLicenseAuthResponse *lpsResponse)
1046710441 {
10468 #ifdef LINUX
1046910442 ECLicenseClient *lpLicenseClient = new ECLicenseClient();
10470 unsigned char *data = NULL;
10443 void *data = NULL;
1047110444
1047210445 er = lpLicenseClient->Auth(sAuthData.__ptr, sAuthData.__size, &data, reinterpret_cast<unsigned int *>(&lpsResponse->sAuthResponse.__size));
1047310446 if (er != erSuccess)
1047710450 memcpy(lpsResponse->sAuthResponse.__ptr, data, lpsResponse->sAuthResponse.__size);
1047810451
1047910452 exit:
10480 delete[] data;
10453 free(data);
1048110454 delete lpLicenseClient;
10482 #else
10483 er = KCERR_NOT_IMPLEMENTED;
10484 #endif
1048510455 }
1048610456 SOAP_ENTRY_END()
1048710457
1048810458 SOAP_ENTRY_START(getLicenseCapa, lpsResponse->er, unsigned int ulServiceType, struct getLicenseCapaResponse *lpsResponse)
1048910459 {
10490 #ifdef LINUX
1049110460 ECLicenseClient *lpLicenseClient = new ECLicenseClient();
1049210461 std::vector<std::string> lstCapabilities;
1049310462
1050310472 exit:
1050410473
1050510474 delete lpLicenseClient;
10506 #else
10507 er = KCERR_NOT_IMPLEMENTED;
10508 #endif
1050910475 }
1051010476 SOAP_ENTRY_END()
1051110477
1051210478 SOAP_ENTRY_START(getLicenseUsers, lpsResponse->er, unsigned int ulServiceType, struct getLicenseUsersResponse *lpsResponse)
1051310479 {
10514 #ifdef LINUX
1051510480 unsigned int ulUsers = 0;
1051610481
1051710482 ECLicenseClient *lpLicenseClient = new ECLicenseClient();
1052610491 exit:
1052710492
1052810493 delete lpLicenseClient;
10529 #else
10530 er = KCERR_NOT_IMPLEMENTED;
10531 #endif
1053210494 }
1053310495 SOAP_ENTRY_END()
1053410496
1056210524 goto exit;
1056310525
1056410526 lpsResponse->lpszServerPath = STROUT_FIX_CPY(strServerPath.c_str());
10565 lpsResponse->bIsPeer = stricmp(g_lpSessionManager->GetConfig()->GetSetting("server_name"), lpszPseudoUrl + 9) == 0;
10527 lpsResponse->bIsPeer = strcasecmp(g_lpSessionManager->GetConfig()->GetSetting("server_name"), lpszPseudoUrl + 9) == 0;
1056610528
1056710529 exit:
1056810530 ;
1061110573 goto exit;
1061210574
1061310575
10614 if (stricmp(sDetails.GetServerName().c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0)
10576 if (strcasecmp(sDetails.GetServerName().c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) == 0)
1061510577 lpsResponse->sServerList.__ptr[i].ulFlags |= EC_SDFLAG_IS_PEER;
1061610578
1061710579 // note: "contains a public of a company" is also a possibility
10618 if (!strPublicServer.empty() && stricmp(sDetails.GetServerName().c_str(), strPublicServer.c_str()) == 0)
10580 if (!strPublicServer.empty() && strcasecmp(sDetails.GetServerName().c_str(), strPublicServer.c_str()) == 0)
1061910581 lpsResponse->sServerList.__ptr[i].ulFlags |= EC_SDFLAG_HAS_PUBLIC;
1062010582
1062110583 if ((ulFlags & EC_SERVERDETAIL_NO_NAME) != EC_SERVERDETAIL_NO_NAME)
1068210644 MTOMSessionInfo *lpSessionInfo;
1068310645 } MTOMStreamInfo;
1068410646
10685
1068610647 typedef MTOMStreamInfo * LPMTOMStreamInfo;
1068710648
1068810649 static ECRESULT SerializeObject(void *arg)
1080810769 delete lpInfo->lpThreadPool;
1080910770 delete lpInfo;
1081010771 }
10811
1081210772
1081310773 SOAP_ENTRY_START(exportMessageChangesAsStream, lpsResponse->er, unsigned int ulFlags, struct propTagArray sPropTags, struct sourceKeyPairArray sSourceKeyPairs, unsigned int ulPropTag, exportMessageChangesAsStreamResponse *lpsResponse)
1081410774 {
1110811068 soap->error = SOAP_FATAL_ERROR;
1110911069 }
1111011070 }
11111
1111211071
1111311072 SOAP_ENTRY_START(importMessageFromStream, *result, unsigned int ulFlags, unsigned int ulSyncId, entryId sFolderEntryId, entryId sEntryId, bool bIsNew, struct propVal *lpsConflictItems, struct xsd__Binary sStreamData, unsigned int *result)
1111411073 {
1141811377 if (er != erSuccess)
1141911378 goto exit;
1142011379
11421
1142211380 // Get the Change Key
1142311381 strQuery = "SELECT val_binary FROM properties "
1142411382 "WHERE tag = " + stringify(PROP_ID(PR_CHANGE_KEY)) +
1144511403 }
1144611404
1144711405 FREE_DBRESULT();
11448
1144911406
1145011407 // Get the Predecessor Change List
1145111408 strQuery = "SELECT val_binary FROM properties "
1616
1717 #include <kopano/platform.h>
1818
19 // STL defines
2019 #include <exception>
2120 #include <set>
2221 #include <string>
2322 #include <list>
2423 #include <map>
2524
26 // mapi defines
2725 #include <mapidefs.h>
2826 #include <mapitags.h>
2927 #include <kopano/mapiext.h>
4846 #define FIELD_NR_NAMEID (FIELD_NR_MAX + 1)
4947 #define FIELD_NR_NAMESTR (FIELD_NR_MAX + 2)
5048 #define FIELD_NR_NAMEGUID (FIELD_NR_MAX + 3)
51
52 #ifdef _DEBUG
53 #define new DEBUG_NEW
54 #endif
5549
5650 extern ECSessionManager* g_lpSessionManager; // FIXME: remove this global and change the depended source code!
5751 extern ECStatsCollector* g_lpStatsCollector;
510504 PARENTINFO pi;
511505
512506 std::map<unsigned int, PARENTINFO> mapFolderCounts;
513 std::map<unsigned int, PARENTINFO>::const_iterator iterFolderCounts;
514507
515508 // Build where condition
516509 for (iterDeleteItems=lstDeleteItems.begin();
13431336 return erSuccess;
13441337 }
13451338
1346
13471339 ECRESULT CheckQuota(ECSession *lpecSession, ULONG ulStoreId)
13481340 {
13491341 ECRESULT er;
13841376 ECRESULT UpdateFolderCounts(ECDatabase *lpDatabase, ULONG ulParentId, ULONG ulFlags, propValArray *lpModProps)
13851377 {
13861378 ECRESULT er = erSuccess;
1387 struct propVal *lpPropMessageFlags = NULL; // non-free
13881379
13891380 if (ulFlags & MAPI_ASSOCIATED)
13901381 er = UpdateFolderCount(lpDatabase, ulParentId, PR_ASSOC_CONTENT_COUNT, 1);
13911382 else {
13921383 er = UpdateFolderCount(lpDatabase, ulParentId, PR_CONTENT_COUNT, 1);
1393
1384 struct propVal *lpPropMessageFlags = NULL;
13941385 lpPropMessageFlags = FindProp(lpModProps, PR_MESSAGE_FLAGS);
13951386 if (er == erSuccess && (!lpPropMessageFlags || (lpPropMessageFlags->Value.ul & MSGFLAG_READ) == 0))
13961387 er = UpdateFolderCount(lpDatabase, ulParentId, PR_CONTENT_UNREAD, 1);
7474 return d->usType;
7575 }
7676
77 #if 0
78 unsigned int flags() const {
79 auto d = reinterpret_cast<EID_V0 *>(const_cast<char *>(m_data.data()));
80 if (m_data.size() < offsetof(EID_V0, usFlags) + sizeof(d->usFlags)) {
81 ec_log_err("%s: entryid has size %zu; not enough for EID_V0.usFlags",
82 __func__, m_data.size());
83 throw runtime_error("entryid is not of type EID_V0");
84 }
85 return d->usFlags;
86 }
87 #endif
88
8977 void setFlags(unsigned int ulFlags) {
9078 auto d = reinterpret_cast<EID_V0 *>(const_cast<char *>(m_data.data()));
9179 if (m_data.size() < offsetof(EID_V0, usFlags) + sizeof(d->usFlags)) {
5353 unsigned int m_ulRefCount;
5454
5555 /**
56 * Constructor
57 *
5856 * @param[in] lpParent
5957 * Pointer to ECConfig to read configuration option from the server
6058 * @param[in] lpStatsCollector
7068 * while the plugin doesn't support multi-server.
7169 */
7270 ECPluginSharedData(ECConfig *lpParent, ECStatsCollector *, bool bHosted, bool bDistributed);
73
74 /**
75 * Default destructor
76 */
7771 virtual ~ECPluginSharedData(void);
7872
7973 public:
9696 objectdetails_t details;
9797 objectid_t lastid;
9898 objectid_t curid;
99 std::list<objectid_t>::const_iterator iterID;
10099
101100 if(objectids.empty())
102101 return std::unique_ptr<std::map<objectid_t, objectdetails_t> >(mapdetails);
182181 details.SetPropString(OB_PROP_O_SYSADMIN, lpDBRow[3]);
183182 } else if (strcmp(lpDBRow[2], OB_AB_HIDDEN) == 0)
184183 details.SetPropString(OB_PROP_B_AB_HIDDEN, lpDBRow[3]);
185 else if (strnicmp(lpDBRow[2], "0x", strlen("0x")) == 0) {
184 else if (strncasecmp(lpDBRow[2], "0x", strlen("0x")) == 0) {
186185 unsigned int key = xtoi(lpDBRow[2]);
187186 if (PROP_TYPE(key) == PT_BINARY)
188187 details.SetPropString((property_key_t)key, base64_decode(lpDBRow[3]));
231230
232231 lastid = curid;
233232
234 if (strnicmp(lpDBRow[0], "0x", strlen("0x")) == 0) {
233 if (strncasecmp(lpDBRow[0], "0x", strlen("0x")) == 0) {
235234 unsigned int key = xtoi(lpDBRow[0]);
236235 if (PROP_TYPE(key) == PT_BINARY || PROP_TYPE(key) == PT_MV_BINARY)
237236 iterDetails->second.AddPropString((property_key_t)key, base64_decode(lpDBRow[1]));
303302 bool bFirstOne = true;
304303 bool bFirstDel = true;
305304 string strData;
306 string strMD5Pw;
307305 property_map anonymousProps;
308306 property_map::const_iterator iterAnonymous;
309307 property_mv_map anonymousMVProps;
395393 while (sValidProps[i].column != NULL) {
396394 string propvalue = details.GetPropString(sValidProps[i].id);
397395
398 if (stricmp(sValidProps[i].column, OP_PASSWORD) == 0 && !propvalue.empty()) {
396 if (strcasecmp(sValidProps[i].column, OP_PASSWORD) == 0 && !propvalue.empty()) {
399397 // Password value has special treatment
400398 if (CreateMD5Hash(propvalue, &propvalue) != erSuccess) // WARNING input and output point to the same data
401399 throw runtime_error(string("db_changeUser: create md5"));
718716 std::unique_ptr<signatures_t> DBPlugin::searchObjects(const std::string &match,
719717 const char **search_props, const char *return_prop, unsigned int ulFlags)
720718 {
721 string signature;
722719 objectid_t objectid;
723720 std::unique_ptr<signatures_t> lpSignatures(new signatures_t());
724721
807804
808805 if (bGetUserDefault) {
809806 if (objectid.objclass != CONTAINER_COMPANY && strcmp(lpDBRow[0], OP_UD_HARDQUOTA) == 0)
810 lpDetails->llHardSize = _atoi64(lpDBRow[1]);
807 lpDetails->llHardSize = atoll(lpDBRow[1]);
811808 else if(objectid.objclass != CONTAINER_COMPANY && strcmp(lpDBRow[0], OP_UD_SOFTQUOTA) == 0)
812 lpDetails->llSoftSize = _atoi64(lpDBRow[1]);
809 lpDetails->llSoftSize = atoll(lpDBRow[1]);
813810 else if(strcmp(lpDBRow[0], OP_UD_WARNQUOTA) == 0)
814 lpDetails->llWarnSize = _atoi64(lpDBRow[1]);
811 lpDetails->llWarnSize = atoll(lpDBRow[1]);
815812 else if(strcmp(lpDBRow[0], OP_UD_USEDEFAULTQUOTA) == 0)
816813 lpDetails->bUseDefaultQuota = !!atoi(lpDBRow[1]);
817814 } else {
818815 if (objectid.objclass != CONTAINER_COMPANY && strcmp(lpDBRow[0], OP_HARDQUOTA) == 0)
819 lpDetails->llHardSize = _atoi64(lpDBRow[1]);
816 lpDetails->llHardSize = atoll(lpDBRow[1]);
820817 else if(objectid.objclass != CONTAINER_COMPANY && strcmp(lpDBRow[0], OP_SOFTQUOTA) == 0)
821 lpDetails->llSoftSize = _atoi64(lpDBRow[1]);
818 lpDetails->llSoftSize = atoll(lpDBRow[1]);
822819 else if(strcmp(lpDBRow[0], OP_WARNQUOTA) == 0)
823 lpDetails->llWarnSize = _atoi64(lpDBRow[1]);
820 lpDetails->llWarnSize = atoll(lpDBRow[1]);
824821 else if(strcmp(lpDBRow[0], OP_USEDEFAULTQUOTA) == 0)
825822 lpDetails->bUseDefaultQuota = !!atoi(lpDBRow[1]);
826823 }
10781075 throw runtime_error(string("db_query: ") + strerror(er));
10791076
10801077 while ((lpDBRow = m_lpDatabase->FetchRow(lpResult)) != NULL)
1081 if (lpDBRow[1] != NULL && stricmp(lpDBRow[1], strPropValue.c_str()) == 0)
1078 if (lpDBRow[1] != NULL && strcasecmp(lpDBRow[1], strPropValue.c_str()) == 0)
10821079 throw collision_error(string("Object exist: ") + strPropValue);
10831080
10841081 if (CoCreateGuid(&guidExternId) != S_OK)
7373 class DB_RESULT_AUTOFREE {
7474 public:
7575 /**
76 * Constructor
77 *
7876 * @param[in] lpDatabase
7977 * The database to which the result belongs
8078 */
8381 m_lpResult = NULL;
8482 };
8583
86 /**
87 * Destructor
88 *
89 * Calls ECDatabase::FreeResult()
90 */
9184 ~DB_RESULT_AUTOFREE() {
9285 if(m_lpDatabase && m_lpResult)
9386 m_lpDatabase->FreeResult(m_lpResult);
129122 class DBPlugin : public UserPlugin {
130123 public:
131124 /**
132 * Constructor
133 *
134125 * @param[in] pluginlock
135126 * The plugin mutex
136127 * @param[in] shareddata
138129 * @throw std::exception
139130 */
140131 DBPlugin(pthread_mutex_t *pluginlock, ECPluginSharedData *shareddata);
141
142 /**
143 * Destructor
144 */
145132 virtual ~DBPlugin();
146133
147134 /**
2323
2424 #include <cerrno>
2525 #include <cassert>
26 #ifdef HAVE_MALLOC_H
27 #include <malloc.h>
28 #endif
29
3026 #include <kopano/EMSAbTag.h>
3127 #include <kopano/ECConfig.h>
3228 #include <kopano/ECDefs.h>
151147 if (lpDBRow[0] == NULL || lpDBRow[1] == NULL || lpDBRow[3] == NULL)
152148 throw runtime_error(string("db_row_failed: object null"));
153149
154 if (stricmp(lpDBRow[3], name.c_str()) != 0)
150 if (strcasecmp(lpDBRow[3], name.c_str()) != 0)
155151 continue;
156152
157153 lpDBLen = m_lpDatabase->FetchRowLengths(lpResult);
167163
168164 throw objectnotfound(name);
169165 }
170
171166
172167 objectsignature_t DBUserPlugin::authenticateUser(const string &username, const string &password, const objectid_t &company)
173168 {
222217 if (lpDBRow[0] == NULL || lpDBRow[1] == NULL || lpDBRow[2] == NULL || lpDBRow[4] == NULL)
223218 throw runtime_error("Trying to authenticate failed: database error");
224219
225 if (stricmp(lpDBRow[4], username.c_str()) != 0)
220 if (strcasecmp(lpDBRow[4], username.c_str()) != 0)
226221 continue;
227222
228223 lpDBLen = m_lpDatabase->FetchRowLengths(lpResult);
4040 class DBUserPlugin _kc_final : public DBPlugin {
4141 public:
4242 /**
43 * Constructor
44 *
4543 * @param[in] pluginlock
4644 * The plugin mutex
4745 * @param[in] shareddata
6967 * The company beneath which the name should be searched
7068 * This objectid can be empty.
7169 * @return The object signature of the resolved object
72 * @throw runtime_error When a Database error occured.
70 * @throw runtime_error When a Database error occurred.
7371 * @throw objectnotfound When no object was found.
7472 * @throw toomanyobjects When more then one object was found.
7573 */
8684 * The objectid of the company to which the user belongs.
8785 * This objectid can be empty.
8886 * @return The objectsignature of the authenticated user
89 * @throw runtime_error When a Database error occured.
87 * @throw runtime_error When a Database error occurred.
9088 * @throw login_error When no user was found or the password was incorrect.
9189 */
9290 virtual objectsignature_t authenticateUser(const string &username, const string &password, const objectid_t &company);
129127 * The objectid which should be updated
130128 * @param[in] quotadetails
131129 * The quota information which should be written to the object
132 * @throw runtime_error When a Database error occured.
130 * @throw runtime_error When a Database error occurred.
133131 * @throw objectnotfound When the object was not found.
134132 */
135133 virtual void setQuota(const objectid_t &id, const quotadetails_t &quotadetails);
178176 * The parent object.
179177 * @param[in] childobject
180178 * The child object.
181 * @throw runtime_error When a Database error occured
179 * @throw runtime_error When a Database error occurred
182180 * @throw objectnotfound When the parent does not exist.
183181 */
184182 virtual void addSubObjectRelation(userobject_relation_t relation,
175175 /* Key should be larger then current guess, but has to be smaller then the userobject dn */
176176 /* If key matches the end of the userobject dn, we have a positive match */
177177 if (it->second.size() > parent_dn.size() && it->second.size() < dn.size() &&
178 stricmp(dn.c_str() + (dn.size() - it->second.size()), it->second.c_str()) == 0) {
178 strcasecmp(dn.c_str() + (dn.size() - it->second.size()), it->second.c_str()) == 0) {
179179 parent_dn = it->second;
180180 entry = it->first;
181181 }
197197 /* Key should be larger then root DN */
198198 /* If key matches the end of the root dn, we have a positive match */
199199 if (iter->second.size() > dn.size() &&
200 stricmp(iter->second.c_str() + (iter->second.size() - dn.size()), dn.c_str()) == 0)
200 strcasecmp(iter->second.c_str() + (iter->second.size() - dn.size()), dn.c_str()) == 0)
201201 list->push_back(iter->second);
202202
203203 return list;
220220 /* Key should be larger or equal then user DN */
221221 /* If key matches the end of the user dn, we have a positive match */
222222 if (iter->size() <= dn.size() &&
223 stricmp(dn.c_str() + (dn.size() - iter->size()), iter->c_str()) == 0)
223 strcasecmp(dn.c_str() + (dn.size() - iter->size()), iter->c_str()) == 0)
224224 return true;
225225
226226 return false;
2727 #include <cerrno>
2828 #include <cassert>
2929 #include <sys/time.h> /* gettimeofday */
30 #ifdef HAVE_MALLOC_H
31 #include <malloc.h>
32 #endif
33
3430 #include <kopano/EMSAbTag.h>
3531 #include <kopano/ECConfig.h>
3632 #include <kopano/ECLogger.h>
493489 goto fail;
494490 }
495491
496 #if 0 // OpenLDAP stupidly closes the connection when TLS is not configured on the server.
497 #ifdef LINUX // Only available in Windows XP, so we can't use this on windows platform.
498 #ifdef HAVE_LDAP_START_TLS_S
499 // Initialize TLS-secured connection - this is the first command
500 // after ldap_init, so it will be the call that actually connects
501 // to the server.
502 if ((rc = ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS) {
503 ec_log_err("Failed to enable TLS on LDAP session: %s", ldap_err2string(rc));
504 goto fail;
505 }
506 #endif
507 #endif
508 #endif
509
510492 // Bind
511493 // For these two values: if they are both NULL, anonymous bind
512494 // will be used (ldap_binddn, ldap_bindpw)
735717 const char *class_dynamic_type = m_config->GetSetting("ldap_dynamicgroup_type_attribute_value");
736718
737719 FOREACH_ATTR(entry) {
738 if (class_attr && stricmp(att, class_attr) == 0)
720 if (class_attr && strcasecmp(att, class_attr) == 0)
739721 objclasses = getLDAPAttributeValues(att, entry);
740722
741 if (nonactive_attr && stricmp(att, nonactive_attr) == 0) {
723 if (nonactive_attr && strcasecmp(att, nonactive_attr) == 0) {
742724 nonactive_type = getLDAPAttributeValue(att, entry);
743725
744726 }
745727
746 if (resource_attr && stricmp(att, resource_attr) == 0)
728 if (resource_attr && strcasecmp(att, resource_attr) == 0)
747729 resource_type = getLDAPAttributeValue(att, entry);
748730
749 if (security_attr && stricmp(att, security_attr) == 0) {
731 if (security_attr && strcasecmp(att, security_attr) == 0) {
750732 security_type = getLDAPAttributeValue(att, entry);
751733
752734 }
753735
754 if (user_unique_attr && stricmp(att, user_unique_attr) == 0)
736 if (user_unique_attr && strcasecmp(att, user_unique_attr) == 0)
755737 user_unique = getLDAPAttributeValue(att, entry);
756738
757 if (group_unique_attr && stricmp(att, group_unique_attr) == 0)
739 if (group_unique_attr && strcasecmp(att, group_unique_attr) == 0)
758740 group_unique = getLDAPAttributeValue(att, entry);
759741
760 if (company_unique_attr && stricmp(att, company_unique_attr) == 0)
742 if (company_unique_attr && strcasecmp(att, company_unique_attr) == 0)
761743 company_unique = getLDAPAttributeValue(att, entry);
762744
763 if (addresslist_unique_attr && stricmp(att, addresslist_unique_attr) == 0)
745 if (addresslist_unique_attr && strcasecmp(att, addresslist_unique_attr) == 0)
764746 addresslist_unique = getLDAPAttributeValue(att, entry);
765747
766 if (dynamicgroup_unique_attr && stricmp(att, dynamicgroup_unique_attr) == 0)
748 if (dynamicgroup_unique_attr && strcasecmp(att, dynamicgroup_unique_attr) == 0)
767749 dynamicgroup_unique = getLDAPAttributeValue(att, entry);
768750 }
769751 END_FOREACH_ATTR
832814
833815 if (objclass == NONACTIVE_USER && !resource_type.empty()) {
834816 /* Overwrite objectclass, a resource is allowed to overwrite the nonactive type */
835 if (stricmp(resource_type.c_str(), "room") == 0)
817 if (strcasecmp(resource_type.c_str(), "room") == 0)
836818 objclass = NONACTIVE_ROOM;
837 else if (stricmp(resource_type.c_str(), "equipment") == 0)
819 else if (strcasecmp(resource_type.c_str(), "equipment") == 0)
838820 objclass = NONACTIVE_EQUIPMENT;
839821 }
840822
847829 }
848830
849831 if (objclass == OBJECTCLASS_DISTLIST) {
850 if (!stricmp(security_attr_type, "ads")) {
832 if (!strcasecmp(security_attr_type, "ads")) {
851833 if(atoi(security_type.c_str()) & 0x80000000)
852834 objclass = DISTLIST_SECURITY;
853835 else
872854 if (objclass == CONTAINER_ADDRESSLIST) {
873855 object_uid = addresslist_unique;
874856 }
875
876857
877858 return objectid_t(object_uid, objclass);
878859 }
920901 /* Needed for cache */
921902 CONFIG_TO_ATTR(request_attrs, modify_attr, "ldap_last_modification_attribute");
922903
923
924904 FOREACH_PAGING_SEARCH((char *)basedn.c_str(), scope,
925905 (char *)search_filter.c_str(), (char **)request_attrs->get(),
926906 FETCH_ATTR_VALS, res)
935915 }
936916
937917 FOREACH_ATTR(entry) {
938 if (modify_attr && stricmp(att, modify_attr) == 0)
918 if (modify_attr && strcasecmp(att, modify_attr) == 0)
939919 signature = getLDAPAttributeValue(att, entry);
940920 }
941921 END_FOREACH_ATTR
11401120 string search_data;
11411121
11421122 // Set binary uniqueid to escaped string
1143 if(attr_type && stricmp(attr_type, LDAP_DATA_TYPE_BINARY) == 0)
1123 if(attr_type && strcasecmp(attr_type, LDAP_DATA_TYPE_BINARY) == 0)
11441124 BintoEscapeSequence(data.c_str(), data.size(), &search_data);
11451125 else
11461126 search_data = StringEscapeSequence(data);
12571237 }
12581238
12591239 FOREACH_ATTR(entry) {
1260 if (stricmp(att, lpAttr) == 0) {
1240 if (strcasecmp(att, lpAttr) == 0) {
12611241 strData = getLDAPAttributeValue(att, entry);
12621242 bDataAttrFound = true;
12631243 }
13031283 }
13041284
13051285 FOREACH_ATTR(entry) {
1306 if (stricmp(att, lpAttr) == 0) {
1286 if (strcasecmp(att, lpAttr) == 0) {
13071287 strData = getLDAPAttributeValue(att, entry);
13081288 bAttrFound = true;
13091289 }
15081488 * and we must incur the penalty of having to resolve each entry one by one.
15091489 * When the relation attribute is not the DN, we can optimize the lookup
15101490 * by creating a single query that obtains all the required data in a single query. */
1511 if (lpAttrType && stricmp(lpAttrType, LDAP_DATA_TYPE_DN) == 0) {
1491 if (lpAttrType && strcasecmp(lpAttrType, LDAP_DATA_TYPE_DN) == 0) {
15121492 signatures = objectDNtoObjectSignatures(objclass, objects);
15131493 } else {
15141494 /* We have the full member list, create a new query that
16261606 gettimeofday(&tstart, NULL);
16271607
16281608 try {
1629 if (!stricmp(authmethod, "password")) {
1609 if (!strcasecmp(authmethod, "password")) {
16301610 id = authenticateUserPassword(username, password, company);
16311611 } else {
16321612 id = authenticateUserBind(username, password, company);
17201700 }
17211701
17221702 FOREACH_ATTR(entry) {
1723 if (loginname_attr && !stricmp(att, loginname_attr)) {
1703 if (loginname_attr && !strcasecmp(att, loginname_attr)) {
17241704 d.SetPropString(OB_PROP_S_LOGIN, m_iconv->convert(getLDAPAttributeValue(att, entry)));
1725 } else if (password_attr && !stricmp(att, password_attr)) {
1705 } else if (password_attr && !strcasecmp(att, password_attr)) {
17261706 d.SetPropString(OB_PROP_S_PASSWORD, getLDAPAttributeValue(att, entry));
17271707 }
17281708
1729 if (unique_attr && !stricmp(att, unique_attr)) {
1709 if (unique_attr && !strcasecmp(att, unique_attr)) {
17301710 signature.id.id = getLDAPAttributeValue(att, entry);
17311711 signature.id.objclass = ACTIVE_USER; // only users can authenticate
17321712 }
17331713
1734 if (nonactive_attr && !stricmp(att, nonactive_attr)) {
1714 if (nonactive_attr && !strcasecmp(att, nonactive_attr)) {
17351715 if (parseBool(getLDAPAttributeValue(att, entry)))
17361716 throw login_error("Cannot login as nonactive user");
17371717 }
17471727 if (signature.id.id.empty())
17481728 throw login_error("Trying to authenticate failed: uniqueid is empty or unreadable");
17491729
1750 if (!strnicmp("{CRYPT}", strCryptedpw.c_str(), 7)) {
1730 if (!strncasecmp("{CRYPT}", strCryptedpw.c_str(), 7)) {
17511731 if(checkPassword(PASSWORD_CRYPT, strPasswordConverted.c_str(), &(strCryptedpw.c_str()[7])) != 0)
17521732 throw login_error("Trying to authenticate failed: wrong username or password");
1753 } else if (!strnicmp("{MD5}", strCryptedpw.c_str(), 5)) {
1733 } else if (!strncasecmp("{MD5}", strCryptedpw.c_str(), 5)) {
17541734 if(checkPassword(PASSWORD_MD5, strPasswordConverted.c_str(), &(strCryptedpw.c_str()[5])) != 0)
17551735 throw login_error("Trying to authenticate failed: wrong username or password");
1756 } else if (!strnicmp("{SMD5}", strCryptedpw.c_str(), 6)) {
1736 } else if (!strncasecmp("{SMD5}", strCryptedpw.c_str(), 6)) {
17571737 if(checkPassword(PASSWORD_SMD5, strPasswordConverted.c_str(), &(strCryptedpw.c_str()[6])) != 0)
17581738 throw login_error("Trying to authenticate failed: wrong username or password");
1759 } else if (!strnicmp("{SSHA}", strCryptedpw.c_str(), 6)) {
1739 } else if (!strncasecmp("{SSHA}", strCryptedpw.c_str(), 6)) {
17601740 if(checkPassword(PASSWORD_SSHA, strPasswordConverted.c_str(), &(strCryptedpw.c_str()[6])) != 0)
17611741 throw login_error("Trying to authenticate failed: wrong username or password");
1762 } else if (!strnicmp("{SHA}", strCryptedpw.c_str(), 5)) {
1742 } else if (!strncasecmp("{SHA}", strCryptedpw.c_str(), 5)) {
17631743 if(checkPassword(PASSWORD_SHA, strPasswordConverted.c_str(), &(strCryptedpw.c_str()[5])) != 0)
17641744 throw login_error("Trying to authenticate failed: wrong username or password");
1765 } else if(!strnicmp("{MD5CRYPT}", strCryptedpw.c_str(), 10)) {
1745 } else if(!strncasecmp("{MD5CRYPT}", strCryptedpw.c_str(), 10)) {
17661746 throw login_error("Trying to authenticate failed: unsupported encryption scheme");
17671747 } else {
17681748 if(strcmp(strCryptedpw.c_str(), strPasswordConverted.c_str()) != 0) { //Plain password
17931773 else
17941774 return string();
17951775 }
1796
17971776
17981777 list<string> LDAPUserPlugin::getLDAPAttributeValues(char *attribute, LDAPMessage *entry) {
17991778 list<string> r;
18471826 /* That was easy ... */
18481827 if (objectids.empty())
18491828 return mapdetails;
1850
18511829
18521830 bool bCutOff = false;
18531831
20051983 ldap_filter += ")";
20061984 }
20071985
2008
20091986 FOREACH_PAGING_SEARCH((char *)ldap_basedn.c_str(), LDAP_SCOPE_SUBTREE,
20101987 (char *)ldap_filter.c_str(), (char **)request_attrs->get(),
20111988 FETCH_ATTR_VALS, res)
20282005 * We check the attribute for every match possible,
20292006 * because an attribute can be used in multiple config options
20302007 */
2031 if (ldap_addressbook_hide_attr && !stricmp(att, ldap_addressbook_hide_attr)) {
2008 if (ldap_addressbook_hide_attr && !strcasecmp(att, ldap_addressbook_hide_attr)) {
20322009 ldap_attr = getLDAPAttributeValue(att, entry);
20332010 sObjDetails.SetPropBool(OB_PROP_B_AB_HIDDEN, parseBool(ldap_attr.c_str()));
20342011 }
2035
20362012
20372013 for (std::list<configsetting_t>::const_iterator iter = lExtraAttrs.begin();
20382014 iter != lExtraAttrs.end(); ++iter) {
20422018 * The value should be set to something, as protection to make sure
20432019 * the name is a property tag all names should be prefixed with '0x'.
20442020 */
2045 if (stricmp(iter->szValue, att) != 0 || strnicmp(iter->szName, "0x", strlen("0x")) != 0)
2021 if (strcasecmp(iter->szValue, att) != 0 || strncasecmp(iter->szName, "0x", strlen("0x")) != 0)
20462022 continue;
20472023
20482024 ulPropTag = xtoi(iter->szName);
21482124 case NONACTIVE_ROOM:
21492125 case NONACTIVE_EQUIPMENT:
21502126 case NONACTIVE_CONTACT:
2151 if (loginname_attr && !stricmp(att, loginname_attr)) {
2127 if (loginname_attr && !strcasecmp(att, loginname_attr)) {
21522128 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
21532129 sObjDetails.SetPropString(OB_PROP_S_LOGIN, ldap_attr);
21542130 }
21552131
2156 if (user_fullname_attr && !stricmp(att, user_fullname_attr)) {
2132 if (user_fullname_attr && !strcasecmp(att, user_fullname_attr)) {
21572133 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
21582134 sObjDetails.SetPropString(OB_PROP_S_FULLNAME, ldap_attr);
21592135 }
21602136
2161 if (password_attr && !stricmp(att, password_attr)) {
2137 if (password_attr && !strcasecmp(att, password_attr)) {
21622138 ldap_attr = getLDAPAttributeValue(att, entry);
21632139 sObjDetails.SetPropString(OB_PROP_S_PASSWORD, ldap_attr);
21642140 }
21652141
2166 if (emailaddress_attr && !stricmp(att, emailaddress_attr)) {
2142 if (emailaddress_attr && !strcasecmp(att, emailaddress_attr)) {
21672143 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
21682144 sObjDetails.SetPropString(OB_PROP_S_EMAIL, ldap_attr);
21692145 }
21702146
2171 if (emailaliases_attr && !stricmp(att, emailaliases_attr)) {
2147 if (emailaliases_attr && !strcasecmp(att, emailaliases_attr)) {
21722148 ldap_attrs = getLDAPAttributeValues(att, entry);
21732149 sObjDetails.SetPropListString(OB_PROP_LS_ALIASES, ldap_attrs);
21742150 }
21752151
2176 if (isadmin_attr && !stricmp(att, isadmin_attr)) {
2152 if (isadmin_attr && !strcasecmp(att, isadmin_attr)) {
21772153 ldap_attr = getLDAPAttributeValue(att, entry);
21782154 sObjDetails.SetPropInt(OB_PROP_I_ADMINLEVEL, min(2, atoi(ldap_attr.c_str())));
21792155 }
21802156
2181 if (resource_type_attr && !stricmp(att, resource_type_attr)) {
2157 if (resource_type_attr && !strcasecmp(att, resource_type_attr)) {
21822158 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
21832159 sObjDetails.SetPropString(OB_PROP_S_RESOURCE_DESCRIPTION, ldap_attr);
21842160 }
21852161
2186 if (resource_capacity_attr && !stricmp(att, resource_capacity_attr)) {
2162 if (resource_capacity_attr && !strcasecmp(att, resource_capacity_attr)) {
21872163 ldap_attr = getLDAPAttributeValue(att, entry);
21882164 sObjDetails.SetPropInt(OB_PROP_I_RESOURCE_CAPACITY, atoi(ldap_attr.c_str()));
21892165 }
21902166
2191 if (usercert_attr && !stricmp(att, usercert_attr)) {
2167 if (usercert_attr && !strcasecmp(att, usercert_attr)) {
21922168 ldap_attrs = getLDAPAttributeValues(att, entry);
21932169 sObjDetails.SetPropListString(OB_PROP_LS_CERTIFICATE, ldap_attrs);
21942170 }
21952171
2196 if (sendas_attr && !stricmp(att, sendas_attr)) {
2172 if (sendas_attr && !strcasecmp(att, sendas_attr)) {
21972173 postaction p;
21982174
21992175 p.objectid = objectid;
22122188 }
22132189
22142190 #ifdef WITH_MULTISERVER
2215 if (user_server_attr && !stricmp(att, user_server_attr)) {
2191 if (user_server_attr && !strcasecmp(att, user_server_attr)) {
22162192 ldap_attr = getLDAPAttributeValue(att, entry);
22172193 sObjDetails.SetPropString(OB_PROP_S_SERVERNAME, ldap_attr);
22182194 }
22202196 break;
22212197 case DISTLIST_GROUP:
22222198 case DISTLIST_SECURITY:
2223 if (group_fullname_attr && !stricmp(att, group_fullname_attr)) {
2199 if (group_fullname_attr && !strcasecmp(att, group_fullname_attr)) {
22242200 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
22252201 sObjDetails.SetPropString(OB_PROP_S_LOGIN, ldap_attr);
22262202 sObjDetails.SetPropString(OB_PROP_S_FULLNAME, ldap_attr);
22272203 }
22282204
2229 if (emailaddress_attr && !stricmp(att, emailaddress_attr)) {
2205 if (emailaddress_attr && !strcasecmp(att, emailaddress_attr)) {
22302206 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
22312207 sObjDetails.SetPropString(OB_PROP_S_EMAIL, ldap_attr);
22322208 }
22332209
2234 if (emailaliases_attr && !stricmp(att, emailaliases_attr)) {
2210 if (emailaliases_attr && !strcasecmp(att, emailaliases_attr)) {
22352211 ldap_attrs = getLDAPAttributeValues(att, entry);
22362212 sObjDetails.SetPropListString(OB_PROP_LS_ALIASES, ldap_attrs);
22372213 }
22382214
2239 if (sendas_attr && !stricmp(att, sendas_attr)) {
2215 if (sendas_attr && !strcasecmp(att, sendas_attr)) {
22402216 postaction p;
22412217
22422218 p.objectid = objectid;
22552231 }
22562232 break;
22572233 case DISTLIST_DYNAMIC:
2258 if (dynamicgroup_name_attr && !stricmp(att, dynamicgroup_name_attr)) {
2234 if (dynamicgroup_name_attr && !strcasecmp(att, dynamicgroup_name_attr)) {
22592235 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
22602236 sObjDetails.SetPropString(OB_PROP_S_LOGIN, ldap_attr);
22612237 sObjDetails.SetPropString(OB_PROP_S_FULLNAME, ldap_attr);
22622238 }
22632239
2264 if (emailaddress_attr && !stricmp(att, emailaddress_attr)) {
2240 if (emailaddress_attr && !strcasecmp(att, emailaddress_attr)) {
22652241 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
22662242 sObjDetails.SetPropString(OB_PROP_S_EMAIL, ldap_attr);
22672243 }
22682244
2269 if (emailaliases_attr && !stricmp(att, emailaliases_attr)) {
2245 if (emailaliases_attr && !strcasecmp(att, emailaliases_attr)) {
22702246 ldap_attrs = getLDAPAttributeValues(att, entry);
22712247 sObjDetails.SetPropListString(OB_PROP_LS_ALIASES, ldap_attrs);
22722248 }
22732249 break;
22742250 case CONTAINER_COMPANY:
2275 if (company_fullname_attr && !stricmp(att, company_fullname_attr)) {
2251 if (company_fullname_attr && !strcasecmp(att, company_fullname_attr)) {
22762252 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
22772253 sObjDetails.SetPropString(OB_PROP_S_LOGIN, ldap_attr);
22782254 sObjDetails.SetPropString(OB_PROP_S_FULLNAME, ldap_attr);
22792255 }
22802256
22812257 #ifdef WITH_MULTISERVER
2282 if (company_server_attr && !stricmp(att, company_server_attr)) {
2258 if (company_server_attr && !strcasecmp(att, company_server_attr)) {
22832259 ldap_attr = getLDAPAttributeValue(att, entry);
22842260 sObjDetails.SetPropString(OB_PROP_S_SERVERNAME, ldap_attr);
22852261 }
22862262 #endif
22872263
2288 if (sysadmin_attr && !stricmp(att, sysadmin_attr)) {
2264 if (sysadmin_attr && !strcasecmp(att, sysadmin_attr)) {
22892265 postaction p;
22902266
22912267 p.objectid = objectid;
23012277
23022278 break;
23032279 case CONTAINER_ADDRESSLIST:
2304 if (addresslist_name_attr && !stricmp(att, addresslist_name_attr)) {
2280 if (addresslist_name_attr && !strcasecmp(att, addresslist_name_attr)) {
23052281 ldap_attr = m_iconv->convert(getLDAPAttributeValue(att, entry));
23062282 sObjDetails.SetPropString(OB_PROP_S_LOGIN, ldap_attr);
23072283 sObjDetails.SetPropString(OB_PROP_S_FULLNAME, ldap_attr);
26012577 if(member_attr_rel == NULL || strlen(member_attr_rel) == 0)
26022578 member_attr_rel = unique_attr;
26032579
2604 if (member_attr_type && stricmp(member_attr_type, LDAP_DATA_TYPE_DN) == 0) {
2580 if (member_attr_type && strcasecmp(member_attr_type, LDAP_DATA_TYPE_DN) == 0) {
26052581 //ads
26062582 member_data = objectUniqueIDtoObjectDN(childobject);
26072583 } else { //LDAP_DATA_TYPE_ATTRIBUTE
26082584 //posix ldap
26092585 // FIXME: No binary support for member_attr_rel
2610 if (stricmp(member_attr_rel, unique_attr) == 0)
2586 if (strcasecmp(member_attr_rel, unique_attr) == 0)
26112587 member_data = childobject.id;
26122588 else
26132589 member_data = objectUniqueIDtoAttributeData(childobject, member_attr_rel);
27722748 // Get the DN for each of the returned entries
27732749 FOREACH_ENTRY(res) {
27742750 FOREACH_ATTR(entry) {
2775 if (member_attr && !stricmp(att, member_attr))
2751 if (member_attr && !strcasecmp(att, member_attr))
27762752 memberlist = getLDAPAttributeValues(att, entry);
27772753 }
27782754 END_FOREACH_ATTR
27882764 dn = GetLDAPEntryDN(entry);
27892765
27902766 FOREACH_ATTR(entry) {
2791 if (member_attr && !stricmp(att, member_attr))
2767 if (member_attr && !strcasecmp(att, member_attr))
27922768 ldap_member_filter = getLDAPAttributeValue(att, entry);
2793 if (base_attr && !stricmp(att, base_attr))
2769 if (base_attr && !strcasecmp(att, base_attr))
27942770 ldap_basedn = getLDAPAttributeValue(att, entry);
27952771 }
27962772 END_FOREACH_ATTR
28892865 LDAPMessage *entry = NULL;
28902866 string ldap_basedn;
28912867 string search_filter;
2892 string subfilter;
28932868 std::unique_ptr<objectdetails_t> details(new objectdetails_t(CONTAINER_COMPANY));
28942869
28952870 if (!m_bDistributed)
29312906 }
29322907
29332908 FOREACH_ATTR(entry) {
2934 if (unique_attr && !stricmp(att, unique_attr))
2909 if (unique_attr && !strcasecmp(att, unique_attr))
29352910 details->SetPropString(OB_PROP_S_SERVERNAME, m_iconv->convert(getLDAPAttributeValue(att, entry)));
29362911 }
29372912 END_FOREACH_ATTR
29532928 if (!m_bDistributed)
29542929 throw objectnotfound("Distributed not enabled");
29552930
2956
29572931 LOG_PLUGIN_DEBUG("%s", __FUNCTION__);
29582932
29592933 string strName;
29752949 FOREACH_ENTRY(res)
29762950 {
29772951 FOREACH_ATTR(entry) {
2978 if (name_attr && !stricmp(att, name_attr)) {
2952 if (name_attr && !strcasecmp(att, name_attr)) {
29792953 strName = m_iconv->convert(getLDAPAttributeValue(att, entry));
29802954 serverlist->push_back(strName);
29812955 }
30513025 }
30523026
30533027 FOREACH_ATTR(entry) {
3054 if (address_attr && !stricmp(att, address_attr)) {
3028 if (address_attr && !strcasecmp(att, address_attr)) {
30553029 strAddress = m_iconv->convert(getLDAPAttributeValue(att, entry));
30563030 }
3057 if (http_port_attr && !stricmp(att, http_port_attr)) {
3031 if (http_port_attr && !strcasecmp(att, http_port_attr)) {
30583032 strHttpPort = m_iconv->convert(getLDAPAttributeValue(att, entry));
30593033 }
3060 if (ssl_port_attr && !stricmp(att, ssl_port_attr)) {
3034 if (ssl_port_attr && !strcasecmp(att, ssl_port_attr)) {
30613035 strSslPort = m_iconv->convert(getLDAPAttributeValue(att, entry));
30623036 }
3063 if (file_path_attr && !stricmp(att, file_path_attr)) {
3037 if (file_path_attr && !strcasecmp(att, file_path_attr)) {
30643038 strFilePath = m_iconv->convert(getLDAPAttributeValue(att, entry));
30653039 }
3066 if (proxy_path_attr && !stricmp(att, proxy_path_attr)) {
3040 if (proxy_path_attr && !strcasecmp(att, proxy_path_attr)) {
30673041 strProxyPath = m_iconv->convert(getLDAPAttributeValue(att, entry));
30683042 }
30693043 }
31793153 // work parsing the results from the ber structs.
31803154 FOREACH_ENTRY(res) {
31813155 FOREACH_ATTR(entry) {
3182 if (usedefaults_attr && !stricmp(att, usedefaults_attr)) {
3156 if (usedefaults_attr && !strcasecmp(att, usedefaults_attr)) {
31833157 // Workarround quotaoverride == !usedefaultquota
31843158 quotaDetails->bUseDefaultQuota = !parseBool(getLDAPAttributeValue(att, entry));
3185 } else if (warnquota_attr && !stricmp(att, warnquota_attr)) {
3159 } else if (warnquota_attr && !strcasecmp(att, warnquota_attr)) {
31863160 quotaDetails->llWarnSize = fromstring<string, long long>(getLDAPAttributeValue(att, entry)) * multiplier;
3187 } else if (id.objclass != CONTAINER_COMPANY && softquota_attr && !stricmp(att, softquota_attr)) {
3161 } else if (id.objclass != CONTAINER_COMPANY && softquota_attr && !strcasecmp(att, softquota_attr)) {
31883162 quotaDetails->llSoftSize = fromstring<string, long long>(getLDAPAttributeValue(att, entry)) * multiplier;
3189 } else if (id.objclass != CONTAINER_COMPANY && hardquota_attr && !stricmp(att, hardquota_attr)) {
3163 } else if (id.objclass != CONTAINER_COMPANY && hardquota_attr && !strcasecmp(att, hardquota_attr)) {
31903164 quotaDetails->llHardSize = fromstring<string, long long>(getLDAPAttributeValue(att, entry)) * multiplier;
31913165 }
31923166 }
6666 * ldap_search_s.
6767 */
6868 LDAPUserPlugin(pthread_mutex_t *pluginlock, ECPluginSharedData *shareddata);
69
70 /**
71 * Destructor
72 */
7369 virtual ~LDAPUserPlugin();
7470
7571 /**
488484 * @param[in] uniqueid
489485 * The unique id which should be converted
490486 * @return the DN for the object
491 * @throw runtime_error When an error occured during the LDAP query.
487 * @throw runtime_error When an error occurred during the LDAP query.
492488 * @throw objectnotfound When no object was found with the given objectid.
493489 * @throw toomanyobjects When more then one object was returned with the objectid.
494490 */
529525 * The length of the binary data
530526 * @param[out] lpEscaped
531527 * Escaped string
532 * @return HRESULT
533528 */
534529 HRESULT BintoEscapeSequence(const char* lpdata, size_t size, string* lpEscaped);
535530
+0
-57
provider/plugins/Makefile.am less more
0 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) $(BOOST_CPPFLAGS) \
1 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon \
2 -I${top_srcdir}/provider/libserver \
3 -I${top_srcdir}/provider/common -I${top_srcdir}/mapi4linux/include
4
5 COMMON_PLUGIN_FILES = plugin.h
6 COMMON_DBPLUGIN_FILES = DBBase.h DBBase.cpp
7
8
9 pkglib_LTLIBRARIES =
10 noinst_DATA =
11
12 if WITH_UNIX
13 pkglib_LTLIBRARIES += unixplugin.la
14 #noinst_DATA += unixplugin.ldd
15 unixplugin_la_CPPFLAGS = ${AM_CPPFLAGS} $(MYSQL_INCLUDES)
16 unixplugin_la_SOURCES = UnixUserPlugin.cpp UnixUserPlugin.h $(COMMON_PLUGIN_FILES) $(COMMON_DBPLUGIN_FILES)
17 unixplugin_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version
18 unixplugin_la_LIBADD = \
19 ${top_builddir}/common/libkcutil.la \
20 ../libserver/libkcserver.la ${MYSQL_LIBS} ${CRYPT_LIBS}
21 endif
22
23 if WITH_LDAP
24 pkglib_LTLIBRARIES += ldapplugin.la
25 #noinst_DATA += ldapplugin.ldd
26 noinst_DATA += .libs/ldapmsplugin.so
27 ldapplugin_la_CPPFLAGS = ${AM_CPPFLAGS} $(LDAP_FLAGS) -DLDAP_THREAD_SAFE -DWITH_MULTISERVER
28 ldapplugin_la_SOURCES = LDAPUserPlugin.cpp LDAPUserPlugin.h LDAPCache.cpp LDAPCache.h ldappasswords.cpp ldappasswords.h $(COMMON_PLUGIN_FILES)
29 ldapplugin_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version
30 ldapplugin_la_LIBADD = \
31 ${top_builddir}/common/libkcutil.la \
32 ../libserver/libkcserver.la ${CRYPTO_LIBS} ${LDAP_LIBS}
33
34 .libs/ldapmsplugin.so: ldapplugin.la
35 ${AM_V_GEN}ln -fs ldapplugin.so .libs/ldapmsplugin.so
36
37 install-exec-local:
38 ln -fs ldapplugin.so ${DESTDIR}${pkglibdir}/ldapmsplugin.so
39
40 endif
41
42 # default plugin
43 pkglib_LTLIBRARIES += dbplugin.la
44 #noinst_DATA += dbplugin.ldd
45 dbplugin_la_CPPFLAGS = ${AM_CPPFLAGS} $(MYSQL_INCLUDES)
46 dbplugin_la_SOURCES = DBUserPlugin.cpp DBUserPlugin.h $(COMMON_PLUGIN_FILES) $(COMMON_DBPLUGIN_FILES)
47 dbplugin_la_LDFLAGS = -module -avoid-version
48 dbplugin_la_LIBADD = \
49 ${top_builddir}/common/libkcutil.la \
50 ../libserver/libkcserver.la ${MYSQL_LIBS}
51
52 check-syntax:
53 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(LDAP_FLAGS) \
54 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
55
56 include ../../global.am
3333 #include <shadow.h>
3434 #include <cerrno>
3535 #endif
36 #ifdef HAVE_MALLOC_H
37 #include <malloc.h>
38 #endif
39
4036 #include <kopano/EMSAbTag.h>
4137 #include <kopano/ECConfig.h>
4238 #include <kopano/ECDefs.h>
319315 // username or fullname
320316 if(ulFlags & EMS_AB_ADDRESS_LOOKUP) {
321317 matched =
322 (stricmp(pw->pw_name, (char*)match.c_str()) == 0) ||
323 (stricmp((char*)m_iconv->convert(pw->pw_gecos).c_str(), (char*)match.c_str()) == 0);
318 (strcasecmp(pw->pw_name, (char*)match.c_str()) == 0) ||
319 (strcasecmp((char*)m_iconv->convert(pw->pw_gecos).c_str(), (char*)match.c_str()) == 0);
324320 } else {
325321 matched =
326 (strnicmp(pw->pw_name, (char*)match.c_str(), match.size()) == 0) ||
327 (strnicmp((char*)m_iconv->convert(pw->pw_gecos).c_str(), (char*)match.c_str(), match.size()) == 0);
322 (strncasecmp(pw->pw_name, (char*)match.c_str(), match.size()) == 0) ||
323 (strncasecmp((char*)m_iconv->convert(pw->pw_gecos).c_str(), (char*)match.c_str(), match.size()) == 0);
328324 }
329325
330326 if (matched)
334330 if(ulFlags & EMS_AB_ADDRESS_LOOKUP)
335331 matched = (email == match);
336332 else
337 matched = (strnicmp((char*)email.c_str(), (char*)match.c_str(), match.size()) == 0);
333 matched = (strncasecmp((char*)email.c_str(), (char*)match.c_str(), match.size()) == 0);
338334
339335 return matched;
340336 }
344340 bool matched = false;
345341
346342 if(ulFlags & EMS_AB_ADDRESS_LOOKUP)
347 matched = stricmp(gr->gr_name, (char*)match.c_str()) == 0;
343 matched = strcasecmp(gr->gr_name, (char*)match.c_str()) == 0;
348344 else
349 matched = strnicmp(gr->gr_name, (char*)match.c_str(), match.size()) == 0;
345 matched = strncasecmp(gr->gr_name, (char*)match.c_str(), match.size()) == 0;
350346
351347 return matched;
352348 }
907903 return mapdetails;
908904 }
909905
910
911906 // -------------
912907 // private
913908 // -------------
4747 class UnixUserPlugin: public DBPlugin {
4848 public:
4949 /**
50 * Constructor
51 *
5250 * @param[in] pluginlock
5351 * The plugin mutex
5452 * @param[in] lpSharedData
5755 * @throw notsupported When multi-server or multi-company support is enabled.
5856 */
5957 UnixUserPlugin(pthread_mutex_t *pluginlock, ECPluginSharedData *lpSharedData);
60
61 /**
62 * Destructor
63 */
6458 virtual ~UnixUserPlugin();
6559
6660 /**
3030 #include "ldappasswords.h"
3131
3232 using namespace std;
33
3433
3534 static const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3635
232231 else
233232 return 1;
234233 }
235
236234
237235 char *encryptPassword(int type, const char *password) {
238236 switch(type) {
251249 }
252250 }
253251
254
255252 int checkPassword(int type, const char *password, const char *crypted) {
256253 switch(type) {
257254 case PASSWORD_CRYPT:
3131 #include <stdexcept>
3232 #include <iostream>
3333 #include <sstream>
34 #include <memory>
3534 #include <pthread.h>
3635 #include <kopano/ECPluginSharedData.h>
3736
122121 class UserPlugin {
123122 public:
124123 /**
125 * Constructor
126 *
127124 * @param[in] pluginlock
128125 * The plugin mutex
129126 * @param[in] shareddata
137134 m_bDistributed(shareddata->IsDistributed())
138135 {}
139136
140 /**
141 * Destructor
142 */
143137 virtual ~UserPlugin(void) {}
144138
145139 /**
454448 class objectnotfound: public runtime_error {
455449 public:
456450 /**
457 * Constructor
458 *
459451 * @param[in] arg
460452 * The description why the exception was thrown
461453 */
473465 class toomanyobjects: public runtime_error {
474466 public:
475467 /**
476 * Constructor
477 *
478468 * @param[in] arg
479469 * The description why the exception was thrown
480470 */
492482 class collision_error: public runtime_error {
493483 public:
494484 /**
495 * Constructor
496 *
497485 * @param[in] arg
498486 * The description why the exception was thrown
499487 */
511499 class data_error: public runtime_error {
512500 public:
513501 /**
514 * Constructor
515 *
516502 * @param[in] arg
517503 * The description why the exception was thrown
518504 */
530516 class notimplemented: public runtime_error {
531517 public:
532518 /**
533 * Constructor
534 *
535519 * @param[in] arg
536520 * The description why the exception was thrown
537521 */
551535 class notsupported : public runtime_error {
552536 public:
553537 /**
554 * Constructor
555 *
556538 * @param[in] arg
557539 * The description why the exception was thrown
558540 */
569551 class login_error: public runtime_error {
570552 public:
571553 /**
572 * Constructor
573 *
574554 * @param[in] arg
575555 * The description why the exception was thrown
576556 */
588568 int m_ldaperror;
589569 public:
590570 /**
591 * Constructor
592 *
593571 * @param[in] arg
594572 * The description why the exception was thrown
595573 * @param[in] ldaperror
6969
7070 ECLicenseClient *lpLicenseClient = NULL;
7171 unsigned int ulLicenseResponse = 0;
72 unsigned char *lpLicenseResponse = NULL;
72 void *lpLicenseResponse = NULL;
7373 ECRESULT er = erSuccess;
7474 ClientVersion currentVersion = {0};
7575 ClientVersion latestVersion = {0};
7676 std::string strClientMSIName;
7777 FILE *fd = NULL;
78
7978
8079 // Get the server.cfg setting
8180 szClientUpdatePath = g_lpConfig->GetSetting("client_update_path");
109108 goto exit;
110109 }
111110
112 strLicenseResponse = base64_encode(lpLicenseResponse, ulLicenseResponse);
111 strLicenseResponse = base64_encode(static_cast<const unsigned char *>(lpLicenseResponse), ulLicenseResponse);
113112
114113 soap->http_content = "binary";
115114 soap_response(soap, SOAP_FILE);
187186 nRet = SOAP_OK;
188187
189188 exit:
190 delete[] lpLicenseResponse;
189 free(lpLicenseResponse);
191190 delete lpLicenseClient;
192191
193192 if (fd)
405404 ClientVersion sCurrentVersion = {0};
406405 ClientVersion sLatestVersion;
407406 unsigned int ulLicenseResponse = 0;
408 unsigned char *lpLicenseResponse = NULL;
407 void *lpLicenseResponse = NULL;
409408 ECLicenseClient *lpLicenseClient = NULL;
410409 std::string strClientMSIName;
411410 std::string strPath;
475474 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, unknown username '%s'", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername);
476475 }
477476
478
479477 if(lpecSession->GetUserManagement()->IsInternalObject(ulUserID)) {
480478 er = KCERR_NO_ACCESS;
481479 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Wrong user data. User name '%s' is a reserved user", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername);
499497 goto exit;
500498 }
501499
502 if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
500 if (strcasecmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) {
503501 string strServerPath;
504502
505503 er = GetBestServerPath(soap, lpecSession, strServerName, &strServerPath);
601599 }
602600
603601 lpsResponse->er = er;
604
605 delete[] lpLicenseResponse;
602 free(lpLicenseResponse);
606603 delete lpLicenseClient;
607604
608605 if (er && fd)
2727 #include <kopano/ECLogger.h>
2828
2929 #include <kopano/ECConfig.h>
30 #include "ECDatabase.h"
3130 #include "ECPluginFactory.h"
3231 #include "ECNotificationManager.h"
3332 #include "ECSessionManager.h"
3534 #include "ECStatsTables.h"
3635 #include <climits>
3736 #include <csignal>
38
39 #ifdef LINUX
4037 #include <kopano/UnixUtil.h>
4138 #include <pwd.h>
42 #endif
43
4439 #include <sys/stat.h>
4540 #include <kopano/ECScheduler.h>
4641 #include <kopano/kcodes.h>
6055 #endif
6156
6257 #include "TmpPath.h"
63
64 #ifdef _DEBUG
65 #define new DEBUG_NEW
66 #endif
6758
6859 // The following value is based on:
6960 // http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_thread_stack
8778 // Reports information on the current state of the license
8879 void* ReportLicense(void *);
8980
90 int running_server(char *szName, const char *config, int argc, char *argv[]);
91
81 static int running_server(char *, const char *, int, char **, int, char **);
9282
9383 int g_Quit = 0;
9484 int daemonize = 1;
10898 ECScheduler* g_lpScheduler = NULL;
10999 ECSoapServerConnection* g_lpSoapServerConn = NULL;
110100
111 #ifdef LINUX
112101 pthread_t signal_thread;
113102 sigset_t signal_mask;
114103 bool m_bNPTL = true;
115 #endif
116104 bool m_bDatabaseUpdateIgnoreSignals = false;
117105
118106 // This is the callback function for libserver/* so that it can notify that a delayed soap
139127 {
140128 ZLOG_AUDIT(g_lpAudit, "server signalled sig=%d", sig);
141129
142 #ifdef LINUX
143130 if (!m_bNPTL)
144 #endif
145131 {
146132 // Win32 has unix semantics and therefore requires us to reset the signal handler.
147133 signal(sig, process_signal);
148 #ifdef LINUX
149134 if(pthread_equal(pthread_self(), mainthread)==0)
150135 return; // soap threads do not handle this signal
151 #endif
152136 }
153137
154138 if (m_bDatabaseUpdateIgnoreSignals) {
170154 if (g_lpSoapServerConn)
171155 g_lpSoapServerConn->ShutDown();
172156
173 #ifdef LINUX
174157 // unblock the signals so the server can exit
175158 sigprocmask(SIG_UNBLOCK, &signal_mask, NULL);
176159 signal(SIGPIPE, SIG_IGN);
177 #endif
178160 signal(SIGTERM, SIG_IGN);
179161 signal(SIGINT, SIG_IGN);
180162
217199 }
218200 }
219201
220 #ifdef LINUX
221202 /**
222203 * Signal handler thread.
223204 *
249230 generic_sigsegv_handler(g_lpLogger, "Server",
250231 PROJECT_VERSION_SERVER_STR, signr, si, uc);
251232 }
252 #endif
253233
254234 static ECRESULT check_database_innodb(ECDatabase *lpDatabase)
255235 {
288268 string strQuery;
289269 DB_RESULT lpResult = NULL;
290270 DB_ROW lpRow = NULL;
291
292271
293272 er = lpDatabase->DoSelect("SELECT value FROM settings WHERE name = 'attachment_storage'", &lpResult);
294273 if (er != erSuccess) {
378357 {
379358 ECRESULT er = erSuccess;
380359
381 #ifdef LINUX
382360 FILE *tmpfile = NULL;
383361 string strtestpath;
384362
398376 fclose(tmpfile);
399377 unlink(strtestpath.c_str());
400378 }
401 #endif
402
403379 return er;
404380 }
405381
566542 if (hostname[0] != '\0')
567543 g_lpConfig->AddSetting("server_hostname", hostname);
568544
569
570545 if (aiResult)
571546 freeaddrinfo(aiResult);
572547
589564 serverdetails_t sServerDetails;
590565 unsigned ulPort = 0;
591566
592
593567 // Upgrade 'enable_sso_ntlmauth' to 'enable_sso'
594568 bCheck = parseBool(g_lpConfig->GetSetting("enable_sso_ntlmauth"));
595569 if (bCheck)
599573 bCheck = parseBool(g_lpConfig->GetSetting("enable_sso"));
600574 if (bCheck && check_server_fqdn() != erSuccess)
601575 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "WARNING: Unable to find FQDN, please specify in 'server_hostname'. Now using '%s'.", g_lpConfig->GetSetting("server_hostname"));
602
603576
604577 // all other checks are only required for multi-server environments
605578 bCheck = parseBool(g_lpConfig->GetSetting("enable_distributed_kopano"));
690663 return er;
691664 }
692665
693 /**
694 * NSPR initialization is not properly guarded for threaded operation;
695 * so call it now before we create threads if it is part of the process image.
696 */
697 static void nspr_thread_workaround(void)
698 {
699 auto f = reinterpret_cast<void (*)(int, int, int)>(dlsym(NULL, "PR_Init"));
700 if (f == NULL)
701 return;
702 ec_log_warn("Calling NSPR's PR_Init now to workaround KC-104.");
703 f(0, 0, 0);
704 }
705
706666 int main(int argc, char* argv[])
707667 {
708668 int nReturn = 0;
709 #ifdef LINUX
710669 const char *config = ECConfig::GetDefaultPath("server.cfg");
711 #else
712 const char *config = "server.cfg";
713 #endif
714670 const char *default_config = config;
715671
716672 enum {
795751 break;
796752 };
797753 }
798 nspr_thread_workaround();
799 nReturn = running_server(argv[0], config, argc - optind, &argv[optind]);
754 nReturn = running_server(argv[0], config, argc, argv,
755 argc - optind, &argv[optind]);
800756 return nReturn;
801757 }
802758
809765 bind_textdomain_codeset("kopano", "UTF-8");
810766 }
811767
812 int running_server(char *szName, const char *szConfig, int argc, char *argv[])
768 static int running_server(char *szName, const char *szConfig,
769 int argc, char **argv, int trim_argc, char **trim_argv)
813770 {
814771 int retval = -1;
815772 ECRESULT er = erSuccess;
824781 bool hosted = false;
825782 bool distributed = false;
826783
827 #ifdef LINUX
828784 // SIGSEGV backtrace support
829785 stack_t st = {0};
830786 struct sigaction act = {{0}};
831787 int tmplock = -1;
832788 struct stat dir = {0};
833789 struct passwd *runasUser = NULL;
834 #endif
835790
836791 const configsetting_t lpDefaults[] = {
837792 // Aliases
853808 { "server_read_timeout", "60", CONFIGSETTING_RELOADABLE }, // timeout during reading of XML request
854809 { "server_send_timeout", "60", CONFIGSETTING_RELOADABLE },
855810 { "server_max_keep_alive_requests", "100" },
856 #ifdef LINUX
857811 { "thread_stacksize", "512" },
858812 { "allow_local_users", "yes", CONFIGSETTING_RELOADABLE }, // allow any user connect through the unix socket
859813 { "local_admin_users", "root", CONFIGSETTING_RELOADABLE }, // this local user is admin
861815 { "run_as_group", "kopano" },
862816 { "pid_file", "/var/run/kopano/server.pid" },
863817 { "running_path", "/var/lib/kopano" },
818 {"allocator_library", "libtcmalloc_minimal.so.4"},
864819 { "coredump_enabled", "yes" },
865820
866821 { "license_path", "/etc/kopano/license", CONFIGSETTING_UNUSED },
867822 { "license_socket", "/var/run/kopano/licensed.sock" },
868823 { "license_timeout", "10", CONFIGSETTING_RELOADABLE},
869 #else
870 { "local_admin_users", "SYSTEM" }, // this local user is admin
871 { "license_path", "license", CONFIGSETTING_UNUSED },
872 #endif
873824 { "system_email_address", "postmaster@localhost", CONFIGSETTING_RELOADABLE },
874825
875826 { "server_ssl_enabled", "no" },
881832 { "server_ssl_protocols", "!SSLv2" },
882833 { "server_ssl_ciphers", "ALL:!LOW:!SSLv2:!EXP:!aNULL" },
883834 { "server_ssl_prefer_server_ciphers", "no" },
884 #ifdef LINUX
885835 { "sslkeys_path", "/etc/kopano/sslkeys" }, // login keys
886 #else
887 { "sslkeys_path", "sslkeys" },
888 #endif
889836 // Database options
890837 { "database_engine", "mysql" },
891838 // MySQL Settings
925872 { "audit_log_timestamp", "0" },
926873
927874 // user plugin
928 #ifdef LINUX
929875 { "plugin_path", PKGLIBDIR },
930876 { "user_plugin", "db" },
931877 { "user_plugin_config", "/etc/kopano/ldap.cfg" },
935881 { "deletegroup_script", "/etc/kopano/userscripts/deletegroup", CONFIGSETTING_RELOADABLE},
936882 { "createcompany_script", "/etc/kopano/userscripts/createcompany", CONFIGSETTING_RELOADABLE },
937883 { "deletecompany_script", "/etc/kopano/userscripts/deletecompany", CONFIGSETTING_RELOADABLE },
938 #else
939 { "plugin_path", "plugins" },
940 { "user_plugin", "ldap" },
941 { "user_plugin_config", "ldap.cfg" },
942 { "createuser_script", "createuser.bat", CONFIGSETTING_RELOADABLE },
943 { "deleteuser_script", "deleteuser.bat", CONFIGSETTING_RELOADABLE },
944 { "creategroup_script", "creategroup.bat", CONFIGSETTING_RELOADABLE },
945 { "deletegroup_script", "deletegroup.bat", CONFIGSETTING_RELOADABLE },
946 { "createcompany_script", "", CONFIGSETTING_RELOADABLE },
947 { "deletecompany_script", "", CONFIGSETTING_RELOADABLE },
948 #endif
949884 { "user_safe_mode", "no", CONFIGSETTING_RELOADABLE },
950885
951886 // Storename format
994929
995930 { "client_update_enabled", "no" },
996931 { "client_update_log_level", "1", CONFIGSETTING_RELOADABLE },
997 #ifdef LINUX
998932 { "client_update_path", "/var/lib/kopano/client", CONFIGSETTING_RELOADABLE },
999933 { "client_update_log_path", "/var/log/kopano/autoupdate", CONFIGSETTING_RELOADABLE },
1000 #else
1001 { "client_update_path", "c:\\client_update_path", CONFIGSETTING_RELOADABLE },
1002 { "client_update_log_path", "C:\\TEMP", CONFIGSETTING_RELOADABLE },
1003 #endif
1004934 { "index_services_enabled", "", CONFIGSETTING_UNUSED },
1005935 { "index_services_path", "", CONFIGSETTING_UNUSED },
1006936 { "index_services_search_timeout", "", CONFIGSETTING_UNUSED },
1030960 { NULL, NULL },
1031961 };
1032962
1033 #ifdef LINUX
1034963 char buffer[256];
1035964 confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer));
1036965 if (strncmp(buffer, "linuxthreads", strlen("linuxthreads")) == 0)
1037966 m_bNPTL = false;
1038 #endif
1039967
1040968 // Init random generator
1041969 rand_init();
1048976 // Load settings
1049977 g_lpConfig = ECConfig::Create(lpDefaults);
1050978
1051 if (!g_lpConfig->LoadSettings(szConfig) || !g_lpConfig->ParseParams(argc, argv, NULL) || (!m_bIgnoreUnknownConfigOptions && g_lpConfig->HasErrors()) ) {
979 if (!g_lpConfig->LoadSettings(szConfig) ||
980 !g_lpConfig->ParseParams(trim_argc, trim_argv, NULL) ||
981 (!m_bIgnoreUnknownConfigOptions && g_lpConfig->HasErrors()) ) {
1052982 g_lpLogger = new ECLogger_File(EC_LOGLEVEL_INFO, 0, "-", false); // create info logger without a timestamp to stderr
1053983 ec_log_set(g_lpLogger);
1054984 LogConfigErrors(g_lpConfig);
1055985 er = MAPI_E_UNCONFIGURED;
1056986 goto exit;
1057987 }
988
989 kc_reexec_with_allocator(argv, g_lpConfig->GetSetting("allocator_library"));
1058990
1059991 // setup logging
1060992 g_lpLogger = CreateLogger(g_lpConfig, szName, "KopanoServer");
10881020 er = KCERR_DATABASE_ERROR;
10891021 goto exit;
10901022 }
1091 #ifdef LINUX
10921023 if (stat(g_lpConfig->GetSetting("attachment_path"), &dir) != 0) {
10931024 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to stat attachment directory '%s', error: %s", g_lpConfig->GetSetting("attachment_path"), strerror(errno));
10941025 er = KCERR_DATABASE_ERROR;
11071038 goto exit;
11081039 }
11091040 }
1110 #endif
11111041 #ifdef HAVE_LIBS3_H
11121042 } else if (strcmp(g_lpConfig->GetSetting("attachment_storage"), "s3") == 0) {
11131043 // @todo check S3 settings and connectivity
11181048 g_lpConfig->AddSetting("attachment_storage", "database");
11191049 }
11201050
1121 if (stricmp(g_lpConfig->GetSetting("user_plugin"), "db") == 0 && parseBool(g_lpConfig->GetSetting("sync_gab_realtime")) == false) {
1051 if (strcasecmp(g_lpConfig->GetSetting("user_plugin"), "db") == 0 && parseBool(g_lpConfig->GetSetting("sync_gab_realtime")) == false) {
11221052 g_lpLogger->Log(EC_LOGLEVEL_INFO, "Unsupported sync_gab_realtime = no when using DB plugin. Enabling sync_gab_realtime.");
11231053 g_lpConfig->AddSetting("sync_gab_realtime", "yes");
11241054 }
11391069 bSSLEnabled = true;
11401070 else
11411071 bSSLEnabled = false;
1142
11431072
11441073 soap_ssl_init(); // Always call this in the main thread once!
11451074
11731102 }
11741103 }
11751104
1176 #ifdef LINUX
11771105 // Set max open file descriptors to FD_SETSIZE .. higher than this number
11781106 // is a bad idea, as it will start breaking select() calls.
11791107 struct rlimit limit;
11911119 er = MAPI_E_CALL_FAILED;
11921120 goto exit;
11931121 }
1194 #endif
1122
11951123 // Priority queue is always enabled, create as first socket, so this socket is returned first too on activity
11961124 er = g_lpSoapServerConn->ListenPipe(g_lpConfig->GetSetting("server_pipe_priority"), true);
11971125 if (er != erSuccess) {
12261154
12271155 hosted = parseBool(g_lpConfig->GetSetting("enable_hosted_kopano"));
12281156 distributed = parseBool(g_lpConfig->GetSetting("enable_distributed_kopano"));
1229 #ifdef LINUX
12301157 // fork if needed and drop privileges as requested.
12311158 // this must be done before we do anything with pthreads
12321159 if (daemonize && unix_daemonize(g_lpConfig, g_lpLogger)) {
12361163 if (!daemonize)
12371164 setsid();
12381165 unix_create_pidfile(szName, g_lpConfig, g_lpLogger);
1239 #endif
12401166
12411167 mainthread = pthread_self();
12421168
1243 #ifdef LINUX
12441169 // SIGSEGV backtrace support
12451170 memset(&st, 0, sizeof(st));
12461171 memset(&act, 0, sizeof(act));
12561181 sigaction(SIGSEGV, &act, NULL);
12571182 sigaction(SIGBUS , &act, NULL);
12581183 sigaction(SIGABRT, &act, NULL);
1259
12601184
12611185 if (m_bNPTL) {
12621186 // normally ignore these signals
12771201 pthread_create(&signal_thread, NULL, signal_handler, NULL);
12781202 set_thread_name(signal_thread, "SignalHThread");
12791203 } else
1280 #endif
12811204 {
12821205 // reset signals to normal server usage
12831206 signal(SIGTERM , process_signal);
12841207 signal(SIGINT , process_signal); //CTRL+C
1285 #ifdef LINUX
12861208 signal(SIGHUP , process_signal); // logrotate
12871209 signal(SIGUSR1, process_signal);
12881210 signal(SIGUSR2, process_signal);
12891211 signal(SIGPIPE, process_signal);
1290 #endif
12911212 }
12921213
12931214 // ignore ignorable signals that might stop the server during database upgrade
12941215 // all these signals will be reset after the database upgrade part.
12951216 m_bDatabaseUpdateIgnoreSignals = true;
12961217
1297 #ifdef LINUX
12981218 // add a lock file to disable the /etc/init.d scripts
12991219 tmplock = open(upgrade_lock_file, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
13001220
13011221 if (tmplock == -1)
13021222 g_lpLogger->Log(EC_LOGLEVEL_WARNING, "WARNING: Unable to place upgrade lockfile: %s", strerror(errno));
1303 #endif
13041223
13051224 #ifdef EMBEDDED_MYSQL
13061225 {
13221241
13231242 // perform database upgrade .. may take a very long time
13241243 er = lpDatabaseFactory->UpdateDatabase(m_bForceDatabaseUpdate, dbError);
1325
1326 #ifdef LINUX
13271244 // remove lock file
13281245 if (tmplock != -1) {
13291246 if (unlink(upgrade_lock_file) == -1)
13311248
13321249 close(tmplock);
13331250 }
1334 #endif
13351251
13361252 if(er == KCERR_INVALID_VERSION) {
13371253 g_lpLogger->Log(EC_LOGLEVEL_WARNING, "WARNING: %s", dbError.c_str());
13731289 er = check_attachment_storage_permissions();
13741290 if (er != erSuccess)
13751291 goto exit;
1376
13771292
13781293 // check upgrade problem with wrong sequence in tproperties table primary key
13791294 er = check_database_tproperties_key(lpDatabase);
14401355 }
14411356 // Close All sessions
14421357 kopano_removeallsessions();
1443
1444 #ifdef LINUX
14451358 if (m_bNPTL) {
14461359 g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Joining signal thread");
14471360 pthread_join(signal_thread, NULL);
14481361 }
1449 #endif
1450
14511362 exit:
1452 if (er != erSuccess || retval != 0) {
1453 std::string msg;
1454
1455 if (er != erSuccess)
1456 msg = format("An error occured (%x).", er);
1457 else
1458 msg = "An error occurred.";
1459
1363 if (er != erSuccess) {
1364 auto msg = format("An error occurred (%x).", er);
14601365 if (g_lpConfig)
14611366 msg += format(" Please check %s for details.", g_lpConfig->GetSetting("log_file"));
14621367 else
14711376 delete g_lpSoapServerConn;
14721377
14731378 delete g_lpScheduler;
1474
1475 #ifdef LINUX
14761379 free(st.ss_sp);
1477 #endif
14781380 delete lpDatabase;
14791381 delete lpDatabaseFactory;
1480
14811382
14821383 kopano_exit();
14831384
2828 #include "ECSoapServerConnection.h"
2929 #include "ECServerEntrypoint.h"
3030 #include "ECClientUpdate.h"
31 #ifdef LINUX
3231 # include <dirent.h>
3332 # include <fcntl.h>
3433 # include <unistd.h>
3534 # include <kopano/UnixUtil.h>
36 #endif
3735
3836 extern ECLogger *g_lpLogger;
3937
4240 struct soap* lpSoap;
4341 };
4442
45 #ifdef LINUX
4643 /**
4744 * Creates a AF_UNIX socket in a given location and starts to listen
4845 * on that socket.
7370 }
7471 memset(&saddr,0,sizeof(saddr));
7572 saddr.sun_family = AF_UNIX;
76 strncpy(saddr.sun_path, unix_socket, sizeof(saddr.sun_path));
73 kc_strlcpy(saddr.sun_path, unix_socket, sizeof(saddr.sun_path));
7774 unlink(unix_socket);
7875
7976 if (bind(s, (struct sockaddr*)&saddr, 2 + strlen(unix_socket)) == -1) {
8077 lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to bind to socket %s (%s). This is usually caused by another process (most likely another server) already using this port. This program will terminate now.", unix_socket, strerror(errno));
81 #ifdef LINUX
8278 kill(0, SIGTERM);
83 #endif
8479 exit(1);
8580 }
8681
8782 er = chmod(unix_socket,mode);
8883 if(er) {
8984 lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to chmod socket %s. Error: %s", unix_socket, strerror(errno));
90 closesocket(s);
85 close(s);
9186 return -1;
9287 }
9388
94 #ifdef LINUX
9589 if(er) {
9690 lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to chown socket %s, to %s:%s. Error: %s", unix_socket, lpConfig->GetSetting("run_as_user"), lpConfig->GetSetting("run_as_group"), strerror(errno));
97 closesocket(s);
91 close(s);
9892 return -1;
9993 }
100 #endif
10194
10295 if (listen(s, SOMAXCONN) == -1) {
10396 lpLogger->Log(EC_LOGLEVEL_FATAL, "Can't listen on unix socket %s", unix_socket);
104 closesocket(s);
97 close(s);
10598 return -1;
10699 }
107100
108101 return s;
109102 }
110
111 #else
112
113 // Named pipe functions
114
115 // Create a namedpipe in windows
116 // the function must be called very time you have used the pipe
117 static int create_pipe_socket(const char *lpszPipename, ECConfig *lpConfig,
118 ECLogger *lpLogger, bool bInit, int mode)
119 {
120 HANDLE hPipe;
121
122 DWORD dwOpenMode = PIPE_ACCESS_DUPLEX | // read/write access
123 FILE_FLAG_OVERLAPPED; // overlapped mode
124
125 if (bInit) {
126 // block create multiple instances of a pipe
127 dwOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
128 }
129
130 hPipe = CreateNamedPipeA(
131 lpszPipename, // pipe name
132 dwOpenMode,
133 PIPE_TYPE_BYTE | // byte-oriented
134 PIPE_READMODE_BYTE |
135 PIPE_WAIT, // blocking mode
136 PIPE_UNLIMITED_INSTANCES, // max. instances
137 0x10000, // output buffer size
138 0x10000, // input buffer size
139 1000, // client time-out
140 NULL); // default security attribute
141
142 if (hPipe == INVALID_HANDLE_VALUE)
143 {
144 lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to create pipe %s", lpszPipename);
145 return SOAP_INVALID_SOCKET;
146 }
147
148 return (int)hPipe;
149 }
150
151 // Override the soap function fsend
152 // Send data over a namedpipe
153 int gsoap_win_fsend(struct soap *soap, const char *s, size_t n)
154 {
155 DWORD ulWritten;
156
157 if(WriteFile((HANDLE)soap->socket, s, n, &ulWritten, NULL))
158 return SOAP_OK;
159 else
160 return SOAP_ERR;
161 }
162
163 // Override the soap function frecv
164 // receive date from a namedpipe
165 size_t gsoap_win_frecv(struct soap *soap, char *s, size_t n)
166 {
167 DWORD ulRead;
168
169 if(ReadFile((HANDLE)soap->socket, s, n, &ulRead, NULL))
170 return ulRead;
171 else
172 return 0;
173 }
174
175 // Override the soap function tcp_disconnect
176 // close the namedpipe
177 int gsoap_win_fclose(struct soap *soap)
178 {
179 if((HANDLE)soap->socket == INVALID_HANDLE_VALUE)
180 return SOAP_OK;
181
182 kopano_disconnect_soap_connection(soap);
183
184 // Flush the data so the client gets any left-over data, then disconnect and close the socket
185 FlushFileBuffers((HANDLE)soap->socket);
186 DisconnectNamedPipe((HANDLE)soap->socket);
187 CloseHandle((HANDLE)soap->socket); // ignore errors
188
189 // Master and socket are the same
190 soap->socket = (int)INVALID_HANDLE_VALUE;
191 soap->master = (int)INVALID_HANDLE_VALUE;
192
193 return SOAP_OK;
194 }
195
196 // Override the soap function tcp_disconnect
197 // close master, ignored by using namedpipe
198 int gsoap_win_closesocket(struct soap *soap, SOAP_SOCKET fd)
199 {
200 // is used only to close the master socket in a server upon soap_done()
201 // skip this for namedpipe
202 return SOAP_OK;
203 }
204
205 // Override the soap function tcp_shutdownsocket
206 // shutdown a socket ignored by using namedpipe
207 int gsoap_win_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
208 {
209 // is used after completing a send operation to send TCP FIN
210 return SOAP_OK;
211 }
212
213
214 // TCP/SSL socket functions
215 #endif // #ifdef LINUX
216103
217104 /*
218105 * Handles the HTTP GET command from soap, only the client update install may be downloaded.
245132 m_lpLogger = lpLogger;
246133 m_lpLogger->AddRef();
247134
248 #ifdef LINUX
249135 #ifdef USE_EPOLL
250136 m_lpDispatcher = new ECDispatcherEPoll(lpLogger, lpConfig, ECSoapServerConnection::CreatePipeSocketCallback, this);
251137 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Using epoll events");
253139 m_lpDispatcher = new ECDispatcherSelect(lpLogger, lpConfig, ECSoapServerConnection::CreatePipeSocketCallback, this);
254140 m_lpLogger->Log(EC_LOGLEVEL_INFO, "Using select events");
255141 #endif
256 #else
257 m_lpDispatcher = new ECDispatcherWin32(lpLogger, lpConfig, ECSoapServerConnection::CreatePipeSocketCallback, this);
258 #endif
259142 }
260143
261144 ECSoapServerConnection::~ECSoapServerConnection(void)
282165 if (bEnableGET)
283166 lpsSoap->fget = http_get;
284167
285 #ifdef LINUX
286168 lpsSoap->bind_flags = SO_REUSEADDR;
287 #endif
288
289169 lpsSoap->socket = socket = soap_bind(lpsSoap, *lpServerName == '\0' ? NULL : lpServerName, nServerPort, 100);
290170 if (socket == -1) {
291171 m_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to bind to port %d: %s. This is usually caused by another process (most likely another server) already using this port. This program will terminate now.", nServerPort, lpsSoap->fault->faultstring);
292 #ifdef LINUX
293172 kill(0, SIGTERM);
294 #endif
295173 exit(1);
296174 }
297175
370248 ssl_neg = true;
371249 }
372250
373 if (strcmp_ci(ssl_name, SSL_TXT_SSLV2) == 0)
251 if (strcasecmp(ssl_name, SSL_TXT_SSLV2) == 0)
374252 ssl_proto = 0x01;
375 else if (strcmp_ci(ssl_name, SSL_TXT_SSLV3) == 0)
253 else if (strcasecmp(ssl_name, SSL_TXT_SSLV3) == 0)
376254 ssl_proto = 0x02;
377 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1) == 0)
255 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1) == 0)
378256 ssl_proto = 0x04;
379257 #ifdef SSL_TXT_TLSV1_1
380 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1_1) == 0)
258 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1_1) == 0)
381259 ssl_proto = 0x08;
382260 #endif
383261 #ifdef SSL_TXT_TLSV1_2
384 else if (strcmp_ci(ssl_name, SSL_TXT_TLSV1_2) == 0)
262 else if (strcasecmp(ssl_name, SSL_TXT_TLSV1_2) == 0)
385263 ssl_proto = 0x10;
386264 #endif
387265 else {
434312
435313 // request certificate from client, is OK if not present.
436314 SSL_CTX_set_verify(lpsSoap->ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
437
438 #ifdef LINUX
439315 lpsSoap->bind_flags = SO_REUSEADDR;
440 #endif
441
442316 lpsSoap->socket = socket = soap_bind(lpsSoap, *lpServerName == '\0' ? NULL : lpServerName, nServerPort, 100);
443317 if (socket == -1) {
444318 m_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to bind to port %d: %s (SSL). This is usually caused by another process (most likely another server) already using this port. This program will terminate now.", nServerPort, lpsSoap->fault->faultstring);
445 #ifdef LINUX
446319 kill(0, SIGTERM);
447 #endif
448320 exit(1);
449321 }
450322
286286 ECThreadManager::~ECThreadManager()
287287 {
288288 unsigned int ulThreads;
289 std::list<ECWorkerThread *>::const_iterator iterThreads;
290289
291290 // Wait for the threads to exit
292291 while(1) {
706705 return erSuccess;
707706 }
708707
709 #ifdef LINUX
710708 ECDispatcherSelect::ECDispatcherSelect(ECLogger *lpLogger, ECConfig *lpConfig, CREATEPIPESOCKETCALLBACK lpCallback, void *lpCallbackParam) : ECDispatcher(lpLogger, lpConfig, lpCallback, lpCallbackParam)
711709 {
712710 int pipes[2];
722720 ECRESULT er = erSuccess;
723721 ECWatchDog *lpWatchDog = NULL;
724722 std::map<int, ACTIVESOCKET>::iterator iterSockets;
725 std::map<int, ACTIVESOCKET>::const_iterator iterErase;
726723 std::map<int, struct soap *>::const_iterator iterListenSockets;
727724 int maxfds = 0;
728725 char s = 0;
730727 struct timeval tv;
731728 CONNECTION_TYPE ulType;
732729 int n = 0;
733
734730
735731 // This will start the threads
736732 m_lpThreadManager = new ECThreadManager(m_lpLogger, this, atoui(m_lpConfig->GetSetting("threads")));
11441140 return erSuccess;
11451141 }
11461142 #endif
1147 #endif
+0
-38
provider/server/Makefile.am less more
0 # -*- Makefile -*-
1
2 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) $(BOOST_CPPFLAGS) \
3 -I${top_srcdir}/mapi4linux/include \
4 -I${top_srcdir}/provider/libserver -I${top_srcdir}/provider/plugins \
5 -I${top_srcdir}/provider/include -I${top_srcdir}/provider/common \
6 -I${top_srcdir}/provider/client -I${top_builddir}/provider/soap \
7 -I${top_srcdir}/provider/soap \
8 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon \
9 -DPKGLIBDIR='"${pkglibdir}"' \
10 $(MYSQL_INCLUDES) $(GSOAP_CFLAGS) $(SSL_CFLAGS) $(SSL_HAS_EVP_PKEY_CMP) $(EPOLL_CFLAGS) $(KRB5_CFLAGS)
11
12 sbin_PROGRAMS = kopano-server
13 noinst_DATA = kopano-server.ldx
14
15 kopano_server_LDFLAGS = ${AM_LDFLAGS} -Wl,-E $(BOOST_FILESYSTEM_LDFLAGS)
16 kopano_server_LDADD = \
17 ${top_builddir}/provider/libserver/libkcserver.la \
18 ${GSOAP_LIBS} \
19 ${top_builddir}/provider/soap/libkcsoapserver.la \
20 ${top_builddir}/provider/common/libkccommon.la \
21 ${top_builddir}/common/libkcutil.la \
22 ${top_builddir}/common/libkcmapi.la \
23 ${top_builddir}/common/libkcssl.la \
24 $(PROG_LIBS) ${icu_uc_LIBS} \
25 $(BOOST_FILESYSTEM_LIBS) $(BOOST_SYSTEM_LIBS) $(ICU_LIBS) $(DL_LIBS) \
26 $(MYSQL_LIBS) $(SSL_LIBS) $(PAM_LIBS) $(KRB5_LIBS) -lrt
27
28 kopano_server_SOURCES = ECServer.cpp \
29 ECSoapServerConnection.h ECSoapServerConnection.cpp \
30 ECClientUpdate.h ECClientUpdate.cpp \
31 ECThreadManager.h ECThreadManager.cpp
32
33 check-syntax:
34 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
35 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
36
37 include ../../global.am
+0
-43
provider/soap/Makefile.am less more
0 # -*- Makefile -*-
1
2 AM_CPPFLAGS = ${ZCPPFLAGS} -I${top_srcdir}/mapi4linux/include \
3 -I${top_srcdir}/provider/include ${GSOAP_CFLAGS}
4 AM_CXXFLAGS = ${ZCXXFLAGS} -Wno-sign-compare
5
6 lib_LTLIBRARIES = libkcsoapserver.la libkcsoapclient.la
7 #noinst_DATA = libkcsoapserver.ldd libkcsoapclient.ldd
8
9 nodist_libkcsoapserver_la_SOURCES = soapC.cpp soapServer.cpp
10 libkcsoapserver_la_LIBADD = ${GSOAP_LIBS}
11 libkcsoapserver_la_LDFLAGS = ${AM_LDFLAGS} \
12 -Wl,--version-script=${top_builddir}/default.sym
13 EXTRA_libkcsoapserver_la_DEPENDENCIES = ${top_builddir}/default.sym
14
15 nodist_libkcsoapclient_la_SOURCES = soapC.cpp soapClient.cpp
16 libkcsoapclient_la_LIBADD = ${GSOAP_LIBS}
17 libkcsoapclient_la_LDFLAGS = ${AM_LDFLAGS} \
18 -Wl,--version-script=${top_builddir}/default.sym
19 EXTRA_libkcsoapclient_la_DEPENDENCIES = ${top_builddir}/default.sym
20
21 SOAPHEADER = ${top_srcdir}/provider/include/proto.h
22 SOAP_INC = ${top_srcdir}/provider/include/
23 SOAP_NS = KCmd.nsmap KCmd.wsdl
24
25 SOAP_H_FILES = soapH.h soapStub.h
26 SOAP_CPP_CLIENT = soapClient.cpp soapC.cpp
27 SOAP_LIB_FILES = soapClientLib.cpp soapServerLib.cpp soapKCmdObject.h
28 SOAP_CPP_SRC=$(SOAP_CPP_CLIENT) soapServer.cpp $(SOAP_H_FILES) $(SOAP_NS) $(SOAP_LIB_FILES)
29
30 $(SOAP_CPP_SRC) : ns.xsd
31 ns.xsd: $(SOAPHEADER)
32 soapcpp2 -z1 -x -I$(SOAP_INC) $<
33
34 #libsoapserver_a_LDADD=$(SOAP_CPP_LIB)
35 BUILT_SOURCES=ns.xsd $(SOAP_CPP_SRC)
36 CLEANFILES=$(SOAP_CPP_SRC) *.req.xml *.res.xml *.wsdl *.nsmap *.xsd *Proxy\.h *~
37
38 check-syntax:
39 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
40 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
41
42 include ../../global.am
5555 #include <kopano/mapi_ptr.h>
5656 #include "fileutil.h"
5757 #include "PyMapiPlugin.h"
58
59 #ifdef LINUX
6058 #include <cerrno>
6159 #include <sys/types.h>
6260 #include <sys/stat.h>
6361 #include <unistd.h>
64 #include <climits>
6562 #include <sys/mman.h>
6663 #include <pwd.h>
67 #endif
68
6964 #include "spmain.h"
7065 #include "TmpPath.h"
7166
10499 #include <kopano/CommonUtil.h>
105100 #include <kopano/Util.h>
106101 #include <kopano/ECLogger.h>
107 #include <kopano/MAPIErrors.h>
108102 #include <kopano/my_getopt.h>
109103 #include <kopano/restrictionutil.h>
110104 #include "rules.h"
123117 #include <kopano/UnixUtil.h>
124118 #include "LMTP.h"
125119 #include <kopano/ecversion.h>
126 #include <kopano/platform.h>
127120 #include <csignal>
128121 #include "SSLUtil.h"
129122 #include "StatsClient.h"
295288 g_bQuit = true;
296289 }
297290
298 #ifdef LINUX
299291 static void sighup(int sig)
300292 {
301293 if (g_lpConfig) {
327319 generic_sigsegv_handler(g_lpLogger, "Spooler/DAgent",
328320 PROJECT_VERSION_SPOOLER_STR, signr, si, uc);
329321 }
330
331 #endif
332322
333323 /**
334324 * Check if the message should be processed with the autoaccepter
411401 MAPIFreeBuffer(lpProps);
412402 return hr == hrSuccess;
413403 }
414
415404
416405 /**
417406 * Auto-respond to the passed message
588577 MAPIFreeBuffer(lpEntryID);
589578 return hr;
590579 }
591
592580
593581 /**
594582 * Save copy of the raw message
14131401 return hr;
14141402 }
14151403
1416 #ifdef LINUX
14171404 /**
14181405 * Write into the given fd, and if that fails log an error.
14191406 *
17911778 MAPIFreeBuffer(lpMessageProps);
17921779 return hr;
17931780 }
1794 #endif
17951781
17961782 /**
17971783 * Create an empty message for delivery
23582344 const WCHAR *szUsername, IMAPISession **lppSession, bool bSuppress = false)
23592345 {
23602346 HRESULT hr = hrSuccess;
2361 #ifdef LINUX
23622347 struct passwd *pwd = NULL;
23632348 string strUnixUser;
2364 #endif
23652349
23662350 hr = HrOpenECSession(g_lpLogger, lppSession, "spooler/dagent", PROJECT_SVN_REV_STR, szUsername, L"", lpArgs->strPath.c_str(), 0, g_lpConfig->GetSetting("sslkey_file","",NULL), g_lpConfig->GetSetting("sslkey_pass","",NULL));
23672351 if (hr != hrSuccess) {
23752359 case MAPI_E_LOGON_FAILED:
23762360 // running dagent as unix user != lpRecip->strUsername and ! listed in local_admin_user, which gives this error too
23772361 if (!bSuppress) g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Access denied or connection failed for user %ls, using socket: '%s', error code: 0x%08X", szUsername, lpArgs->strPath.c_str(), hr);
2378 #ifdef LINUX
23792362 // so also log userid we're running as
23802363 pwd = getpwuid(getuid());
23812364 if (pwd && pwd->pw_name)
23832366 else
23842367 strUnixUser = stringify(getuid());
23852368 if (!bSuppress) g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Current uid:%d username:%s", getuid(), strUnixUser.c_str());
2386 #endif
23872369 break;
23882370
23892371 default:
24662448 // continue, still send possible out-of-office message
24672449 }
24682450
2469 #ifdef LINUX
24702451 // do not send vacation message for junk messages
24712452 if (lpArgs->ulDeliveryMode != DM_JUNK &&
24722453 // do not send vacation message on delegated messages
24742455 {
24752456 SendOutOfOffice(lpAdrBook, lpStore, *lppMessage, lpRecip, lpArgs->strAutorespond);
24762457 }
2477 #endif
2478
24792458 exit:
24802459 if (lpUserSession)
24812460 lpUserSession->Release();
35733552 int err = 0;
35743553 unsigned int nMaxThreads;
35753554 int nCloseFDs = 0, pCloseFDs[1] = {0};
3576
3577 #ifdef LINUX
35783555 stack_t st;
35793556 struct sigaction act;
35803557 memset(&st, 0, sizeof(st));
35813558 memset(&act, 0, sizeof(act));
3582 #endif
35833559
35843560 nMaxThreads = atoui(g_lpConfig->GetSetting("lmtp_max_threads"));
35853561 if (nMaxThreads == 0 || nMaxThreads == INT_MAX) {
36093585 signal(SIGTERM, sigterm);
36103586 signal(SIGINT, sigterm);
36113587
3612 #ifdef LINUX
36133588 signal(SIGHUP, sighup); // logrotate
36143589 signal(SIGCHLD, sigchld);
36153590 signal(SIGPIPE, SIG_IGN);
36513626 unix_create_pidfile(servicename, g_lpConfig, g_lpLogger);
36523627 g_lpLogger = StartLoggerProcess(g_lpConfig, g_lpLogger); // maybe replace logger
36533628 ec_log_set(g_lpLogger);
3654 #endif
3629
36553630 hr = MAPIInitialize(NULL);
36563631 if (hr != hrSuccess) {
36573632 g_lpLogger->Log(EC_LOGLEVEL_FATAL, "Unable to initialize MAPI: %s (%x)",
37283703
37293704 g_lpLogger->Log(EC_LOGLEVEL_ALWAYS, "LMTP service will now exit");
37303705
3731 #ifdef LINUX
37323706 // in forked mode, send all children the exit signal
37333707 signal(SIGTERM, SIG_IGN);
37343708 kill(0, SIGTERM);
37443718 g_lpLogger->Log(EC_LOGLEVEL_NOTICE, "Forced shutdown with %d processes left", g_nLMTPThreads);
37453719 else
37463720 g_lpLogger->Log(EC_LOGLEVEL_INFO, "LMTP service shutdown complete");
3747 #endif
37483721
37493722 MAPIUninitialize();
37503723
37513724 exit:
37523725 ECChannel::HrFreeCtx();
3753 #ifdef LINUX
37543726 free(st.ss_sp);
3755 #endif
37563727 return hr;
37573728 }
37583729
39263897 cout << " -r\t\t Mark mail as read on delivery. Default: mark mail as new unread mail." << endl;
39273898 cout << " -l\t\t Run DAgent as LMTP listener" << endl;
39283899 cout << " -d\t\t Run DAgent as LMTP daemon, implicates -l. DAgent will run in the background." << endl;
3929 #ifdef LINUX
39303900 cout << endl;
39313901 cout << " -a responder\t path to autoresponder (e.g. /usr/local/bin/autoresponder)" << endl;
39323902 cout << "\t\t The autoresponder is called with </path/to/autoresponder> <from> <to> <subject> <kopano-username> <messagefile>" << endl;
39333903 cout << "\t\t when the autoresponder is enabled for this user, and -j is not specified" << endl;
3934 #endif
39353904 cout << endl;
39363905 cout << "<storename> is the name of the user where to deliver this mail." << endl;
39373906 cout << "If no file is specified with -f, it will be read from standard in." << endl;
39603929 sDeliveryArgs.bNewmailNotify = true;
39613930 sDeliveryArgs.ulDeliveryMode = DM_STORE;
39623931 imopt_default_delivery_options(&sDeliveryArgs.sDeliveryOpts);
3963
3964 #ifdef LINUX
39653932 const char *szConfig = ECConfig::GetDefaultPath("dagent.cfg");
3966 #else
3967 char *szConfig = "dagent.cfg";
3968 #if 0
3969 // FIXME
3970 ECNTService ecNTService;
3971 #endif
3972 #endif
39733933
39743934 enum {
39753935 OPT_HELP = UCHAR_MAX + 1,
40073967 static const configsetting_t lpDefaults[] = {
40083968 { "server_bind", "" },
40093969 { "server_bind_intf", "" },
4010 #ifdef LINUX
40113970 { "run_as_user", "kopano" },
40123971 { "run_as_group", "kopano" },
40133972 { "pid_file", "/var/run/kopano/dagent.pid" },
40143973 { "coredump_enabled", "no" },
4015 #endif
40163974 { "lmtp_port", "2003" },
40173975 { "lmtp_max_threads", "20" },
40183976 { "process_model", "", CONFIGSETTING_UNUSED },
42034161 if (!bExplicitConfig && loglevel)
42044162 g_lpLogger->SetLoglevel(loglevel);
42054163
4206
42074164 /* Warn users that we are using the default configuration */
42084165 if (bDefaultConfigWarning && bExplicitConfig) {
42094166 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to open configuration file %s", szConfig);
3939 #include "fileutil.h"
4040
4141 using namespace std;
42
4342
4443 LMTP::LMTP(ECChannel *lpChan, const char *szServerPath, ECLogger *lpLog, ECConfig *lpConf)
4544 {
7069 {
7170 HRESULT hr = hrSuccess;
7271
73 if (strnicmp(strCommand.c_str(), "LHLO", strlen("LHLO")) == 0)
72 if (strncasecmp(strCommand.c_str(), "LHLO", strlen("LHLO")) == 0)
7473 eCommand = LMTP_Command_LHLO;
75 else if (strnicmp(strCommand.c_str(), "MAIL FROM:", strlen("MAIL FROM:")) == 0)
74 else if (strncasecmp(strCommand.c_str(), "MAIL FROM:", strlen("MAIL FROM:")) == 0)
7675 eCommand = LMTP_Command_MAIL_FROM;
77 else if (strnicmp(strCommand.c_str(), "RCPT TO:", strlen("RCPT TO:")) == 0)
76 else if (strncasecmp(strCommand.c_str(), "RCPT TO:", strlen("RCPT TO:")) == 0)
7877 eCommand = LMTP_Command_RCPT_TO;
79 else if (strnicmp(strCommand.c_str(), "DATA", strlen("DATA")) == 0)
78 else if (strncasecmp(strCommand.c_str(), "DATA", strlen("DATA")) == 0)
8079 eCommand = LMTP_Command_DATA;
81 else if (strnicmp(strCommand.c_str(), "RSET", strlen("RSET")) == 0)
80 else if (strncasecmp(strCommand.c_str(), "RSET", strlen("RSET")) == 0)
8281 eCommand = LMTP_Command_RSET;
83 else if (strnicmp(strCommand.c_str(), "QUIT", strlen("QUIT")) == 0)
82 else if (strncasecmp(strCommand.c_str(), "QUIT", strlen("QUIT")) == 0)
8483 eCommand = LMTP_Command_QUIT;
8584 else
8685 hr = MAPI_E_CALL_FAILED;
1111
1212 sbin_PROGRAMS = kopano-dagent kopano-spooler
1313 noinst_DATA = kopano-dagent.ldx kopano-spooler.ldx
14 CLEANFILES = ${noinst_DATA}
1415
1516 kopano_dagent_LDADD = ${top_builddir}/inetmapi/libkcinetmapi.la \
1617 ${top_builddir}/mapi4linux/src/libmapi.la \
3940 PyMapiPlugin.cpp PyMapiPlugin.h PythonSWIGRuntime.h
4041
4142 BUILT_SOURCES=PythonSWIGRuntime.h
42
43 CLEANFILES=PythonSWIGRuntime.h
43 CLEANFILES += PythonSWIGRuntime.h
4444 EXTRA_DIST=PythonSWIGRuntime.h
4545
4646 PythonSWIGRuntime.h:
324324 return hr;
325325 }
326326
327
328
329327 PyMapiPluginFactory::PyMapiPluginFactory()
330328 : m_ptrModMapiPlugin(NULL)
331329 , m_bEnablePlugin(false)
5959 #include <kopano/CommonUtil.h>
6060 #include <kopano/ECLogger.h>
6161 #include <kopano/ECConfig.h>
62 #ifdef LINUX
6362 #include <kopano/UnixUtil.h>
64 #endif
65 #include <kopano/MAPIErrors.h>
6663 #include <kopano/my_getopt.h>
6764 #include <kopano/ecversion.h>
6865 #include <kopano/Util.h>
9895 static int nReload = 0;
9996 static int disconnects = 0;
10097 static const char *szCommand = NULL;
101 #ifdef LINUX
10298 static const char *szConfig = ECConfig::GetDefaultPath("spooler.cfg");
103 #else
104 static const char *szConfig = "spooler.cfg";
105 #endif
10699 ECConfig *g_lpConfig = NULL;
107100 ECLogger *g_lpLogger = NULL;
108101
109 #ifdef LINUX
110102 static pthread_t signal_thread;
111103 static sigset_t signal_mask;
112104 static bool bNPTL = true;
113 #endif
114105
115106 // notification
116107 static bool bMessagesWaiting = false;
201192 return 0;
202193 }
203194
204
205195 /*
206196 * starting fork, passes:
207197 * -c config for all log settings and smtp server and such
212202 * if (szSMTP) smtp host
213203 * if (szSMTPPport) smtp port
214204 */
215 #ifdef LINUX
216205 /**
217206 * Starts a forked process which sends the actual mail, and removes it
218207 * from the queue, in normal situations. On error, the
308297 exit:
309298 return hr;
310299 }
311 #endif
312300
313301 /**
314302 * Opens all required objects of the administrator to move an error
407395 IECSpooler *lpSpooler)
408396 {
409397 HRESULT hr = hrSuccess;
410 std::map<pid_t, int>::const_iterator i, iDel;
398 std::map<pid_t, int>::const_iterator i;
411399 SendData sSendData;
412400 bool bErrorMail;
413401 map<pid_t, int> finished; // exit status of finished processes
905893 return hr;
906894 }
907895
908 #ifdef LINUX
909896 /**
910897 * Segfault signal handler. Prints the backtrace of the crash in the log.
911898 *
1009996
1010997 return NULL;
1011998 }
1012 #endif
1013999
10141000 /**
10151001 * Main program loop. Calls ProcessQueue, which logs in to MAPI. This
10991085 { "smtp_server","localhost", CONFIGSETTING_RELOADABLE },
11001086 { "smtp_port","25", CONFIGSETTING_RELOADABLE },
11011087 { "server_socket", "default:" },
1102 #ifdef LINUX
11031088 { "run_as_user", "kopano" },
11041089 { "run_as_group", "kopano" },
11051090 { "pid_file", "/var/run/kopano/spooler.pid" },
11061091 { "running_path", "/var/lib/kopano" },
11071092 { "coredump_enabled", "no" },
1108 #endif
11091093 { "log_method","file" },
11101094 { "log_file","-" },
11111095 { "log_level", "3", CONFIGSETTING_RELOADABLE },
11361120 { "tmp_path", "/tmp" },
11371121 { NULL, NULL },
11381122 };
1139 #ifdef LINUX
11401123 // SIGSEGV backtrace support
11411124 stack_t st;
11421125 struct sigaction act;
11431126
11441127 memset(&st, 0, sizeof(st));
11451128 memset(&act, 0, sizeof(act));
1146 #endif
11471129
11481130 setlocale(LC_CTYPE, "");
11491131 setlocale(LC_MESSAGES, "");
12391221 szCommand = argv[0];
12401222
12411223 // setup logging, use pipe to log if started in forked mode and using pipe (file) logger, create normal logger for syslog
1242 #ifdef LINUX
12431224 if (bForked && logfd != -1)
12441225 g_lpLogger = new ECLogger_Pipe(logfd, 0, atoi(g_lpConfig->GetSetting("log_level")));
12451226 else
1246 #endif
12471227 g_lpLogger = CreateLogger(g_lpConfig, argv[0], "KopanoSpooler");
12481228
12491229 ec_log_set(g_lpLogger);
12531233 if (!TmpPath::getInstance() -> OverridePath(g_lpConfig))
12541234 g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Ignoring invalid path-setting!");
12551235
1256 #ifdef LINUX
12571236 // detect linuxthreads, which is too broken to correctly run the spooler
12581237 if (!bForked) {
12591238 char buffer[256] = { 0 };
12661245 g_lpLogger->Log(EC_LOGLEVEL_WARNING, "WARNING: the kopano-spooler will only be able to send one message at a time.");
12671246 }
12681247 }
1269 #endif
12701248
12711249 // set socket filename
12721250 if (!szPath)
12761254 // keep sending mail when we're killed in forked mode
12771255 signal(SIGTERM, SIG_IGN);
12781256 signal(SIGINT, SIG_IGN);
1279 #ifdef LINUX
12801257 signal(SIGHUP, SIG_IGN);
12811258 signal(SIGUSR1, SIG_IGN);
12821259 signal(SIGUSR2, SIG_IGN);
1283 #endif
12841260 }
12851261 else {
12861262 pthread_mutex_init(&hMutexFinished, NULL);
12951271 sigaddset(&signal_mask, SIGUSR2);
12961272 }
12971273
1298 #ifdef LINUX
12991274 st.ss_sp = malloc(65536);
13001275 st.ss_flags = 0;
13011276 st.ss_size = 65536;
13071282 sigaction(SIGSEGV, &act, NULL);
13081283 sigaction(SIGBUS, &act, NULL);
13091284 sigaction(SIGABRT, &act, NULL);
1310 #endif
13111285
13121286 bQuit = bMessagesWaiting = false;
1313
1314 #ifdef LINUX
13151287 if (parseBool(g_lpConfig->GetSetting("coredump_enabled")))
13161288 unix_coredump_enable(g_lpLogger);
13171289
13351307 }
13361308 g_lpLogger = StartLoggerProcess(g_lpConfig, g_lpLogger);
13371309 ec_log_set(g_lpLogger);
1338 #endif
13391310 g_lpLogger->SetLogprefix(LP_PID);
13401311
13411312 hr = MAPIInitialize(NULL);
13451316 goto exit;
13461317 }
13471318
1348 #ifdef LINUX
13491319 if (!bForked) {
13501320 if (bNPTL) {
13511321 // valid for all threads afterwards
13631333 signal(SIGUSR2, process_signal);
13641334 }
13651335 }
1366 #endif
13671336
13681337 sc = new StatsClient(g_lpLogger);
13691338 sc->startup(g_lpConfig->GetSetting("z_statsd_stats"));
13741343
13751344 delete sc;
13761345
1377 #ifdef LINUX
13781346 if (!bForked) {
13791347 if (bNPTL) {
13801348 g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Joining signal thread");
13861354 signal(SIGCHLD, SIG_IGN);
13871355 }
13881356 }
1389 #endif
1390
13911357 MAPIUninitialize();
13921358
13931359 exit:
13941360 delete g_lpConfig;
13951361 DeleteLogger(g_lpLogger);
1396
1397 #ifdef LINUX
13981362 free(st.ss_sp);
1399 #endif
1400
14011363 switch(hr) {
14021364 case hrSuccess:
14031365 return EXIT_OK;
4646 typedef std::ostringstream tostringstream;
4747 #endif
4848
49
5049 void ArchiveResult::AddMessage(MessagePtr ptrMessage) {
5150 m_lstMessages.push_back(ptrMessage);
5251 }
5655 i != m_lstMessages.end(); ++i)
5756 Util::HrDeleteMessage(lpSession, *i);
5857 }
59
6058
6159 HRESULT Archive::Create(IMAPISession *lpSession, ECLogger *lpLogger, ArchivePtr *lpptrArchive)
6260 {
239237 return hr;
240238 }
241239
242
243240 HRESULT Archive::HrArchiveMessageForSending(IMessage *lpMessage, ArchiveResult *lpResult)
244241 {
245242 HRESULT hr = hrSuccess;
11521152 lpPropValue[ulPropPos++].Value.bin.lpb = lpPropArrayOriginal[OR_SEARCH_KEY].Value.bin.lpb;
11531153 }
11541154
1155
11561155 // Add the original message into the errorMessage
11571156 hr = lpErrorMsg->CreateAttach(NULL, 0, &ulAttachNum, &lpAttach);
11581157 if (hr != hrSuccess) {
18681867 SizedSPropTagArray(3, sptaIDProps) = { 3, { PR_DISPLAY_NAME_W, PR_EC_SENDAS_USER_ENTRYIDS, PR_DISPLAY_TYPE } };
18691868 ULONG cValues = 0;
18701869
1871
18721870 hr = SMTPToZarafa(lpAddrBook, ulRepresentCB, lpRepresentEID, &sSpoofEID.Value.bin.cb, (LPENTRYID*)&sSpoofEID.Value.bin.lpb);
18731871 if (hr != hrSuccess)
18741872 hr = ContactToKopano(lpUserStore, lpAddrBook, ulRepresentCB, lpRepresentEID, &sSpoofEID.Value.bin.cb, (LPENTRYID*)&sSpoofEID.Value.bin.lpb);
20011999 LPSPropValue lpDelegates = NULL;
20022000 SPropValue sSpoofEID = {0};
20032001
2004
20052002 hr = SMTPToZarafa(lpAddrBook, ulRepresentCB, lpRepresentEID, &sSpoofEID.Value.bin.cb, (LPENTRYID*)&sSpoofEID.Value.bin.lpb);
20062003 if (hr != hrSuccess)
20072004 hr = ContactToKopano(lpUserStore, lpAddrBook, ulRepresentCB, lpRepresentEID, &sSpoofEID.Value.bin.cb, (LPENTRYID*)&sSpoofEID.Value.bin.lpb);
24262423 // ignore error if unable to open, just the copy of the mail might possibily not be done.
24272424 } else if(strcmp(g_lpConfig->GetSetting("allow_delegate_meeting_request"), "yes") == 0 &&
24282425 HrGetOneProp(lpMessage, PR_MESSAGE_CLASS_A, &lpMsgClass) == hrSuccess &&
2429 ((stricmp(lpMsgClass->Value.lpszA, "IPM.Schedule.Meeting.Request" ) == 0) ||
2430 (stricmp(lpMsgClass->Value.lpszA, "IPM.Schedule.Meeting.Canceled" ) == 0))) {
2426 ((strcasecmp(lpMsgClass->Value.lpszA, "IPM.Schedule.Meeting.Request" ) == 0) ||
2427 (strcasecmp(lpMsgClass->Value.lpszA, "IPM.Schedule.Meeting.Canceled" ) == 0))) {
24312428 // Meeting request can always sent as 'on behalf of' (Zarafa and SMTP user).
24322429 // This is needed if a user forward a meeting request. If you have permissions on a calendar,
24332430 // you can always sent with 'on behalve of'. This behavior is like exchange.
26042601 }
26052602 }
26062603
2607
26082604 // Now hand message to library which will send it, inetmapi will handle addressbook
26092605 hr = IMToINet(lpUserSession, lpAddrBook, lpMessage, lpMailer, sopt, g_lpLogger);
26102606
26442640 // We always return the processes message to the caller, whether it failed or not
26452641 if (lpMessage)
26462642 lpMessage->QueryInterface(IID_IMessage, (void**)lppMessage);
2647
26482643
26492644 if (lpMessage)
26502645 lpMessage->Release();
221221 ++pos;
222222 }
223223
224
225224 {
226225 strHTMLForwardText = "<b>From:</b> ";
227226 if (PROP_TYPE(ptrInfo[0].ulPropTag) != PT_ERROR)
410409 goto exit;
411410 }
412411
413
414412 // append To with original sender
415413 // @todo get Reply-To ?
416414 hr = lpOrigMessage->GetProps((LPSPropTagArray)&sReplyRecipient, 0, &cValues, &lpReplyRecipient);
723721 sForwardProps[cfp++].Value.lpszW = LPWSTR(bDoPreserveSender ? L"redirect" : L"forward");
724722 }
725723
726 hr = lpFwdMsg->SetProps(cfp, (LPSPropValue)&sForwardProps, NULL);
724 hr = lpFwdMsg->SetProps(cfp, sForwardProps, NULL);
727725 if (hr != hrSuccess)
728726 goto exit;
729727
790788 sNewProps[1].ulPropTag = PR_DELETE_AFTER_SUBMIT;
791789 sNewProps[1].Value.b = TRUE;
792790
793 hr = lpMessage->SetProps(2, (LPSPropValue)&sNewProps, NULL);
791 hr = lpMessage->SetProps(2, sNewProps, NULL);
794792 if (hr != hrSuccess)
795793 goto exit;
796794
12231221 GetSystemTimeAsFileTime(&sForwardProps[2].Value.ft);
12241222
12251223 // set forward in msg flag
1226 hr = (*lppMessage)->SetProps(3, (LPSPropValue)&sForwardProps, NULL);
1224 hr = (*lppMessage)->SetProps(3, sForwardProps, NULL);
12271225 }
12281226
12291227 exit:
0 # make sure common swig lib builds first
1
2 SUBDIRS = . include/kopano python
3
4 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) \
5 -I$(top_srcdir)/mapi4linux/include -I$(top_srcdir)/provider/common \
6 -I${top_srcdir}/common -I${top_srcdir}/m4lcommon
0 SUBDIRS = include/kopano python
71
82 EXTRA_DIST = edkmdb.i mapi.i mapiutil.i mapidefs.i mapicode.i mapix.i \
9 mapinotifsink.i typemap.i helpers.i IECExportChanges.i \
3 mapinotifsink.i helpers.i IECExportChanges.i \
104 IECMultiStoreTable.i IECServiceAdmin.i IECSpooler.i \
115 IECTestProtocol.i IECLicense.i inetmapi.i icalmapi.i \
12 swig_iunknown.h ecdefs.i libcommon.i archiver.i licenseclient.i \
6 ecdefs.i libcommon.i archiver.i licenseclient.i \
137 libfreebusy.i kopanosync.i ECLogger.i RecurrenceState.i \
148 RecurrenceState.swig.h
15
16 check-syntax:
17 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
18 -fsyntax-only -fmessage-length=0 ${CHK_SOURCES} -Wall -Wformat=2
2323 struct thread_info {
2424 bool bCalledFromPython;
2525 };
26
27
28 static void free_tls_data(void *lpvoid) {
29 delete (thread_info *)lpvoid;
30 }
3126
3227 static void make_key() {
3328 pthread_key_create(&g_key, NULL); // We need cleanup here
2121 %}
2222
2323 %include "wchar.i"
24 %include <windows.i>
2524 %include "cstring.i"
2625 %include "cwstring.i"
2726 %include "std_string.i"
6665 if(PyErr_Occurred())
6766 goto fail;
6867 }
69
70 bool ConvertFileFromUCS2ToUTF8(const std::string &, const std::string &);
7168
7269 // some common/rtfutil.h functions
7370 HRESULT HrExtractHTMLFromRTF(std::string lpStrRTFIn, std::string &OUTPUT, ULONG ulCodepage);
194194 }
195195 }
196196
197 ECRESULT Auth(unsigned char *lpData, unsigned int ulSize, unsigned char **lpResponse, unsigned int *lpulResponseSize);
197 ECRESULT Auth(unsigned char *lpData, unsigned int ulSize, void **, unsigned int *);
198198 };
1616
1717 // DIRTIEST HACK IN THE WORLD WARNING: we need to fix the broken swig output for mapi_wrap.h .....
1818 #pragma include_alias( "mapi_wrap.h", "mapi_wrap_fixed.h" )
19
20 /*
21 * perl: CORE/thread.h can define PTHREAD_CREATE_JOINABLE to a value. This clashes with
22 * the windows pthread implementation, where it's used in an enum.
23 */
24 #ifdef PTHREAD_CREATE_JOINABLE
25 #undef PTHREAD_CREATE_JOINABLE
26 #endif
2719
2820 #include "MAPINotifSink.h"
2921 #include <kopano/director_util.h>
12881288 PR_EMSMDB_SECTION_UID = PROP_TAG(PT_BINARY, 0x3D15)
12891289 PR_EMS_AB_CONTAINERID = PROP_TAG(PT_LONG, 0xFFFD)
12901290
1291 # MAPI Shortcuts
1292 PR_WLINK_TYPE = PROP_TAG(PT_BINARY, 0x6849)
1293 PR_WLINK_FLAGS = PROP_TAG(PT_LONG, 0x684A)
1294 PR_WLINK_ORDINAL = PROP_TAG(PT_BINARY, 0x684B)
1295 PR_WLINK_ENTRYID = PROP_TAG(PT_BINARY, 0x684C)
1296 PR_WLINK_RECKEY = PROP_TAG(PT_BINARY, 0x684D)
1297 PR_WLINK_STORE_ENTRYID = PROP_TAG(PT_BINARY, 0x684E)
1298 PR_WLINK_SECTION = PROP_TAG(PT_BINARY, 0x6852)
1299
12911300 # Freebusy properties
12921301 PR_FREEBUSY_START_RANGE = PROP_TAG(PT_LONG, 0x6847)
12931302 PR_FREEBUSY_END_RANGE = PROP_TAG(PT_LONG, 0x6848)
1010 noinst_DATA = libkcpyconv.ldd _MAPICore.ldd _inetmapi.ldd _icalmapi.ldd \
1111 _libcommon.ldd _archiver.ldd _libfreebusy.ldd _RecurrenceState.ldd \
1212 _licenseclient.ldd
13 CLEANFILES = ${noinst_DATA}
1314
1415 # disable warnings since code is mostly generated
1516 AM_CPPFLAGS = ${ZCPPFLAGS} $(DEBUGFLAGS) \
1819 $(PYTHON_INCLUDES) -I${top_srcdir}/swig -w \
1920 -DSWIG_PYTHON_OUTPUT_TUPLE -DSWIG_TYPE_TABLE=MAPI
2021
21 libkcpyconv_la_SOURCES = conversion.cpp conversion.h
22 libkcpyconv_la_SOURCES = conversion.cpp
2223 libkcpyconv_la_LDFLAGS = -Wl,--version-script=${top_builddir}/default.sym
2324 libkcpyconv_la_LIBADD = ${PYTHON_LIBS} \
2425 ${top_builddir}/mapi4linux/src/libmapi.la
25 libkcpydirector_la_SOURCES = ../director_util.cpp ../director_util.h
26 libkcpydirector_la_SOURCES = ../director_util.cpp
2627 libkcpydirector_la_LDFLAGS = -Wl,--version-script=${top_builddir}/default.sym
2728 libkcpydirector_la_LIBADD = -lpthread
2829
6162 ${top_builddir}/ECtools/libkcarchivercore.la \
6263 $(PROG_LIBS) $(PYTHON_LIBS)
6364
64 _licenseclient_la_CPPFLAGS = ${AM_CPPFLAGS} -I${top_srcdir}/provider/common -I${top_builddir}/provider/soap -I${top_srcdir}/provider/soap ${GSOAP_CFLAGS}
65 _licenseclient_la_CPPFLAGS = ${AM_CPPFLAGS} -I${top_srcdir}/provider/common -I${top_builddir}/provider/soap ${GSOAP_CFLAGS}
6566 _licenseclient_la_LDFLAGS = ${AM_LDFLAGS} -module -avoid-version
66 _licenseclient_la_LIBADD = ${top_builddir}/provider/common/libkccommon.la \
67 _licenseclient_la_LIBADD = ${top_builddir}/provider/libkccommon.la \
6768 ${GSOAP_LIBS} \
68 ${top_builddir}/provider/soap/libkcsoapclient.la \
69 ${top_builddir}/provider/libkcsoapclient.la \
6970 ${top_builddir}/common/libkcmapi.la \
7071 ${top_builddir}/common/libkcutil.la \
7172 ${top_builddir}/common/libkcssl.la \
107108 RecurrenceState_wrap.cxx
108109
109110
110 CLEANFILES = $(BUILT_SOURCES) \
111 CLEANFILES += ${BUILT_SOURCES} \
111112 MAPICore.py \
112113 inetmapi.py \
113114 icalmapi.py \
147148 mapi_wrap.h: mapi_wrap.cxx
148149 mapi_wrap.cxx: ../mapi.i ../mapiutil.i ../mapidefs.i ../mapicode.i ../mapix.i ../mapinotifsink.i ../mapiutil.i ../include/kopano/typemap.i ../helpers.i ../edkmdb.i ../IECServiceAdmin.i ../ecdefs.i include/kopano/typemap_python.i helpers_python.i
149150 if test "x$(SWIG_EXEC)" = "x"; then echo "swig is required for 'make dist'"; exit 1; fi
150 ${SWIG_EXEC} -I${top_srcdir}/swig -I${top_srcdir}/libsync ${SWIG_FLAGS} ${SWIG_CXXFLAGS} -o $@ $<
151 ${SWIG_EXEC} -I${top_srcdir}/libsync ${SWIG_FLAGS} ${SWIG_CXXFLAGS} -o $@ $<
151152
152153 inetmapi_wrap.cxx: ../inetmapi.i ../include/kopano/typemap.i ../inetmapi.i include/kopano/typemap_python.i helpers_python.i
153 ${SWIG_EXEC} -I${top_srcdir}/swig ${SWIG_CXXFLAGS} -o $@ $<
154 ${SWIG_EXEC} ${SWIG_CXXFLAGS} -o $@ $<
154155
155156 icalmapi_wrap.cxx: ../icalmapi.i ../include/kopano/typemap.i include/kopano/typemap_python.i helpers_python.i ../../libicalmapi/icalmapi.h
156 ${SWIG_EXEC} -I${top_srcdir}/libicalmapi -I${top_srcdir}/libfreebusy -I${top_srcdir/swig} ${SWIG_CXXFLAGS} -o $@ $<
157 ${SWIG_EXEC} -I${top_srcdir}/libicalmapi -I${top_srcdir}/libfreebusy ${SWIG_CXXFLAGS} -o $@ $<
157158
158159 archiver_wrap.cxx: ../archiver.i archiver_python.i
159160 ${SWIG_EXEC} -I${top_srcdir}/ECtools/archiver ${SWIG_CXXFLAGS} -o $@ $<
160161
161162 libcommon_wrap.cxx: ../libcommon.i
162 ${SWIG_EXEC} -I${top_srcdir}/common -I${top_srcdir}/m4lcommon -I${top_srcdir/swig} ${SWIG_CXXFLAGS} -o $@ $<
163 ${SWIG_EXEC} -I${top_srcdir}/common -I${top_srcdir}/m4lcommon ${SWIG_CXXFLAGS} -o $@ $<
163164
164165 RecurrenceState_wrap.cxx: ../RecurrenceState.i
165 ${SWIG_EXEC} -I${top_srcdir}/common -I${top_srcdir}/m4lcommon -I${top_srcdir/swig} ${SWIG_CXXFLAGS} -o $@ $<
166 ${SWIG_EXEC} -I${top_srcdir}/common -I${top_srcdir}/m4lcommon ${SWIG_CXXFLAGS} -o $@ $<
166167
167168 licenseclient_wrap.cxx: ../licenseclient.i
168 ${SWIG_EXEC} -I${top_srcdir}/provider/common -I${top_srcdir}/common -I${top_srcdir}/m4lcommon -I${top_srcdir/swig} ${SWIG_CXXFLAGS} -o $@ $<
169 ${SWIG_EXEC} -I${top_srcdir}/provider/common -I${top_srcdir}/common -I${top_srcdir}/m4lcommon ${SWIG_CXXFLAGS} -o $@ $<
169170
170171 libfreebusy_wrap.cxx: ../libfreebusy.i
171 ${SWIG_EXEC} -I${top_srcdir}/libfreebusy -I${top_srcdir/swig} ${SWIG_CXXFLAGS} -o $@ $<
172 ${SWIG_EXEC} -I${top_srcdir}/libfreebusy ${SWIG_CXXFLAGS} -o $@ $<
172173
173174 check-syntax:
174175 $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) \
176177
177178 install-exec-local:
178179 test "$(DISTRO)" = "suse" -o "$(DISTRO)" = "sles" && pyrpm="--record-rpm=INSTALLED_FILES"; \
179 cd ${srcdir} && ${PYTHON} setup.py install -f \
180 $${DESTDIR+--root=${DESTDIR}} \
180 cd ${srcdir} && ${PYTHON} setup.py \
181 build --build-base="${abs_builddir}/build" \
182 install -f $${DESTDIR+--root=${DESTDIR}} \
181183 --prefix="${prefix}" --install-purelib ${pythondir} $${pyrpm}
182184 rm -Rf build
183185
186 uninstall-local:
187 rm -Rf ${DESTDIR}${pythondir}/MAPI \
188 ${DESTDIR}${pythondir}/MAPI-1*.egg-info
189
184190 include ../../global.am
1616
1717 #include "archiver_conv.h"
1818
19
2019 PyObject* PyObject_from_Iterator(const ArchiveList::const_iterator &i) {
2120 return Py_BuildValue("(sssi)", i->StoreName.c_str(), i->FolderName.c_str(), i->StoreOwner.c_str(), i->Rights);
2221 }
2423 PyObject* PyObject_from_Iterator(const UserList::const_iterator &i) {
2524 return Py_BuildValue("s", i->UserName.c_str());
2625 }
27
2826
2927 template<typename ListType>
3028 PyObject* List_from(const ListType &lst)
5957 return list;
6058 }
6159
62
6360 PyObject* List_from_ArchiveList(const ArchiveList &lst)
6461 {
6562 return List_from<ArchiveList>(lst);
103103 #else
104104 #define NATIVE_UNICODE 0
105105 #endif
106
107106
108107 void Init()
109108 {
488487 return list;
489488 }
490489
491
492490 void Object_to_LPSPropValue(PyObject *object, LPSPropValue lpProp, ULONG ulFlags, void *lpBase)
493491 {
494492 PyObject *ulPropTag = NULL;
727725 CopyPyUnicode(&lpProp->Value.MVszW.lppszW[n], Value, lpBase);
728726 }
729727
730
731728 Py_DECREF(elem);
732729 ++n;
733730 }
802799 return lpProp;
803800 }
804801 }
805
806802
807803 LPSPropValue List_to_LPSPropValue(PyObject *object, ULONG *cValues, ULONG ulFlags, void *lpBase)
808804 {
25002496 {
25012497 LPMAPIERROR lpError = NULL;
25022498 if (MAPIAllocateBuffer(sizeof(LPMAPIERROR), (LPVOID*)&lpError) == hrSuccess)
2503 memset(lpError, 0, sizeof(LPMAPIERROR));
2499 memset(lpError, 0, sizeof(*lpError));
25042500 return lpError;
25052501 }
25062502
28932889 return result;
28942890 }
28952891
2896
28972892 PyObject *List_from_LPECUSER(ECUSER *lpUser, ULONG cElements, ULONG ulFlags)
28982893 {
28992894 PyObject *list = PyList_New(0);
30763071 // @todo charset conversion ?
30773072 return PyObject_CallFunction(PyTypeECUserClientUpdateStatus, "(llsssl)", lpECUCUS->ulTrackId, lpECUCUS->tUpdatetime, lpECUCUS->lpszCurrentversion, lpECUCUS->lpszLatestversion, lpECUCUS->lpszComputername, lpECUCUS->ulStatus);
30783073 }
3079
30803074
30813075 LPROWLIST List_to_LPROWLIST(PyObject *object, ULONG ulFlags)
30823076 {
33083302 ++lpSvrNameList->cServers;
33093303 }
33103304
3311
33123305 exit:
33133306 if(PyErr_Occurred()) {
33143307 MAPIFreeBuffer(lpSvrNameList);
99 kopano/daemon/version/version_info.py
1010
1111 install-exec-local:
12 cd ${srcdir} && ${PYTHON} setup.py install -f \
13 $${DESTDIR+--root=${DESTDIR}} \
12 cd ${srcdir} && ${PYTHON} setup.py \
13 build --build-base="${abs_builddir}/build" \
14 install -f $${DESTDIR+--root=${DESTDIR}} \
1415 --prefix="${prefix}" --install-purelib ${pythondir}
1516 rm -Rf build
17
18 uninstall-local:
19 rm -Rf ${DESTDIR}${pythondir}/kopano \
20 ${DESTDIR}${pythondir}/kopano-0*.egg-info
00 """
1 High-level python bindings
1 High-level python bindings for Kopano
22
33 Copyright 2005 - 2016 Zarafa and its licensors (see LICENSE file for details)
44 Copyright 2016 Kopano and its licensors (see LICENSE file for details)
608608 self.idname = REV_TAG.get(self.proptag) # XXX slow, often unused: make into properties?
609609 self.type_ = PROP_TYPE(self.proptag)
610610 self.typename = REV_TYPE.get(self.type_)
611 self.named = (self.id_ >= 0x8000)
611 self.named = False
612612 self.kind = None
613613 self.kindname = None
614614 self.guid = None
615615 self.name = None
616616 self.namespace = None
617617
618 if self.named:
618 if self.id_ >= 0x8000: # possible named prop
619619 try:
620620 lpname = self._parent_mapiobj.GetNamesFromIDs([self.proptag], None, 0)[0]
621 self.guid = bin2hex(lpname.guid)
622 self.namespace = GUID_NAMESPACE.get(lpname.guid)
623 self.name = lpname.id
624 self.kind = lpname.kind
625 self.kindname = 'MNID_STRING' if lpname.kind == MNID_STRING else 'MNID_ID'
621 if lpname:
622 self.guid = bin2hex(lpname.guid)
623 self.namespace = GUID_NAMESPACE.get(lpname.guid)
624 self.name = lpname.id
625 self.kind = lpname.kind
626 self.kindname = 'MNID_STRING' if lpname.kind == MNID_STRING else 'MNID_ID'
627 self.named = True
626628 except MAPIErrorNoSupport: # XXX user.props()?
627629 pass
628630
633635 # The datetime object is of "naive" type, has local time and
634636 # no TZ info. :-(
635637 #
636 self._value = datetime.datetime.fromtimestamp(self.mapiobj.Value.unixtime)
637
638 try:
639 self._value = datetime.datetime.fromtimestamp(self.mapiobj.Value.unixtime)
640 except ValueError: # Y10K: datetime is limited to 4-digit years
641 self._value = datetime.datetime(9999, 1, 1)
638642 else:
639643 self._value = self.mapiobj.Value
640644 return self._value
847851 entryid = HrGetOneProp(self.mapistore, PR_STORE_ENTRYID).Value
848852 self.pseudo_url = entryid[entryid.find(b'pseudo:'):-1] # XXX ECSERVER
849853 self.name = self.pseudo_url[9:] # XXX get this kind of stuff from pr_ec_statstable_servers..?
850 self._archive_sessions = {}
851854
852855 def nodes(self): # XXX delay mapi sessions until actually needed
853856 for row in self.table(PR_EC_STATSTABLE_SERVERS).dict_rows():
12621265 def hidden(self, value):
12631266 self._update(hidden=value)
12641267
1265 @property
1266 def groupid(self):
1267 return bin2hex(self._ecgroup.GroupID)
1268
12691268 # XXX: also does groups..
12701269 def add_user(self, user):
12711270 if isinstance(user, Group):
14971496 pass
14981497
14991498 @property
1499 def findroot(self):
1500 """ :class:`Folder` designated as search-results root """
1501
1502 try:
1503 return self.root.folder('FINDER_ROOT')
1504 except NotFoundError:
1505 pass
1506
1507 @property
15001508 def inbox(self):
15011509 """ :class:`Folder` designated as inbox """
15021510
15391547
15401548 try:
15411549 return Folder(self, HrGetOneProp(self._root, PR_IPM_CONTACT_ENTRYID).Value)
1550 except MAPIErrorNotFound:
1551 pass
1552
1553 @property
1554 def common_views(self):
1555 """ :class:`Folder` contains folders for managing views for the message store """
1556
1557 try:
1558 return Folder(self, self.prop(PR_COMMON_VIEWS_ENTRYID).value)
15421559 except MAPIErrorNotFound:
15431560 pass
15441561
17881805
17891806 def create_searchfolder(self, text=None): # XXX store.findroot.create_folder()?
17901807 import uuid # XXX username+counter? permission problems to determine number?
1791 finder_root = self.root.folder('FINDER_ROOT') # XXX store.findroot?
1792 mapiobj = finder_root.mapiobj.CreateFolder(FOLDER_SEARCH, str(uuid.uuid4()), 'comment', None, 0)
1808 mapiobj = self.findroot.mapiobj.CreateFolder(FOLDER_SEARCH, str(uuid.uuid4()), 'comment', None, 0)
17931809 return Folder(self, mapiobj=mapiobj)
17941810
17951811 def permissions(self):
17971813
17981814 def permission(self, member, create=False):
17991815 return _permission(self, member, create)
1816
1817 def favorites(self):
1818 """Returns a list of favorite folders """
1819
1820 table = self.common_views.mapiobj.GetContentsTable(MAPI_ASSOCIATED)
1821 table.SetColumns([PR_MESSAGE_CLASS, PR_SUBJECT, PR_WLINK_ENTRYID, PR_WLINK_FLAGS, PR_WLINK_ORDINAL, PR_WLINK_STORE_ENTRYID, PR_WLINK_TYPE], 0)
1822 table.Restrict(SPropertyRestriction(RELOP_EQ, PR_MESSAGE_CLASS, SPropValue(PR_MESSAGE_CLASS, "IPM.Microsoft.WunderBar.Link")), TBL_BATCH)
1823
1824 for row in table.QueryRows(-1, 0):
1825 entryid = bin2hex(row[2].Value)
1826 store_entryid = bin2hex(row[5].Value)
1827
1828 if store_entryid != self.entryid: # XXX: Handle favorites from public stores
1829 continue
1830
1831 try:
1832 yield self.folder(entryid=bin2hex(row[2].Value))
1833 except MAPIErrorNotFound:
1834 pass
18001835
18011836 def __eq__(self, s): # XXX check same server?
18021837 if isinstance(s, Store):
22522287 searchfolder.search_wait()
22532288 for item in searchfolder:
22542289 yield item
2255 self.store.root.folder('FINDER_ROOT').mapiobj.DeleteFolder(searchfolder.entryid.decode('hex'), 0, None, 0) # XXX store.findroot
2290 self.store.findroot.mapiobj.DeleteFolder(searchfolder.entryid.decode('hex'), 0, None, 0) # XXX store.findroot
22562291
22572292 def search_start(self, folder, text): # XXX RECURSIVE_SEARCH
22582293 # specific restriction format, needed to reach indexer
23082343 return self.primary_store.folder(entryid=entryid.encode('hex'))
23092344 except MAPIErrorNotFound:
23102345 pass
2346
2347 @property
2348 def created(self):
2349 try:
2350 return self.prop(PR_CREATION_TIME).value
2351 except MAPIErrorNotFound:
2352 pass
23112353
23122354 def __eq__(self, f): # XXX check same store?
23132355 if isinstance(f, Folder):
24802522 def body(self, x):
24812523 self.mapiobj.SetProps([SPropValue(PR_BODY_W, unicode(x))])
24822524 self.mapiobj.SaveChanges(KEEP_OPEN_READWRITE)
2525
2526 @property
2527 def created(self):
2528 try:
2529 return self.prop(PR_CREATION_TIME).value
2530 except MAPIErrorNotFound:
2531 pass
24832532
24842533 @property
24852534 def received(self):
28632912 for prop in self.props():
28642913 if (bestbody != PR_NULL and prop.proptag in (PR_BODY_W, PR_HTML, PR_RTF_COMPRESSED) and prop.proptag != bestbody):
28652914 continue
2866 if prop.id_ >= 0x8000: # named prop: prop.id_ system dependant..
2915 if prop.named: # named prop: prop.id_ system dependant..
28672916 data = [prop.proptag, prop.mapiobj.Value, self.mapiobj.GetNamesFromIDs([prop.proptag], None, 0)[0]]
28682917 if not archiver and data[2].guid == PSETID_Archive:
28692918 continue
37243773 user_class = kwargs.get('user_class', self._ecuser.Class)
37253774 admin = kwargs.get('admin', self._ecuser.IsAdmin)
37263775
3727 usereid = self.server.sa.SetUser(ECUSER(Username=username, Password=password, Email=email, FullName=fullname,
3728 Class=user_class, UserID=self._ecuser.UserID, IsAdmin=admin, MVPropMap = self._ecuser.MVPropMap), MAPI_UNICODE)
3776 # Thrown when a user tries to set his own features, handle gracefully otherwise you'll end up without a store
3777 try:
3778 # Pass the MVPropMAP otherwise the set values are reset
3779 if hasattr(self._ecuser, 'MVPropMap'):
3780 usereid = self.server.sa.SetUser(ECUSER(Username=username, Password=password, Email=email, FullName=fullname,
3781 Class=user_class, UserID=self._ecuser.UserID, IsAdmin=admin, MVPropMap = self._ecuser.MVPropMap), MAPI_UNICODE)
3782
3783 else:
3784 usereid = self.server.sa.SetUser(ECUSER(Username=username, Password=password, Email=email, FullName=fullname,
3785 Class=user_class, UserID=self._ecuser.UserID, IsAdmin=admin), MAPI_UNICODE)
3786 except MAPIErrorNoSupport:
3787 pass
37293788
37303789 self._ecuser = self.server.sa.GetUser(self.server.sa.ResolveUserName(username, MAPI_UNICODE), MAPI_UNICODE)
37313790 if self.name != username:
39564015 log.info('stopping %s', service.name)
39574016
39584017 def daemonize(func, options=None, foreground=False, log=None, config=None, service=None):
3959 if log and service:
3960 log.info('starting %s', service.logname or service.name)
39614018 uid = gid = None
39624019 working_directory = '/'
39634020 pidfile = None
44574514 config2.update(config)
44584515 if getattr(options, 'config_file', None):
44594516 options.config_file = os.path.abspath(options.config_file) # XXX useful during testing. could be generalized with optparse callback?
4517 if getattr(options, 'service', True) == False:
4518 options.foreground = True
44604519 self.config = Config(config2, service=name, options=options)
44614520 self.config.data['server_socket'] = os.getenv("KOPANO_SOCKET") or self.config.data['server_socket']
44624521 if getattr(options, 'worker_processes', None):
44694528 self.log.error(msg)
44704529 sys.exit(1)
44714530 self.stats = collections.defaultdict(int, {'errors': 0})
4531 self._server = None
44724532
44734533 @property
44744534 def server(self):
4475 return Server(options=self.options, config=self.config.data, log=self.log, service=self)
4535 if self._server is None:
4536 self._server = Server(options=self.options, config=self.config.data, log=self.log, service=self)
4537 return self._server
44764538
44774539 def start(self):
44784540 for sig in (signal.SIGTERM, signal.SIGINT):
44794541 signal.signal(sig, lambda *args: sys.exit(-sig))
44804542 signal.signal(signal.SIGHUP, signal.SIG_IGN) # XXX long term, reload config?
4543
4544 self.log.info('starting %s', self.logname or self.name)
44814545 with log_exc(self.log):
4482 daemonize(self.main, options=self.options, log=self.log, config=self.config, service=self)
4546 if getattr(self.options, 'service', True): # do not run-as-service (eg backup)
4547 daemonize(self.main, options=self.options, log=self.log, config=self.config, service=self)
4548 else:
4549 daemon_helper(self.main, self, self.log)
44834550
44844551 class Worker(Process):
44854552 def __init__(self, service, name, **kwargs):
44994566 self.log.setLevel(loglevel)
45004567
45014568 def run(self):
4569 self.service._server = None # do not re-use "forked" session
45024570 signal.signal(signal.SIGINT, signal.SIG_IGN)
45034571 signal.signal(signal.SIGHUP, signal.SIG_IGN)
45044572 signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
513513
514514 """
515515 try:
516 os.setgroups([])
516 # KC custom modification of python-daemon.
517 # If we cannot get rid of the groups, leave them.
518 try:
519 os.setgroups([])
520 except Exception, exc:
521 pass
517522 os.setgid(gid)
518523 os.setuid(uid)
519524 except Exception, exc:
6767 if password == 'test':
6868 try:
6969 user = server.user(username)
70 except kopano.ZException:
70 except kopano.Error:
7171 return False
7272 return True
7373 return False
157157 itemlist = []
158158 try:
159159 folder = user.store.folder(foldername)
160 except kopano.ZException:
160 except kopano.Error:
161161 return jsonify({'error': 'Folder does not exist'})
162162 for item in folder.items():
163163 itemlist.append({
174174 def item(folderid, itemid):
175175 try:
176176 folder = user.store.folder(entryid=folderid)
177 except kopano.ZException:
177 except kopano.Error:
178178 return jsonify({'error': 'Folder does not exist'})
179179 try:
180180 item = folder.item(itemid)
00 EXTRA_DIST = setup.py zarafa/__init__.py
11
22 install-exec-local:
3 cd ${srcdir} && ${PYTHON} setup.py install -f \
4 $${DESTDIR+--root=${DESTDIR}} \
3 cd ${srcdir} && ${PYTHON} setup.py \
4 build --build-base="${abs_builddir}/build" \
5 install -f $${DESTDIR+--root=${DESTDIR}} \
56 --prefix="${prefix}" --install-purelib ${pythondir}
67 rm -Rf build
8
9 uninstall-local:
10 rm -Rf ${DESTDIR}${pythondir}/zarafa \
11 ${DESTDIR}${pythondir}/zarafa-0*.egg-info
0 # Create a lot of dummy SFs
1 import kopano
2 s = kopano.Server(auth_user='bar', auth_pass='xbar')
3 u = s.user('bar')
4 for x in range(0, 10000):
5 findroot = u.root.folder('FINDER_ROOT') # search folders are stored here as regular MAPI folders, but with the data coming from special DB tables
6 print 'searchfolder count:', findroot.subfolder_count # count search folders
7 sf = u.create_searchfolder() # create search folder in 'findroot'
8 sf.search_start(u.inbox, 'blah')
0 import datetime
1 import kopano
2 from MAPI.Tags import PR_CREATION_TIME
3
4 for u in kopano.users():
5 print 'user', u
6 try:
7 findroot = u.root.folder('FINDER_ROOT')
8 except:
9 print 'ERROR getting findroot, skipping user'
10 continue
11 print findroot, findroot.subfolder_count
12 for sf in findroot.folders():
13 print sf, sf.entryid, sf.hierarchyid
14 creation_time = sf.prop(PR_CREATION_TIME).value
15 print 'created at', creation_time
16 if creation_time < datetime.datetime.now()-datetime.timedelta(days=30):
17 print 'DELETING!'
18 findroot.delete(sf)
0 # Count children of FINDER_ROOTs without using PR_SUBFOLDERS
1 #
2 SELECT COUNT(*)
3 FROM properties AS p
4 INNER JOIN hierarchy AS hp ON p.hierarchyid=hp.id AND p.tag=0x3001
5 INNER JOIN hierarchy AS hc ON hp.id=hc.parent
6 WHERE p.val_string="FINDER_ROOT";
7
8 # Uses PR_SUBFOLDERS hack to count
9 # (It's an integer rather than a boolean in the KC DB)
10 #
11 SELECT SUM(p2.val_ulong)
12 FROM properties AS p1
13 INNER JOIN properties AS p2
14 ON p1.hierarchyid=p2.hierarchyid AND p1.tag=0x3001 AND p2.tag=0x360A
15 WHERE p1.val_string="FINDER_ROOT";
16
17 # Show distribution
18 #
19 SELECT p2.val_ulong
20 FROM properties AS p1
21 INNER JOIN properties AS p2
22 ON p1.hierarchyid=p2.hierarchyid AND p1.tag=0x3001 AND p2.tag=0x360A
23 WHERE p1.val_string="FINDER_ROOT"
24 ORDER BY p2.val_ulong DESC
25 LIMIT 25;