Monotone-Parent: f6d4ca8944c94273bc0dae0565c60e45be9f2ca1

Monotone-Revision: 98896091d472e0ee7990f69f32f5981f5d1dc546

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-01-16T18:46:32
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2008-01-16 18:46:32 +00:00
parent d0db04a31e
commit 8aae87afd5
16 changed files with 508 additions and 129 deletions

View File

@ -42,6 +42,7 @@
#import <WEExtensions/WEResourceManager.h>
#import <SoObjects/SOGo/SOGoCache.h>
#import <SoObjects/SOGo/SOGoDAVAuthenticator.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUserFolder.h>
@ -56,6 +57,7 @@
@interface SOGo : SoApplication
{
NSMutableDictionary *localeLUT;
SOGoCache *cache;
}
- (NSDictionary *) currentLocaleConsideringLanguages:(NSArray *)_langs;
@ -390,7 +392,9 @@ static BOOL debugObjectAllocation = NO;
static NSArray *runLoopModes = nil;
WOResponse *resp;
cache = [SOGoCache sharedCache];
resp = [super dispatchRequest: _request];
[SOGoCache killCache];
if (![self isTerminating])
{

View File

@ -104,11 +104,8 @@
- (NSArray *)subFolderNames;
- (NSArray *)allSubFolderNames;
- (NSNumber *)versionOfContentWithName:(NSString *)_name;
- (NSCalendarDate *)creationDateOfEntryWithName:(NSString *)_name;
- (NSCalendarDate *)lastModificationOfEntryWithName:(NSString *)_name;
- (NSDictionary *) recordOfEntryWithName: (NSString *) name;
- (NSString *)fetchContentWithName:(NSString *)_name;
- (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name
baseVersion:(unsigned int)_baseVersion;
- (NSException *)writeContent:(NSString *)_content toName:(NSString *)_name;

View File

@ -251,15 +251,14 @@ static GCSStringFormatter *stringFormatter = nil;
recursive:YES];
}
- (id) _fetchValueOfColumn: (NSString *)_col
inContentWithName: (NSString *)_name
ignoreDeleted: (BOOL) ignoreDeleted
- (NSDictionary *) _fetchValueOfColumns: (NSArray *) _cols
inContentWithName: (NSString *) _name
ignoreDeleted: (BOOL) ignoreDeleted
{
EOAdaptorChannel *channel;
NSException *error;
NSDictionary *row;
NSArray *attrs;
NSString *result;
NSMutableString *sql;
if ((channel = [self acquireStoreChannel]) == nil) {
@ -271,12 +270,13 @@ static GCSStringFormatter *stringFormatter = nil;
sql = [NSMutableString stringWithFormat: @"SELECT %@"
@" FROM %@"
@" WHERE c_name = '%@'",
_col, [self storeTableName], _name];
[_cols componentsJoinedByString: @","],
[self storeTableName], _name];
if (ignoreDeleted)
[sql appendString: @" AND (c_deleted != 1 OR c_deleted IS NULL)"];
/* run SQL */
if ((error = [channel evaluateExpressionX:sql]) != nil) {
[self errorWithFormat:@"%s: cannot execute SQL '%@': %@",
__PRETTY_FUNCTION__, sql, error];
@ -286,51 +286,64 @@ static GCSStringFormatter *stringFormatter = nil;
/* fetch results */
result = nil;
attrs = [channel describeResults:NO /* do not beautify names */];
if ((row = [channel fetchAttributes:attrs withZone:NULL]) != nil) {
result = [[[row objectForKey:_col] copy] autorelease];
if (![result isNotNull]) result = nil;
row = [channel fetchAttributes: attrs withZone: NULL];
if (row)
[channel cancelFetch];
}
/* release and return result */
[self releaseChannel:channel];
return result;
return row;
}
- (NSNumber *)versionOfContentWithName:(NSString *)_name {
return [self _fetchValueOfColumn:@"c_version" inContentWithName:_name
ignoreDeleted: YES];
- (NSDictionary *) recordOfEntryWithName: (NSString *) name
{
NSDictionary *row;
NSMutableDictionary *record;
NSArray *columns;
NSString *strValue;
int intValue;
columns = [NSArray arrayWithObjects: @"c_content", @"c_version",
@"c_creationdate", @"c_lastmodified", nil];
row = [self _fetchValueOfColumns: columns
inContentWithName: name
ignoreDeleted: YES];
if (row)
{
record = [NSMutableDictionary dictionaryWithCapacity: 5];
strValue = [row objectForKey: @"c_content"];
if (![strValue isNotNull])
strValue = @"";
[record setObject: strValue forKey: @"c_content"];
[record setObject: [row objectForKey: @"c_version"]
forKey: @"c_version"];
intValue = [[row objectForKey: @"c_creationdate"] intValue];
[record
setObject: [NSCalendarDate dateWithTimeIntervalSince1970: intValue]
forKey: @"c_creationdate"];
intValue = [[row objectForKey: @"c_lastmodified"] intValue];
[record
setObject: [NSCalendarDate dateWithTimeIntervalSince1970: intValue]
forKey: @"c_lastmodified"];
}
else
record = nil;
return record;
}
- (NSCalendarDate *)creationDateOfEntryWithName:(NSString *)_name {
int seconds;
- (NSNumber *) deletionOfEntryWithName: (NSString *) name
{
NSDictionary *row;
seconds = [[self _fetchValueOfColumn:@"c_creationdate" inContentWithName:_name
ignoreDeleted: YES] intValue];
row = [self _fetchValueOfColumns: [NSArray arrayWithObject: @"c_deleted"]
inContentWithName: name
ignoreDeleted: NO];
return [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
}
- (NSCalendarDate *)lastModificationOfEntryWithName:(NSString *)_name {
int seconds;
seconds = [[self _fetchValueOfColumn:@"c_lastmodified" inContentWithName:_name
ignoreDeleted: YES] intValue];
return [NSCalendarDate dateWithTimeIntervalSince1970: seconds];
}
- (NSNumber *)deletionOfContentWithName:(NSString *)_name {
return [self _fetchValueOfColumn:@"c_deleted" inContentWithName:_name
ignoreDeleted: NO];
}
- (NSString *)fetchContentWithName:(NSString *)_name {
return [self _fetchValueOfColumn:@"c_content" inContentWithName:_name
ignoreDeleted: YES];
return [row objectForKey: @"c_deleted"];
}
- (NSDictionary *)fetchContentsOfAllFiles {
@ -571,6 +584,7 @@ static GCSStringFormatter *stringFormatter = nil;
{
EOAdaptorChannel *storeChannel, *quickChannel;
NSMutableDictionary *quickRow, *contentRow;
NSDictionary *currentRow;
GCSFieldExtractor *extractor;
NSException *error;
NSNumber *storedVersion;
@ -598,19 +612,24 @@ static GCSStringFormatter *stringFormatter = nil;
if (doLogStore)
[self logWithFormat:@"should store content: '%@'\n%@", _name, _content];
storedVersion = [self versionOfContentWithName:_name];
currentRow = [self _fetchValueOfColumns: [NSArray arrayWithObjects:
@"c_version",
@"c_deleted", nil]
inContentWithName: _name
ignoreDeleted: NO];
storedVersion = [currentRow objectForKey: @"c_version"];
if (doLogStore)
[self logWithFormat:@" version: %@", storedVersion];
isNewRecord = [storedVersion isNotNull] ? NO : YES;
if (!isNewRecord)
{
if ([[self deletionOfContentWithName:_name] intValue] > 0)
if ([[currentRow objectForKey: @"c_deleted"] intValue] > 0)
{
[self _purgeRecordWithName: _name];
isNewRecord = YES;
}
}
/* check whether sequence matches */
if (_baseVersion != 0 /* use 0 to override check */) {
if (_baseVersion != [storedVersion unsignedIntValue]) {

View File

@ -1,3 +1,47 @@
Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m
===================================================================
--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1557)
+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail)
@@ -713,6 +713,39 @@
return ms;
}
+/* GCSEOAdaptorChannel protocol */
+static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \
+ @" c_name VARCHAR (256) NOT NULL,\n"
+ @" c_content VARCHAR (100000) NOT NULL,\n"
+ @" c_creationdate INT4 NOT NULL,\n"
+ @" c_lastmodified INT4 NOT NULL,\n"
+ @" c_version INT4 NOT NULL,\n"
+ @" c_deleted INT4 NULL\n"
+ @")");
+static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \
+ @" c_uid VARCHAR (256) NOT NULL,\n"
+ @" c_object VARCHAR (256) NOT NULL,\n"
+ @" c_role VARCHAR (80) NOT NULL\n"
+ @")");
+
+- (NSException *) createGCSFolderTableWithName: (NSString *) tableName
+{
+ NSString *sql;
+
+ sql = [NSString stringWithFormat: sqlFolderFormat, tableName];
+
+ return [self evaluateExpressionX: sql];
+}
+
+- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName
+{
+ NSString *sql;
+
+ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName];
+
+ return [self evaluateExpressionX: sql];
+}
+
@end /* PostgreSQL72Channel */
@implementation PostgreSQL72Channel(PrimaryKeyGeneration)
Index: sope-mime/NGImap4/NGImap4Connection.m
===================================================================
--- sope-mime/NGImap4/NGImap4Connection.m (révision 1557)
@ -470,11 +514,14 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
===================================================================
--- sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (révision 1557)
+++ sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m (copie de travail)
@@ -19,88 +19,30 @@
@@ -19,88 +19,45 @@
02111-1307, USA.
*/
+#ifdef HAVE_STRNDUP
+#define _GNU_SOURCE 1
+#endif
+
+#include <string.h>
+
#include "NGMimeHeaderFieldParser.h"
@ -483,6 +530,18 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
#include "common.h"
-#include <string.h>
+#ifndef HAVE_STRNDUP
+char *strndup(const char *str, size_t len)
+{
+ char *dup = (char *)malloc(len+1);
+ if (dup) {
+ strncpy(dup,str,len);
+ dup[len]= '\0';
+ }
+ return dup;
+}
+#endif
+
@implementation NGMimeRFC822DateHeaderFieldParser
-static Class CalDateClass = Nil;
@ -567,7 +626,7 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
}
/*
@@ -147,162 +89,110 @@
@@ -147,162 +104,110 @@
}
}
@ -815,7 +874,7 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
/* remove leading chars (skip to first digit, the day of the month) */
while (length > 0 && (!isdigit(*bytes))) {
bytes++;
@@ -312,7 +202,7 @@
@@ -312,7 +217,7 @@
if (length == 0) {
NSLog(@"WARNING(%s): empty value for header field %@ ..",
__PRETTY_FUNCTION__, _field);
@ -824,7 +883,7 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
}
// TODO: should be a category on NSCalendarDate
@@ -435,7 +325,7 @@
@@ -435,7 +340,7 @@
for (pe = bytes; isalnum(*pe) || *pe == '-' || *pe == '+'; pe++)
;
*pe = '\0';
@ -833,7 +892,7 @@ Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
[self logWithFormat:
@"WARNING: failed to parse RFC822 timezone: '%s' (value='%@')",
bytes, _data];
@@ -444,9 +334,9 @@
@@ -444,9 +349,9 @@
/* construct and return */
finished:
@ -897,6 +956,22 @@ Index: sope-mime/NGMime/NGMimeBodyPart.m
}
- (NSString *)contentId {
Index: sope-mime/NGMime/GNUmakefile.preamble
===================================================================
--- sope-mime/NGMime/GNUmakefile.preamble (révision 1557)
+++ sope-mime/NGMime/GNUmakefile.preamble (copie de travail)
@@ -5,6 +5,11 @@
-DLIBRARY_MINOR_VERSION=${MINOR_VERSION} \
-DLIBRARY_SUBMINOR_VERSION=${SUBMINOR_VERSION} \
+ifeq ($(patsubstr GNU/%,glibc,$(shell uname -o)),glibc)
+ADDITIONAL_CPPFLAGS += \
+ -DHAVE_STRNDUP
+endif
+
NGMime_INCLUDE_DIRS += \
-I.. -I../.. \
-I../../sope-core/NGStreams/ \
Index: sope-mime/NGMime/NGMimeBodyParser.m
===================================================================
--- sope-mime/NGMime/NGMimeBodyParser.m (révision 1557)
@ -1127,50 +1202,6 @@ Index: sope-mime/NGMime/NGMimeContentDispositionHeaderFieldGenerator.m
}
return data;
}
Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m
===================================================================
--- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (révision 1557)
+++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m (copie de travail)
@@ -713,6 +713,39 @@
return ms;
}
+/* GCSEOAdaptorChannel protocol */
+static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n" \
+ @" c_name VARCHAR (256) NOT NULL,\n"
+ @" c_content VARCHAR (100000) NOT NULL,\n"
+ @" c_creationdate INT4 NOT NULL,\n"
+ @" c_lastmodified INT4 NOT NULL,\n"
+ @" c_version INT4 NOT NULL,\n"
+ @" c_deleted INT4 NULL\n"
+ @")");
+static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n" \
+ @" c_uid VARCHAR (256) NOT NULL,\n"
+ @" c_object VARCHAR (256) NOT NULL,\n"
+ @" c_role VARCHAR (80) NOT NULL\n"
+ @")");
+
+- (NSException *) createGCSFolderTableWithName: (NSString *) tableName
+{
+ NSString *sql;
+
+ sql = [NSString stringWithFormat: sqlFolderFormat, tableName];
+
+ return [self evaluateExpressionX: sql];
+}
+
+- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName
+{
+ NSString *sql;
+
+ sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName];
+
+ return [self evaluateExpressionX: sql];
+}
+
@end /* PostgreSQL72Channel */
@implementation PostgreSQL72Channel(PrimaryKeyGeneration)
Index: sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m
===================================================================
--- sope-core/NGExtensions/FdExt.subproj/NSString+Encoding.m (révision 1557)

View File

@ -0,0 +1,292 @@
#/usr/bin/perl
# TODO:
# - partial delete: appointment tables only, contact tables only
# - stats: nb of calendars, nb of events, nb of events with
# participants, nb of recurrent events, nb of contacts, nb of
# addressbooks, nb of contacts, etc
=head1 NAME
sogo-user
=head1 SYNOPSIS
create-ldap-fburl [options] username ...
Options:
-help brief help message
-c, --config=FILE read configuration from FILE
-i, --info show information on the user
--delete delete user from SOGo databases
--fburl update Free-Busy URL in LDAP directory
-v, --verbose be verbose
=head1 DESCRIPTION
Apply various operations on a user with respect to her/his
SOGo environment.
=head1 AUTHOR
=over
=item Francis Lachapelle <flachapelle@inverse.ca>
=head1 COPYRIGHT
Copyright (c) 2007 Inverse groupe conseil
This program is available under the GPL.
=cut
#use diagnostics;
use strict;
use warnings;
use Config::IniFiles;
#use Data::Dumper;
use DBI;
use Getopt::Long qw(:config bundling);
#use Log::Log4perl;
use Net::LDAP;
use Pod::Usage;
use constant {
CONF_FILE => "sogo.conf"
};
my $help = '';
my $configfile = CONF_FILE;
my $info = '';
my $delete = '';
my $fburl = '';
my $verbose = '';
GetOptions(
"help|?" => \$help,
"config|c=s" => \$configfile,
"info|i" => \$info,
"delete" => \$delete,
"fburl" => \$fburl,
"verbose|v" => \$verbose
) or pod2usage( -verbose => 1);
pod2usage( -verbose => 2) if $help;
pod2usage( -verbose => 1) unless ($help || $info || $delete || $fburl);
pod2usage( -verbose => 1) if ($#ARGV < 0);
my $config;
my $dbh;
my $ldap;
$config = new Config::IniFiles( -file => $configfile, -nocase => 1);
die "ERROR: Can't read configuration file $configfile: $!\n" unless $config;
die "ERROR: Missing \"url\" in section [sogo]\n" unless ($config->val('sogo', 'url'));
# Verify LDAP parameters
foreach ('host', 'port', 'binddn', 'password', 'searchbase', 'uid_attr', 'mail_attr', 'fburl_attr') {
unless ($config->val('ldap', $_)) {
die "ERROR: Missing value for parameter \"$_\" in section [ldap].\n";
}
}
# Verify DB parameters
foreach ('uri', 'username', 'password') {
unless ($config->val('database', $_)) {
die "ERROR: Missing value for parameter \"$_\" in section [database].\n";
}
}
##
# Functions
sub initDatabase
{
$dbh = DBI->connect($config->val('database', 'uri'),
$config->val('database', 'username'),
$config->val('database', 'password'),
{ AutoCommit => 1, PrintError => 0 }) or die "ERROR: Can't connect to database: $DBI::errstr\n";
}
sub initLdap
{
$ldap = new Net::LDAP($config->val('ldap', 'host'))
or die "ERROR: Can't connect to ldap: $@\n";
my $msg = $ldap->bind($config->val('ldap', 'binddn'),
password => $config->val('ldap', 'password'));
if ($msg->is_error()) {
die "ERROR: Can't bind to ldap: ".$msg->error()."\n";
}
}
sub info
{
my $username = shift;
my $results;
my @entries;
my $hash_ref;
&initLdap() unless $ldap;
&initDatabase() unless $dbh;
# Fetch LDAP attributes
$results = $ldap->search(base => $config->val('ldap', 'searchbase'),
scope => 'sub',
attrs => [$config->val('ldap', 'uid_attr'),
$config->val('ldap', 'mail_attr'),
$config->val('ldap', 'fburl_attr')],
filter => sprintf('(%s=%s)', $config->val('ldap', 'uid_attr'), $username));
if ($results->is_error()) {
die "ERROR: Can't perform ldap search: ",$results->error(),"\n";
}
@entries = $results->entries;
die "ERROR: Unknown user $username\n" if ($#entries < 0);
foreach my $entry (@entries) {
print "Username: ", $entry->get_value( $config->val('ldap', 'uid_attr') ), "\n";
print "Mail: ", $entry->get_value( $config->val('ldap', 'mail_attr') ), "\n";
print "Freebusy URL: ", $entry->get_value( $config->val('ldap', 'fburl_attr') ) || "(undefined)", "\n";
}
# Retrive database tables information
$hash_ref = $dbh->selectall_hashref("select c_folder_id, c_folder_type, c_location, c_quick_location, c_acl_location from sogo_folder_info where c_path2 = ?", ($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_folder_id':'C_FOLDER_ID', undef, ($username))
or die "Can't execute select statement: $DBI::errstr\n";
print "Tables:\n";
foreach my $id (keys %{$hash_ref}) {
print "\tType ", ($hash_ref->{$id}->{'C_FOLDER_TYPE'} || $hash_ref->{$id}->{'c_folder_type'})
, ", ID ", $id, "\n";
foreach my $col ('C_LOCATION', 'C_QUICK_LOCATION', 'C_ACL_LOCATION') {
print "\t\t", ($hash_ref->{$id}->{$col} || $hash_ref->{$id}->{lc($col)}), "\n";
}
}
print "\t(no table found)\n" unless (%{$hash_ref});
}
sub delete
{
my $username = shift;
my $hash_ref;
&initDatabase() unless $dbh;
# Select entries from sogo_folder_info
$hash_ref = $dbh->selectall_hashref("select C_UID from sogo_user_profile where C_UID = ?",
($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_uid':'C_UID',
undef, ($username))
or die "ERROR: Can't execute select statement: $DBI::errstr\n";
if (%{$hash_ref}) {
# Delete entries from sogo_user_profile
$dbh->do("delete from sogo_user_profile where c_uid = ?", undef, ($username))
or die "ERROR: Can't delete entries from sogo_user_profile: $DBI::errstr\n";
}
else {
warn "No entries in sogo_user_profile\n";
}
# Select entries from sogo_folder_info
$hash_ref = $dbh->selectall_hashref("select c_folder_id, c_folder_type, c_location, c_quick_location, c_acl_location from sogo_folder_info where c_path2 = ?", ($config->val('database', 'uri') =~ /^dbi:Pg/)?'c_folder_id':'C_FOLDER_ID', undef, ($username))
or die "Can't execute select statement: $DBI::errstr\n";
if (%{$hash_ref}) {
# Delete entries from sogo_folder_info
$dbh->do("delete from sogo_folder_info where c_path2 = ?", undef, ($username))
or die "Can't delete entries from sogo_info_folder: $DBI::errstr\n";
}
else {
die "No entries in sogo_folder_info\n";
}
# Drop tables
foreach my $id (keys %{$hash_ref}) {
print "Folder ID $id, type ",($hash_ref->{$id}->{'C_FOLDER_TYPE'} || $hash_ref->{$id}->{'c_folder_type'}),"\n";
foreach my $col ('C_LOCATION', 'C_QUICK_LOCATION', 'C_ACL_LOCATION') {
$col = lc($col) unless ($hash_ref->{$id}->{$col});
if ($hash_ref->{$id}->{$col} =~ m#([^:]+)://([^:]+):([^@]+)@([^:]+):([^/]+)/([^/]+)/([^/]+)#) {
my ($type, $username, $password, $host, $port, $db, $table) = ($1, $2, $3, $4, $5, $6, $7);
my $uri;
print "Dropping ",$hash_ref->{$id}->{$col},"\n";
$uri = 'dbi:Pg:host=%s;port=%s;dbname=%s' if ($type eq 'http');
$uri = 'dbi:Oracle:host=%s;port=%s;sid=%s' if ($type eq 'oracle');
my $s = DBI->connect(sprintf($uri, $host, $port, $db), $username, $password, { AutoCommit => 1, PrintError => 0 }) or die "\tCan't connect: $!\n";
$s->do("drop table $table") or warn "\tERROR: Can't drop table $table: $DBI::errstr\n";
$s->disconnect();
}
}
}
}
sub fburl
{
my $username = shift;
my $results;
my @entries;
my $modified = '';
&initLdap() unless $ldap;
$results = $ldap->search(base => $config->val('ldap', 'searchbase'),
scope => 'sub',
attrs => ['objectClass',
$config->val('ldap', 'uid_attr'),
$config->val('ldap', 'mail_attr'),
$config->val('ldap', 'fburl_attr')],
filter => sprintf('(%s=%s)', $config->val('ldap', 'uid_attr'), $username));
if ($results->is_error()) {
die "ERROR: Can't perform ldap search: ",$results->error(),"\n";
}
@entries = $results->entries;
die "ERROR: Unknown user $username\n" if ($#entries < 0);
foreach my $entry (@entries) {
my $caldav_objectclass = $config->val('ldap', 'caldav_objectclass');
if (length($caldav_objectclass) > 0) {
# Add objectClass if not present
my @objectClasses = $entry->get_value('objectClass');
#print "classes = ", join(", ", @objectClasses), "\n";
unless (grep {/^$caldav_objectclass$/} @objectClasses) {
print "Adding objectClass ", $caldav_objectclass,"\n";
$entry->add('objectClass' => $caldav_objectclass);
$modified = 1;
}
}
# Add Freebusy URL if not present
my $fburl_attr = $config->val('ldap', 'fburl_attr');
if ($entry->get_value($fburl_attr)) {
print "Freebusy URL already defined (",$entry->get_value($fburl_attr),")\n";
}
else {
my $fburl = $config->val('sogo', 'url') . "/SOGo/dav/$username/freebusy.ifb";
print "Adding attribute ", $fburl_attr, " with value ", $fburl, "\n";
$entry->add($fburl_attr => $fburl);
$modified = 1;
}
if ($modified) {
# Perform update
my $msg = $entry->update($ldap);
if ($msg->is_error()) {
print "ERROR: Can't update entry: \n";
print $entry->dump();
print $msg->error(),"\n";
}
}
}
}
##
# Main
foreach my $username (@ARGV) {
#print $username,"\n";
&info($username) if $info;
&delete($username) if $delete;
&fburl($username) if $fburl;
}
$dbh->disconnect if $dbh;
$ldap->unbind if $ldap;

View File

@ -48,6 +48,7 @@
#import <SaxObjC/XMLNamespaces.h>
// #import <NGObjWeb/SoClassSecurityInfo.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCustomGroupFolder.h>
#import <SOGo/LDAPUserManager.h>
#import <SOGo/SOGoPermissions.h>
@ -299,8 +300,8 @@ static NSNumber *sharedYes = nil;
[r setStatus: 207];
[r setContentEncoding: NSUTF8StringEncoding];
[r setHeader: @"text/xml; charset=\"utf-8\"" forKey: @"content-type"];
[r setHeader: @"no-cache" forKey: @"pragma"];
[r setHeader: @"no-cache" forKey: @"cache-control"];
// [r setHeader: @"no-cache" forKey: @"pragma"];
// [r setHeader: @"no-cache" forKey: @"cache-control"];
[r appendContentString:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"];
[r appendContentString: @"<D:multistatus xmlns:D=\"DAV:\""
@" xmlns:C=\"urn:ietf:params:xml:ns:caldav\">\r\n"];
@ -403,6 +404,11 @@ static NSNumber *sharedYes = nil;
obj = [NSException exceptionWithHTTPStatus:404 /* Not Found */];
}
if (obj)
[[SOGoCache sharedCache] registerObject: obj
withName: _key
inContainer: container];
return obj;
}

View File

@ -126,7 +126,7 @@ static BOOL sendEMailNotifications = NO;
sm = [SoSecurityManager sharedSecurityManager];
if (![sm validatePermission: SOGoCalendarPerm_ViewAllComponent
onObject: self inContext: context])
iCalString = content;
iCalString = [record objectForKey: @"c_content"];
else if (![sm validatePermission: SOGoCalendarPerm_ViewDAndT
onObject: self inContext: context])
{
@ -165,7 +165,7 @@ static BOOL sendEMailNotifications = NO;
if (secure)
iCalString = [self secureContentAsString];
else
iCalString = content;
iCalString = [record objectForKey: @"c_content"];
if ([iCalString length] > 0)
calendar = [iCalCalendar parseSingleFromSource: iCalString];

View File

@ -48,8 +48,11 @@
- (NGVCard *) vCard
{
NSString *content;
if (!card)
{
content = [record objectForKey: @"c_content"];
if ([[content uppercaseString] hasPrefix: @"BEGIN:VCARD"])
card = [NGVCard parseSingleFromSource: content];
else

View File

@ -104,7 +104,7 @@ static NSString *AgenorShareLoginMarker = @".-.";
/* first check attributes directly bound to the application */
if ((obj = [super lookupName:_key inContext:_ctx acquire:NO]))
return obj;
if (![self isInHomeFolderBranchOfLoggedInAccount: userLogin]) {
[self warnWithFormat:@ "User %@ tried to access mail hierarchy of %@",
userLogin, [container nameInContainer]];

View File

@ -850,7 +850,7 @@ static BOOL debugSoParts = NO;
}
else
clazz = Nil;
return [clazz objectWithName:_key inContainer: self];
}

View File

@ -20,6 +20,7 @@ libSOGo_HEADER_FILES_INSTALL_DIR = /SOGo
FHS_HEADER_DIRS = SOGo
libSOGo_HEADER_FILES = \
SOGoCache.h \
SOGoObject.h \
SOGoContentObject.h \
SOGoFolder.h \
@ -56,6 +57,7 @@ libSOGo_HEADER_FILES = \
WORequest+SOGo.h
libSOGo_OBJC_FILES = \
SOGoCache.m \
SOGoObject.m \
SOGoContentObject.m \
SOGoFolder.m \

View File

@ -31,7 +31,7 @@
@interface SOGoContentObject : SOGoObject
{
NSString *ocsPath;
NSString *content;
NSDictionary *record;
BOOL isNew;
}

View File

@ -49,9 +49,9 @@
if ((self = [super initWithName: newName inContainer: newContainer]))
{
ocsPath = nil;
content = [[self ocsFolder] fetchContentWithName: newName];
[content retain];
isNew = (!content);
record = [[self ocsFolder] recordOfEntryWithName: newName];
[record retain];
isNew = (!record);
}
return self;
@ -59,19 +59,11 @@
- (void) dealloc
{
[content release];
[record release];
[ocsPath release];
[super dealloc];
}
/* notifications */
- (void) sleep
{
[content release]; content = nil;
[super sleep];
}
/* accessors */
- (BOOL) isFolderish
@ -136,19 +128,25 @@
- (NSString *) contentAsString
{
return content;
return [record objectForKey: @"c_content"];
}
- (NSException *) saveContentString: (NSString *) newContent
baseVersion: (unsigned int) newBaseVersion
{
/* Note: "iCal multifolder saves" are implemented in the apt subclass! */
GCSFolder *folder;
GCSFolder *folder;
NSException *ex;
NSMutableDictionary *newRecord;
ex = nil;
ASSIGN (content, newContent);
if (record)
newRecord = [NSMutableDictionary dictionaryWithDictionary: record];
else
newRecord = [NSMutableDictionary dictionary];
[newRecord setObject: newContent forKey: @"c_content"];
ASSIGN (record, newRecord);
folder = [container ocsFolder];
if (folder)
@ -307,7 +305,7 @@
folder = [self ocsFolder];
if (folder)
{
versionValue = [folder versionOfContentWithName: [self nameInContainer]];
versionValue = [record objectForKey: @"c_version"];
sprintf (buf, "\"gcs%08d\"", [versionValue unsignedIntValue]);
entityTag = [NSString stringWithCString: buf];
}
@ -325,7 +323,7 @@
{
NSCalendarDate *date;
date = [[self ocsFolder] creationDateOfEntryWithName: nameInContainer];
date = [record objectForKey: @"c_creationdate"];
return [date rfc822DateString];
}
@ -334,16 +332,19 @@
{
NSCalendarDate *date;
date = [[self ocsFolder] lastModificationOfEntryWithName: nameInContainer];
date = [record objectForKey: @"c_lastmodified"];
return [date rfc822DateString];
}
- (NSString *) davContentLength
{
NSString *content;
content = [record objectForKey: @"c_content"];
return [NSString stringWithFormat: @"%u",
[content
lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]];
[content lengthOfBytesUsingEncoding: NSISOLatin1StringEncoding]];
}
- (NSException *) davMoveToTargetObject: (id) _target

View File

@ -62,6 +62,7 @@
#import "NSDictionary+Utilities.h"
#import "NSString+Utilities.h"
#import "SOGoCache.h"
#import "SOGoObject.h"
@interface SOGoObject(Content)
@ -560,10 +561,19 @@ static BOOL kontactGroupDAV = YES;
acquire: (BOOL) acquire
{
id obj;
SOGoCache *cache;
obj = [[self soClass] lookupKey: lookupName inContext: localContext];
if (obj)
[obj bindToObject: self inContext: localContext];
cache = [SOGoCache sharedCache];
obj = [cache objectNamed: lookupName inContainer: self];
if (!obj)
{
obj = [[self soClass] lookupKey: lookupName inContext: localContext];
if (obj)
{
[obj bindToObject: self inContext: localContext];
[cache registerObject: obj withName: lookupName inContainer: self];
}
}
return obj;
}

View File

@ -32,10 +32,11 @@
#import "AgenorUserDefaults.h"
#import "LDAPUserManager.h"
#import "NSArray+Utilities.h"
#import "SOGoCache.h"
#import "SOGoDateFormatter.h"
#import "SOGoObject.h"
#import "SOGoPermissions.h"
#import "NSArray+Utilities.h"
#import "SOGoUser.h"
@ -124,10 +125,18 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
+ (SOGoUser *) userWithLogin: (NSString *) newLogin
roles: (NSArray *) newRoles
{
SOGoCache *cache;
SOGoUser *user;
user = [[self alloc] initWithLogin: newLogin roles: newRoles];
[user autorelease];
cache = [SOGoCache sharedCache];
user = [cache userNamed: newLogin];
if (!user)
{
user = [[self alloc] initWithLogin: newLogin roles: newRoles];
[user autorelease];
[cache registerUser: user];
}
[user setPrimaryRoles: newRoles];
return user;
}
@ -181,6 +190,11 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
[super dealloc];
}
- (void) setPrimaryRoles: (NSArray *) newRoles
{
ASSIGN (roles, newRoles);
}
- (void) setCurrentPassword: (NSString *) newPassword
{
ASSIGN (currentPassword, newPassword);

View File

@ -10,7 +10,7 @@
<!-- TODO: add iMIP actions -->
<input id="iCalendarAttachment" type="hidden"
var:value="pathToAttachmentObject"/>
var:value="pathToAttachment"/>
<var:if condition="couldParseCalendar" const:negate="1">
<fieldset>