]> err.no Git - scalable-opengroupware.org/blob - UI/MailerUI/UIxMailView.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1275 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 *) messageSubject
92 {
93   NSString *subject;
94
95   subject = [[self clientObject] decodedSubject];
96   if (![subject length])
97     subject = [self labelForKey: @"Untitled"];
98
99   return subject;
100 }
101
102 - (NSString *) panelTitle
103 {
104   return [NSString stringWithFormat: @"%@: %@",
105                    [self labelForKey: @"View Mail"],
106                    [self messageSubject]];
107 }
108
109 /* links (DUP to UIxMailPartViewer!) */
110
111 - (NSString *) linkToEnvelopeAddress: (NGImap4EnvelopeAddress *) _address
112 {
113   // TODO: make some web-link, eg open a new compose panel?
114   return [NSString stringWithFormat: @"mailto: %@", [_address baseEMail]];
115 }
116
117 - (NSString *) currentAddressLink
118 {
119   return [self linkToEnvelopeAddress:[self currentAddress]];
120 }
121
122 /* fetching */
123
124 - (id) message
125 {
126   return [[self clientObject] fetchCoreInfos];
127 }
128
129 - (BOOL) hasCC
130 {
131   return [[[self clientObject] ccEnvelopeAddresses] count] > 0 ? YES : NO;
132 }
133
134 - (BOOL) hasReplyTo
135 {
136   return [[[self clientObject] replyToEnvelopeAddresses] count] > 0 ? YES : NO;
137 }
138
139 /* viewers */
140
141 - (id) contentViewerComponent
142 {
143   // TODO: I would prefer to flatten the body structure prior rendering,
144   //       using some delegate to decide which parts to select for alternative.
145   id info;
146   
147   info = [[self clientObject] bodyStructure];
148
149   return [[context mailRenderingContext] viewerForBodyInfo:info];
150 }
151
152 /* actions */
153
154 - (id) defaultAction
155 {
156   WOResponse *response;
157   NSString *s;
158
159   /* check etag to see whether we really must rerender */
160   if (mailETag)
161     {
162       /*
163         Note: There is one thing which *can* change for an existing message,
164         those are the IMAP4 flags (and annotations, which we do not use).
165         Since we don't render the flags, it should be OK, if this changes
166         we must embed the flagging into the etag.
167       */
168       s = [[context request] headerForKey: @"if-none-match"];
169       if (s)
170         {
171           if ([s rangeOfString:mailETag].length > 0) /* not perfectly correct */
172             { 
173               /* client already has the proper entity */
174               // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag];
175               
176               if (![[self clientObject] doesMailExist]) {
177                 return [NSException exceptionWithHTTPStatus:404 /* Not Found */
178                                     reason:@"message got deleted"];
179               }
180
181               response = [context response];
182               [response setStatus: 304 /* Not Modified */];
183
184               return response;
185             }
186         }
187     }
188   
189   if (![self message]) // TODO: redirect to proper error
190     return [NSException exceptionWithHTTPStatus:404 /* Not Found */
191                         reason:@"did not find specified message!"];
192   
193   return self;
194 }
195
196 - (BOOL) isDeletableClientObject
197 {
198   return [[self clientObject] respondsToSelector: @selector (delete)];
199 }
200
201 - (BOOL) isInlineViewer
202 {
203   return NO;
204 }
205
206 - (BOOL) mailIsDraft
207 {
208   return [[self clientObject] isInDraftsFolder];
209 }
210
211 - (id) redirectToParentFolder
212 {
213   id url;
214   
215   url = [[[self clientObject] container] baseURLInContext: context];
216
217   return [self redirectToLocation: url];
218 }
219
220 /* generating response */
221
222 - (void) appendToResponse: (WOResponse *) _response
223                 inContext: (WOContext *) _ctx
224 {
225   UIxMailRenderingContext *mctx;
226
227   if (mailETag != nil)
228     [[_ctx response] setHeader:mailETag forKey:@"etag"];
229
230   mctx = [[UIxMailRenderingContext alloc] initWithViewer: self
231                                           context: _ctx];
232
233   [_ctx pushMailRenderingContext: mctx];
234   [mctx release];
235
236   [super appendToResponse: _response inContext: _ctx];
237   
238   [[_ctx popMailRenderingContext] reset];
239 }
240
241 @end /* UIxMailView */