]> err.no Git - scalable-opengroupware.org/blob - UI/MailerUI/UIxMailView.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1238 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 /* viewers */
135
136 - (id) contentViewerComponent
137 {
138   // TODO: I would prefer to flatten the body structure prior rendering,
139   //       using some delegate to decide which parts to select for alternative.
140   id info;
141   
142   info = [[self clientObject] bodyStructure];
143
144   return [[context mailRenderingContext] viewerForBodyInfo:info];
145 }
146
147 /* actions */
148
149 - (id) defaultAction
150 {
151   WOResponse *response;
152   NSString *s;
153
154   /* check etag to see whether we really must rerender */
155   if (mailETag)
156     {
157       /*
158         Note: There is one thing which *can* change for an existing message,
159         those are the IMAP4 flags (and annotations, which we do not use).
160         Since we don't render the flags, it should be OK, if this changes
161         we must embed the flagging into the etag.
162       */
163       s = [[context request] headerForKey: @"if-none-match"];
164       if (s)
165         {
166           if ([s rangeOfString:mailETag].length > 0) /* not perfectly correct */
167             { 
168               /* client already has the proper entity */
169               // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag];
170               
171               if (![[self clientObject] doesMailExist]) {
172                 return [NSException exceptionWithHTTPStatus:404 /* Not Found */
173                                     reason:@"message got deleted"];
174               }
175
176               response = [context response];
177               [response setStatus: 304 /* Not Modified */];
178
179               return response;
180             }
181         }
182     }
183   
184   if (![self message]) // TODO: redirect to proper error
185     return [NSException exceptionWithHTTPStatus:404 /* Not Found */
186                         reason:@"did not find specified message!"];
187   
188   return self;
189 }
190
191 - (BOOL) isDeletableClientObject
192 {
193   return [[self clientObject] respondsToSelector: @selector (delete)];
194 }
195
196 - (BOOL) isInlineViewer
197 {
198   return NO;
199 }
200
201 - (BOOL) mailIsDraft
202 {
203   return [[self clientObject] isInDraftsFolder];
204 }
205
206 - (id) redirectToParentFolder
207 {
208   id url;
209   
210   url = [[[self clientObject] container] baseURLInContext: context];
211
212   return [self redirectToLocation: url];
213 }
214
215 /* generating response */
216
217 - (void) appendToResponse: (WOResponse *) _response
218                 inContext: (WOContext *) _ctx
219 {
220   UIxMailRenderingContext *mctx;
221
222   if (mailETag != nil)
223     [[_ctx response] setHeader:mailETag forKey:@"etag"];
224
225   mctx = [[UIxMailRenderingContext alloc] initWithViewer: self
226                                           context: _ctx];
227
228   [_ctx pushMailRenderingContext: mctx];
229   [mctx release];
230
231   [super appendToResponse: _response inContext: _ctx];
232   
233   [[_ctx popMailRenderingContext] reset];
234 }
235
236 @end /* UIxMailView */