]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1163 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 4 Sep 2007 15:56:40 +0000 (15:56 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Tue, 4 Sep 2007 15:56:40 +0000 (15:56 +0000)
26 files changed:
ChangeLog
Main/SOGo.m
NEWS
SoObjects/Appointments/SOGoCalendarComponent.m
SoObjects/Appointments/iCalEntityObject+SOGo.m
SoObjects/Mailer/SOGoMailBaseObject.m
SoObjects/SOGo/GNUmakefile
SoObjects/SOGo/LDAPSource.m
SoObjects/SOGo/NSString+Utilities.m
SoObjects/SOGo/SOGoAuthenticator.h
SoObjects/SOGo/SOGoObject.m
UI/Common/UIxPageFrame.m
UI/MainUI/English.lproj/Localizable.strings
UI/MainUI/French.lproj/Localizable.strings
UI/MainUI/German.lproj/Localizable.strings
UI/MainUI/SOGoRootPage.h [new file with mode: 0644]
UI/MainUI/SOGoRootPage.m
UI/MainUI/SOGoUserHomePage.m
UI/MainUI/product.plist
UI/Templates/MainUI/SOGoRootPage.wox
UI/Templates/UIxPageFrame.wox
UI/WebServerResources/JavascriptAPIExtensions.js
UI/WebServerResources/SOGoRootPage.css [new file with mode: 0644]
UI/WebServerResources/SOGoRootPage.js [new file with mode: 0644]
UI/WebServerResources/generic.css
UI/WebServerResources/generic.js

index 915951cb4c4589e4522edc5b8707cdc16d894d3c..012f73bf1f1294e39a0eacc1f836781bc22e448c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2007-09-04  Wolfgang Sourdeau  <wsourdeau@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
+
+       * 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  <wsourdeau@inverse.ca>
 
        * SoObjects/Mailer/SOGoDraftObject.m: added support for the
index 702297498368dfb5e2b10ec88e7182f2d163e093..52c2a0d767fbf6b90451ea423ead6c41f8d95122 100644 (file)
 
 #import <WEExtensions/WEResourceManager.h>
 
-#import <SoObjects/SOGo/SOGoAuthenticator.h>
+#import <SoObjects/SOGo/SOGoDAVAuthenticator.h>
+#import <SoObjects/SOGo/SOGoPermissions.h>
 #import <SoObjects/SOGo/SOGoUserFolder.h>
 #import <SoObjects/SOGo/SOGoUser.h>
-#import <SoObjects/SOGo/SOGoPermissions.h>
+#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
 
 #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 c0c4a0c6d1749c2ac727ce4c58494ad30d9e775a..8e8a4f282cdd49182fadc35739b78f1b6bfcd4f4 100644 (file)
--- 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
index 73f9766d67ac42d3aae249edb299c94e22882daf..f61b756f4f1196edc01f659edef7cb8a6e715fc1 100644 (file)
@@ -567,7 +567,7 @@ static BOOL sendEMailNotifications = NO;
     }
   else
     role = SOGoCalendarRole_Organizer;
-  
+
   return role;
 }
 
index 6b67f2da4a451b7485330295778e616ffb8a05a5..3a441116151ca2302f8db547b4dcb4527d594a56 100644 (file)
@@ -23,6 +23,8 @@
 #import <Foundation/NSArray.h>
 #import <Foundation/NSEnumerator.h>
 
+#import <NGCards/iCalPerson.h>
+
 #import <SoObjects/SOGo/NSArray+Utilities.h>
 #import <SoObjects/SOGo/SOGoUser.h>
 
 
 - (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
index 11b74259bf96140aa5eca45711590c1f8dffb7fc..e6c2260d4c24e8556fb26d438bbc37a5513e9321 100644 (file)
@@ -20,7 +20,6 @@
 */
 
 #import <NGObjWeb/SoObject+SoDAV.h>
-#import <NGObjWeb/SoHTTPAuthenticator.h>
 #import <NGExtensions/NSNull+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
 #import <NGExtensions/NSString+misc.h>
index 0b3e7ef24f39a07081bd07c391fc976befed8573..f8a602b736aec1dde1b40141472bb3fc7948c0fd 100644 (file)
@@ -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                      \
 
index eeb0a14afb043414fc6b07c217fa138df5b8d54c..c2350e446793a451b4ea500f56a2908c3ef35e88 100644 (file)
@@ -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;
 }
index bb8ece23c54e7f1b76b38f1b5d91b015892ab170..3cab55fb13e71c7c47e8dcf35fa6197047f6b9f4 100644 (file)
@@ -24,6 +24,8 @@
 #import <Foundation/NSCharacterSet.h>
 #import <Foundation/NSEnumerator.h>
 
+#import <NGExtensions/NGQuotedPrintableCoding.h>
+
 #import "NSArray+Utilities.h"
 #import "NSDictionary+URL.h"
 
index 6f8cd5febdf68c48ef8027f498335b3c2ababb9d..2a2f11d9962bf24620470568c8342fc63c50a907 100644 (file)
@@ -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 <wsourdeau@inverse.ca>
+ *
+ * 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 <Foundation/NSObject.h>
 
-  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 <NGObjWeb/SoHTTPAuthenticator.h>
-
-/*
-  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 <NSObject>
 
-- (SOGoUser *) userInContext: (WOContext *) _ctx;
 - (NSString *) passwordInContext: (WOContext *) context;
+- (SOGoUser *) userInContext: (WOContext *) context;
 
 @end
 
-#endif /* __Main_SOGoAuthenticator_H__ */
+#endif /* SOGOAUTHENTICATOR_H */
index 8d84e92898f426834625c8549ad0577e798e58a6..280211e53699e2aaaafdc7727336af1fbdc5275a 100644 (file)
@@ -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];
index b093fa75b4c05260b7c6110884cac67ee66c718a..267a653d85fe770de39f91e9796b8904a6441ae7 100644 (file)
   WOComponent *page;
   NSString *pageJSFilename;
   
-  page     = [[self context] page];
+  page     = [context page];
   pageJSFilename = [NSString stringWithFormat: @"%@.js",
                             NSStringFromClass([page class])];
 
   WOComponent *page;
   NSString *fwJSFilename;
 
-  page = [[self context] page];
+  page = [context page];
   fwJSFilename = [NSString stringWithFormat: @"%@.js",
                           [page frameworkName]];
   
 {
   WOComponent *page;
 
-  page = [[self context] page];
+  page = [context page];
 
   return [NSString stringWithFormat: @"%@.SOGo", [page frameworkName]];
 }
   WOComponent *page;
   NSString *pageJSFilename;
 
-  page = [[self context] page];
+  page = [context page];
   pageJSFilename = [NSString stringWithFormat: @"%@.css",
                             NSStringFromClass([page class])];
 
   WOComponent *page;
   NSString *fwJSFilename;
 
-  page = [[self context] page];
+  page = [context page];
   fwJSFilename = [NSString stringWithFormat: @"%@.css",
                           [page frameworkName]];
   
 
 - (NSString *) thisPageURL
 {
-  return [[[self context] page] uri];
+  return [[context page] uri];
 }
 
 - (BOOL) hasPageSpecificCSS
index ae3e21df0822457d90f3148a73f1217f34aa8bfd..b9ccf8f2fb0bbf30a0db371898c2b98b7cfb7496 100644 (file)
@@ -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:";
index 90f6e89c342155655dfd35d4987f02ca8c9ceef3..88966d5f50bc7133df3369c31fd6006b788171b2 100644 (file)
@@ -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 :";
index 57d2a15a5a753db5c3ba71603c4f3b3cf333cf99..536e765b5c546c42f4fbf60a8d4dad20d0283819 100644 (file)
@@ -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 (file)
index 0000000..fe3ebe4
--- /dev/null
@@ -0,0 +1,35 @@
+/* SOGoRootPage.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * 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 <UI/Common/UIxPageFrame.h>
+
+@interface SOGoRootPage : UIxPageFrame
+{
+  NSString *userName;
+}
+
+@end
+
+#endif /* SOGOROOTPAGE_H */
index 912def2172ccf67268e55afc3321b27b058397ff..01801d0f0e242563bb73227b74dfa82b2a9027b1 100644 (file)
   02111-1307, USA.
 */
 
-#import <Foundation/NSUserDefaults.h>
-
-#import <NGObjWeb/SoComponent.h>
-#import <NGObjWeb/SoObject.h>
 #import <NGObjWeb/WOApplication.h>
 #import <NGObjWeb/WOContext.h>
+#import <NGObjWeb/WOCookie.h>
 #import <NGObjWeb/WORequest.h>
 #import <NGObjWeb/WOResponse.h>
 #import <NGExtensions/NSNull+misc.h>
-#import <NGExtensions/NSObject+Logs.h>
 #import <NGExtensions/NSString+misc.h>
-#import <SOGo/SOGoAuthenticator.h>
-#import <SOGo/SOGoUser.h>
+#import <NGExtensions/NSObject+Logs.h>
 
-@interface SOGoRootPage : SoComponent
-{
-  NSString *userName;
-}
+#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
+#import <SoObjects/SOGo/SOGoUser.h>
 
-@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<WOActionResults>)defaultAction {
+- (id <WOActionResults>) 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 */
index 410753ec8e375e32b8733666a37c7a99bfe922cb..572ee1aa803bcbdbe8f24094caa0ed56ef68c92a 100644 (file)
 #import <Foundation/NSURL.h>
 #import <Foundation/NSUserDefaults.h>
 #import <Foundation/NSValue.h>
+#import <NGObjWeb/WOCookie.h>
 #import <NGObjWeb/WORequest.h>
 #import <NGObjWeb/WOResponse.h>
 #import <NGExtensions/NSCalendarDate+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
 
 #import <Appointments/SOGoFreeBusyObject.h>
-#import <SOGo/SOGoUser.h>
-#import <SOGo/NSCalendarDate+SOGo.h>
+#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
+#import <SoObjects/SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/NSCalendarDate+SOGo.h>
 #import <SOGoUI/UIxComponent.h>
 
 static NSString *defaultModule = nil;
@@ -198,4 +200,27 @@ static NSString *defaultModule = nil;
   return response;
 }
 
+- (id <WOActionResults>) 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
index 7582875fb91bb3f6d813648528c84cd1661a21f6..213438a6bb8265206a4a3d4198eca36229327a08 100644 (file)
@@ -1,5 +1,5 @@
 {
-  requires = ( MAIN );
+  requires = ( MAIN, CommonUI );
 
   publicResources = (
   );
   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"; 
         };
       };
     };
           protectedBy = "<public>";
           pageName = "SOGoUserHomePage"; 
         };
+       logoff = {
+          protectedBy = "<public>";
+          pageName = "SOGoUserHomePage";
+         actionName = "logoff";
+       };
       };
     };
     SOGoGroupsFolder = {
       methods = {
         index = { 
           protectedBy = "View";
-          pageName    = "SOGoGroupsPage"; 
+          pageName = "SOGoGroupsPage"; 
         };
       };
     };
       methods = {
         index = { 
           protectedBy = "View";
-          pageName    = "SOGoGroupPage"; 
+          pageName = "SOGoGroupPage"; 
         };
       };
     };
index 5cf9a093f390baad9e43f002f0a6626fab89ebf5..314b97f893a4da91b2dcb3c3a389b0af7fa82cbb 100644 (file)
@@ -1,24 +1,81 @@
-<?xml version='1.0' standalone='yes'?>
-<html
+<?xml version="1.0" standalone="yes"?>
+<!DOCTYPE container>
+<container 
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:var="http://www.skyrix.com/od/binding"
   xmlns:const="http://www.skyrix.com/od/constant"
->
-  <head>
-    <title>Scalable OGo Homepage</title>
-  </head>
+  xmlns:rsrc="OGo:url"
+  xmlns:label="OGo:label"
+  ><var:string var:value="doctype" const:escapeHTML="NO" />
+  <html>
+    <head>
+      <title>
+       <var:string value="title"/>
+      </title>
+      <meta name="hideFrame" var:content="hideFrame" />
+      <meta name="description" content="SOGo Web Interface" />
+      <meta name="author" content="SKYRIX Software AG/Inverse groupe conseil" />
+      <meta name="robots" content="stop" />
+      <meta name="build" var:content="buildDate" />
+      <link href="mailto:support@inverse.ca" rev="made" />
+      <link rel="shortcut icon" rsrc:href="lori_16x16.ico" type="image/x-icon" />
+      <link type="text/css" rel="stylesheet" rsrc:href="generic.css" />
+      <link type="text/css" rel="stylesheet" rsrc:href="dtree.css" />
+      <var:if-ie
+       ><link type="text/css" rel="stylesheet" rsrc:href="iefixes.css"
+         /></var:if-ie>
+      <link type="text/css" rel="stylesheet" rsrc:href="SOGoRootPage.css" />
+    </head>
 
-  <body>
-    <h3>Scalable OGo Homepage</h3>
+    <body class="loginPage">
+      <script type="text/javascript">
+       var ResourcesURL = '/SOGo.woa/WebServerResources';
+      </script>
 
-    <form href="connect">
-      Login:
-      <input name="userName" type="text" var:value="userName" />
-      <input name="submit" type="submit" value="connect" />
-    </form>
-       <!--
-       <hr />
-       Current locale: <pre><var:string value="context.locale" /></pre>
-       -->
-  </body>
-</html>
+      <script type="text/javascript" rsrc:src="_IEtoW3C.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="events.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="prototype.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="JavascriptAPIExtensions.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="HTMLElement.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="HTMLInputElement.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="HTMLTableElement.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="HTMLUListElement.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="generic.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="SOGoDragAndDrop.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="SOGoDragHandles.js"><!-- space required --></script>
+      <script type="text/javascript" rsrc:src="SOGoRootPage.js"><!-- space required --></script>
+      <!-- var:js-stringtable
+       var:framework="productFrameworkName"
+       const:identifier="labels" -->
+      <!-- var:js-stringtable
+       const:identifier="clabels" -->
+      <div class="pageContent">
+       <form href="view">
+         <div id="loginScreen">
+           <img rsrc:src="lori-login.jpg"/><br/><br/>
+           <label><var:string label:value="Login:"/><br/>
+             <input class="textField" id="userName" name="userName"
+               type="text" var:value="userName" /></label><br/>
+           <label><var:string label:value="Password:"/><br/>
+             <input class="textField" id="password"
+               name="password" type="password" var:value="password" /><br/></label>
+           <div id="loginButton">
+             <input class="button" id="submit" name="submit" type="submit" label:value="Connect" />
+           </div>
+         </div>
+       </form>
+      </div>
+      <noscript>
+       <div class="javascriptPopupBackground">
+       </div>
+       <div class="javascriptMessagePseudoWindow noJavascriptErrorMessage">
+         <var:string label:value="noJavascriptError"
+           /><br /><br
+           /><a class="button" var:href="page.context.uri"
+           ><var:string label:value="noJavascriptRetry"
+             /></a>
+       </div>
+      </noscript>
+    </body>
+  </html>
+</container>
index 08ec47188062bde32fdeb02b5c531ea9c009462a..a38aa506b0f3aaceb04c6fe7c74169272f3b8b6e 100644 (file)
@@ -69,6 +69,8 @@
            ><div id="logConsole"><!-- space --></div></var:if>
 
          <div id="linkBanner" class="linkbanner">
+           <a id="logoff" var:href="logoffPath"
+             ><var:string label:value="Logoff" /></a>
            <a var:href="relativeCalendarPath"
              ><var:string label:value="Calendar" /></a> |
            <a var:href="relativeContactsPath"
@@ -77,8 +79,6 @@
              ><var:string label:value="Mail" /></a> |
            <a var:href="relativePreferencesPath"
              ><var:string label:value="Preferences" /></a>
-           <!--              | <a var:href="logoffPath"
-           ><var:string label:value="Logoff" /></a> -->
            <var:if condition="context.isUIxDebugEnabled"
              >| <a href="#"><var:string
                  label:value="Log Console (dev.)" /></a
index 509b2ed8cfe71777197c531c424ba9e464135a69..2e39fe69a8b675b71f8e87ae37708204e6911bf0 100644 (file)
@@ -82,8 +82,14 @@ Date.prototype.sogoDayName = function() {
 Date.prototype.daysUpTo = function(otherDate) {
   var days = new Array();
 
-  var day1 = this.getTime();
-  var day2 = otherDate.getTime();
+  var day1Date = new Date();
+  day1Date.setTime(this.getTime());
+  day1Date.setHours(0, 0, 0, 0);
+  var day2Date = new Date();
+  day2Date.setTime(otherDate.getTime());
+  day2Date.setHours(23, 59, 59, 999);
+  var day1 = day1Date.getTime();
+  var day2 = day2Date.getTime();
 
   var nbrDays = Math.floor((day2 - day1) / 86400000) + 1;
   for (var i = 0; i < nbrDays; i++) {
@@ -222,3 +228,118 @@ Date.prototype.endOfWeek = function() {
 
    return endOfWeek;
 }
+
+String.prototype._base64_keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+String.prototype.base64encode = function () {
+  var output = "";
+  var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+  var i = 0;
+  var input = this._base64_utf8_encode();
+
+  while (i < input.length) {
+    chr1 = input.charCodeAt(i++);
+    chr2 = input.charCodeAt(i++);
+    chr3 = input.charCodeAt(i++);
+    enc1 = chr1 >> 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 (file)
index 0000000..ee7ab94
--- /dev/null
@@ -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 (file)
index 0000000..dd93cb3
--- /dev/null
@@ -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);
index d399878bae247dad9bdbda5271fc71277e375e31..65ea6e83a9c4626811e0015124b513db75535fec 100644 (file)
@@ -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; }
index 0e5d7587fd1e7a9dd98085fab32f1d81a5348756..608947f61cb78ce1e820adfce37f1e5a6d76d4d0 100644 (file)
@@ -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);
   }
 }