// Copyright 1997-2002 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import <OWF/OWCookiePath.h>

#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

#import <OWF/OWCookie.h>
#import <OWF/OWCookieDomain.h>
#import <OWF/OWContentCache.h>

RCS_ID("$Header: /Network/Source/CVS/OmniGroup/Frameworks/OWF/Processors.subproj/Protocols.subproj/HTTP.subproj/OWCookiePath.m,v 1.10 2002/01/06 00:25:29 bungi Exp $")


static NSLock *pathLock = nil;

@implementation OWCookiePath

+ (void) initialize;
{
    [super initialize];
    if (pathLock);
        return;
        
    pathLock = [[NSLock alloc] init];
}

- initWithPath: (NSString *) aPath;
{
    _path = [aPath copy];
    _cookies = [[NSMutableArray alloc] init];
    
    return self;
}

- (void) dealloc;
{
    [_path release];
    [super dealloc];
}

- (NSString *) path;
{
    return _path;
}

- (BOOL)appliesToPath:(NSString *)aPath;
{
    BOOL applies;
    
    applies = [aPath hasPrefix: _path];
    
    if (OWCookiesDebug)
        NSLog(@"COOKIES: Path %@ applies to path %@ --> %d", _path, aPath, applies);

    return applies;
}

- (void) addCookie: (OWCookie *) cookie;
{
    [self addCookie: cookie andNotify: YES];
}

- (void) removeCookie: (OWCookie *) cookie;
{
    unsigned int index;
    
    [pathLock lock];
    index = [_cookies indexOfObjectIdenticalTo: cookie];
    if (index != NSNotFound)
        [_cookies removeObjectAtIndex: index];
    [pathLock unlock];
    
    if (index != NSNotFound)
        [OWCookieDomain didChange];
}

- (NSArray *) cookies;
{
    NSArray *cookies;
    
    [pathLock lock];
    cookies = [[NSArray alloc] initWithArray: _cookies];
    [pathLock unlock];
    
    return [cookies autorelease];
}

- (OWCookie *) cookieNamed: (NSString *) name;
{
    unsigned int cookieIndex;
    OWCookie *cookie = nil;
    BOOL found = NO;
    
    [pathLock lock];

    cookieIndex = [_cookies count];
    while (cookieIndex--) {
        cookie = [_cookies objectAtIndex: cookieIndex];
        if ([[cookie name] isEqualToString: name]) {
            [[cookie retain] autorelease];
            found = YES;
            break;
        }
    }

    [pathLock unlock];
    
    if (found)
        return cookie;
    return nil;
}

// For use by OWCookieDomain
- (void)addCookie: (OWCookie *) cookie andNotify: (BOOL) shouldNotify;
{
    unsigned int cookieIndex;
    OWCookie *oldCookie;
    BOOL needsAdding = YES;
    NSString *name;
    
    name = [cookie name];
    
    [pathLock lock];

    // We we have a cookie with the same name, replace it.
    cookieIndex = [_cookies count];
    while (cookieIndex--) {
        oldCookie = [_cookies objectAtIndex: cookieIndex];
        
        // Don't remove and readd the cookie if it is already there
        // since it might get deallocated.
        if (oldCookie == cookie) {
            needsAdding = NO;
            break;
        }
        
        if ([[oldCookie name] isEqualToString: name]) {
            // Replace the old cookie
            [_cookies replaceObjectAtIndex: cookieIndex withObject: cookie];
            needsAdding = NO;
            break;
        }
    }

    if (needsAdding) {
        [_cookies insertObject: cookie inArraySortedUsingSelector: @selector(compare:)];
    }
    
    [pathLock unlock];
    
    if (shouldNotify) {
        [OWCookieDomain didChange];
        [OWContentCache flushCachedContentMatchingCookie:cookie];
    }
}

- (void) addNonExpiredCookiesToArray: (NSMutableArray *) array
                       usageIsSecure: (BOOL) secure;
{
    unsigned int cookieIndex, cookieCount;
    OWCookie *cookie;
    
    [pathLock lock];
    
    cookieCount = [_cookies count];
    for (cookieIndex = 0; cookieIndex < cookieCount; cookieIndex++) {
        cookie = [_cookies objectAtIndex: cookieIndex];
        if ([cookie isExpired])
            continue;
        if ([cookie secure] && !secure)
            continue;
        [array addObject: cookie];
    }
    
    [pathLock unlock];
}

- (NSComparisonResult) compare: (id) otherObject;
{
    if (![otherObject isKindOfClass: isa])
        return NSOrderedAscending;
    
    return [_path compare: [(OWCookiePath *)otherObject path]];
}

- (NSMutableDictionary *) debugDictionary;
{
    NSMutableDictionary *dict;
    
    dict = [super debugDictionary];
    [dict setObject: _path forKey: @"path"];
    [dict setObject: _cookies forKey: @"cookies"];
    
    return dict;
}

@end

