From 9e056529e16ad82917ea07c5054d3fcf4f4c4297 Mon Sep 17 00:00:00 2001 From: wolfgang Date: Tue, 4 Sep 2007 15:56:40 +0000 Subject: [PATCH] git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1163 d1b88da0-ebda-0310-925b-ed51d893ca5b --- ChangeLog | 23 ++++ Main/SOGo.m | 16 ++- NEWS | 5 + .../Appointments/SOGoCalendarComponent.m | 2 +- .../Appointments/iCalEntityObject+SOGo.m | 45 +++---- SoObjects/Mailer/SOGoMailBaseObject.m | 1 - SoObjects/SOGo/GNUmakefile | 6 +- SoObjects/SOGo/LDAPSource.m | 5 +- SoObjects/SOGo/NSString+Utilities.m | 2 + SoObjects/SOGo/SOGoAuthenticator.h | 72 +++++----- SoObjects/SOGo/SOGoObject.m | 6 +- UI/Common/UIxPageFrame.m | 12 +- UI/MainUI/English.lproj/Localizable.strings | 10 +- UI/MainUI/French.lproj/Localizable.strings | 10 +- UI/MainUI/German.lproj/Localizable.strings | 10 +- UI/MainUI/SOGoRootPage.h | 35 +++++ UI/MainUI/SOGoRootPage.m | 124 +++++++---------- UI/MainUI/SOGoUserHomePage.m | 29 +++- UI/MainUI/product.plist | 22 ++- UI/Templates/MainUI/SOGoRootPage.wox | 95 ++++++++++--- UI/Templates/UIxPageFrame.wox | 4 +- .../JavascriptAPIExtensions.js | 125 +++++++++++++++++- UI/WebServerResources/SOGoRootPage.css | 36 +++++ UI/WebServerResources/SOGoRootPage.js | 15 +++ UI/WebServerResources/generic.css | 6 + UI/WebServerResources/generic.js | 38 ++++-- 26 files changed, 523 insertions(+), 231 deletions(-) create mode 100644 UI/MainUI/SOGoRootPage.h create mode 100644 UI/WebServerResources/SOGoRootPage.css create mode 100644 UI/WebServerResources/SOGoRootPage.js diff --git a/ChangeLog b/ChangeLog index 915951cb..012f73bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2007-09-04 Wolfgang Sourdeau + + * Main/SOGo.m ([SOGo -authenticatorInContext:_ctx]): choose the + authenticator based on the request handler key. "dav" returns the + SOGoDAVAuthenticator, anything else returns the Web authenticator. + + * SoObjects/SOGo/SOGoDAVAuthenticator.m: renamed module from + "SOGoAuthenticator". + + * SoObjects/SOGo/SOGoWebAuthenticator.m: new class module + implementing a subclass of SoCookieAuthenticator, designed for + web-based cookie authentication of users.m + + * UI/MainUI/SOGoUserHomePage.m ([SOGoUserHomePage -logoffAction]): + new method that resets the authentification cookie. + +2007-08-29 Wolfgang Sourdeau + + * SoObjects/SOGo/LDAPSource.m ([LDAPSource + -checkLogin:loginToCheckandPassword:passwordToCheck]): initialize + didBind to NO to make sure no false authentication is returned if + the bind operation is not executed. + 2007-08-28 Wolfgang Sourdeau * SoObjects/Mailer/SOGoDraftObject.m: added support for the diff --git a/Main/SOGo.m b/Main/SOGo.m index 70229749..52c2a0d7 100644 --- a/Main/SOGo.m +++ b/Main/SOGo.m @@ -41,10 +41,11 @@ #import -#import +#import +#import #import #import -#import +#import #import "build.h" #import "SOGoProductLoader.h" @@ -233,7 +234,16 @@ static BOOL debugObjectAllocation = NO; - (id) authenticatorInContext: (id) _ctx { - return [$(@"SOGoAuthenticator") sharedSOGoAuthenticator]; + id authenticator; + NSString *key; + + key = [[_ctx request] requestHandlerKey]; + if ([key isEqualToString: @"dav"]) + authenticator = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator]; + else + authenticator = [SOGoWebAuthenticator sharedSOGoWebAuthenticator]; + + return authenticator; } /* name lookup */ diff --git a/NEWS b/NEWS index c0c4a0c6..8e8a4f28 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +0.9.0-200709XX +-------------- +- fixed a bug where a false positive happening whenever a wrong user login was + given during an indirect bind; + 0.9.0-20070824 -------------- - added the ability to choose the default module from the diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index 73f9766d..f61b756f 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -567,7 +567,7 @@ static BOOL sendEMailNotifications = NO; } else role = SOGoCalendarRole_Organizer; - + return role; } diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m index 6b67f2da..3a441116 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m @@ -23,6 +23,8 @@ #import #import +#import + #import #import @@ -32,44 +34,31 @@ - (BOOL) userIsParticipant: (SOGoUser *) user { - NSEnumerator *emails; - NSArray *identities; - NSString *currentEmail; - BOOL response; + NSEnumerator *participants; + iCalPerson *currentParticipant; + BOOL isParticipant; - response = NO; + isParticipant = NO; - identities = [user allIdentities]; - emails = [[identities objectsForKey: @"email"] objectEnumerator]; - currentEmail = [emails nextObject]; - while (!response && currentEmail) - if ([self isParticipant: currentEmail]) - response = YES; + participants = [[self participants] objectEnumerator]; + currentParticipant = [participants nextObject]; + while (!isParticipant + && currentParticipant) + if ([user hasEmail: [currentParticipant rfc822Email]]) + isParticipant = YES; else - currentEmail = [emails nextObject]; + currentParticipant = [participants nextObject]; - return response; + return isParticipant; } - (BOOL) userIsOrganizer: (SOGoUser *) user { - NSEnumerator *emails; - NSArray *identities; - NSString *currentEmail; - BOOL response; - - response = NO; + NSString *orgMail; - identities = [user allIdentities]; - emails = [[identities objectsForKey: @"email"] objectEnumerator]; - currentEmail = [emails nextObject]; - while (!response && currentEmail) - if ([self isOrganizer: currentEmail]) - response = YES; - else - currentEmail = [emails nextObject]; + orgMail = [[self organizer] rfc822Email]; - return response; + return [user hasEmail: orgMail]; } @end diff --git a/SoObjects/Mailer/SOGoMailBaseObject.m b/SoObjects/Mailer/SOGoMailBaseObject.m index 11b74259..e6c2260d 100644 --- a/SoObjects/Mailer/SOGoMailBaseObject.m +++ b/SoObjects/Mailer/SOGoMailBaseObject.m @@ -20,7 +20,6 @@ */ #import -#import #import #import #import diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile index 0b3e7ef2..f8a602b7 100644 --- a/SoObjects/SOGo/GNUmakefile +++ b/SoObjects/SOGo/GNUmakefile @@ -43,7 +43,8 @@ libSOGo_HEADER_FILES = \ NSDictionary+URL.h \ NSCalendarDate+SOGo.h \ \ - SOGoAuthenticator.h \ + SOGoDAVAuthenticator.h \ + SOGoWebAuthenticator.h \ SOGoMailer.h \ SOGoUser.h \ @@ -71,7 +72,8 @@ libSOGo_OBJC_FILES = \ NSNull+Utilities.m \ NSCalendarDate+SOGo.m \ \ - SOGoAuthenticator.m \ + SOGoDAVAuthenticator.m \ + SOGoWebAuthenticator.m \ SOGoMailer.m \ SOGoUser.m \ diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index eeb0a14a..c2350e44 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -272,6 +272,8 @@ static int sizeLimit; NSString *userDN; NGLdapConnection *bindConnection; + didBind = NO; + if ([loginToCheck length] > 0) { bindConnection = [[NGLdapConnection alloc] initWithHostName: hostname @@ -290,13 +292,10 @@ static int sizeLimit; binddn: userDN credentials: passwordToCheck]; NS_HANDLER - didBind = NO; NS_ENDHANDLER } [bindConnection release]; } - else - didBind = NO; return didBind; } diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index bb8ece23..3cab55fb 100644 --- a/SoObjects/SOGo/NSString+Utilities.m +++ b/SoObjects/SOGo/NSString+Utilities.m @@ -24,6 +24,8 @@ #import #import +#import + #import "NSArray+Utilities.h" #import "NSDictionary+URL.h" diff --git a/SoObjects/SOGo/SOGoAuthenticator.h b/SoObjects/SOGo/SOGoAuthenticator.h index 6f8cd5fe..2a2f11d9 100644 --- a/SoObjects/SOGo/SOGoAuthenticator.h +++ b/SoObjects/SOGo/SOGoAuthenticator.h @@ -1,51 +1,39 @@ -/* - Copyright (C) 2004-2005 SKYRIX Software AG +/* SOGoAuthenticator.h - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOAUTHENTICATOR_H +#define SOGOAUTHENTICATOR_H + +#import - This file is part of OpenGroupware.org. - - OGo 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. - - OGo 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 OGo; see the file COPYING. If not, write to the - Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -#ifndef __Main_SOGoAuthenticator_H__ -#define __Main_SOGoAuthenticator_H__ - -#include - -/* - SOGoAuthenticator - - This just overrides the login/pwd check method and always returns YES since - the password is already checked in Apache. -*/ - -@class NSUserDefaults; @class NSString; - @class SOGoUser; +@class WOContext; -@interface SOGoAuthenticator : SoHTTPAuthenticator -{ - NSString *authMethod; -} - -+ (id) sharedSOGoAuthenticator; +@protocol SOGoAuthenticator -- (SOGoUser *) userInContext: (WOContext *) _ctx; - (NSString *) passwordInContext: (WOContext *) context; +- (SOGoUser *) userInContext: (WOContext *) context; @end -#endif /* __Main_SOGoAuthenticator_H__ */ +#endif /* SOGOAUTHENTICATOR_H */ diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 8d84e928..280211e5 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -46,7 +46,7 @@ #import "SOGoPermissions.h" #import "SOGoUser.h" -#import "SOGoAuthenticator.h" +#import "SOGoDAVAuthenticator.h" #import "SOGoUserFolder.h" #import "SOGoDAVRendererTypes.h" @@ -268,13 +268,13 @@ static BOOL kontactGroupDAV = YES; - (SOGoDAVSet *) davCurrentUserPrivilegeSet { - SOGoAuthenticator *sAuth; + SOGoDAVAuthenticator *sAuth; SoUser *user; NSArray *roles; SoClassSecurityInfo *sInfo; NSArray *davPermissions; - sAuth = [SOGoAuthenticator sharedSOGoAuthenticator]; + sAuth = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator]; user = [sAuth userInContext: context]; roles = [user rolesForObject: self inContext: context]; sInfo = [[self class] soClassSecurityInfo]; diff --git a/UI/Common/UIxPageFrame.m b/UI/Common/UIxPageFrame.m index b093fa75..267a653d 100644 --- a/UI/Common/UIxPageFrame.m +++ b/UI/Common/UIxPageFrame.m @@ -171,7 +171,7 @@ WOComponent *page; NSString *pageJSFilename; - page = [[self context] page]; + page = [context page]; pageJSFilename = [NSString stringWithFormat: @"%@.js", NSStringFromClass([page class])]; @@ -183,7 +183,7 @@ WOComponent *page; NSString *fwJSFilename; - page = [[self context] page]; + page = [context page]; fwJSFilename = [NSString stringWithFormat: @"%@.js", [page frameworkName]]; @@ -194,7 +194,7 @@ { WOComponent *page; - page = [[self context] page]; + page = [context page]; return [NSString stringWithFormat: @"%@.SOGo", [page frameworkName]]; } @@ -214,7 +214,7 @@ WOComponent *page; NSString *pageJSFilename; - page = [[self context] page]; + page = [context page]; pageJSFilename = [NSString stringWithFormat: @"%@.css", NSStringFromClass([page class])]; @@ -226,7 +226,7 @@ WOComponent *page; NSString *fwJSFilename; - page = [[self context] page]; + page = [context page]; fwJSFilename = [NSString stringWithFormat: @"%@.css", [page frameworkName]]; @@ -235,7 +235,7 @@ - (NSString *) thisPageURL { - return [[[self context] page] uri]; + return [[context page] uri]; } - (BOOL) hasPageSpecificCSS diff --git a/UI/MainUI/English.lproj/Localizable.strings b/UI/MainUI/English.lproj/Localizable.strings index ae3e21df..b9ccf8f2 100644 --- a/UI/MainUI/English.lproj/Localizable.strings +++ b/UI/MainUI/English.lproj/Localizable.strings @@ -2,11 +2,5 @@ "Homepage" = "Homepage"; -"Internet access unauthorized and" = "Internet access unauthorized and"; -"Internet access authorized and" = "Internet access authorized and"; -"internetAccessState_0" = "CLOSED"; -"internetAccessState_1" = "OPEN"; - -"Automatic vacation messages activation" = "Automatic vacation messages activation"; -"Internet" = "Internet"; -"Intranet" = "Intranet"; +"Login:" = "Login:"; +"Password:" = "Password:"; diff --git a/UI/MainUI/French.lproj/Localizable.strings b/UI/MainUI/French.lproj/Localizable.strings index 90f6e89c..88966d5f 100644 --- a/UI/MainUI/French.lproj/Localizable.strings +++ b/UI/MainUI/French.lproj/Localizable.strings @@ -2,11 +2,5 @@ "Homepage" = "Accueil"; -"Internet access authorized and" = "L'accès depuis internet est autorisé et "; -"Internet access unauthorized and" = "L'accès depuis internet est interdit et "; -"internetAccessState_0" = "FERMÉ"; -"internetAccessState_1" = "OUVERT"; - -"Automatic vacation messages activation" = "Activation du message de réponse automatique "; -"Internet" = "Internet"; -"Intranet" = "Intranet"; +"Login:" = "Nom d'utilisateur :"; +"Password:" = "Mot de passe :"; diff --git a/UI/MainUI/German.lproj/Localizable.strings b/UI/MainUI/German.lproj/Localizable.strings index 57d2a15a..536e765b 100644 --- a/UI/MainUI/German.lproj/Localizable.strings +++ b/UI/MainUI/German.lproj/Localizable.strings @@ -2,11 +2,5 @@ "Homepage" = "Startseite"; -"Internet access authorized and" = "Internetzugang ist erlaubt und "; -"Internet access unauthorized and" = "Internetzugang ist nicht erlaubt und "; -"internetAccessState_0" = "GESCHLOSSEN"; -"internetAccessState_1" = "OFFEN"; - -"Automatic vacation messages activation" = "Activation du message de réponse automatique "; -"Internet" = "Internet"; -"Intranet" = "Intranet"; +"Login:" = "Login:"; +"Password:" = "Password:"; diff --git a/UI/MainUI/SOGoRootPage.h b/UI/MainUI/SOGoRootPage.h new file mode 100644 index 00000000..fe3ebe46 --- /dev/null +++ b/UI/MainUI/SOGoRootPage.h @@ -0,0 +1,35 @@ +/* SOGoRootPage.h - this file is part of SOGo + * + * Copyright (C) 2007 Inverse groupe conseil + * + * Author: Wolfgang Sourdeau + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SOGOROOTPAGE_H +#define SOGOROOTPAGE_H + +#import + +@interface SOGoRootPage : UIxPageFrame +{ + NSString *userName; +} + +@end + +#endif /* SOGOROOTPAGE_H */ diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 912def21..01801d0f 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -19,100 +19,71 @@ 02111-1307, USA. */ -#import - -#import -#import #import #import +#import #import #import #import -#import #import -#import -#import +#import -@interface SOGoRootPage : SoComponent -{ - NSString *userName; -} +#import +#import -@end +#import "SOGoRootPage.h" @implementation SOGoRootPage -static BOOL doNotRedirect = NO; - -+ (void)initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - if ((doNotRedirect = [ud boolForKey:@"SOGoDoNotRedirectRootPage"])) - NSLog(@"SOGoRootPage: home-page redirect is disabled."); -} - -- (void)dealloc { - [self->userName release]; +- (void) dealloc +{ + [userName release]; [super dealloc]; } /* accessors */ -- (void)setUserName:(NSString *)_value { - ASSIGNCOPY(self->userName, _value); +- (void) setUserName: (NSString *) _value +{ + ASSIGNCOPY (userName, _value); } -- (NSString *)userName { - return self->userName; + +- (NSString *) userName +{ + return userName; } /* actions */ -- (id)connectAction { - NSString *url; - - [self takeFormValuesForKeys:@"userName", nil]; - - if ([[self userName] length] == 0) - return nil; - - url = [@"/" stringByAppendingString:[[self userName] stringByEscapingURL]]; - if (![url hasSuffix:@"/"]) - url = [url stringByAppendingString:@"/"]; - - url = [[self context] urlWithRequestHandlerKey:@"so" - path:url queryString:nil]; - return [self redirectToLocation:url]; -} - -- (id)defaultAction { +- (id ) defaultAction +{ WOResponse *r; NSString *login, *rhk; - id auth, user; - id home, base; + SOGoWebAuthenticator *auth; + SOGoUser *user; + SOGoUserFolder *home; + WOApplication *base; - if (doNotRedirect) - return self; - /* Note: ctx.activeUser is NOT set here. Don't know why, so we retrieve the user from the authenticator. */ - auth = [[self clientObject] authenticatorInContext:[self context]]; - user = [auth userInContext:[self context]]; + auth = [[self clientObject] authenticatorInContext: context]; + user = [auth userInContext: context]; login = [user login]; - + if ([login isEqualToString:@"anonymous"]) { /* use root page for unauthenticated users */ return self; } /* check base */ - + base = [self application]; - rhk = [[[self context] request] requestHandlerKey]; + rhk = [[context request] requestHandlerKey]; if (([rhk length] == 0) || ([base requestHandlerForKey:rhk] == nil)) { - base = [base lookupName:@"so" inContext:[self context] acquire:NO]; + base = [base lookupName: @"so" inContext: context acquire: NO]; if (![base isNotNull] || [base isKindOfClass:[NSException class]]) { /* use root page if home could not be found */ @@ -123,7 +94,7 @@ static BOOL doNotRedirect = NO; /* lookup home-page */ - home = [base lookupName:login inContext:[self context] acquire:NO]; + home = [base lookupName: login inContext: context acquire: NO]; if (![home isNotNull] || [home isKindOfClass:[NSException class]]) { /* use root page if home could not be found */ return self; @@ -131,33 +102,40 @@ static BOOL doNotRedirect = NO; /* redirect to home-page */ - r = [[self context] response]; - [r setStatus:302 /* moved */]; - [r setHeader:[home baseURLInContext:[self context]] forKey:@"location"]; + r = [context response]; + [r setStatus: 302 /* moved */]; + [r setHeader: [home baseURLInContext: context] + forKey: @"location"]; + return r; } /* response generation */ -- (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { +- (void) appendToResponse: (WOResponse *) response + inContext: (WOContext *) ctx +{ NSString *rhk; // TODO: we might also want to look into the HTTP basic-auth to redirect to // the login URL! - rhk = [[_ctx request] requestHandlerKey]; - if ([rhk length]==0 || [[self application] requestHandlerForKey:rhk]==nil) { - /* a small hack to redirect to a valid URL */ - NSString *url; + rhk = [[ctx request] requestHandlerKey]; + if ([rhk length] == 0 + || [[self application] requestHandlerForKey: rhk] == nil) + { + /* a small hack to redirect to a valid URL */ + NSString *url; - url = [_ctx urlWithRequestHandlerKey:@"so" path:@"/" queryString:nil]; - [_response setStatus:302 /* moved */]; - [_response setHeader:url forKey:@"location"]; - [self logWithFormat:@"URL: %@", url]; - return; - } - - [super appendToResponse:_response inContext:_ctx]; + url = [ctx urlWithRequestHandlerKey: @"so" path: @"/" queryString: nil]; + [response setStatus: 302 /* moved */]; + [response setHeader: url forKey: @"location"]; + [self logWithFormat: @"URL: %@", url]; + return; + } + + [response setHeader: @"text/html" forKey: @"content-type"]; + [super appendToResponse: response inContext: ctx]; } @end /* SOGoRootPage */ diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m index 410753ec..572ee1aa 100644 --- a/UI/MainUI/SOGoUserHomePage.m +++ b/UI/MainUI/SOGoUserHomePage.m @@ -26,14 +26,16 @@ #import #import #import +#import #import #import #import #import #import -#import -#import +#import +#import +#import #import static NSString *defaultModule = nil; @@ -198,4 +200,27 @@ static NSString *defaultModule = nil; return response; } +- (id ) logoffAction +{ + WOResponse *response; + NSEnumerator *cookies; + WOCookie *cookie; + SOGoWebAuthenticator *auth; + id container; + + container = [[self clientObject] container]; + + response = [context response]; + [response setStatus: 302]; + [response setHeader: [container baseURLInContext: context] + forKey: @"location"]; + cookies = [[response cookies] objectEnumerator]; + auth = [[self clientObject] authenticatorInContext: context]; + cookie = [WOCookie cookieWithName: [auth cookieNameInContext: context] + value: @"logoff"]; + [response addCookie: cookie]; + + return response; +} + @end diff --git a/UI/MainUI/product.plist b/UI/MainUI/product.plist index 7582875f..213438a6 100644 --- a/UI/MainUI/product.plist +++ b/UI/MainUI/product.plist @@ -1,5 +1,5 @@ { - requires = ( MAIN ); + requires = ( MAIN, CommonUI ); publicResources = ( ); @@ -59,13 +59,18 @@ categories = { SOGo = { // TODO: move decls to class methods = { - index = { + view = { protectedBy = "View"; - pageName = "SOGoRootPage"; + pageName = "SOGoRootPage"; + }; + connect = { + protectedBy = "View"; + pageName = "SOGoRootPage"; + actionName = "connect"; }; GET = { // more or less a hack, see README of dbd protectedBy = "View"; - pageName = "SOGoRootPage"; + pageName = "SOGoRootPage"; }; }; }; @@ -77,13 +82,18 @@ protectedBy = ""; pageName = "SOGoUserHomePage"; }; + logoff = { + protectedBy = ""; + pageName = "SOGoUserHomePage"; + actionName = "logoff"; + }; }; }; SOGoGroupsFolder = { methods = { index = { protectedBy = "View"; - pageName = "SOGoGroupsPage"; + pageName = "SOGoGroupsPage"; }; }; }; @@ -91,7 +101,7 @@ methods = { index = { protectedBy = "View"; - pageName = "SOGoGroupPage"; + pageName = "SOGoGroupPage"; }; }; }; diff --git a/UI/Templates/MainUI/SOGoRootPage.wox b/UI/Templates/MainUI/SOGoRootPage.wox index 5cf9a093..314b97f8 100644 --- a/UI/Templates/MainUI/SOGoRootPage.wox +++ b/UI/Templates/MainUI/SOGoRootPage.wox @@ -1,24 +1,81 @@ - - + + - - Scalable OGo Homepage - + xmlns:rsrc="OGo:url" + xmlns:label="OGo:label" + > + + + + <var:string value="title"/> + + + + + + + + + + + + + - -

Scalable OGo Homepage

+ + -
- Login: - - -
- - - + + + + + + + + + + + + + + +
+
+
+

+
+ +
+ +
+
+
+
+ + + +
diff --git a/UI/Templates/UIxPageFrame.wox b/UI/Templates/UIxPageFrame.wox index 08ec4718..a38aa506 100644 --- a/UI/Templates/UIxPageFrame.wox +++ b/UI/Templates/UIxPageFrame.wox @@ -69,6 +69,8 @@ >
+ | | - | > 2; + enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + enc4 = chr3 & 63; + + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + + output = output + + this._base64_keyStr.charAt(enc1) + this._base64_keyStr.charAt(enc2) + + this._base64_keyStr.charAt(enc3) + this._base64_keyStr.charAt(enc4); + } + + return output; +}; + +String.prototype.base64decode = function() { + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + var input = this.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + while (i < input.length) { + enc1 = this._base64_keyStr.indexOf(input.charAt(i++)); + enc2 = this._base64_keyStr.indexOf(input.charAt(i++)); + enc3 = this._base64_keyStr.indexOf(input.charAt(i++)); + enc4 = this._base64_keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) { + output = output + String.fromCharCode(chr3); + } + } + + return output._base64_utf8_decode(); +}; + +String.prototype._base64_utf8_encode = function() { + var string = this.replace(/\r\n/g,"\n"); + var utftext = ""; + + for (var n = 0; n < this.length; n++) { + var c = this.charCodeAt(n); + + if (c < 128) { + utftext += String.fromCharCode(c); + } + else if((c > 127) && (c < 2048)) { + utftext += String.fromCharCode((c >> 6) | 192); + utftext += String.fromCharCode((c & 63) | 128); + } + else { + utftext += String.fromCharCode((c >> 12) | 224); + utftext += String.fromCharCode(((c >> 6) & 63) | 128); + utftext += String.fromCharCode((c & 63) | 128); + } + } + + return utftext; +}; + +String.prototype._base64_utf8_decode = function() { + var string = ""; + var i = 0; + var c = c1 = c2 = 0; + + while (i < string.length) { + c = utftext.charCodeAt(i); + + if (c < 128) { + string += String.fromCharCode(c); + i++; + } + else if((c > 191) && (c < 224)) { + c2 = this.charCodeAt(i+1); + string += String.fromCharCode(((c & 31) << 6) | (c2 & 63)); + i += 2; + } + else { + c2 = this.charCodeAt(i+1); + c3 = this.charCodeAt(i+2); + string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + i += 3; + } + } + + return string; +}; diff --git a/UI/WebServerResources/SOGoRootPage.css b/UI/WebServerResources/SOGoRootPage.css new file mode 100644 index 00000000..ee7ab944 --- /dev/null +++ b/UI/WebServerResources/SOGoRootPage.css @@ -0,0 +1,36 @@ +BODY +{ background-color: #999; } + +DIV#loginScreen +{ + background-color: #d4d0c8; + margin: 0px auto; + margin-top: 5em; + padding: 10px; + border: 2px solid transparent; + width: 158px; + height: 250px; + -moz-border-top-colors: #efebe7 #fff; + -moz-border-left-colors: #efebe7 #fff; + -moz-border-right-colors: #000 #9c9a94 transparent; + -moz-border-bottom-colors: #000 #9c9a94 transparent; +} + +DIV#loginScreen IMG +{ border: 1px solid #999; } + +DIV#loginScreen INPUT +{ width: 100%; } + +DIV#loginButton +{ text-align: right; } + +DIV#loginButton INPUT +{ width: auto; + margin-top: 5px; } + +DIV#loginButton IMG#progressIndicator +{ float: left; + border: 0px none; + margin-top: 5px; + margin-left: 5px; } diff --git a/UI/WebServerResources/SOGoRootPage.js b/UI/WebServerResources/SOGoRootPage.js new file mode 100644 index 00000000..dd93cb3b --- /dev/null +++ b/UI/WebServerResources/SOGoRootPage.js @@ -0,0 +1,15 @@ +function initLogin() { + var submit = $("submit"); + var userName = $("userName"); + userName.focus(); + Event.observe(submit, "click", onLoginClick); +} + +function onLoginClick(event) { + startAnimation($("loginButton"), $("submit")); + + var loginString = $("userName").value + ":" + $("password").value; + document.cookie = "0xHIGHFLYxSOGo-0.9 = basic" + loginString.base64encode(); +} + +addEvent(window, 'load', initLogin); diff --git a/UI/WebServerResources/generic.css b/UI/WebServerResources/generic.css index d399878b..65ea6e83 100644 --- a/UI/WebServerResources/generic.css +++ b/UI/WebServerResources/generic.css @@ -155,6 +155,12 @@ DIV.linkbanner A DIV.linkbanner A:hover { color: #dd5; } +DIV.linkbanner A#logoff +{ float: right; + margin: 0px; + padding: 0px; + padding-right: .5em; } + .linkbannerlinks { vertical-align: bottom; text-align: left; } diff --git a/UI/WebServerResources/generic.js b/UI/WebServerResources/generic.js index 0e5d7587..608947f6 100644 --- a/UI/WebServerResources/generic.js +++ b/UI/WebServerResources/generic.js @@ -309,19 +309,27 @@ function triggerAjaxRequest(url, callback, userdata) { return http; } +function startAnimation(parent, nextNode) { + var anim = document.createElement("img"); + anim = $(anim); + anim.id = "progressIndicator"; + anim.src = ResourcesURL + "/busy.gif"; + anim.setStyle({ visibility: "hidden" }); + if (nextNode) + parent.insertBefore(anim, nextNode); + else + parent.appendChild(anim); + anim.setStyle({ visibility: "visible" }); + + return anim; +} + function checkAjaxRequestsState() { var toolbar = document.getElementById("toolbar"); if (toolbar) { if (activeAjaxRequests > 0 && !document.busyAnim) { - var anim = document.createElement("img"); - anim = $(anim); - document.busyAnim = anim; - anim.id = "progressIndicator"; - anim.src = ResourcesURL + "/busy.gif"; - anim.setStyle({ visibility: "hidden" }); - toolbar.appendChild(anim); - anim.setStyle({ visibility: "visible" }); + document.busyAnim = startAnimation(toolbar); } else if (activeAjaxRequests == 0 && document.busyAnim @@ -1252,7 +1260,9 @@ function loadPreferences() { } function onLoadHandler(event) { - loadPreferences(); + if (!document.body.hasClassName("loginPage")) { + loadPreferences(); + } queryParameters = parseQueryParameters('' + window.location); if (!$(document.body).hasClassName("popup")) { initLogConsole(); @@ -1304,14 +1314,14 @@ function configureLinkBanner() { var linkBanner = $("linkBanner"); if (linkBanner) { var anchors = linkBanner.childNodesWithTag("a"); - for (var i = 0; i < 2; i++) { + for (var i = 1; i < 3; i++) { Event.observe(anchors[i], "mousedown", listRowMouseDownHandler); Event.observe(anchors[i], "click", onLinkBannerClick); } - Event.observe(anchors[3], "mousedown", listRowMouseDownHandler); - Event.observe(anchors[3], "click", onPreferencesClick); - if (anchors.length > 4) - Event.observe(anchors[4], "click", toggleLogConsole); + Event.observe(anchors[4], "mousedown", listRowMouseDownHandler); + Event.observe(anchors[4], "click", onPreferencesClick); + if (anchors.length > 5) + Event.observe(anchors[5], "click", toggleLogConsole); } } -- 2.39.5