]> err.no Git - scalable-opengroupware.org/blob - UI/MailerUI/UIxMailView.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1125 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / UI / MailerUI / UIxMailView.m
1 /*
2   Copyright (C) 2004-2005 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #import <Foundation/NSException.h>
23 #import <Foundation/NSUserDefaults.h>
24 #import <NGObjWeb/NSException+HTTP.h>
25 #import <NGObjWeb/WORequest.h>
26 #import <NGObjWeb/WOResponse.h>
27 #import <NGExtensions/NSException+misc.h>
28 #import <NGExtensions/NSString+misc.h>
29 #import <NGImap4/NGImap4Envelope.h>
30 #import <NGImap4/NGImap4EnvelopeAddress.h>
31 #import <SoObjects/Mailer/SOGoMailObject.h>
32 #import <SoObjects/Mailer/SOGoMailAccount.h>
33 #import <SoObjects/Mailer/SOGoMailFolder.h>
34 #import <SOGoUI/UIxComponent.h>
35 #import <MailPartViewers/UIxMailRenderingContext.h> // cyclic
36
37 #import "WOContext+UIxMailer.h"
38
39 @interface UIxMailView : UIxComponent
40 {
41   id currentAddress;
42 }
43
44 - (BOOL)isDeletableClientObject;
45
46 @end
47
48 @implementation UIxMailView
49
50 static NSString *mailETag = nil;
51
52 + (int)version {
53   return [super version] + 0 /* v2 */;
54 }
55
56 + (void)initialize {
57   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
58   
59   NSAssert2([super version] == 2,
60             @"invalid superclass (%@) version %i !",
61             NSStringFromClass([self superclass]), [super version]);
62   
63   if ([ud boolForKey:@"SOGoDontUseETagsForMailViewer"]) {
64     NSLog(@"Note: usage of constant etag for mailer viewer is disabled.");
65   }
66   else {
67     mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"",
68                                  UIX_MAILER_MAJOR_VERSION,
69                                  UIX_MAILER_MINOR_VERSION,
70                                  UIX_MAILER_SUBMINOR_VERSION];
71     NSLog(@"Note: using constant etag for mail viewer: '%@'", mailETag);
72   }
73 }
74
75 - (void)dealloc {
76   [super dealloc];
77 }
78
79 /* accessors */
80
81 - (void) setCurrentAddress: (id) _addr
82 {
83   currentAddress = _addr;
84 }
85
86 - (id) currentAddress
87 {
88   return currentAddress;
89 }
90
91 - (NSString *) objectTitle
92 {
93   return [[self clientObject] subject];
94 }
95
96 - (NSString *) panelTitle
97 {
98   return [NSString stringWithFormat: @"%@: %@",
99                    [self labelForKey: @"View Mail"],
100                    [self objectTitle]];
101 }
102
103 /* links (DUP to UIxMailPartViewer!) */
104
105 - (NSString *)linkToEnvelopeAddress:(NGImap4EnvelopeAddress *)_address {
106   // TODO: make some web-link, eg open a new compose panel?
107   return [@"mailto:" stringByAppendingString:[_address baseEMail]];
108 }
109
110 - (NSString *)currentAddressLink {
111   return [self linkToEnvelopeAddress:[self currentAddress]];
112 }
113
114 /* fetching */
115
116 - (id)message {
117   return [[self clientObject] fetchCoreInfos];
118 }
119
120 - (BOOL)hasCC {
121   return [[[self clientObject] ccEnvelopeAddresses] count] > 0 ? YES : NO;
122 }
123
124 /* viewers */
125
126 - (id)contentViewerComponent {
127   // TODO: I would prefer to flatten the body structure prior rendering,
128   //       using some delegate to decide which parts to select for alternative.
129   id info;
130   
131   info = [[self clientObject] bodyStructure];
132   return [[context mailRenderingContext] viewerForBodyInfo:info];
133 }
134
135 /* actions */
136
137 - (id) defaultAction
138 {
139   /* check etag to see whether we really must rerender */
140   if (mailETag != nil ) {
141     /*
142       Note: There is one thing which *can* change for an existing message,
143             those are the IMAP4 flags (and annotations, which we do not use).
144             Since we don't render the flags, it should be OK, if this changes
145             we must embed the flagging into the etag.
146     */
147     NSString *s;
148     
149     if ((s = [[context request] headerForKey:@"if-none-match"])) {
150       if ([s rangeOfString:mailETag].length > 0) { /* not perfectly correct */
151         /* client already has the proper entity */
152         // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag];
153         
154         if (![[self clientObject] doesMailExist]) {
155           return [NSException exceptionWithHTTPStatus:404 /* Not Found */
156                               reason:@"message got deleted"];
157         }
158         
159         [[context response] setStatus:304 /* Not Modified */];
160         return [context response];
161       }
162     }
163   }
164   
165   if ([self message] == nil) {
166     // TODO: redirect to proper error
167     return [NSException exceptionWithHTTPStatus:404 /* Not Found */
168                         reason:@"did not find specified message!"];
169   }
170   
171   return self;
172 }
173
174 - (BOOL)isDeletableClientObject {
175   return [[self clientObject] respondsToSelector:@selector(delete)];
176 }
177 - (BOOL)isInlineViewer {
178   return NO;
179 }
180
181 - (id)redirectToParentFolder {
182   id url;
183   
184   url = [[[self clientObject] container] baseURLInContext:context];
185   return [self redirectToLocation:url];
186 }
187
188 - (id)deleteAction {
189   NSException *ex;
190   
191   if (![self isDeletableClientObject]) {
192     return [NSException exceptionWithHTTPStatus:400 /* Bad Request */
193                         reason:@"method cannot be invoked on "
194                                @"the specified object"];
195   }
196   
197   if ([self isInvokedBySafeMethod]) {
198     // TODO: fix UI to use POST for unsafe actions
199     [self logWithFormat:@"WARNING: method is invoked using safe HTTP method!"];
200   }
201   
202   if ((ex = [[self clientObject] delete]) != nil) {
203     id url;
204     
205     url = [[ex reason] stringByEscapingURL];
206     url = [@"view?error=" stringByAppendingString:url];
207     return [self redirectToLocation:url];
208     //return ex;
209   }
210   
211   if (![self isInlineViewer]) {
212     // if everything is ok, close the window (send a JS closing the Window)
213     id page;
214     
215     page = [self pageWithName:@"UIxMailWindowCloser"];
216     [page takeValue:@"YES" forKey:@"refreshOpener"];
217     return page;
218   }
219   
220   return [self redirectToParentFolder];
221 }
222
223 - (id)trashAction {
224   NSException *ex;
225   
226   if ([self isInvokedBySafeMethod]) {
227     // TODO: fix UI to use POST for unsafe actions
228     [self logWithFormat:@"WARNING: method is invoked using safe HTTP method!"];
229   }
230   
231   if ((ex = [[self clientObject] trashInContext:context]) != nil) {
232     id url;
233     
234     if ([[[context request] formValueForKey:@"jsonly"] boolValue])
235       /* called using XMLHttpRequest */
236       return ex;
237     
238     url = [[ex reason] stringByEscapingURL];
239     url = [@"view?error=" stringByAppendingString:url];
240     return [self redirectToLocation:url];
241   }
242
243   if ([[[context request] formValueForKey:@"jsonly"] boolValue]) {
244     /* called using XMLHttpRequest */
245     [[context response] setStatus:200 /* OK */];
246     return [context response];
247   }
248   
249   if (![self isInlineViewer]) {
250     // if everything is ok, close the window (send a JS closing the Window)
251     id page;
252     
253     page = [self pageWithName:@"UIxMailWindowCloser"];
254     [page takeValue:@"YES" forKey:@"refreshOpener"];
255     return page;
256   }
257   
258   return [self redirectToParentFolder];
259 }
260
261 - (id <WOActionResults>) moveAction
262 {
263   id <WOActionResults> result;
264   NSString *destinationFolder;
265   id url;
266
267   if ([self isInvokedBySafeMethod]) {
268     // TODO: fix UI to use POST for unsafe actions
269     [self logWithFormat:@"WARNING: method is invoked using safe HTTP method!"];
270   }
271
272   destinationFolder = [self queryParameterForKey: @"tofolder"];
273   if ([destinationFolder length] > 0)
274     {
275       result = [[self clientObject] moveToFolderNamed: destinationFolder
276                                     inContext: context];
277       if (result)
278         {
279           if (![[[context request] formValueForKey:@"jsonly"] boolValue])
280             {
281               url = [NSString stringWithFormat: @"view?error=%@",
282                               [[result reason] stringByEscapingURL]];
283               result = [self redirectToLocation: url];
284             }
285         }
286       else
287         {
288           result = [context response];
289           [result setStatus: 200];
290         }
291     }
292   else
293     result = [NSException exceptionWithHTTPStatus:500 /* Server Error */
294                           reason: @"No destination folder given"];
295
296   return result;
297 }
298
299 /* generating response */
300
301 - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx {
302   UIxMailRenderingContext *mctx;
303
304   if (mailETag != nil)
305     [[_ctx response] setHeader:mailETag forKey:@"etag"];
306
307   mctx = [[NSClassFromString(@"UIxMailRenderingContext")
308                             alloc] initWithViewer:self context:_ctx];
309   [_ctx pushMailRenderingContext:mctx];
310   [mctx release];
311   
312   [super appendToResponse:_response inContext:_ctx];
313   
314   [[_ctx popMailRenderingContext] reset];
315 }
316
317 @end /* UIxMailView */