]> err.no Git - scalable-opengroupware.org/blob - SOPE/sope-patchset-r1546.diff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1229 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / SOPE / sope-patchset-r1546.diff
1 Index: sope-gdl1/PostgreSQL/PostgreSQL72Channel.m
2 ===================================================================
3 --- sope-gdl1/PostgreSQL/PostgreSQL72Channel.m  (révision 1546)
4 +++ sope-gdl1/PostgreSQL/PostgreSQL72Channel.m  (copie de travail)
5 @@ -713,6 +713,39 @@
6    return ms;
7  }
8  
9 +/* GCSEOAdaptorChannel protocol */
10 +static NSString *sqlFolderFormat = (@"CREATE TABLE %@ (\n"     \
11 +                                   @"  c_name VARCHAR (256) NOT NULL,\n"
12 +                                   @"  c_content VARCHAR (100000) NOT NULL,\n"
13 +                                   @"  c_creationdate INT4 NOT NULL,\n"
14 +                                   @"  c_lastmodified INT4 NOT NULL,\n"
15 +                                   @"  c_version INT4 NOT NULL,\n"
16 +                                   @"  c_deleted INT4 NULL\n"
17 +                                   @")");
18 +static NSString *sqlFolderACLFormat = (@"CREATE TABLE %@ (\n"  \
19 +                                      @"  c_uid VARCHAR (256) NOT NULL,\n"
20 +                                      @"  c_object VARCHAR (256) NOT NULL,\n"
21 +                                      @"  c_role VARCHAR (80) NOT NULL\n"
22 +                                      @")");
23 +
24 +- (NSException *) createGCSFolderTableWithName: (NSString *) tableName
25 +{
26 +  NSString *sql;
27 +
28 +  sql = [NSString stringWithFormat: sqlFolderFormat, tableName];
29 +
30 +  return [self evaluateExpressionX: sql];
31 +}
32 +
33 +- (NSException *) createGCSFolderACLTableWithName: (NSString *) tableName
34 +{
35 +  NSString *sql;
36 +
37 +  sql = [NSString stringWithFormat: sqlFolderACLFormat, tableName];
38 +
39 +  return [self evaluateExpressionX: sql];
40 +}
41 +
42  @end /* PostgreSQL72Channel */
43  
44  @implementation PostgreSQL72Channel(PrimaryKeyGeneration)
45 Index: sope-gdl1/Oracle8/GNUmakefile
46 ===================================================================
47 --- sope-gdl1/Oracle8/GNUmakefile       (révision 1546)
48 +++ sope-gdl1/Oracle8/GNUmakefile       (copie de travail)
49 @@ -28,15 +28,23 @@
50  SOPE_ROOT=../..
51  ORACLE_VERSION=10.2.0.3
52  #ORACLE_VERSION=11.1.0.1
53 -ADDITIONAL_INCLUDE_DIRS += -I../GDLAccess -I.. -I/usr/include/oracle/$(ORACLE_VERSION)/client
54 +ADDITIONAL_INCLUDE_DIRS += -I../../sope-core -I../../sope-core/NGExtensions -I../GDLAccess -I.. -I/usr/include/oracle/$(ORACLE_VERSION)/client
55  
56 +local_arch = $(subst 64,,$(shell uname -m))
57 +
58 +ifeq ($(local_arch),ppc)
59 +PPC_LDFLAGS=-L/opt/ibmcmp/lib -libmc++
60 +else
61 +PPC_LDFLAGS=
62 +endif
63 +
64  ifneq ($(frameworks),yes)
65 -Oracle8_BUNDLE_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -lGDLAccess -lEOControl
66 -otest_TOOL_LIBS   += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -lGDLAccess -lEOControl
67 +common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -L../GDLAccess/obj -lGDLAccess -L../../sope-core/EOControl/obj -lEOControl $(PPC_LDFLAGS)
68  else
69 -Oracle8_BUNDLE_LIBS += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl
70 -otest_TOOL_LIBS   += -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl
71 +common_LIBS = -L/usr/lib/oracle/$(ORACLE_VERSION)/client/lib/ -locci -lociei -lclntsh -lnnz10 -framework GDLAccess -framework EOControl $(PPC_LDFLAGS)
72  endif
73 +Oracle8_BUNDLE_LIBS += $(common_LIBS)
74 +otest_TOOL_LIBS   += $(common_LIBS)
75  
76  # Bundle
77  BUNDLE_NAME = Oracle8
78 Index: sope-gdl1/Oracle8/OracleAdaptorChannel.m
79 ===================================================================
80 --- sope-gdl1/Oracle8/OracleAdaptorChannel.m    (révision 1546)
81 +++ sope-gdl1/Oracle8/OracleAdaptorChannel.m    (copie de travail)
82 @@ -53,14 +53,17 @@
83    while (c--)
84      {
85        info = [[_row_buffer objectAtIndex: c] pointerValue];
86 -      [_row_buffer removeObjectAtIndex: c];
87  
88        // We free our LOB object. If it fails, it likely mean it isn't a LOB
89        // so we just free the value instead.
90 -      if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS)
91 -       {
92 -         free(info->value);
93 -       }
94 +      if (info->value)
95 +       {
96 +         if (OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB) != OCI_SUCCESS)
97 +           free(info->value);
98 +         info->value = NULL;
99 +       }
100 +      free(info);
101 +      [_row_buffer removeObjectAtIndex: c];
102      }
103  
104    OCIHandleFree(_current_stm, OCI_HTYPE_STMT);
105 @@ -75,6 +78,30 @@
106  //
107  @implementation OracleAdaptorChannel
108  
109 +static void
110 +DBTerminate()
111 +{
112 +  if (OCITerminate(OCI_DEFAULT))
113 +    NSLog(@"FAILED: OCITerminate()");
114 +  else
115 +    NSLog(@"Oracle8: environment shut down");
116 +}
117 +
118 ++ (void) initialize
119 +{
120 +  // We Initialize the OCI process environment.
121 +  if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0,
122 +                    (dvoid * (*)(dvoid *, size_t)) 0,
123 +                    (dvoid * (*)(dvoid *, dvoid *, size_t))0,
124 +                    (void (*)(dvoid *, dvoid *)) 0 ))
125 +    NSLog(@"FAILED: OCIInitialize()");
126 +  else
127 +    {
128 +      NSLog(@"Oracle8: environment initialized");
129 +      atexit(DBTerminate);
130 +    }
131 +}
132 +
133  - (id) initWithAdaptorContext: (EOAdaptorContext *) theAdaptorContext
134  {
135    if ((self = [super initWithAdaptorContext: theAdaptorContext]))
136 @@ -134,10 +161,14 @@
137           NSLog(@"FAILED: OCILogoff()");
138         }
139  
140 -      if (OCITerminate(OCI_DEFAULT))
141 -       {
142 -         NSLog(@"FAILED: OCITerminate()");
143 -       }
144 +
145 +      OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX);
146 +      OCIHandleFree(_oci_err, OCI_HTYPE_ERROR);
147 +      OCIHandleFree(_oci_env, OCI_HTYPE_ENV);
148 +
149 +      _oci_ctx = (OCISvcCtx *)0;
150 +      _oci_err = (OCIError *)0;
151 +      _oci_env = (OCIEnv *)0;
152      }
153  }
154  
155 @@ -151,11 +182,6 @@
156    [self _cleanup];
157  
158    RELEASE(_resultSetProperties);
159 -
160 -  OCIHandleFree(_oci_ctx, OCI_HTYPE_SVCCTX);
161 -  OCIHandleFree(_oci_err, OCI_HTYPE_ERROR);
162 -  OCIHandleFree(_oci_env, OCI_HTYPE_ENV);
163 -
164    RELEASE(delegate);
165  
166    [super dealloc];
167 @@ -368,15 +394,6 @@
168        return NO;
169      }
170  
171 -  // We Initialize the OCI process environment.
172 -  if (OCIInitialize((ub4)OCI_DEFAULT, (dvoid *)0,
173 -                    (dvoid * (*)(dvoid *, size_t)) 0,
174 -                    (dvoid * (*)(dvoid *, dvoid *, size_t))0,
175 -                    (void (*)(dvoid *, dvoid *)) 0 ))
176 -    {
177 -      NSLog(@"FAILED: OCIInitialize()");
178 -      return NO;
179 -    }
180    
181    if (OCIEnvInit((OCIEnv **)&_oci_env, (ub4)OCI_DEFAULT, (size_t)0, (dvoid **)0))
182      {
183 Index: sope-gdl1/Oracle8/OracleAdaptorChannelController.m
184 ===================================================================
185 --- sope-gdl1/Oracle8/OracleAdaptorChannelController.m  (révision 1546)
186 +++ sope-gdl1/Oracle8/OracleAdaptorChannelController.m  (copie de travail)
187 @@ -155,7 +155,9 @@
188           OCILobFreeTemporary([theChannel serviceContext], [theChannel errorHandle], info->value);
189           OCIDescriptorFree((dvoid *)info->value, (ub4)OCI_DTYPE_LOB);
190         }
191 +      free(info);
192      }
193 +  [theColumns release];
194  
195    OCIHandleFree(theStatement, OCI_HTYPE_STMT);
196  }
197 Index: sope-mime/NGImap4/NGImap4Connection.m
198 ===================================================================
199 --- sope-mime/NGImap4/NGImap4Connection.m       (révision 1546)
200 +++ sope-mime/NGImap4/NGImap4Connection.m       (copie de travail)
201 @@ -381,7 +381,7 @@
202    
203    if (debugCache) [self logWithFormat:@"  no folders cached yet .."];
204    
205 -  result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"*")
206 +  result = [[self client] list:(onlyFetchInbox ? @"INBOX" : @"")
207                           pattern:@"*"];
208    if (![[result valueForKey:@"result"] boolValue]) {
209      [self errorWithFormat:@"Could not list mailbox hierarchy!"];
210 Index: sope-mime/NGImap4/NGImap4ResponseNormalizer.m
211 ===================================================================
212 --- sope-mime/NGImap4/NGImap4ResponseNormalizer.m       (révision 1546)
213 +++ sope-mime/NGImap4/NGImap4ResponseNormalizer.m       (copie de travail)
214 @@ -648,14 +648,13 @@
215    enumerator = [_flags objectEnumerator];
216    cnt = 0;
217    while ((obj = [enumerator nextObject])) {
218 -    if (![obj isNotEmpty])
219 -      continue;
220 -    
221 -    if (![[obj substringToIndex:1] isEqualToString:@"\\"])
222 -      continue;
223 -
224 -    objs[cnt] = [obj substringFromIndex:1];
225 -    cnt++;
226 +    if ([obj isNotEmpty]) {
227 +      if ([obj hasPrefix:@"\\"])
228 +       objs[cnt] = [obj substringFromIndex:1];
229 +      else
230 +       objs[cnt] = obj;
231 +      cnt++;
232 +    }
233    }
234    result = [NSArray arrayWithObjects:objs count:cnt];
235    if (objs) free(objs);
236 Index: sope-mime/NGImap4/NGImap4ResponseParser.m
237 ===================================================================
238 --- sope-mime/NGImap4/NGImap4ResponseParser.m   (révision 1546)
239 +++ sope-mime/NGImap4/NGImap4ResponseParser.m   (copie de travail)
240 @@ -84,6 +84,8 @@
241  static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self,
242                                          BOOL isBodyStructure);
243  
244 +static NSArray *_parseLanguages();
245 +
246  static NSString *_parseBodyString(NGImap4ResponseParser *self,
247                                    BOOL _convertString);
248  static NSString *_parseBodyDecodeString(NGImap4ResponseParser *self,
249 @@ -111,6 +113,7 @@
250  static NSNumber *_parseUnsigned(NGImap4ResponseParser *self);
251  static NSString *_parseUntil(NGImap4ResponseParser *self, char _c);
252  static NSString *_parseUntil2(NGImap4ResponseParser *self, char _c1, char _c2);
253 +static BOOL _endsWithCQuote(NSString *_string);
254  
255  static __inline__ NSException *_consumeIfMatch
256    (NGImap4ResponseParser *self, unsigned char _m);
257 @@ -649,12 +652,31 @@
258  }
259  
260  - (NSString *)_parseQuotedString {
261 +  NSMutableString *quotedString;
262 +  NSString *tmpString;
263 +  BOOL stop;
264 +
265    /* parse a quoted string, eg '"' */
266    if (_la(self, 0) == '"') {
267      _consume(self, 1);
268 -    return _parseUntil(self, '"');
269 +    quotedString = [NSMutableString string];
270 +    stop = NO;
271 +    while (!stop) {
272 +      tmpString = _parseUntil(self, '"');
273 +      [quotedString appendString: tmpString];
274 +      if(_endsWithCQuote(tmpString)) {
275 +       [quotedString deleteSuffix: @"\\"];
276 +       [quotedString appendString: @"\""];
277 +      }
278 +      else {
279 +       stop = YES;
280 +      }
281 +    }
282    }
283 -  return nil;
284 +  else {
285 +    quotedString = nil;
286 +  }
287 +  return quotedString;
288  }
289  - (void)_consumeOptionalSpace {
290    if (_la(self, 0) == ' ') _consume(self, 1);
291 @@ -1185,7 +1207,7 @@
292    route   = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
293    mailbox = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
294    host    = [self _parseQuotedStringOrNIL]; [self _consumeOptionalSpace];
295 -  
296 +
297    if (_la(self, 0) != ')') {
298      [self logWithFormat:@"WARNING: IMAP4 envelope "
299             @"address not properly closed (c0=%c,c1=%c): %@",
300 @@ -1197,6 +1219,7 @@
301    address = [[NGImap4EnvelopeAddress alloc] initWithPersonalName:pname
302                                             sourceRoute:route mailbox:mailbox
303                                             host:host];
304 +
305    return address;
306  }
307  
308 @@ -1627,6 +1650,29 @@
309    return _parseBodyDecodeString(self, _convertString, NO /* no decode */);
310  }
311  
312 +static NSArray *_parseLanguages(NGImap4ResponseParser *self) {
313 +  NSMutableArray *languages;
314 +  NSString *language;
315 +
316 +  languages = [NSMutableArray array];
317 +  if (_la(self, 0) == '(') {
318 +    while (_la(self, 0) != ')') {
319 +      _consume(self,1);
320 +      language = _parseBodyString(self, YES);
321 +      if ([language length])
322 +       [languages addObject: language];
323 +    }
324 +    _consume(self,1);
325 +  }
326 +  else {
327 +    language = _parseBodyString(self, YES);
328 +    if ([language length])
329 +      [languages addObject: language];
330 +  }
331 +
332 +  return languages;
333 +}
334 +
335  static NSDictionary *_parseBodyParameterList(NGImap4ResponseParser *self)
336  {
337    NSMutableDictionary *list;
338 @@ -1734,10 +1780,11 @@
339                       *encoding, *bodysize;
340    NSDictionary        *parameterList;
341    NSMutableDictionary *dict;
342 +  NSArray            *languages;
343  
344    type = [_parseBodyString(self, YES) lowercaseString];
345    _consumeIfMatch(self, ' ');
346 -  subtype = _parseBodyString(self, YES);
347 +  subtype = [_parseBodyString(self, YES) lowercaseString];
348    _consumeIfMatch(self, ' ');
349    parameterList = _parseBodyParameterList(self);
350    _consumeIfMatch(self, ' ');
351 @@ -1762,7 +1809,8 @@
352      _consumeIfMatch(self, ' ');
353      [dict setObject:_parseBodyString(self, YES) forKey:@"lines"];
354    }
355 -  else if ([type isEqualToString:@"message"]) {
356 +  else if ([type isEqualToString:@"message"]
357 +          && [subtype isEqualToString:@"rfc822"]) {
358      if (_la(self, 0) != ')') {
359        _consumeIfMatch(self, ' ');
360        _consumeIfMatch(self, '(');
361 @@ -1805,14 +1853,9 @@
362               forKey: @"disposition"];
363         if (_la(self, 0) != ')') {
364           _consume(self,1);
365 -         if (_la(self, 0) == '(') {
366 -           [dict setObject: _parseBodyParameterList(self)
367 -                 forKey: @"language"];
368 -         }
369 -         else {
370 -           [dict setObject: _parseBodyString(self, YES)
371 -                 forKey: @"language"];
372 -         }
373 +         languages = _parseLanguages(self);
374 +         if ([languages count])
375 +           [dict setObject: languages forKey: @"languages"];
376           if (_la(self, 0) != ')') {
377             _consume(self,1);
378             [dict setObject: _parseBodyString(self, YES)
379 @@ -1829,6 +1872,7 @@
380  static NSDictionary *_parseMultipartBody(NGImap4ResponseParser *self,
381                                          BOOL isBodyStructure) {
382    NSMutableArray *parts;
383 +  NSArray       *languages;
384    NSString       *kind;
385    NSMutableDictionary *dict;
386  
387 @@ -1854,14 +1898,9 @@
388               forKey: @"disposition"];
389         if (_la(self, 0) != ')') {
390           _consume(self,1);
391 -         if (_la(self, 0) == '(') {
392 -           [dict setObject: _parseBodyParameterList(self)
393 -                 forKey: @"language"];
394 -         }
395 -         else {
396 -           [dict setObject: _parseBodyString(self, YES)
397 -                 forKey: @"language"];
398 -         }
399 +         languages = _parseLanguages(self);
400 +         if ([languages count])
401 +           [dict setObject: languages forKey: @"languages"];
402           if (_la(self, 0) != ')') {
403             _consume(self,1);
404             [dict setObject: _parseBodyString(self, YES)
405 @@ -2170,6 +2209,21 @@
406    }
407  }
408  
409 +static BOOL _endsWithCQuote(NSString *_string){
410 +  unsigned int quoteSlashes;
411 +  int pos;
412 +
413 +  quoteSlashes = 0;
414 +  pos = [_string length] - 1;
415 +  while (pos > -1
416 +        && [_string characterAtIndex: pos] == '\\') {
417 +    quoteSlashes++;
418 +    pos--;
419 +  }
420 +
421 +  return ((quoteSlashes % 2) == 1);
422 +}
423 +
424  - (NSException *)exceptionForFailedMatch:(unsigned char)_match
425    got:(unsigned char)_avail
426  {
427 Index: sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m
428 ===================================================================
429 --- sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m        (révision 1546)
430 +++ sope-mime/NGMime/NGMimeRFC822DateHeaderFieldParser.m        (copie de travail)
431 @@ -285,24 +285,16 @@
432  - (id)parseValue:(id)_data ofHeaderField:(NSString *)_field {
433    // TODO: use UNICODE
434    NSCalendarDate *date       = nil;
435 -  unsigned char  buf[256];
436 -  unsigned char  *bytes = buf, *pe;
437 +  unsigned char  *bytes, *pe;
438    unsigned       length = 0;
439    NSTimeZone     *tz = nil;
440    char  dayOfMonth, monthOfYear, hour, minute, second;
441    short year;
442    BOOL  flag;
443 -  
444 -  if ((length = [_data cStringLength]) > 254) {
445 -    [self logWithFormat:
446 -           @"header field value to large for date parsing: '%@'(%i)",
447 -           _data, length];
448 -    length = 254;
449 -  }
450 -  
451 -  [_data getCString:(char *)buf maxLength:length];
452 -  buf[length] = '\0';
453 -  
454 +
455 +  length = [_data length];
456 +  bytes = [_data cStringUsingEncoding: NSASCIIStringEncoding];
457 +
458    /* remove leading chars (skip to first digit, the day of the month) */
459    while (length > 0 && (!isdigit(*bytes))) {
460      bytes++;
461 Index: sope-mime/NGMime/NGMimeBodyPart.m
462 ===================================================================
463 --- sope-mime/NGMime/NGMimeBodyPart.m   (révision 1546)
464 +++ sope-mime/NGMime/NGMimeBodyPart.m   (copie de travail)
465 @@ -31,18 +31,6 @@
466    return 2;
467  }
468  
469 -static NGMimeType *defaultType = nil;
470 -
471 -+ (void)initialize {
472 -  static BOOL isInitialized = NO;
473 -  if (!isInitialized) {
474 -    isInitialized = YES;
475 -    
476 -    defaultType =
477 -      [[NGMimeType mimeType:@"text/plain; charset=us-ascii"] retain];
478 -  }
479 -}
480 -  
481  + (id)bodyPartWithHeader:(NGHashMap *)_header {
482    return [[[self alloc] initWithHeader:_header] autorelease];
483  }
484 @@ -156,13 +144,12 @@
485    if (!Fields)
486      Fields = (NGMimeHeaderNames *)[NGMimePartParser headerFieldNames];
487    
488 -  
489    type = [self->header objectForKey:Fields->contentType];
490    
491    if (![type isKindOfClass:[NGMimeType class]])
492      type = [NGMimeType mimeType:[type stringValue]];
493    
494 -  return (type != nil ? type : (id)defaultType);
495 +  return type;
496  }
497  
498  - (NSString *)contentId {
499 Index: sope-mime/NGMime/NGMimeBodyParser.m
500 ===================================================================
501 --- sope-mime/NGMime/NGMimeBodyParser.m (révision 1546)
502 +++ sope-mime/NGMime/NGMimeBodyParser.m (copie de travail)
503 @@ -67,7 +67,10 @@
504    if (_data == nil) return nil;
505    
506    ctype = [_part contentType];
507 -  
508 +  if (!ctype
509 +      && [_d respondsToSelector: @selector(parser:contentTypeOfPart:)])
510 +    ctype = [_d parser: self contentTypeOfPart: _part];
511 +
512    if (![ctype isKindOfClass:[NGMimeType class]])
513      ctype = [NGMimeType mimeType:[ctype stringValue]];
514    
515 Index: sope-mime/NGMime/NGMimePartParser.h
516 ===================================================================
517 --- sope-mime/NGMime/NGMimePartParser.h (révision 1546)
518 +++ sope-mime/NGMime/NGMimePartParser.h (copie de travail)
519 @@ -117,6 +117,7 @@
520      BOOL parserParseRawBodyDataOfPart:1;
521      BOOL parserBodyParserForPart:1;
522      BOOL parserDecodeBodyOfPart:1;
523 +    BOOL parserContentTypeOfPart:1;
524    } delegateRespondsTo;
525  
526    
527 @@ -275,6 +276,9 @@
528  - (id<NGMimeBodyParser>)parser:(NGMimePartParser *)_parser
529    bodyParserForPart:(id<NGMimePart>)_part;
530  
531 +- (NGMimeType *)parser:(id)_parser
532 +  contentTypeOfPart:(id<NGMimePart>)_part;
533 +
534  @end /* NSObject(NGMimePartParserDelegate) */
535  
536  @interface NSObject(NGMimePartParser)
537 Index: sope-mime/NGMime/NGMimePartParser.m
538 ===================================================================
539 --- sope-mime/NGMime/NGMimePartParser.m (révision 1546)
540 +++ sope-mime/NGMime/NGMimePartParser.m (copie de travail)
541 @@ -1091,7 +1091,10 @@
542    id<NGMimeBodyParser> bodyParser   = nil;
543    
544    ctype = [_p contentType];
545 -  
546 +  if (!ctype
547 +      && self->delegateRespondsTo.parserContentTypeOfPart)
548 +    ctype = [self->delegate parser: self contentTypeOfPart: _p];
549 +
550    contentType = ([ctype isKindOfClass:[NGMimeType class]])
551      ? ctype
552      : [NGMimeType mimeType:[ctype stringValue]];
553 Index: sope-appserver/NGObjWeb/GNUmakefile.postamble
554 ===================================================================
555 --- sope-appserver/NGObjWeb/GNUmakefile.postamble       (révision 1546)
556 +++ sope-appserver/NGObjWeb/GNUmakefile.postamble       (copie de travail)
557 @@ -23,14 +23,20 @@
558  
559  # install makefiles
560  
561 -after-install ::
562 +after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make
563 +
564 +ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0)
565 +after-install :: $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make
566 +endif
567 +
568 +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make: ngobjweb.make
569         $(MKDIRS) $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/
570         $(INSTALL_DATA) ngobjweb.make $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/Additional/ngobjweb.make
571  
572 -ifneq ($(GNUSTEP_MAKE_VERSION),1.3.0)
573 -after-install ::
574 +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make: woapp-gs.make
575         $(INSTALL_DATA) woapp-gs.make    \
576                 $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/woapp.make
577 +
578 +$(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make: wobundle-gs.make
579         $(INSTALL_DATA) wobundle-gs.make \
580                 $(INSTALL_ROOT_DIR)/$(GNUSTEP_MAKEFILES)/wobundle.make
581 -endif
582 Index: sope-appserver/NGObjWeb/WOContext.m
583 ===================================================================
584 --- sope-appserver/NGObjWeb/WOContext.m (révision 1546)
585 +++ sope-appserver/NGObjWeb/WOContext.m (copie de travail)
586 @@ -64,11 +64,13 @@
587  static BOOL     testNSURLs           = NO;
588  static BOOL     newCURLStyle         = NO;
589  static NSString *WOApplicationSuffix = nil;
590 +static NSURL    *redirectURL         = nil;
591  
592  + (void)initialize {
593    static BOOL    didInit = NO;
594    NSUserDefaults *ud;
595    NSString       *cn;
596 +  NSString       *url;
597  
598    if (didInit) return;
599  
600 @@ -91,6 +93,9 @@
601    debugCursor         = [ud boolForKey:@"WODebugCursor"] ? 1 : 0;
602    debugComponentAwake = [ud boolForKey:@"WODebugComponentAwake"];
603    WOApplicationSuffix = [[ud stringForKey:@"WOApplicationSuffix"] copy];
604 +  url                 = [ud stringForKey:@"WOApplicationRedirectURL"];
605 +  if (url != nil)
606 +    redirectURL       = [NSURL URLWithString: url];
607  }
608  
609  + (id)contextWithRequest:(WORequest *)_r {
610 @@ -503,6 +508,11 @@
611      return nil;
612    }
613    
614 +  if (redirectURL) {
615 +    // Use URL from user defaults (WOApplicationRedirectURL)
616 +    return redirectURL;
617 +  }
618 +  
619    if ((serverURL = [rq headerForKey:@"x-webobjects-server-url"]) == nil) {
620      if ((host = [rq headerForKey:@"host"]))
621        serverURL = [@"http://" stringByAppendingString:host];
622 Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m
623 ===================================================================
624 --- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m   (révision 1546)
625 +++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.m   (copie de travail)
626 @@ -216,6 +216,12 @@
627        assocCount++;
628      }
629    }
630 +  if (count > 0) {
631 +    if ((self->isAbsolute = OWGetProperty(_config, @"absolute"))) {
632 +      count--;
633 +      assocCount++;
634 +    }
635 +  }
636    
637    self->rest = _config;
638    
639 Index: sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m
640 ===================================================================
641 --- sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m       (révision 1546)
642 +++ sope-appserver/NGObjWeb/DynamicElements/_WOComplexHyperlink.m       (copie de travail)
643 @@ -40,6 +40,7 @@
644    WOAssociation *string;
645    WOAssociation *target;
646    WOAssociation *disabled;
647 +  WOAssociation *isAbsolute;
648    WOElement     *template;
649    
650    /* new in WO4: */
651 @@ -359,6 +360,7 @@
652  {
653    if ((self = [super initWithName:_name hyperlinkInfo:_info template:_t])) {
654      self->href = _info->href;
655 +    self->isAbsolute = _info->isAbsolute;
656    }
657    return self;
658  }
659 @@ -374,6 +376,9 @@
660    // TODO: we need a binding to disable rewriting!
661    NSRange  r;
662    
663 +  if ([[self->isAbsolute valueInContext:_ctx] boolValue] == YES)
664 +    return NO;
665 +
666    r = [_s rangeOfString:@":"];
667    if (r.length == 0) 
668      return YES;
669 Index: sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h
670 ===================================================================
671 --- sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h   (révision 1546)
672 +++ sope-appserver/NGObjWeb/DynamicElements/WOHyperlinkInfo.h   (copie de travail)
673 @@ -41,7 +41,8 @@
674    WOAssociation *pageName;
675    WOAssociation *actionClass;
676    WOAssociation *directActionName;
677 -  
678 +  WOAssociation *isAbsolute;
679 +
680    BOOL          sidInUrl;
681  
682    /* 'ivar' associations */
683 Index: sope-appserver/NGObjWeb/SoObjects/SoObject.m
684 ===================================================================
685 --- sope-appserver/NGObjWeb/SoObjects/SoObject.m        (révision 1546)
686 +++ sope-appserver/NGObjWeb/SoObjects/SoObject.m        (copie de travail)
687 @@ -39,22 +39,34 @@
688  static int debugLookup  = -1;
689  static int debugBaseURL = -1;
690  static int useRelativeURLs = -1;
691 +static int redirectInitted = -1;
692 +static NSURL *redirectURL = nil;
693 +
694  static void _initialize(void) {
695 +  NSString *url;
696 +  NSUserDefaults *ud;
697 +
698 +  ud = [NSUserDefaults standardUserDefaults];
699 +
700    if (debugLookup == -1) {
701 -    debugLookup = [[NSUserDefaults standardUserDefaults]
702 -                                  boolForKey:@"SoDebugKeyLookup"] ? 1 : 0;
703 +    debugLookup = [ud boolForKey:@"SoDebugKeyLookup"] ? 1 : 0;
704      NSLog(@"Note(SoObject): SoDebugKeyLookup is enabled!");
705    }
706    if (debugBaseURL == -1) {
707 -    debugBaseURL = [[NSUserDefaults standardUserDefaults]
708 -                                    boolForKey:@"SoDebugBaseURL"] ? 1 : 0;
709 +    debugBaseURL = [ud boolForKey:@"SoDebugBaseURL"] ? 1 : 0;
710      NSLog(@"Note(SoObject): SoDebugBaseURL is enabled!");
711    }
712    if (useRelativeURLs == -1) {
713 -    useRelativeURLs = [[NSUserDefaults standardUserDefaults]
714 -                                      boolForKey:@"WOUseRelativeURLs"] ?1:0;
715 +    useRelativeURLs = [ud boolForKey:@"WOUseRelativeURLs"] ?1:0;
716      NSLog(@"Note(SoObject): relative base URLs are enabled.");
717    }
718 +  if (redirectInitted == -1) {
719 +    url = [ud stringForKey:@"WOApplicationRedirectURL"];
720 +    if ([url length]) {
721 +      redirectURL = [[NSURL alloc] initWithString: url];
722 +    }
723 +    redirectInitted = 1;
724 +  }
725  }
726  
727  /* classes */
728 @@ -318,56 +330,61 @@
729    
730    rq = [_ctx request];
731    ms = [[NSMutableString alloc] initWithCapacity:128];
732 +
733 +  if (redirectURL) {
734 +    [ms appendString: [redirectURL absoluteString]];
735 +  }
736 +  else {  
737 +    if (!useRelativeURLs) {
738 +      port = [[rq headerForKey:@"x-webobjects-server-port"] intValue];
739    
740 -  if (!useRelativeURLs) {
741 -    port = [[rq headerForKey:@"x-webobjects-server-port"] intValue];
742 -  
743 -    /* this is actually a bug in Apache */
744 -    if (port == 0) {
745 -      static BOOL didWarn = NO;
746 -      if (!didWarn) {
747 -       [self warnWithFormat:@"(%s:%i): got an empty port from Apache!",
748 -              __PRETTY_FUNCTION__, __LINE__];
749 -       didWarn = YES;
750 +      /* this is actually a bug in Apache */
751 +      if (port == 0) {
752 +       static BOOL didWarn = NO;
753 +       if (!didWarn) {
754 +         [self warnWithFormat:@"(%s:%i): got an empty port from Apache!",
755 +               __PRETTY_FUNCTION__, __LINE__];
756 +         didWarn = YES;
757 +       }
758 +       port = 80;
759        }
760 -      port = 80;
761 -    }
762    
763 -    if ((tmp = [rq headerForKey:@"host"]) != nil) { 
764 -      /* check whether we have a host header with port */
765 -      if ([tmp rangeOfString:@":"].length == 0)
766 -       tmp = nil;
767 -    }
768 -    if (tmp != nil) { /* we have a host header with port */
769 -      isHTTPS = 
770 -       [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"];
771 -      [ms appendString:isHTTPS ? @"https://" : @"http://"]; 
772 -      [ms appendString:tmp];
773 -    }
774 -    else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) {
775 -      /* sometimes the URL is just wrong! (suggests port 80) */
776 -      if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad
777 -       [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'",
778 -             __PRETTY_FUNCTION__, tmp];
779 -       tmp = [tmp substringToIndex:([tmp length] - 2)];
780 +      if ((tmp = [rq headerForKey:@"host"]) != nil) { 
781 +       /* check whether we have a host header with port */
782 +       if ([tmp rangeOfString:@":"].length == 0)
783 +         tmp = nil;
784        }
785 -      else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) {
786 -       /* see OGo bug #1435, Debian Apache hack */
787 -       [self warnWithFormat:@"%s: got 'http' protocol but 443 port, "
788 -             @"assuming Debian/Apache bug (OGo #1435): '%@'",
789 -             __PRETTY_FUNCTION__, tmp];
790 -       tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)];
791 -       tmp = [@"https" stringByAppendingString:tmp];
792 +      if (tmp != nil) { /* we have a host header with port */
793 +       isHTTPS = 
794 +         [[rq headerForKey:@"x-webobjects-server-url"] hasPrefix:@"https"];
795 +       [ms appendString:isHTTPS ? @"https://" : @"http://"]; 
796 +       [ms appendString:tmp];
797        }
798 -      [ms appendString:tmp];
799 -    }
800 -    else {
801 -      // TODO: isHTTPS always no in this case?
802 -      [ms appendString:isHTTPS ? @"https://" : @"http://"]; 
803 +      else if ((tmp = [rq headerForKey:@"x-webobjects-server-url"]) != nil) {
804 +       /* sometimes the URL is just wrong! (suggests port 80) */
805 +       if ([tmp hasSuffix:@":0"] && [tmp length] > 2) { // TODO: bad bad bad
806 +         [self warnWithFormat:@"%s: got incorrect URL from Apache: '%@'",
807 +               __PRETTY_FUNCTION__, tmp];
808 +         tmp = [tmp substringToIndex:([tmp length] - 2)];
809 +       }
810 +       else if ([tmp hasSuffix:@":443"] && [tmp hasPrefix:@"http://"]) {
811 +         /* see OGo bug #1435, Debian Apache hack */
812 +         [self warnWithFormat:@"%s: got 'http' protocol but 443 port, "
813 +               @"assuming Debian/Apache bug (OGo #1435): '%@'",
814 +               __PRETTY_FUNCTION__, tmp];
815 +         tmp = [tmp substringWithRange:NSMakeRange(4, [tmp length] - 4 - 4)];
816 +         tmp = [@"https" stringByAppendingString:tmp];
817 +       }
818 +       [ms appendString:tmp];
819 +      }
820 +      else {
821 +       // TODO: isHTTPS always no in this case?
822 +       [ms appendString:isHTTPS ? @"https://" : @"http://"]; 
823    
824 -      [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]];
825 -      if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0)
826 -       [ms appendFormat:@":%i", port];
827 +       [ms appendString:[rq headerForKey:@"x-webobjects-server-name"]];
828 +       if ((isHTTPS ? (port != 443) : (port != 80)) && port != 0)
829 +         [ms appendFormat:@":%i", port];
830 +      }
831      }
832    }
833    
834 Index: sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m
835 ===================================================================
836 --- sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m   (révision 1546)
837 +++ sope-appserver/NGObjWeb/WOHttpAdaptor/WOHttpTransaction.m   (copie de travail)
838 @@ -31,6 +31,7 @@
839  #include <NGObjWeb/WOCookie.h>
840  #include <NGExtensions/NSData+gzip.h>
841  #include <NGHttp/NGHttp.h>
842 +#include <NGMime/NGMimeType.h>
843  #include "common.h"
844  
845  #include <string.h>
846 @@ -1016,6 +1017,12 @@
847  - (void)parser:(NGMimePartParser *)_parser didParseHeader:(NGHashMap *)_header {
848  }
849  
850 +- (NGMimeType *)parser:(id)_parser
851 +  contentTypeOfPart:(id<NGMimePart>)_part
852 +{
853 +  return [NGMimeType mimeType: @"text/plain; charset=utf-8"];
854 +}
855 +
856  @end /* WOHttpAdaptor */
857  
858  @implementation WOCoreApplication(SimpleParserSelection)