merge of '571d9bfb5bd40cb2435fe9c4ecec1069f13f7a7d'

and 'b8d56bd5a31be825cfe66b8fe9f9a15269a09fbc'

Monotone-Parent: 571d9bfb5bd40cb2435fe9c4ecec1069f13f7a7d
Monotone-Parent: b8d56bd5a31be825cfe66b8fe9f9a15269a09fbc
Monotone-Revision: 787fab4426e6ea6fab09ccfcc61ecc658e06ed5e

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2009-06-12T15:56:10
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Francis Lachapelle
2009-06-12 15:56:10 +00:00
12 changed files with 645 additions and 517 deletions

View File

@@ -4,6 +4,34 @@
-addressBooksList]): LDAP-based addressbooks must not be
editable, even for super users.
2009-06-11 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoUserFolder.m (-davUserQuery:): do not return
the user information for the current user.
* UI/MainUI/SOGoUserHomePage.m (-usersSearchAction): do not return
the user information for the current user.
(-foldersSearchAction): the method only search folders for the
owner of the current folder. The "user" parameter has thus been
removed.
2009-06-10 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/NSString+Utilities.m (-stringByDetectingURLs):
fixed a leak. Fixed a crash on GNUstep by using arrays of pointers
to NSRange instead of converting/parsing them to/from NSString.
* SoObjects/SOGo/NSArray+Utilities.m (-addRange): removed method.
(-addNonNSObject:withSize:copy:): new helper method to add object
pointers to arrays.
(-freeNonNSObjects): new helper method to release the above object
pointers.
* UI/MailPartViewers/UIxMailPartHTMLViewer.m: fixed rendering of
CSS content containing comment characters. Ignore certain HTML
tags that can alter the appearance of the SOGo display altogether
(SCRIPT, LINK, BASE, META, TITLE).
2009-06-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/Appointments/SOGoFreeBusyObject.m

View File

@@ -24,7 +24,6 @@
#define SOGOUSERFOLDER_CONTACTS_H
@class NSArray;
@class NSString;
#import <SOGo/SOGoUserFolder.h>

View File

@@ -53,9 +53,13 @@
@interface NSMutableArray (SOGoArrayUtilities)
- (void) addNonNSObject: (void *) objectPtr
withSize: (size_t) objectSize
copy: (BOOL) doCopy;
- (void) freeNonNSObjects;
- (void) addObjectUniquely: (id) object;
- (void) addRange: (NSRange) newRange;
- (BOOL) hasRangeIntersection: (NSRange) testRange;
@end

View File

@@ -24,6 +24,7 @@
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSString.h>
#import <Foundation/NSValue.h>
#import "NSArray+Utilities.h"
@@ -199,17 +200,42 @@
@implementation NSMutableArray (SOGoArrayUtilities)
- (void) addNonNSObject: (void *) objectPtr
withSize: (size_t) objectSize
copy: (BOOL) doCopy
{
void *newObjectPtr;
if (doCopy)
{
newObjectPtr = NSZoneMalloc (NULL, objectSize);
memcpy (newObjectPtr, objectPtr, objectSize);
}
else
newObjectPtr = objectPtr;
[self addObject: [NSValue valueWithPointer: newObjectPtr]];
}
- (void) freeNonNSObjects
{
unsigned int count, max;
void *objectPtr;
max = [self count];
for (count = 0; count < max; count++)
{
objectPtr = [[self objectAtIndex: count] pointerValue];
NSZoneFree (NULL, objectPtr);
}
}
- (void) addObjectUniquely: (id) object
{
if (![self containsObject: object])
[self addObject: object];
}
- (void) addRange: (NSRange) newRange
{
[self addObject: NSStringFromRange (newRange)];
}
- (BOOL) hasRangeIntersection: (NSRange) testRange
{
NSEnumerator *ranges;

View File

@@ -23,6 +23,7 @@
#import <Foundation/NSArray.h>
#import <Foundation/NSCharacterSet.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSValue.h>
#import <EOControl/EOQualifier.h>
@@ -88,7 +89,7 @@ static NSMutableCharacterSet *urlStartChars = nil;
r = [self rangeOfString:@"?" options: NSBackwardsSearch];
if (r.length > 0)
newUrl = [self substringToIndex: NSMaxRange(r) - 1];
newUrl = [self substringToIndex: NSMaxRange (r) - 1];
else
newUrl = self;
@@ -132,11 +133,10 @@ static NSMutableCharacterSet *urlStartChars = nil;
{
nsEnclosing = [self rangeOfString: @"}"];
length = [self length];
if (nsEnclosing.length > 0
&& nsEnclosing.location < (length - 1))
if (nsEnclosing.length > 0 && nsEnclosing.location < (length - 1))
{
methodEnclosing = NSMakeRange(nsEnclosing.location + 1,
length - nsEnclosing.location - 1);
methodEnclosing = NSMakeRange (nsEnclosing.location + 1,
length - nsEnclosing.location - 1);
nsEnclosing.length = nsEnclosing.location - 1;
nsEnclosing.location = 1;
davInvocation = [NSMutableDictionary dictionaryWithCapacity: 2];
@@ -176,7 +176,7 @@ static NSMutableCharacterSet *urlStartChars = nil;
start--;
start++;
length = [self length] - start;
workRange = NSMakeRange(start, length);
workRange = NSMakeRange (start, length);
workRange = [self rangeOfCharacterFromSet: urlAfterEndingChars
options: NSLiteralSearch range: workRange];
if (workRange.location != NSNotFound)
@@ -198,7 +198,8 @@ static NSMutableCharacterSet *urlStartChars = nil;
NSEnumerator *enumRanges;
NSMutableArray *newRanges;
NSRange matchRange, currentUrlRange, rest;
NSString *urlText, *newUrlText, *range;
NSRange *rangePtr;
NSString *urlText, *newUrlText;
unsigned int length, matchLength, offset;
int startLocation;
@@ -209,10 +210,11 @@ static NSMutableCharacterSet *urlStartChars = nil;
@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@"0123456789:@"];
}
newRanges = [NSMutableArray new];
newRanges = [NSMutableArray array];
matchLength = [match length];
rest.location = -1;
matchRange = [selfCopy rangeOfString: match];
while (matchRange.location != NSNotFound)
{
@@ -225,12 +227,14 @@ static NSMutableCharacterSet *urlStartChars = nil;
currentUrlRange = [selfCopy _rangeOfURLInRange: matchRange];
if ([ranges hasRangeIntersection: currentUrlRange])
rest.location = NSMaxRange(currentUrlRange);
rest.location = NSMaxRange (currentUrlRange);
else
{
if (currentUrlRange.length > matchLength)
[newRanges addRange: currentUrlRange];
rest.location = NSMaxRange(currentUrlRange);
[newRanges addNonNSObject: &currentUrlRange
withSize: sizeof (NSRange)
copy: YES];
rest.location = NSMaxRange (currentUrlRange);
}
length = [selfCopy length];
@@ -242,25 +246,24 @@ static NSMutableCharacterSet *urlStartChars = nil;
// Make the substitutions, keep track of the new offset
offset = 0;
enumRanges = [newRanges objectEnumerator];
range = [enumRanges nextObject];
while (range)
while ((rangePtr = [[enumRanges nextObject] pointerValue]))
{
currentUrlRange = NSRangeFromString(range);
currentUrlRange.location += offset;
urlText = [selfCopy substringFromRange: currentUrlRange];
rangePtr->location += offset;
urlText = [selfCopy substringFromRange: *rangePtr];
if ([urlText hasPrefix: prefix]) prefix = @"";
newUrlText = [NSString stringWithFormat: @"<a href=\"%@%@\">%@</a>",
prefix, urlText, urlText];
[selfCopy replaceCharactersInRange: currentUrlRange
[selfCopy replaceCharactersInRange: *rangePtr
withString: newUrlText];
offset += ([newUrlText length] - [urlText length]);
// Add range for further substitutions
currentUrlRange = NSMakeRange (currentUrlRange.location, [newUrlText length]);
[ranges addRange: currentUrlRange];
range = [enumRanges nextObject];
[ranges addNonNSObject: &currentUrlRange
withSize: sizeof (NSRange)
copy: YES];
}
[newRanges freeNonNSObjects];
}
- (NSString *) stringByDetectingURLs
@@ -268,7 +271,7 @@ static NSMutableCharacterSet *urlStartChars = nil;
NSMutableString *selfCopy;
NSMutableArray *ranges;
ranges = [NSMutableArray new];
ranges = [NSMutableArray array];
selfCopy = [NSMutableString stringWithString: self];
[self _handleURLs: selfCopy
textToMatch: @"://"
@@ -278,7 +281,7 @@ static NSMutableCharacterSet *urlStartChars = nil;
textToMatch: @"@"
prefix: @"mailto:"
inRanges: ranges];
[ranges release];
[ranges freeNonNSObjects];
return selfCopy;
}

View File

@@ -718,7 +718,7 @@ static NSArray *childRecordFields = nil;
currentUser = [localContext activeUser];
if (delegatedUsers && [delegatedUsers count])
if ([delegatedUsers count])
{
if (![currentUser isSuperUser])
{

View File

@@ -129,7 +129,8 @@ static NSString *LDAPContactInfoAttribute = nil;
for (count = 0; count < max; count++)
{
node = [children objectAtIndex: count];
componentName = [[(id<DOMElement>)node attribute: @"name"] lowercaseString];
componentName = [[(id<DOMElement>)node attribute: @"name"]
lowercaseString];
[filter setObject: [node textValue] forKey: componentName];
}
@@ -381,13 +382,14 @@ static NSString *LDAPContactInfoAttribute = nil;
LDAPUserManager *um;
NSMutableString *fetch;
NSDictionary *currentUser;
NSString *field;
NSString *field, *login;
NSArray *users;
int i;
#warning the attributes returned here should match the one requested in the query
fetch = [NSMutableString string];
login = [[context activeUser] login];
um = [LDAPUserManager sharedUserManager];
// We sort our array - this is pretty useful for the
@@ -397,25 +399,26 @@ static NSString *LDAPContactInfoAttribute = nil;
for (i = 0; i < [users count]; i++)
{
currentUser = [users objectAtIndex: i];
[fetch appendString: @"<user>"];
field = [currentUser objectForKey: @"c_uid"];
[fetch appendFormat: @"<id>%@</id>",
[field stringByEscapingXMLString]];
field = [currentUser objectForKey: @"cn"];
[fetch appendFormat: @"<displayName>%@</displayName>",
[field stringByEscapingXMLString]];
field = [currentUser objectForKey: @"c_email"];
[fetch appendFormat: @"<email>%@</email>",
[field stringByEscapingXMLString]];
if (LDAPContactInfoAttribute)
{
field = [currentUser objectForKey: LDAPContactInfoAttribute];
if ([field length])
[fetch appendFormat: @"<info>%@</info>",
[field stringByEscapingXMLString]];
}
[fetch appendString: @"</user>"];
if (![field isEqualToString: login])
{
[fetch appendFormat: @"<user><id>%@</id>",
[field stringByEscapingXMLString]];
field = [currentUser objectForKey: @"cn"];
[fetch appendFormat: @"<displayName>%@</displayName>",
[field stringByEscapingXMLString]];
field = [currentUser objectForKey: @"c_email"];
[fetch appendFormat: @"<email>%@</email>",
[field stringByEscapingXMLString]];
if (LDAPContactInfoAttribute)
{
field = [currentUser objectForKey: LDAPContactInfoAttribute];
if ([field length])
[fetch appendFormat: @"<info>%@</info>",
[field stringByEscapingXMLString]];
}
[fetch appendString: @"</user>"];
}
}
return fetch;

View File

@@ -49,6 +49,9 @@
#define showWhoWeAre()
#endif
/* Tags that are forbidden within the body of the html content */
static NSArray *BannedTags = nil;
static xmlCharEncoding
_xmlCharsetForCharset (NSString *charset)
{
@@ -102,14 +105,14 @@ _xmlCharsetForCharset (NSString *charset)
NSMutableString *result;
NSMutableString *css;
NSDictionary *attachmentIds;
BOOL ignoreContent;
NSString *ignoreTag;
BOOL inBody;
BOOL inStyle;
BOOL inScript;
BOOL inCSSDeclaration;
BOOL hasEmbeddedCSS;
BOOL hasExternalImages;
BOOL unsafe;
NSMutableArray *crumb;
xmlCharEncoding contentEncoding;
}
@@ -119,13 +122,23 @@ _xmlCharsetForCharset (NSString *charset)
@implementation _UIxHTMLMailContentHandler
+ (void) initialize
{
if (!BannedTags)
{
BannedTags = [NSArray arrayWithObjects: @"SCRIPT", @"LINK", @"BASE",
@"META", @"TITLE", nil];
[BannedTags retain];
}
}
- (id) init
{
if ((self = [super init]))
{
crumb = nil;
css = nil;
result = nil;
ignoreTag = nil;
attachmentIds = nil;
contentEncoding = XML_CHAR_ENCODING_UTF8;
}
@@ -135,7 +148,6 @@ _xmlCharsetForCharset (NSString *charset)
- (void) dealloc
{
[crumb release];
[result release];
[css release];
[super dealloc];
@@ -181,34 +193,25 @@ _xmlCharsetForCharset (NSString *charset)
{
showWhoWeAre();
[crumb release];
[css release];
[result release];
result = [NSMutableString new];
css = [NSMutableString new];
crumb = [NSMutableArray new];
ignoreContent = NO;
[ignoreTag release];
ignoreTag = nil;
inBody = NO;
inStyle = NO;
inScript = NO;
inCSSDeclaration = NO;
hasEmbeddedCSS = NO;
}
- (void) endDocument
{
unsigned int count, max;
showWhoWeAre();
max = [crumb count];
if (max > 0)
for (count = max - 1; count > -1; count--)
{
[result appendFormat: @"</%@>", [crumb objectAtIndex: count]];
[crumb removeObjectAtIndex: count];
}
}
- (void) startPrefixMapping: (NSString *)_prefix
@@ -225,10 +228,13 @@ _xmlCharsetForCharset (NSString *charset)
- (void) _appendStyle: (unichar *) _chars
length: (int) _len
{
unsigned int count;
unsigned int count, length;
unichar *start, *currentChar;
start = _chars;
while (*start < 33)
start++;
currentChar = start;
for (count = 0; count < _len; count++)
{
@@ -243,28 +249,39 @@ _xmlCharsetForCharset (NSString *charset)
}
else
{
if (*currentChar == '{')
inCSSDeclaration = YES;
if (*currentChar == ',')
hasEmbeddedCSS = NO;
else if (!hasEmbeddedCSS)
if (*currentChar < 32)
{
if (*currentChar == '@')
hasEmbeddedCSS = YES;
else
if (*currentChar > 32)
{
[css appendString: [NSString stringWithCharacters: start
length: (currentChar - start)]];
[css appendString: @".SOGoHTMLMail-CSS-Delimiter "];
if (currentChar > start)
[css appendString: [NSString stringWithCharacters: start
length: (currentChar - start)]];
start = currentChar + 1;
}
else
{
if (*currentChar == '{')
inCSSDeclaration = YES;
else if (*currentChar == ',')
hasEmbeddedCSS = NO;
else if (!hasEmbeddedCSS)
{
if (*currentChar == '@')
hasEmbeddedCSS = YES;
start = currentChar;
}
else
if (*currentChar > 32)
{
length = (currentChar - start);
[css appendFormat: @"%@\n.SOGoHTMLMail-CSS-Delimiter ",
[NSString stringWithCharacters: start length: length]];
hasEmbeddedCSS = YES;
start = currentChar;
}
}
}
}
}
[css appendString: [NSString stringWithCharacters: start
length: (currentChar - start)]];
if (currentChar > start)
[css appendString: [NSString stringWithCharacters: start
length: (currentChar - start)]];
}
- (void) startElement: (NSString *) _localName
@@ -273,111 +290,146 @@ _xmlCharsetForCharset (NSString *charset)
attributes: (id <SaxAttributes>) _attributes
{
unsigned int count, max;
NSString *name, *value, *cid;
NSString *name, *value, *cid, *upperName;
NSMutableString *resultPart;
BOOL skipAttribute;
showWhoWeAre();
if (inStyle || inScript)
upperName = [_localName uppercaseString];
if (inStyle || ignoreContent)
;
else if ([_localName caseInsensitiveCompare: @"base"] == NSOrderedSame)
else if ([upperName isEqualToString: @"BASE"])
;
else if ([_localName caseInsensitiveCompare: @"meta"] == NSOrderedSame)
else if ([upperName isEqualToString: @"META"])
;
else if ([_localName caseInsensitiveCompare: @"body"] == NSOrderedSame)
else if ([upperName isEqualToString: @"BODY"])
inBody = YES;
else if ([_localName caseInsensitiveCompare: @"script"] == NSOrderedSame)
inScript = YES;
else if ([_localName caseInsensitiveCompare: @"style"] == NSOrderedSame)
else if ([upperName isEqualToString: @"STYLE"])
inStyle = YES;
else if (inBody)
{
resultPart = [NSMutableString new];
[resultPart appendFormat: @"<%@", _rawName];
max = [_attributes count];
for (count = 0; count < max; count++)
if ([BannedTags containsObject: upperName])
{
skipAttribute = NO;
name = [_attributes nameAtIndex: count];
if ([[name lowercaseString] hasPrefix: @"on"])
skipAttribute = YES;
else if ([name caseInsensitiveCompare: @"src"] == NSOrderedSame)
{
value = [_attributes valueAtIndex: count];
if ([value hasPrefix: @"cid:"])
{
cid = [NSString stringWithFormat: @"<%@>",
[value substringFromIndex: 4]];
value = [attachmentIds objectForKey: cid];
skipAttribute = (value == nil);
}
else if ([_rawName caseInsensitiveCompare: @"img"] == NSOrderedSame)
{
hasExternalImages = YES;
if (!unsafe) skipAttribute = YES;
}
else
skipAttribute = YES;
}
else if ([name caseInsensitiveCompare: @"href"] == NSOrderedSame
|| [name caseInsensitiveCompare: @"action"] == NSOrderedSame)
{
value = [_attributes valueAtIndex: count];
skipAttribute = ([value rangeOfString: @"://"].location
== NSNotFound
&& ![value hasPrefix: @"#"]);
}
else
value = [_attributes valueAtIndex: count];
if (!skipAttribute)
[resultPart appendFormat: @" %@=\"%@\"",
name, [value stringByReplacingString: @"\""
withString: @"\\\""]];
ignoreTag = [upperName copy];
ignoreContent = YES;
}
else
{
resultPart = [NSMutableString new];
[resultPart appendFormat: @"<%@", _rawName];
[resultPart appendString: @">"];
[result appendString: resultPart];
[resultPart release];
max = [_attributes count];
for (count = 0; count < max; count++)
{
skipAttribute = NO;
name = [[_attributes nameAtIndex: count] uppercaseString];
if ([name hasPrefix: @"ON"])
skipAttribute = YES;
else if ([name isEqualToString: @"SRC"])
{
value = [_attributes valueAtIndex: count];
if ([value hasPrefix: @"cid:"])
{
cid = [NSString stringWithFormat: @"<%@>",
[value substringFromIndex: 4]];
value = [attachmentIds objectForKey: cid];
skipAttribute = (value == nil);
}
else if ([upperName isEqualToString: @"IMG"])
{
hasExternalImages = YES;
if (!unsafe) skipAttribute = YES;
}
else
skipAttribute = YES;
}
else if ([name isEqualToString: @"HREF"]
|| [name isEqualToString: @"ACTION"])
{
value = [_attributes valueAtIndex: count];
skipAttribute = ([value rangeOfString: @"://"].location
== NSNotFound
&& ![value hasPrefix: @"#"]);
}
else
value = [_attributes valueAtIndex: count];
if (!skipAttribute)
[resultPart appendFormat: @" %@=\"%@\"",
name, [value stringByReplacingString: @"\""
withString: @"\\\""]];
}
[resultPart appendString: @">"];
[result appendString: resultPart];
[resultPart release];
}
}
}
- (void) _finishCSS
{
NSRange excessiveDelimiter;
[css replaceString: @"<!--" withString: @""];
[css replaceString: @"-->" withString: @""];
[css replaceString: @".SOGoHTMLMail-CSS-Delimiter body"
withString: @".SOGoHTMLMail-CSS-Delimiter"];
[css replaceString: @";" withString: @" !important;"];
[css replaceString: @"<!--" withString: @""];
[css replaceString: @"-->" withString: @""];
excessiveDelimiter = [css rangeOfString: @".SOGoHTMLMail-CSS-Delimiter "
options: NSBackwardsSearch];
if (excessiveDelimiter.location != NSNotFound)
{
if (NSMaxRange (excessiveDelimiter) == [css length])
[css deleteCharactersInRange: excessiveDelimiter];
}
}
- (void) endElement: (NSString *) _localName
namespace: (NSString *) _ns
rawName: (NSString *) _rawName
{
NSString *upperName;
showWhoWeAre();
if (inStyle)
upperName = [_localName uppercaseString];
if (ignoreContent)
{
if ([_localName caseInsensitiveCompare: @"style"] == NSOrderedSame)
{
inStyle = NO;
inCSSDeclaration = NO;
}
if ([upperName isEqualToString: ignoreTag])
{
ignoreContent = NO;
[ignoreTag release];
ignoreTag = nil;
}
}
else if (inScript)
inScript = ([_localName caseInsensitiveCompare: @"script"] != NSOrderedSame);
else if (inBody)
else
{
if ([_localName caseInsensitiveCompare: @"body"] == NSOrderedSame)
{
inBody = NO;
if (css)
[self _finishCSS];
}
else
[result appendFormat: @"</%@>", _localName];
if (inStyle)
{
if ([upperName isEqualToString: @"STYLE"])
{
inStyle = NO;
inCSSDeclaration = NO;
}
}
else if (inBody)
{
if ([upperName isEqualToString: @"BODY"])
{
inBody = NO;
if (css)
[self _finishCSS];
}
else
{
NSLog (@"%@", _localName);
[result appendFormat: @"</%@>", _localName];
}
}
}
}
@@ -385,7 +437,7 @@ _xmlCharsetForCharset (NSString *charset)
length: (int) _len
{
showWhoWeAre();
if (!inScript)
if (!ignoreContent)
{
if (inStyle)
[self _appendStyle: _chars length: _len];
@@ -394,7 +446,7 @@ _xmlCharsetForCharset (NSString *charset)
NSString *tmpString;
tmpString = [NSString stringWithCharacters: _chars length: _len];
// HACK: This is to avoid appending the useless junk in the <html> tag
// that Outlook adds. It seems to confuse the XML parser for
// forwarded messages as we get this in the _body_ of the email

View File

@@ -289,16 +289,17 @@ static NSString *LDAPContactInfoAttribute = nil;
return response;
}
- (WOResponse *) _usersResponseForResults: (NSEnumerator *) users
- (WOResponse *) _usersResponseForResults: (NSArray *) users
{
WOResponse *response;
NSString *uid;
NSMutableString *responseString;
NSDictionary *contact;
NSString *contactInfo;
NSString *contactInfo, *login;
NSArray *allUsers;
int i;
login = [[context activeUser] login];
response = [context response];
[response setStatus: 200];
[response setHeader: @"text/plain; charset=utf-8"
@@ -308,25 +309,28 @@ static NSString *LDAPContactInfoAttribute = nil;
// We sort our array - this is pretty useful for the Web
// interface of SOGo.
allUsers = [[users allObjects]
sortedArrayUsingSelector: @selector(caseInsensitiveDisplayNameCompare:)];
allUsers = [users
sortedArrayUsingSelector: @selector (caseInsensitiveDisplayNameCompare:)];
for (i = 0; i < [allUsers count]; i++)
{
contact = [allUsers objectAtIndex: i];
uid = [contact objectForKey: @"c_uid"];
if ([LDAPContactInfoAttribute length])
{
contactInfo = [contact objectForKey: LDAPContactInfoAttribute];
if (!contactInfo)
contactInfo = @"";
}
else
contactInfo = @"";
[responseString appendFormat: @"%@:%@:%@:%@\n", uid,
[contact objectForKey: @"cn"],
[contact objectForKey: @"c_email"],
contactInfo];
if (![uid isEqualToString: login])
{
if ([LDAPContactInfoAttribute length])
{
contactInfo = [contact objectForKey: LDAPContactInfoAttribute];
if (!contactInfo)
contactInfo = @"";
}
else
contactInfo = @"";
[responseString appendFormat: @"%@:%@:%@:%@\n", uid,
[contact objectForKey: @"cn"],
[contact objectForKey: @"c_email"],
contactInfo];
}
}
[response appendContentString: responseString];
[responseString release];
@@ -339,14 +343,13 @@ static NSString *LDAPContactInfoAttribute = nil;
NSString *contact;
id <WOActionResults> result;
LDAPUserManager *um;
NSEnumerator *users;
um = [LDAPUserManager sharedUserManager];
contact = [self queryParameterForKey: @"search"];
if ([contact length])
{
users = [[um fetchUsersMatching: contact] objectEnumerator];
result = [self _usersResponseForResults: users];
result
= [self _usersResponseForResults: [um fetchUsersMatching: contact]];
}
else
result = [NSException exceptionWithHTTPStatus: 400
@@ -375,27 +378,23 @@ static NSString *LDAPContactInfoAttribute = nil;
- (id <WOActionResults>) foldersSearchAction
{
NSString *contact, *folderType;
NSString *folderType;
NSArray *folders;
id <WOActionResults> result;
SOGoUserFolder *userFolder;
contact = [self queryParameterForKey: @"user"];
if ([contact length])
folderType = [self queryParameterForKey: @"type"];
if ([folderType length])
{
folderType = [self queryParameterForKey: @"type"];
if ([folderType length])
{
folders = [[self clientObject] foldersOfType: folderType
forUID: contact];
result = [self _foldersResponseForResults: folders];
}
else
result = [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'type' parameter"];
userFolder = [self clientObject];
folders
= [userFolder foldersOfType: folderType
forUID: [userFolder ownerInContext: context]];
result = [self _foldersResponseForResults: folders];
}
else
result = [NSException exceptionWithHTTPStatus: 400
reason: @"missing 'user' parameter"];
reason: @"missing 'type' parameter"];
return result;
}

View File

@@ -94,9 +94,9 @@ function onUserNodeToggle(event) {
this.stopObserving("click", onUserNodeToggle);
var person = this.parentNode.getAttribute("dataname");
var url = (UserFolderURL + "foldersSearch"
+ "?user=" + escape(person)
+ "&type=" + window.opener.userFolderType);
var url = (UserFolderURLForUser(person) + "foldersSearch"
+ "?type=" + window.opener.userFolderType);
var nodeId = this.getAttribute("id").substr(3);
triggerAjaxRequest(url, foldersSearchCallback,
{ nodeId: nodeId, user: person });

View File

@@ -34,333 +34,336 @@ function Node(id, pid, name, isParent, url, dataname, datatype, title, target,
// Tree object
function dTree(objName) {
this.config = {
target : null,
hideRoot : false,
folderLinks : true,
useSelection : true,
useCookies : false,
useLines : true,
useIcons : true,
useStatusText : false,
closeSameLevel : false,
inOrder : false
}
this.icon = {
root : 'img/base.gif',
folder : 'img/folder.gif',
folderOpen : 'img/folderopen.gif',
node : 'img/page.gif',
empty : 'img/empty.gif',
line : 'img/line.gif',
join : 'img/join.gif',
joinBottom : 'img/joinbottom.gif',
plus : 'img/plus.gif',
plusBottom : 'img/plusbottom.gif',
minus : 'img/minus.gif',
minusBottom : 'img/minusbottom.gif',
nlPlus : 'img/nolines_plus.gif',
nlMinus : 'img/nolines_minus.gif'
};
this.obj = objName;
this.aNodes = [];
this.aIndent = [];
this.root = new Node(-1);
this.selectedNode = null;
this.selectedFound = false;
this.completed = false;
return this;
};
// Adds a new node to the node array
dTree.prototype.add = function(id, pid, name, isParent, url, datatype,
title, target, icon, iconOpen, open, hasUnseen) {
this.aNodes[this.aNodes.length] = new Node(id, pid, name, isParent, url,
datatype, title, target, icon,
iconOpen, open, false, hasUnseen);
};
dTree.prototype = {
obj: null,
config: {
target: null,
hideRoot: false,
folderLinks: true,
useSelection: true,
useCookies: false,
useLines: true,
useIcons: true,
useStatusText: false,
closeSameLevel: false,
inOrder: false
},
icon: {
root: 'img/base.gif',
folder: 'img/folder.gif',
folderOpen: 'img/folderopen.gif',
node: 'img/page.gif',
empty: 'img/empty.gif',
line: 'img/line.gif',
join: 'img/join.gif',
joinBottom: 'img/joinbottom.gif',
plus: 'img/plus.gif',
plusBottom: 'img/plusbottom.gif',
minus: 'img/minus.gif',
minusBottom: 'img/minusbottom.gif',
nlPlus: 'img/nolines_plus.gif',
nlMinus: 'img/nolines_minus.gif'
},
aNodes: [],
aIndent: [],
root: new Node(-1),
selectedNode: null,
selectedFound: false,
completed: false,
// Open/close all nodes
dTree.prototype.openAll = function() {
this.oAll(true);
};
dTree.prototype.closeAll = function() {
this.oAll(false);
};
// Adds a new node to the node array
add: function(id, pid, name, isParent, url, datatype,
title, target, icon, iconOpen, open, hasUnseen) {
this.aNodes[this.aNodes.length] = new Node(id, pid, name, isParent, url,
datatype, title, target, icon,
iconOpen, open, false, hasUnseen);
},
// Outputs the tree to the page
dTree.prototype.toString = function() {
var str = '<div class="dtree" id="' + this.obj + '">\n';
if (document.getElementById) {
if (this.config.useCookies)
this.selectedNode = this.getSelected();
str += this.addNode(this.root);
} else str += 'Browser not supported.';
str += '</div>';
if (!this.selectedFound) this.selectedNode = null;
this.completed = true;
return str;
};
// Open/close all nodes
openAll: function() {
this.oAll(true);
},
closeAll: function() {
this.oAll(false);
},
// Creates the tree structure
dTree.prototype.addNode = function(pNode) {
var str = '';
var n=0;
if (this.config.inOrder) n = pNode._ai;
for (n; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == pNode.id) {
var cn = this.aNodes[n];
cn._p = pNode;
cn._ai = n;
this.setCS(cn);
if (!cn.target && this.config.target) cn.target = this.config.target;
if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);
if (!this.config.folderLinks && cn._hc) cn.url = null;
if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {
cn._is = true;
this.selectedNode = n;
this.selectedFound = true;
}
str += this.node(cn, n);
if (cn._ls) break;
// Outputs the tree to the page
toString: function() {
var str = '<div class="dtree" id="' + this.obj + '">\n';
if (document.getElementById) {
if (this.config.useCookies)
this.selectedNode = this.getSelected();
str += this.addNode(this.root);
} else str += 'Browser not supported.';
str += '</div>';
if (!this.selectedFound) this.selectedNode = null;
this.completed = true;
return str;
},
// Creates the tree structure
addNode: function(pNode) {
var str = '';
var n=0;
if (this.config.inOrder) n = pNode._ai;
for (n; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == pNode.id) {
var cn = this.aNodes[n];
cn._p = pNode;
cn._ai = n;
this.setCS(cn);
if (!cn.target && this.config.target) cn.target = this.config.target;
if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);
if (!this.config.folderLinks && cn._hc) cn.url = null;
if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {
cn._is = true;
this.selectedNode = n;
this.selectedFound = true;
}
str += this.node(cn, n);
if (cn._ls) break;
}
}
return str;
},
// Creates the node icon, url and text
node: function(node, nodeId) {
var str = '';
this.aNodes[nodeId] = node;
if (this.root.id != node.pid || !this.config.hideRoot) {
str += '<div class="dTreeNode"';
if (node.datatype) str += ' datatype="' + node.datatype + '"';
if (node.dataname) str += ' dataname="' + node.dataname + '"';
str += '>' + this.indent(node, nodeId);
if (node.url) {
str += '<a id="s' + this.obj + nodeId + '" class="node" href="' + node.url + '"';
if (node.title) str += ' title="' + node.title + '"';
if (node.target) str += ' target="' + node.target + '"';
if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc))
str += ' onclick="' + this.obj + '.s(' + nodeId + ');"';
str += '>';
}
else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id)
str += '<a href="#" onclick="' + this.obj + '.o(' + nodeId + ');" class="node">';
if (this.config.useIcons) {
if (!node.icon) node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);
if (!node.iconOpen) node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;
if (this.root.id == node.pid) {
node.icon = this.icon.root;
node.iconOpen = this.icon.root;
}
str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';
}
str += '<span class="nodeName';
if (!node.isParent)
str += ' leaf';
if (node.hasUnseen)
str += ' unseen';
str += '">' + node.name + '</span>';
if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';
str += '</div>';
}
if (node._hc) {
str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block' : 'none') + ';">';
str += this.addNode(node);
str += '</div>';
}
this.aIndent.pop();
return str;
},
// Adds the empty and line icons
indent: function(node, nodeId) {
var str = '';
if (this.root.id != node.pid)
{
for (var n=0; n<this.aIndent.length; n++)
str += '<img src="' + ( (this.aIndent[n] == 1 && this.config.useLines) ? this.icon.line : this.icon.empty ) + '" alt="" />';
(node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);
if (node._hc)
{
str += '<a href="#" id="tg' + this.obj + nodeId + '" onclick="return ' + this.obj + '.o(' + nodeId + ');"><img id="j' + this.obj + nodeId + '" src="';
if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus : this.icon.nlPlus;
else str += ( (node._io) ? ((node._ls && this.config.useLines) ? this.icon.minusBottom : this.icon.minus) : ((node._ls && this.config.useLines) ? this.icon.plusBottom : this.icon.plus ) );
str += '" alt="" /></a>';
}
else
str += '<img src="' + ( (this.config.useLines) ? ((node._ls) ? this.icon.joinBottom : this.icon.join ) : this.icon.empty) + '" alt="" />';
}
return str;
},
// Checks if a node has any children and if it is the last sibling
setCS: function(node) {
var lastId;
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.id) node._hc = true;
if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;
}
if (lastId==node.id) node._ls = true;
},
// Returns the selected node
getSelected: function() {
var sn = this.getCookie('cs' + this.obj);
return (sn) ? sn : null;
},
// Highlights the selected node
s: function(id) {
if (!this.config.useSelection) return;
var cn = this.aNodes[id];
if (cn._hc && !this.config.folderLinks) return;
if (this.selectedNode != id) {
if (this.selectedNode || this.selectedNode==0) {
eOld = document.getElementById("s" + this.obj + this.selectedNode);
eOld.deselect();
}
eNew = document.getElementById("s" + this.obj + id);
eNew.selectElement();
this.selectedNode = id;
if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
}
},
// Toggle Open or close
o: function(id) {
var cn = this.aNodes[id];
this.nodeStatus(!cn._io, id, cn._ls);
cn._io = !cn._io;
if (this.config.closeSameLevel) this.closeLevel(cn);
if (this.config.useCookies) this.updateCookie();
return false;
},
// Open or close all nodes
oAll: function(status) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
this.nodeStatus(status, n, this.aNodes[n]._ls)
this.aNodes[n]._io = status;
}
}
if (this.config.useCookies) this.updateCookie();
},
// Opens the tree to a specific node
openTo: function(nId, bSelect, bFirst) {
if (!bFirst) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].id == nId) {
nId=n;
break;
}
}
}
var cn=this.aNodes[nId];
if (cn.pid==this.root.id || !cn._p) return;
cn._io = true;
cn._is = bSelect;
if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
if (this.completed && bSelect) this.s(cn._ai);
else if (bSelect) this._sn=cn._ai;
this.openTo(cn._p._ai, false, true);
},
// Closes all nodes on the same level as certain node
closeLevel: function(node) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {
this.nodeStatus(false, n, this.aNodes[n]._ls);
this.aNodes[n]._io = false;
this.closeAllChildren(this.aNodes[n]);
}
}
},
// Closes all children of a node
closeAllChildren: function(node) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {
if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);
this.aNodes[n]._io = false;
this.closeAllChildren(this.aNodes[n]);
}
}
},
// Change the status of a node(open or closed)
nodeStatus: function(status, id, bottom) {
eDiv = document.getElementById('d' + this.obj + id);
if (eDiv) {
eJoin = document.getElementById('j' + this.obj + id);
if (this.config.useIcons) {
eIcon = document.getElementById('i' + this.obj + id);
eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
}
eJoin.src = (this.config.useLines)?
((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus)):
((status)?this.icon.nlMinus:this.icon.nlPlus);
eDiv.style.display = (status) ? 'block': 'none';
}
},
// [Cookie] Clears a cookie
clearCookie: function() {
var now = new Date();
var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
this.setCookie('co'+this.obj, 'cookieValue', yesterday);
this.setCookie('cs'+this.obj, 'cookieValue', yesterday);
},
// [Cookie] Sets value in a cookie
setCookie: function(cookieName, cookieValue, expires, path, domain, secure) {
document.cookie =
escape(cookieName) + '=' + escape(cookieValue)
+ (expires ? '; expires=' + expires.toGMTString() : '')
+ (path ? '; path=' + path : '')
+ (domain ? '; domain=' + domain : '')
+ (secure ? '; secure' : '');
},
// [Cookie] Gets a value from a cookie
getCookie: function(cookieName) {
var cookieValue = '';
var posName = document.cookie.indexOf(escape(cookieName) + '=');
if (posName != -1) {
var posValue = posName + (escape(cookieName) + '=').length;
var endPos = document.cookie.indexOf(';', posValue);
if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
else cookieValue = unescape(document.cookie.substring(posValue));
}
return (cookieValue);
},
// [Cookie] Returns ids of open nodes as a string
updateCookie: function() {
var str = '';
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
if (str) str += '.';
str += this.aNodes[n].id;
}
}
this.setCookie('co' + this.obj, str);
},
// [Cookie] Checks if a node id is in a cookie
isOpen: function(id) {
var aOpen = this.getCookie('co' + this.obj).split('.');
for (var n=0; n<aOpen.length; n++)
if (aOpen[n] == id) return true;
return false;
}
}
return str;
};
// Creates the node icon, url and text
dTree.prototype.node = function(node, nodeId) {
var str = '';
this.aNodes[nodeId] = node;
if (this.root.id != node.pid || !this.config.hideRoot) {
str += '<div class="dTreeNode"';
if (node.datatype) str += ' datatype="' + node.datatype + '"';
if (node.dataname) str += ' dataname="' + node.dataname + '"';
str += '>' + this.indent(node, nodeId);
if (node.url) {
str += '<a id="s' + this.obj + nodeId + '" class="node" href="' + node.url + '"';
if (node.title) str += ' title="' + node.title + '"';
if (node.target) str += ' target="' + node.target + '"';
if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc))
str += ' onclick="' + this.obj + '.s(' + nodeId + ');"';
str += '>';
}
else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id)
str += '<a href="#" onclick="' + this.obj + '.o(' + nodeId + ');" class="node">';
if (this.config.useIcons) {
if (!node.icon) node.icon = (this.root.id == node.pid) ? this.icon.root : ((node._hc) ? this.icon.folder : this.icon.node);
if (!node.iconOpen) node.iconOpen = (node._hc) ? this.icon.folderOpen : this.icon.node;
if (this.root.id == node.pid) {
node.icon = this.icon.root;
node.iconOpen = this.icon.root;
}
str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';
}
str += '<span class="nodeName';
if (!node.isParent)
str += ' leaf';
if (node.hasUnseen)
str += ' unseen';
str += '">' + node.name + '</span>';
if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';
str += '</div>';
}
if (node._hc) {
str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block' : 'none') + ';">';
str += this.addNode(node);
str += '</div>';
}
this.aIndent.pop();
return str;
};
// Adds the empty and line icons
dTree.prototype.indent = function(node, nodeId) {
var str = '';
if (this.root.id != node.pid)
{
for (var n=0; n<this.aIndent.length; n++)
str += '<img src="' + ( (this.aIndent[n] == 1 && this.config.useLines) ? this.icon.line : this.icon.empty ) + '" alt="" />';
(node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);
if (node._hc)
{
str += '<a href="#" id="tg' + this.obj + nodeId + '" onclick="return ' + this.obj + '.o(' + nodeId + ');"><img id="j' + this.obj + nodeId + '" src="';
if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus : this.icon.nlPlus;
else str += ( (node._io) ? ((node._ls && this.config.useLines) ? this.icon.minusBottom : this.icon.minus) : ((node._ls && this.config.useLines) ? this.icon.plusBottom : this.icon.plus ) );
str += '" alt="" /></a>';
}
else
str += '<img src="' + ( (this.config.useLines) ? ((node._ls) ? this.icon.joinBottom : this.icon.join ) : this.icon.empty) + '" alt="" />';
}
return str;
};
// Checks if a node has any children and if it is the last sibling
dTree.prototype.setCS = function(node) {
var lastId;
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.id) node._hc = true;
if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;
}
if (lastId==node.id) node._ls = true;
};
// Returns the selected node
dTree.prototype.getSelected = function() {
var sn = this.getCookie('cs' + this.obj);
return (sn) ? sn : null;
};
// Highlights the selected node
dTree.prototype.s = function(id) {
if (!this.config.useSelection) return;
var cn = this.aNodes[id];
if (cn._hc && !this.config.folderLinks) return;
if (this.selectedNode != id) {
if (this.selectedNode || this.selectedNode==0) {
eOld = document.getElementById("s" + this.obj + this.selectedNode);
eOld.deselect();
}
eNew = document.getElementById("s" + this.obj + id);
eNew.selectElement();
this.selectedNode = id;
if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
}
};
// Toggle Open or close
dTree.prototype.o = function(id) {
var cn = this.aNodes[id];
this.nodeStatus(!cn._io, id, cn._ls);
cn._io = !cn._io;
if (this.config.closeSameLevel) this.closeLevel(cn);
if (this.config.useCookies) this.updateCookie();
return false;
};
// Open or close all nodes
dTree.prototype.oAll = function(status) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {
this.nodeStatus(status, n, this.aNodes[n]._ls)
this.aNodes[n]._io = status;
}
}
if (this.config.useCookies) this.updateCookie();
};
// Opens the tree to a specific node
dTree.prototype.openTo = function(nId, bSelect, bFirst) {
if (!bFirst) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].id == nId) {
nId=n;
break;
}
}
}
var cn=this.aNodes[nId];
if (cn.pid==this.root.id || !cn._p) return;
cn._io = true;
cn._is = bSelect;
if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
if (this.completed && bSelect) this.s(cn._ai);
else if (bSelect) this._sn=cn._ai;
this.openTo(cn._p._ai, false, true);
};
// Closes all nodes on the same level as certain node
dTree.prototype.closeLevel = function(node) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {
this.nodeStatus(false, n, this.aNodes[n]._ls);
this.aNodes[n]._io = false;
this.closeAllChildren(this.aNodes[n]);
}
}
}
// Closes all children of a node
dTree.prototype.closeAllChildren = function(node) {
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {
if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);
this.aNodes[n]._io = false;
this.closeAllChildren(this.aNodes[n]);
}
}
}
// Change the status of a node(open or closed)
dTree.prototype.nodeStatus = function(status, id, bottom) {
eDiv = document.getElementById('d' + this.obj + id);
if (eDiv) {
eJoin = document.getElementById('j' + this.obj + id);
if (this.config.useIcons) {
eIcon = document.getElementById('i' + this.obj + id);
eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;
}
eJoin.src = (this.config.useLines)?
((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus)):
((status)?this.icon.nlMinus:this.icon.nlPlus);
eDiv.style.display = (status) ? 'block': 'none';
}
};
// [Cookie] Clears a cookie
dTree.prototype.clearCookie = function() {
var now = new Date();
var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);
this.setCookie('co'+this.obj, 'cookieValue', yesterday);
this.setCookie('cs'+this.obj, 'cookieValue', yesterday);
};
// [Cookie] Sets value in a cookie
dTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {
document.cookie =
escape(cookieName) + '=' + escape(cookieValue)
+ (expires ? '; expires=' + expires.toGMTString() : '')
+ (path ? '; path=' + path : '')
+ (domain ? '; domain=' + domain : '')
+ (secure ? '; secure' : '');
};
// [Cookie] Gets a value from a cookie
dTree.prototype.getCookie = function(cookieName) {
var cookieValue = '';
var posName = document.cookie.indexOf(escape(cookieName) + '=');
if (posName != -1) {
var posValue = posName + (escape(cookieName) + '=').length;
var endPos = document.cookie.indexOf(';', posValue);
if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));
else cookieValue = unescape(document.cookie.substring(posValue));
}
return (cookieValue);
};
// [Cookie] Returns ids of open nodes as a string
dTree.prototype.updateCookie = function() {
var str = '';
for (var n=0; n<this.aNodes.length; n++) {
if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {
if (str) str += '.';
str += this.aNodes[n].id;
}
}
this.setCookie('co' + this.obj, str);
};
// [Cookie] Checks if a node id is in a cookie
dTree.prototype.isOpen = function(id) {
var aOpen = this.getCookie('co' + this.obj).split('.');
for (var n=0; n<aOpen.length; n++)
if (aOpen[n] == id) return true;
return false;
};
// If Push and pop is not implemented by the browser

View File

@@ -352,9 +352,7 @@ function getContrastingTextColor(bgColor) {
// Consider all colors with less than 56% brightness as dark colors and
// use white as the foreground color, otherwise use black.
return ((brightness < 144)
? "white"
: "black");
return ((brightness < 144) ? "white" : "black");
}
function triggerAjaxRequest(url, callback, userdata, content, headers) {
@@ -1615,6 +1613,19 @@ function configureLinkBanner() {
}
}
/* accessing another user's data */
function UserFolderURLForUser(user) {
var folderArray = UserFolderURL.split("/");
var count;
if (UserFolderURL.endsWith('/'))
count = folderArray.length - 2;
else
count = folderArray.length - 1;
folderArray[count] = escape(user);
return folderArray.join("/");
}
/* folder creation */
function createFolder(name, okCB, notOkCB) {
if (name) {