mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-17 07:33:57 +00:00
feat(api): add endpoint for caldav/cardav url
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,6 +10,7 @@
|
|||||||
*/obj/
|
*/obj/
|
||||||
.scss-lint-config.yml_
|
.scss-lint-config.yml_
|
||||||
ActiveSync/ActiveSync.SOGo
|
ActiveSync/ActiveSync.SOGo
|
||||||
|
API/API.SOGo
|
||||||
Documentation/*.docbook
|
Documentation/*.docbook
|
||||||
Documentation/*.pdf
|
Documentation/*.pdf
|
||||||
Documentation/*.html
|
Documentation/*.html
|
||||||
|
|||||||
28
API/GNUmakefile
Normal file
28
API/GNUmakefile
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
# GNUstep makefile
|
||||||
|
|
||||||
|
include common.make
|
||||||
|
|
||||||
|
BUNDLE_NAME = API
|
||||||
|
|
||||||
|
API_PRINCIPAL_CLASS = SOGoAPIProduct
|
||||||
|
|
||||||
|
API_OBJC_FILES = \
|
||||||
|
SOGoAPIProduct.m \
|
||||||
|
SOGoAPI.m \
|
||||||
|
SOGoAPIVersion.m \
|
||||||
|
SOGoAPIUserFolder.m \
|
||||||
|
SOGoAPIDispatcher.m
|
||||||
|
|
||||||
|
API_RESOURCE_FILES += \
|
||||||
|
product.plist
|
||||||
|
|
||||||
|
API_LANGUAGES = $(SOGO_LANGUAGES)
|
||||||
|
|
||||||
|
API_LOCALIZED_RESOURCE_FILES = Localizable.strings
|
||||||
|
|
||||||
|
ADDITIONAL_INCLUDE_DIRS += -I../SOPE/ -I../SoObjects/
|
||||||
|
|
||||||
|
-include GNUmakefile.preamble
|
||||||
|
include $(GNUSTEP_MAKEFILES)/bundle.make
|
||||||
|
-include GNUmakefile.postamble
|
||||||
16
API/GNUmakefile.preamble
Normal file
16
API/GNUmakefile.preamble
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# compile settings
|
||||||
|
|
||||||
|
ADDITIONAL_CPPFLAGS += \
|
||||||
|
-DSOGO_MAJOR_VERSION=$(MAJOR_VERSION) \
|
||||||
|
-DSOGO_MINOR_VERSION=$(MINOR_VERSION) \
|
||||||
|
-DSOGO_PATCH_VERSION=$(SUBMINOR_VERSION) \
|
||||||
|
-DSOGO_LIBDIR="@\"$(SOGO_LIBDIR)\""
|
||||||
|
|
||||||
|
ADDITIONAL_INCLUDE_DIRS += \
|
||||||
|
-D_GNU_SOURCE -I../SOPE/ -I../SoObjects/
|
||||||
|
|
||||||
|
ADDITIONAL_LIB_DIRS += \
|
||||||
|
-L../SoObjects/SOGo/SOGo.framework/sogo -lSOGo \
|
||||||
|
-L../SOPE/GDLContentStore/$(GNUSTEP_OBJ_DIR)/ -lGDLContentStore \
|
||||||
|
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ -lNGCards \
|
||||||
|
-lEOControl -lNGStreams -lNGMime -lNGExtensions -lNGObjWeb -lWEExtensions
|
||||||
35
API/SOGoAPI.h
Normal file
35
API/SOGoAPI.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
|
This file is part of SOPE.
|
||||||
|
|
||||||
|
SOPE is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOPE; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
|
||||||
|
@class WOContext;
|
||||||
|
|
||||||
|
@interface SOGoAPI : NSObject
|
||||||
|
- (NSArray *) methodAllowed;
|
||||||
|
- (BOOL) needAuth;
|
||||||
|
- (NSArray *) paramNeeded;
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
|
||||||
|
|
||||||
|
@end
|
||||||
52
API/SOGoAPI.m
Normal file
52
API/SOGoAPI.m
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) todo...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <SOGoAPI.h>
|
||||||
|
|
||||||
|
|
||||||
|
@implementation SOGoAPI
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) methodAllowed
|
||||||
|
{
|
||||||
|
NSArray *result;
|
||||||
|
|
||||||
|
result = [NSArray arrayWithObjects:@"GET",nil];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) needAuth
|
||||||
|
{
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) paramNeeded
|
||||||
|
{
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
|
||||||
|
{
|
||||||
|
NSDictionary* result;
|
||||||
|
|
||||||
|
result = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||||
|
@"API not defined", @"error",
|
||||||
|
nil];
|
||||||
|
[result autorelease];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end /* SOGoAPI */
|
||||||
0
API/SOGoAPIConstants.h
Normal file
0
API/SOGoAPIConstants.h
Normal file
54
API/SOGoAPIDispatcher.h
Normal file
54
API/SOGoAPIDispatcher.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014-2015, Inverse inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Inverse inc. nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
#import <SOGo/WORequest+SOGo.h>
|
||||||
|
#import <SOGo/WOResponse+SOGo.h>
|
||||||
|
|
||||||
|
@class NSCalendarDate;
|
||||||
|
@class NSException;
|
||||||
|
@class NSMutableDictionary;
|
||||||
|
@class NSURL;
|
||||||
|
@class NSNumber;
|
||||||
|
|
||||||
|
static volatile BOOL apiShouldTerminate = NO;
|
||||||
|
|
||||||
|
@interface SOGoAPIDispatcher : NSObject
|
||||||
|
{
|
||||||
|
|
||||||
|
id context;
|
||||||
|
BOOL debugOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSException *) dispatchRequest: (WORequest*) theRequest
|
||||||
|
inResponse: (WOResponse*) theResponse
|
||||||
|
context: (id) theContext;
|
||||||
|
|
||||||
|
@end
|
||||||
399
API/SOGoAPIDispatcher.m
Normal file
399
API/SOGoAPIDispatcher.m
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2014, Inverse inc.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Inverse inc. nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SOGoAPIDispatcher.h"
|
||||||
|
|
||||||
|
#import <Foundation/NSAutoreleasePool.h>
|
||||||
|
#import <NGObjWeb/NSException+HTTP.h>
|
||||||
|
#import <NGObjWeb/WOContext+SoObjects.h>
|
||||||
|
#import <NGObjWeb/WOCoreApplication.h>
|
||||||
|
#import <NGExtensions/NSObject+Logs.h>
|
||||||
|
#import <NGExtensions/NSString+misc.h>
|
||||||
|
#import <NGExtensions/NSString+Encoding.h>
|
||||||
|
#import <SOGo/SOGoSystemDefaults.h>
|
||||||
|
#import <SOGo/SOGoUser.h>
|
||||||
|
#import <SOGo/SOGoUserManager.h>
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
#import <SOGo/WORequest+SOGo.h>
|
||||||
|
#import <SOGo/WOResponse+SOGo.h>
|
||||||
|
#import <SOGo/NSArray+Utilities.h>
|
||||||
|
#import <SOGo/NSString+Utilities.h>
|
||||||
|
#import <SOGo/SOGoOpenIdSession.h>
|
||||||
|
|
||||||
|
|
||||||
|
void handle_api_terminate(int signum)
|
||||||
|
{
|
||||||
|
NSLog(@"Forcing termination of API loop.");
|
||||||
|
apiShouldTerminate = YES;
|
||||||
|
[[WOCoreApplication application] terminateAfterTimeInterval: 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation SOGoAPIDispatcher
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
|
||||||
|
debugOn = [[SOGoSystemDefaults sharedSystemDefaults] apiDebugEnabled];
|
||||||
|
apiShouldTerminate = NO;
|
||||||
|
|
||||||
|
signal(SIGTERM, handle_api_terminate);
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) _sendAPIErrorResponse: (WOResponse* ) response
|
||||||
|
withMessage: (NSString *) message
|
||||||
|
withStatus: (unsigned int) status
|
||||||
|
{
|
||||||
|
NSDictionary *msg;
|
||||||
|
msg = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||||
|
message, @"error",
|
||||||
|
nil];
|
||||||
|
[response setStatus: status];
|
||||||
|
[response setContent: [msg jsonRepresentation]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *) _getActionFromUri: (NSString *) _uri
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
_uri always start with /SOGo/SOGoAPI
|
||||||
|
full _uri example /SOGo/SOGoAPI/Action/subaction1?param1¶m2
|
||||||
|
*/
|
||||||
|
|
||||||
|
NSString *uriWithoutParams, *action, *prefix;
|
||||||
|
NSArray *uriSplits;
|
||||||
|
|
||||||
|
prefix = @"/SOGo/SOGoAPI";
|
||||||
|
action = @"";
|
||||||
|
|
||||||
|
uriWithoutParams = [_uri urlWithoutParameters];
|
||||||
|
if(![uriWithoutParams hasPrefix: prefix])
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"Uri for API request does not start with /SOGo/SOGoAPI: %@", uriWithoutParams];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uriWithoutParams = [uriWithoutParams substringFromIndex:[prefix length]];
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove first and last '/'' if needed
|
||||||
|
if([uriWithoutParams hasPrefix: @"/"])
|
||||||
|
{
|
||||||
|
uriWithoutParams = [uriWithoutParams substringFromIndex:1];
|
||||||
|
}
|
||||||
|
if([uriWithoutParams hasSuffix: @"/"])
|
||||||
|
{
|
||||||
|
uriWithoutParams = [uriWithoutParams substringToIndex:([uriWithoutParams length] -1)];
|
||||||
|
}
|
||||||
|
if([uriWithoutParams length] == 0)
|
||||||
|
{
|
||||||
|
[self warnWithFormat: @"Uri for API request has no action, make Version instead: %@", uriWithoutParams];
|
||||||
|
return @"SOGoAPIVersion";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uriSplits = [uriWithoutParams componentsSeparatedByString: @"/"];
|
||||||
|
action = [@"SOGoAPI" stringByAppendingString: [uriSplits objectAtIndex: 0]];
|
||||||
|
if(debugOn)
|
||||||
|
[self logWithFormat: @"API request, action made is %@", action];
|
||||||
|
}
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) _authBasicCheck: (NSString *) auth
|
||||||
|
{
|
||||||
|
NSDictionary *user;
|
||||||
|
NSRange rng;
|
||||||
|
NSString *decodeCred, *domain, *login, *pwd;
|
||||||
|
SOGoUserManager *lm;
|
||||||
|
SOGoPasswordPolicyError perr;
|
||||||
|
int expire, grace;
|
||||||
|
BOOL rc;
|
||||||
|
|
||||||
|
user = nil;
|
||||||
|
|
||||||
|
decodeCred = [[auth substringFromIndex:5] stringByTrimmingLeadWhiteSpaces];
|
||||||
|
decodeCred = [decodeCred stringByDecodingBase64];
|
||||||
|
|
||||||
|
rng = [decodeCred rangeOfString:@":"];
|
||||||
|
login = [decodeCred substringToIndex:rng.location];
|
||||||
|
pwd = [decodeCred substringFromIndex:(rng.location + rng.length)];
|
||||||
|
|
||||||
|
domain = nil;
|
||||||
|
perr = PolicyNoError;
|
||||||
|
rc = ([[SOGoUserManager sharedUserManager]
|
||||||
|
checkLogin: [login stringByReplacingString: @"%40"
|
||||||
|
withString: @"@"]
|
||||||
|
password: pwd
|
||||||
|
domain: &domain
|
||||||
|
perr: &perr
|
||||||
|
expire: &expire
|
||||||
|
grace: &grace
|
||||||
|
additionalInfo: nil]
|
||||||
|
&& perr == PolicyNoError);
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
//Fecth user info
|
||||||
|
lm = [SOGoUserManager sharedUserManager];
|
||||||
|
user = [lm contactInfosForUserWithUIDorEmail: login];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
user = nil;
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) _authOpenId: (NSString *) auth withDomain: (NSString *) domain
|
||||||
|
{
|
||||||
|
NSDictionary *user;
|
||||||
|
NSString *token, *login;
|
||||||
|
SOGoOpenIdSession *openIdSession;
|
||||||
|
SOGoUserManager *lm;
|
||||||
|
|
||||||
|
user = nil;
|
||||||
|
token = [[auth substringFromIndex:6] stringByTrimmingLeadWhiteSpaces];
|
||||||
|
|
||||||
|
openIdSession = [SOGoOpenIdSession OpenIdSession: domain];
|
||||||
|
if(![openIdSession sessionIsOk])
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"API - OpenId server not found or has unexpected behavior, contact your admin."];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
[openIdSession setAccessToken: token];
|
||||||
|
login = [openIdSession login: @""];
|
||||||
|
|
||||||
|
if(login && ![login isEqualToString: @"anonymous"])
|
||||||
|
{
|
||||||
|
//Fecth user info
|
||||||
|
lm = [SOGoUserManager sharedUserManager];
|
||||||
|
user = [lm contactInfosForUserWithUIDorEmail: login];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
user = nil;
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (NSException *) dispatchRequest: (WORequest*) theRequest
|
||||||
|
inResponse: (WOResponse*) theResponse
|
||||||
|
context: (id) theContext
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
id activeUser;
|
||||||
|
NSString *method, *action, *error;
|
||||||
|
NSDictionary *form;
|
||||||
|
NSArray *paramNeeded;
|
||||||
|
NSMutableDictionary *paramInjected, *ret;
|
||||||
|
NSBundle *bundle;
|
||||||
|
id classAction;
|
||||||
|
Class clazz;
|
||||||
|
|
||||||
|
|
||||||
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
ASSIGN(context, theContext);
|
||||||
|
|
||||||
|
//Get the api action, check it
|
||||||
|
action = [self _getActionFromUri: [theRequest uri]];
|
||||||
|
if(!action)
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"No actions found for request to API: %@", [theRequest uri]];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the class for this action, check it
|
||||||
|
bundle = [NSBundle bundleForClass: NSClassFromString(@"SOGoAPIProduct")];
|
||||||
|
clazz = [bundle classNamed: action];
|
||||||
|
if(!clazz)
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"No backend API found for action: %@", action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
//try to instantiate the class
|
||||||
|
NS_DURING
|
||||||
|
{
|
||||||
|
classAction = [[clazz alloc] init];
|
||||||
|
}
|
||||||
|
NS_HANDLER
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"Can't alloc and init class: %@", classAction];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 500];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NS_ENDHANDLER;
|
||||||
|
|
||||||
|
//Check method
|
||||||
|
method = [theRequest method];
|
||||||
|
if(![[classAction methodAllowed] containsObject: method])
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"Method %@ not allowed for action %@", method, action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
paramInjected = [NSMutableDictionary dictionary];
|
||||||
|
//Check parameters
|
||||||
|
if((paramNeeded = [classAction paramNeeded]) && [paramNeeded count] >= 1)
|
||||||
|
{
|
||||||
|
NSDictionary* formAndQuery = [theRequest formValues];
|
||||||
|
for(NSString *param in paramNeeded)
|
||||||
|
{
|
||||||
|
id value;
|
||||||
|
if((value = [formAndQuery objectForKey: param]))
|
||||||
|
{
|
||||||
|
NSString* trueValue;
|
||||||
|
if ([value isKindOfClass: [NSArray class]])
|
||||||
|
trueValue = [value lastObject];
|
||||||
|
else
|
||||||
|
trueValue = value;
|
||||||
|
[paramInjected setObject: trueValue forKey: param];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"Missing param %@ for action %@", param, action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 400];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if([classAction needAuth])
|
||||||
|
{
|
||||||
|
if(debugOn)
|
||||||
|
[self logWithFormat: @"Check auth for action %@", action];
|
||||||
|
//check auth
|
||||||
|
NSString *auth = [theRequest headerForKey: @"authorization"];
|
||||||
|
if(auth)
|
||||||
|
{
|
||||||
|
NSDictionary* user;
|
||||||
|
if([[auth lowercaseString] hasPrefix: @"basic"])
|
||||||
|
{
|
||||||
|
//basic auth
|
||||||
|
user = [self _authBasicCheck: auth];
|
||||||
|
}
|
||||||
|
else if([[auth lowercaseString] hasPrefix: @"bearer"])
|
||||||
|
{
|
||||||
|
//openid auth, we may need to know the user-domain to know which openid server to fetch
|
||||||
|
NSString *domain = [theRequest headerForKey: @"user-domain"];
|
||||||
|
user = [self _authOpenId: auth withDomain: domain];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"Authorization method incorrect: %@ for action %@", auth, action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add current user in paramInjected
|
||||||
|
if(user){
|
||||||
|
if(debugOn)
|
||||||
|
[self logWithFormat: @"User authenticated %@", user];
|
||||||
|
[paramInjected setObject: user forKey: @"user"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"User wrong login or not found for action %@", action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = [NSString stringWithFormat: @"No authorization header found for action %@", action];
|
||||||
|
[self errorWithFormat: error];
|
||||||
|
[self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 401];
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Execute action
|
||||||
|
// NS_DURING
|
||||||
|
// {
|
||||||
|
ret = [classAction action: context withParam: paramInjected];
|
||||||
|
// }
|
||||||
|
// NS_HANDLER
|
||||||
|
// {
|
||||||
|
// error = [NSString stringWithFormat: @"Internal error during: %@", action];
|
||||||
|
// [self errorWithFormat: error];
|
||||||
|
// [self _sendAPIErrorResponse: theResponse withMessage: error withStatus: 500];
|
||||||
|
// RELEASE(context);
|
||||||
|
// RELEASE(pool);
|
||||||
|
// return nil;
|
||||||
|
// }
|
||||||
|
// NS_ENDHANDLER;
|
||||||
|
|
||||||
|
|
||||||
|
//Make the response
|
||||||
|
[theResponse setContent: [ret jsonRepresentation]];
|
||||||
|
|
||||||
|
RELEASE(context);
|
||||||
|
RELEASE(pool);
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
11
API/SOGoAPIProduct.m
Normal file
11
API/SOGoAPIProduct.m
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) todo...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
|
||||||
|
@interface SOGoAPIProduct : NSObject
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SOGoAPIProduct
|
||||||
|
@end /* SOGoAPIProduct */
|
||||||
33
API/SOGoAPIUserFolder.h
Normal file
33
API/SOGoAPIUserFolder.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
|
This file is part of SOPE.
|
||||||
|
|
||||||
|
SOPE is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOPE; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <SOGoAPI.h>
|
||||||
|
|
||||||
|
@class WOContext;
|
||||||
|
|
||||||
|
@interface SOGoAPIUserFolder : SOGoAPI
|
||||||
|
- (NSArray *) methodAllowed;
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
|
||||||
|
@end
|
||||||
110
API/SOGoAPIUserFolder.m
Normal file
110
API/SOGoAPIUserFolder.m
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) todo...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <SOGoAPIUserFolder.h>
|
||||||
|
|
||||||
|
#import <GDLContentStore/GCSFolderManager.h>
|
||||||
|
#import <GDLContentStore/GCSFolder.h>
|
||||||
|
|
||||||
|
@implementation SOGoAPIUserFolder
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"calendar":[
|
||||||
|
{
|
||||||
|
"name":"DidyShared",
|
||||||
|
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/12509-67F67D00-1-3105AF40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"LocalDidy",
|
||||||
|
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/1BC38-67B60000-1-6E4B6880"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"Personal Calendar",
|
||||||
|
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Calendar/personal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"username":"sogo-tests1@example.org",
|
||||||
|
"contact":[
|
||||||
|
{
|
||||||
|
"name":"Personal Address Book",
|
||||||
|
"url":"http://127.0.0.1/SOGo/dav/sogo-tests1@example.org/Contacts/personal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
|
||||||
|
{
|
||||||
|
NSDictionary* result;
|
||||||
|
NSArray *folders;
|
||||||
|
NSMutableArray *cardavLinks, *caldavLinks;
|
||||||
|
NSString *serverUrl, *basePath, *c_uid, *url;
|
||||||
|
GCSFolderManager *fm;
|
||||||
|
GCSFolder *folder;
|
||||||
|
|
||||||
|
int max, i;
|
||||||
|
|
||||||
|
//Should be a user
|
||||||
|
c_uid = [[[param objectForKey: @"user"] objectForKey: @"emails"] objectAtIndex: 0];
|
||||||
|
|
||||||
|
//fetch folders
|
||||||
|
fm = [GCSFolderManager defaultFolderManager];
|
||||||
|
basePath = [NSString stringWithFormat: @"/Users/%@", c_uid];
|
||||||
|
folders = [fm listSubFoldersAndNamesAtPath: basePath recursive: YES];
|
||||||
|
|
||||||
|
//Generate dav link
|
||||||
|
max = [folders count];
|
||||||
|
serverUrl = [[ctx serverURL] absoluteString];
|
||||||
|
|
||||||
|
cardavLinks = [NSMutableArray array];
|
||||||
|
caldavLinks = [NSMutableArray array];
|
||||||
|
serverUrl = [[ctx serverURL] absoluteString];
|
||||||
|
for (i = 0; i < max; i++)
|
||||||
|
{
|
||||||
|
NSMutableDictionary *folderRet;
|
||||||
|
folderRet = [NSMutableDictionary dictionary];
|
||||||
|
folder = [folders objectAtIndex: i];
|
||||||
|
url = [NSString stringWithFormat: @"%@/SOGo/dav/%@/%@", serverUrl, c_uid, [folder objectForKey: @"path"]];
|
||||||
|
[folderRet setObject: url forKey: @"url"];
|
||||||
|
[folderRet setObject: [folder objectForKey: @"name"] forKey: @"name"];
|
||||||
|
if([url rangeOfString:@"/Calendar/"].location == NSNotFound)
|
||||||
|
{
|
||||||
|
//Contacts
|
||||||
|
[cardavLinks addObject: folderRet];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Calendar
|
||||||
|
[caldavLinks addObject: folderRet];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||||
|
c_uid, @"username",
|
||||||
|
cardavLinks, @"contact",
|
||||||
|
caldavLinks, @"calendar",
|
||||||
|
nil];
|
||||||
|
|
||||||
|
[result autorelease];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end /* SOGoAPIVersion */
|
||||||
33
API/SOGoAPIVersion.h
Normal file
33
API/SOGoAPIVersion.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2004-2005 SKYRIX Software AG
|
||||||
|
|
||||||
|
This file is part of SOPE.
|
||||||
|
|
||||||
|
SOPE is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOPE; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Foundation/NSObject.h>
|
||||||
|
#import <Foundation/NSDictionary.h>
|
||||||
|
#import <Foundation/NSArray.h>
|
||||||
|
#import <SOGoAPI.h>
|
||||||
|
|
||||||
|
@class WOContext;
|
||||||
|
|
||||||
|
@interface SOGoAPIVersion : SOGoAPI
|
||||||
|
- (NSArray *) methodAllowed;
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param;
|
||||||
|
@end
|
||||||
42
API/SOGoAPIVersion.m
Normal file
42
API/SOGoAPIVersion.m
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) todo...
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <SOGoAPIVersion.h>
|
||||||
|
|
||||||
|
|
||||||
|
@implementation SOGoAPIVersion
|
||||||
|
|
||||||
|
- (id) init
|
||||||
|
{
|
||||||
|
[super init];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) needAuth
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) action: (WOContext*) ctx withParam: (NSDictionary *) param
|
||||||
|
{
|
||||||
|
NSDictionary* result;
|
||||||
|
|
||||||
|
result = [[NSDictionary alloc] initWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithInt:SOGO_MAJOR_VERSION], @"major",
|
||||||
|
[NSNumber numberWithInt:SOGO_MINOR_VERSION], @"minor",
|
||||||
|
[NSNumber numberWithInt:SOGO_PATCH_VERSION], @"patch",
|
||||||
|
nil];
|
||||||
|
|
||||||
|
[result autorelease];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@end /* SOGoAPIVersion */
|
||||||
34
API/common.make
Normal file
34
API/common.make
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
include ../config.make
|
||||||
|
include $(GNUSTEP_MAKEFILES)/common.make
|
||||||
|
include ../Version
|
||||||
|
|
||||||
|
NEEDS_GUI=no
|
||||||
|
BUNDLE_EXTENSION = .SOGo
|
||||||
|
BUNDLE_INSTALL_DIR = $(SOGO_LIBDIR)
|
||||||
|
WOBUNDLE_EXTENSION = $(BUNDLE_EXTENSION)
|
||||||
|
WOBUNDLE_INSTALL_DIR = $(BUNDLE_INSTALL_DIR)
|
||||||
|
|
||||||
|
# SYSTEM_LIB_DIR += -L/usr/local/lib -L/usr/lib
|
||||||
|
|
||||||
|
ADDITIONAL_INCLUDE_DIRS += \
|
||||||
|
-I.. \
|
||||||
|
-I../.. \
|
||||||
|
-I../../SOPE
|
||||||
|
|
||||||
|
ADDITIONAL_LIB_DIRS += \
|
||||||
|
-L../SoObjects/SOGo/SOGo.framework/Versions/Current/sogo \
|
||||||
|
-L../SoObjects/SOGo/$(GNUSTEP_OBJ_DIR)/ \
|
||||||
|
-L../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \
|
||||||
|
-L/usr/local/lib \
|
||||||
|
-Wl,-rpath,$(SOGO_SYSLIBDIR)/sogo
|
||||||
|
|
||||||
|
BUNDLE_LIBS += \
|
||||||
|
-lSOGo \
|
||||||
|
-lGDLContentStore \
|
||||||
|
-lGDLAccess \
|
||||||
|
-lNGObjWeb \
|
||||||
|
-lNGCards -lNGMime -lNGLdap \
|
||||||
|
-lNGStreams -lNGExtensions -lEOControl \
|
||||||
|
-lDOM -lSaxObjC -lSBJson
|
||||||
|
|
||||||
|
ADDITIONAL_BUNDLE_LIBS += $(BUNDLE_LIBS)
|
||||||
31
API/product.plist
Normal file
31
API/product.plist
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
requires = ( MAIN, Appointments, Contacts, Mailer );
|
||||||
|
|
||||||
|
publicResources = ();
|
||||||
|
|
||||||
|
factories = {};
|
||||||
|
|
||||||
|
classes = {
|
||||||
|
SOGoAPI = {
|
||||||
|
protectedBy = "<public>";
|
||||||
|
defaultRoles = {
|
||||||
|
"View" = ( "Authenticated", "PublicUser" );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
categories = {
|
||||||
|
SOGoAPI = {
|
||||||
|
slots = {
|
||||||
|
};
|
||||||
|
methods = {
|
||||||
|
Version = {
|
||||||
|
protectedBy = "View";
|
||||||
|
pageName = "SOGoAPI";
|
||||||
|
actionName = "sogoVersion";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ SUBPROJECTS = \
|
|||||||
SoObjects \
|
SoObjects \
|
||||||
Main \
|
Main \
|
||||||
UI \
|
UI \
|
||||||
|
API \
|
||||||
Tools \
|
Tools \
|
||||||
Tests/Unit \
|
Tests/Unit \
|
||||||
|
|
||||||
|
|||||||
10
Main/SOGo.m
10
Main/SOGo.m
@@ -417,7 +417,7 @@ static BOOL debugLeaks;
|
|||||||
{
|
{
|
||||||
id obj;
|
id obj;
|
||||||
WORequest *request;
|
WORequest *request;
|
||||||
BOOL isDAVRequest;
|
BOOL isDAVRequest, isAPIRequest;
|
||||||
SOGoSystemDefaults *sd;
|
SOGoSystemDefaults *sd;
|
||||||
|
|
||||||
/* put locale info into the context in case it's not there */
|
/* put locale info into the context in case it's not there */
|
||||||
@@ -425,8 +425,14 @@ static BOOL debugLeaks;
|
|||||||
|
|
||||||
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
request = [_ctx request];
|
request = [_ctx request];
|
||||||
|
isAPIRequest = [[request requestHandlerKey] isEqualToString:@"SOGoAPI"];
|
||||||
isDAVRequest = [[request requestHandlerKey] isEqualToString:@"dav"];
|
isDAVRequest = [[request requestHandlerKey] isEqualToString:@"dav"];
|
||||||
if (isDAVRequest || [sd isWebAccessEnabled])
|
if(isAPIRequest && ![_key isEqualToString:@"SOGo"] && ![_key isEqualToString:@"SOGoAPI"])
|
||||||
|
{
|
||||||
|
//The request will be handle by the API Dispatcher
|
||||||
|
obj = nil;
|
||||||
|
}
|
||||||
|
else if (isDAVRequest || [sd isWebAccessEnabled])
|
||||||
{
|
{
|
||||||
if (isDAVRequest)
|
if (isDAVRequest)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,6 +76,7 @@
|
|||||||
|
|
||||||
- (BOOL)folderExistsAtPath:(NSString *)_path;
|
- (BOOL)folderExistsAtPath:(NSString *)_path;
|
||||||
- (NSArray *)listSubFoldersAtPath:(NSString *)_path recursive:(BOOL)_flag;
|
- (NSArray *)listSubFoldersAtPath:(NSString *)_path recursive:(BOOL)_flag;
|
||||||
|
- (NSArray *)listSubFoldersAndNamesAtPath:(NSString *)_path recursive:(BOOL)_recursive;
|
||||||
|
|
||||||
- (NSDictionary *) recordAtPath: (NSString *) _path;
|
- (NSDictionary *) recordAtPath: (NSString *) _path;
|
||||||
- (GCSFolder *)folderAtPath:(NSString *)_path;
|
- (GCSFolder *)folderAtPath:(NSString *)_path;
|
||||||
|
|||||||
@@ -598,6 +598,27 @@ static BOOL _singleStoreMode = NO;
|
|||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)generateSQLPathAndNameFetchForInternalNames:(NSArray *)_names
|
||||||
|
exactMatch:(BOOL)_beExact orDirectSubfolderMatch:(BOOL)_directSubs
|
||||||
|
{
|
||||||
|
/* fetches the 'path' subset for a given quick-names */
|
||||||
|
NSMutableString *sql;
|
||||||
|
NSString *ws;
|
||||||
|
|
||||||
|
ws = [self generateSQLWhereForInternalNames:_names
|
||||||
|
exactMatch:_beExact orDirectSubfolderMatch:_directSubs];
|
||||||
|
if ([ws length] == 0)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
sql = [NSMutableString stringWithCapacity:256];
|
||||||
|
[sql appendString:@"SELECT c_path, c_foldername FROM "];
|
||||||
|
[sql appendString:[self folderInfoTableName]];
|
||||||
|
[sql appendString:@" WHERE "];
|
||||||
|
[sql appendString:ws];
|
||||||
|
if (debugSQLGen) [self logWithFormat:@"PathFetch-SQL: %@", sql];
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
/* handling folder names */
|
/* handling folder names */
|
||||||
|
|
||||||
- (BOOL)_isStandardizedPath:(NSString *)_path {
|
- (BOOL)_isStandardizedPath:(NSString *)_path {
|
||||||
@@ -806,6 +827,72 @@ static BOOL _singleStoreMode = NO;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray *)listSubFoldersAndNamesAtPath:(NSString *)_path recursive:(BOOL)_recursive{
|
||||||
|
NSMutableArray *result;
|
||||||
|
NSString *fname;
|
||||||
|
NSArray *fnames, *records;
|
||||||
|
NSString *sql;
|
||||||
|
unsigned i, count;
|
||||||
|
|
||||||
|
if ((fnames = [self internalNamesFromPath:_path]) == nil) {
|
||||||
|
[self debugWithFormat:@"got no internal names for path: '%@'", _path];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = [self generateSQLPathAndNameFetchForInternalNames:fnames
|
||||||
|
exactMatch:NO orDirectSubfolderMatch:(_recursive ? NO : YES)];
|
||||||
|
if ([sql length] == 0) {
|
||||||
|
[self debugWithFormat:@"got no SQL for names: %@", fnames];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((records = [self performSQL:sql]) == nil) {
|
||||||
|
[self logWithFormat:@"ERROR(%s): executing SQL failed: '%@'",
|
||||||
|
__PRETTY_FUNCTION__, sql];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((count = [records count]) == 0)
|
||||||
|
return emptyArray;
|
||||||
|
|
||||||
|
result = [NSMutableArray arrayWithCapacity:(count > 128 ? 128 : count)];
|
||||||
|
|
||||||
|
fname = [self internalNameFromPath:_path];
|
||||||
|
fname = [fname stringByAppendingString:@"/"]; /* add slash */
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
NSDictionary *record, *folderInfo;
|
||||||
|
NSString *sname, *spath, *foldername;
|
||||||
|
|
||||||
|
record = [records objectAtIndex:i];
|
||||||
|
sname = [record objectForKey:GCSPathRecordName];
|
||||||
|
if (![sname hasPrefix:fname]) /* does not match at all ... */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* strip prefix and following slash */
|
||||||
|
sname = [sname substringFromIndex:[fname length]];
|
||||||
|
spath = [self pathPartFromInternalName:sname];
|
||||||
|
|
||||||
|
if (_recursive) {
|
||||||
|
if ([spath length] > 0){
|
||||||
|
foldername = [record objectForKey: @"c_foldername"];
|
||||||
|
folderInfo = [NSDictionary dictionaryWithObjectsAndKeys: spath, @"path", foldername, @"name", nil];
|
||||||
|
[result addObject:folderInfo];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* direct children only, so exclude everything with a slash */
|
||||||
|
if ([sname rangeOfString:@"/"].length == 0 && [spath length] > 0)
|
||||||
|
{
|
||||||
|
foldername = [record objectForKey: @"c_foldername"];
|
||||||
|
folderInfo = [NSDictionary dictionaryWithObjectsAndKeys: spath, @"path", foldername, @"name", nil];
|
||||||
|
[result addObject:folderInfo];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSDictionary *) recordAtPath: (NSString *) _path
|
- (NSDictionary *) recordAtPath: (NSString *) _path
|
||||||
{
|
{
|
||||||
NSMutableString *sql;
|
NSMutableString *sql;
|
||||||
|
|||||||
@@ -139,6 +139,13 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer)
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
|
||||||
|
if(![[sd authenticationType] isEqualToString: @"openid"])
|
||||||
|
{
|
||||||
|
[self errorWithFormat: @"Sogo SOGoAuthenticationType is not openid"];
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
return ([sd openIdConfigUrl] && [sd openIdScope] && [sd openIdClient] && [sd openIdClientSecret]);
|
return ([sd openIdConfigUrl] && [sd openIdScope] && [sd openIdClient] && [sd openIdClientSecret]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +213,7 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self errorWithFormat: @"Missing parameters from sogo.conf"];
|
[self errorWithFormat: @"LoginTypebyDOmain - Openid not found or missing parameters for domain", _domain];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ([[self class] checkUserConfig])
|
else if ([[self class] checkUserConfig])
|
||||||
|
|||||||
@@ -122,28 +122,28 @@ static NSString *productDirectoryName = @"SOGo";
|
|||||||
|
|
||||||
pathes = [[self productSearchPathes] objectEnumerator];
|
pathes = [[self productSearchPathes] objectEnumerator];
|
||||||
while ((lpath = [pathes nextObject]))
|
while ((lpath = [pathes nextObject]))
|
||||||
|
{
|
||||||
|
productNames = [[fm directoryContentsAtPath: lpath] objectEnumerator];
|
||||||
|
while ((productName = [productNames nextObject]))
|
||||||
{
|
{
|
||||||
productNames = [[fm directoryContentsAtPath: lpath] objectEnumerator];
|
if ([[productName pathExtension] isEqualToString: @"SOGo"])
|
||||||
while ((productName = [productNames nextObject]))
|
|
||||||
{
|
|
||||||
if ([[productName pathExtension] isEqualToString: @"SOGo"])
|
|
||||||
{
|
|
||||||
bpath = [lpath stringByAppendingPathComponent: productName];
|
|
||||||
[registry registerProductAtPath: bpath];
|
|
||||||
[loadedProducts addObject: productName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ([loadedProducts count])
|
|
||||||
{
|
{
|
||||||
if (verbose)
|
bpath = [lpath stringByAppendingPathComponent: productName];
|
||||||
{
|
[registry registerProductAtPath: bpath];
|
||||||
[self logWithFormat: @"SOGo products loaded from '%@':", lpath];
|
[loadedProducts addObject: productName];
|
||||||
[self logWithFormat: @" %@",
|
|
||||||
[loadedProducts componentsJoinedByString: @", "]];
|
|
||||||
}
|
|
||||||
[loadedProducts removeAllObjects];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ([loadedProducts count])
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
[self logWithFormat: @"SOGo products loaded from '%@':", lpath];
|
||||||
|
[self logWithFormat: @" %@",
|
||||||
|
[loadedProducts componentsJoinedByString: @", "]];
|
||||||
|
}
|
||||||
|
[loadedProducts removeAllObjects];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (![registry loadAllProducts] && verbose)
|
if (![registry loadAllProducts] && verbose)
|
||||||
[self warnWithFormat: @"could not load all products !"];
|
[self warnWithFormat: @"could not load all products !"];
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ static const NSString *kDisableSharingCalendar = @"Calendar";
|
|||||||
- (BOOL) uixDebugEnabled;
|
- (BOOL) uixDebugEnabled;
|
||||||
- (BOOL) easDebugEnabled;
|
- (BOOL) easDebugEnabled;
|
||||||
- (BOOL) openIdDebugEnabled;
|
- (BOOL) openIdDebugEnabled;
|
||||||
|
- (BOOL) apiDebugEnabled;
|
||||||
- (BOOL) tnefDecoderDebugEnabled;
|
- (BOOL) tnefDecoderDebugEnabled;
|
||||||
- (BOOL) xsrfValidationEnabled;
|
- (BOOL) xsrfValidationEnabled;
|
||||||
|
|
||||||
|
|||||||
@@ -654,6 +654,11 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
|
|||||||
return [self boolForKey: @"SOGoOpenIDDebugEnabled"];
|
return [self boolForKey: @"SOGoOpenIDDebugEnabled"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) apiDebugEnabled
|
||||||
|
{
|
||||||
|
return [self boolForKey: @"SOGoAPIDebugEnabled"];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL) tnefDecoderDebugEnabled
|
- (BOOL) tnefDecoderDebugEnabled
|
||||||
{
|
{
|
||||||
return [self boolForKey: @"SOGoTnefDecoderDebugEnabled"];
|
return [self boolForKey: @"SOGoTnefDecoderDebugEnabled"];
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ MainUI_OBJC_FILES += \
|
|||||||
SOGoUserHomePage.m \
|
SOGoUserHomePage.m \
|
||||||
SOGoBrowsersPanel.m \
|
SOGoBrowsersPanel.m \
|
||||||
SOGoMicrosoftActiveSyncActions.m \
|
SOGoMicrosoftActiveSyncActions.m \
|
||||||
|
SOGoAPIActions.m \
|
||||||
|
|
||||||
ifeq ($(saml2_config), yes)
|
ifeq ($(saml2_config), yes)
|
||||||
MainUI_OBJC_FILES += SOGoSAML2Actions.m
|
MainUI_OBJC_FILES += SOGoSAML2Actions.m
|
||||||
|
|||||||
73
UI/MainUI/SOGoAPIActions.m
Normal file
73
UI/MainUI/SOGoAPIActions.m
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2014-2016 Inverse inc.
|
||||||
|
|
||||||
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
SOGo is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
SOGo is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with SOGo; see the file COPYING. If not, write to the
|
||||||
|
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#import <SOGo/SOGoCache.h>
|
||||||
|
#import <SOGo/NSObject+Utilities.h>
|
||||||
|
|
||||||
|
#import <NGObjWeb/WOContext.h>
|
||||||
|
#import <NGObjWeb/WODirectAction.h>
|
||||||
|
#import <NGObjWeb/NSException+HTTP.h>
|
||||||
|
#import <NGObjWeb/WOResponse.h>
|
||||||
|
|
||||||
|
#import <API/SOGoAPIDispatcher.h>
|
||||||
|
|
||||||
|
@interface SOGoAPIActions : WODirectAction
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SOGoAPIActions
|
||||||
|
|
||||||
|
|
||||||
|
- (WOResponse *) sogoAPIAction
|
||||||
|
{
|
||||||
|
WOResponse *response;
|
||||||
|
WORequest *request;
|
||||||
|
NSBundle *bundle;
|
||||||
|
NSException *ex;
|
||||||
|
id dispatcher;
|
||||||
|
Class clazz;
|
||||||
|
|
||||||
|
request = (WORequest *)[context request];
|
||||||
|
response = (WOResponse *)[context response];
|
||||||
|
[response setStatus: 200];
|
||||||
|
[response setHeader: @"application/json; charset=utf-8" forKey: @"content-type"];
|
||||||
|
|
||||||
|
bundle = [NSBundle bundleForClass: NSClassFromString(@"SOGoAPIProduct")];
|
||||||
|
clazz = [bundle classNamed: @"SOGoAPIDispatcher"];
|
||||||
|
dispatcher = [[clazz alloc] init];
|
||||||
|
|
||||||
|
ex = [dispatcher dispatchRequest: request inResponse: response context: context];
|
||||||
|
|
||||||
|
//[[self class] memoryStatistics];
|
||||||
|
|
||||||
|
if (ex)
|
||||||
|
{
|
||||||
|
return [NSException exceptionWithHTTPStatus: 500];
|
||||||
|
}
|
||||||
|
|
||||||
|
RELEASE(dispatcher);
|
||||||
|
|
||||||
|
//[[SOGoCache sharedCache] killCache];
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -118,6 +118,11 @@
|
|||||||
actionClass = "SOGoMicrosoftActiveSyncActions";
|
actionClass = "SOGoMicrosoftActiveSyncActions";
|
||||||
actionName = "microsoftServerActiveSync";
|
actionName = "microsoftServerActiveSync";
|
||||||
};
|
};
|
||||||
|
SOGoAPI = {
|
||||||
|
protectedBy = "<public>";
|
||||||
|
actionClass = "SOGoAPIActions";
|
||||||
|
actionName = "sogoAPI";
|
||||||
|
};
|
||||||
casProxy = {
|
casProxy = {
|
||||||
protectedBy = "<public>";
|
protectedBy = "<public>";
|
||||||
pageName = "SOGoRootPage";
|
pageName = "SOGoRootPage";
|
||||||
|
|||||||
2
UI/WebServerResources/js/vendor/punycode.js
vendored
2
UI/WebServerResources/js/vendor/punycode.js
vendored
@@ -422,7 +422,7 @@ const punycode = {
|
|||||||
* @memberOf punycode
|
* @memberOf punycode
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
'version': '2.3.1',
|
'version': '2.1.0',
|
||||||
/**
|
/**
|
||||||
* An object of methods to convert from JavaScript's internal character
|
* An object of methods to convert from JavaScript's internal character
|
||||||
* representation (UCS-2) to Unicode code points, and back.
|
* representation (UCS-2) to Unicode code points, and back.
|
||||||
|
|||||||
Reference in New Issue
Block a user