-L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \
-L../../SOGoLogic/$(GNUSTEP_OBJ_DIR)/ \
-L/usr/local/lib -L/usr/lib
+# todo: use syslibs
ADDITIONAL_TOOL_LIBS += \
-lSOGo \
+2004-10-25 Helge Hess <helge.hess@opengroupware.org>
+
+ * SOGoDraftObject.m: added ability to manage a draft object folder
+ (v0.9.37)
+
2004-10-21 Helge Hess <helge.hess@opengroupware.org>
* SOGoMailBaseObject.m: extract IMAP4 password from HTTP basic
folder are some kind of "mail creation transaction".
*/
+@class NSString, NSArray, NSDictionary;
+
@interface SOGoDraftObject : SOGoMailBaseObject
{
+ NSString *path;
}
+/* contents */
+
+- (NSDictionary *)fetchInfo;
+- (BOOL)storeInfo:(NSDictionary *)_info;
+
+- (NSArray *)fetchAttachmentNames;
+
@end
#endif /* __Mailer_SOGoDraftObject_H__ */
*/
#include "SOGoDraftObject.h"
+#include <NGExtensions/NSFileManager+Extensions.h>
#include "common.h"
@implementation SOGoDraftObject
- (void)dealloc {
+ [self->path release];
[super dealloc];
}
+/* draft folder functionality */
+
+- (NSFileManager *)spoolFileManager {
+ return [[self container] spoolFileManager];
+}
+- (NSString *)userSpoolFolderPath {
+ return [[self container] userSpoolFolderPath];
+}
+- (BOOL)_ensureUserSpoolFolderPath {
+ return [[self container] _ensureUserSpoolFolderPath];
+}
+
+/* draft object functionality */
+
+- (NSString *)draftFolderPath {
+ if (self->path != nil)
+ return self->path;
+
+ self->path = [[[self userSpoolFolderPath] stringByAppendingPathComponent:
+ [self nameInContainer]] copy];
+ return self->path;
+}
+- (BOOL)_ensureDraftFolderPath {
+ NSFileManager *fm;
+
+ if (![self _ensureUserSpoolFolderPath])
+ return NO;
+
+ if ((fm = [self spoolFileManager]) == nil) {
+ [self logWithFormat:@"ERROR: missing spool file manager!"];
+ return NO;
+ }
+ return [fm createDirectoriesAtPath:[self draftFolderPath] attributes:nil];
+}
+
+- (NSString *)infoPath {
+ return [[self draftFolderPath]
+ stringByAppendingPathComponent:@".info.plist"];
+}
+
+/* contents */
+
+- (BOOL)storeInfo:(NSDictionary *)_info {
+ if (_info == nil) {
+ [self logWithFormat:@"WARNING: got no info to write for draft!"];
+ return NO;
+ }
+ if (![self _ensureDraftFolderPath]) {
+ [self logWithFormat:@"ERROR: could not create folder for draft!"];
+ return NO;
+ }
+ if (![_info writeToFile:[self infoPath] atomically:YES]) {
+ [self logWithFormat:@"ERROR: could not write info %@", [self infoPath]];
+ return NO;
+ }
+ return YES;
+}
+- (NSDictionary *)fetchInfo {
+ NSDictionary *info;
+ NSString *p;
+
+ p = [self infoPath];
+ if (![[self spoolFileManager] fileExistsAtPath:p]) {
+ [self debugWithFormat:@"Note: info object does not yet exist: %@", p];
+ return nil;
+ }
+
+ if ((info = [NSDictionary dictionaryWithContentsOfFile:p]) == nil)
+ [self logWithFormat:@"ERROR: dictionary broken at path: %@", p];
+
+ return info;
+}
+
+- (NSArray *)fetchAttachmentNames {
+ NSMutableArray *ma;
+ NSFileManager *fm;
+ NSArray *files;
+ unsigned i, count;
+
+ fm = [self spoolFileManager];
+ if ((files = [fm directoryContentsAtPath:[self draftFolderPath]]) == nil)
+ return nil;
+
+ count = [files count];
+ ma = [NSMutableArray arrayWithCapacity:count];
+ for (i = 0; i < count; i++) {
+ NSString *filename;
+
+ filename = [files objectAtIndex:i];
+ if ([filename hasPrefix:@"."])
+ continue;
+
+ [ma addObject:filename];
+ }
+ return ma;
+}
+
+- (BOOL)isValidAttachmentName:(NSString *)_name {
+ NSRange r;
+
+ if (![_name isNotNull]) return NO;
+ if ([_name length] == 0) return NO;
+ if ([_name hasPrefix:@"."]) return NO;
+
+ r = [_name rangeOfString:@"/"];
+ if (r.length > 0) return NO;
+ r = [_name rangeOfString:@".."];
+ if (r.length > 0) return NO;
+ r = [_name rangeOfString:@"~"];
+ if (r.length > 0) return NO;
+
+ return YES;
+}
+
+- (BOOL)saveAttachment:(NSData *)_attachment withName:(NSString *)_name {
+ NSString *p;
+
+ if (_attachment == nil)
+ return NO;
+
+ if (![self _ensureDraftFolderPath]) {
+ [self logWithFormat:@"ERROR: could not create folder for draft!"];
+ return NO;
+ }
+ if (![self isValidAttachmentName:_name])
+ return NO;
+
+ p = [[self draftFolderPath] stringByAppendingPathComponent:_name];
+ return [_attachment writeToFile:p atomically:YES];
+}
+
@end /* SOGoDraftObject */
# Version file
-SUBMINOR_VERSION:=36
+SUBMINOR_VERSION:=37
# v0.9.35 requires SOGoLogic v0.9.24
# v0.9.34 requires SOGoLogic v0.9.22
+2004-10-25 Helge Hess <helge.hess@opengroupware.org>
+
+ * v0.9.45
+
+ * uix.css: replaced invalid "text-color" with "color"
+
+ * UIxMailEditor.wox: bind subject/text, can load/save info object in
+ draft
+
2004-10-22 Marcus Mueller <znek@mulle-kybernetik.com>
* v0.9.44
<br />
<div class="whitesec_title">Email</div><br />
- <li><a href="">Read messages</a></li>
- <li><a href="">Write a new message</a></li>
+ <li><a href="">Read messages (TBD: link)</a></li>
+ <li><a href="">Write a new message (TBD: link)</a></li>
<br />
<br />
+<!--
<div class="whitesec_title">Accounts</div><br />
<li><a href="">View settings for this account</a></li>
<li><a href="">Create a new account</a> [TBD: not in Agenor]</li>
<li><a href="">Offline settings</a> [TBD: not in Agenor]</li>
<br />
<br />
+-->
<div class="whitesec_title">Screenshot</div><br />
<a rsrc:href="tbird_073_accountview.png">screenshot</a>
@end
+#include <SOGo/SoObjects/Mailer/SOGoDraftObject.h>
#include "common.h"
@implementation UIxMailEditor
+static NSArray *infoKeys = nil;
+
++ (void)initialize {
+ infoKeys = [[NSArray alloc] initWithObjects:
+ @"subject", @"text", @"to", @"cc", @"bcc",
+ @"from", @"replyTo",
+ nil];
+}
+
- (void)dealloc {
[self->text release];
[self->subject release];
/* accessors */
+- (void)setFrom:(NSString *)_ignore {
+}
+- (NSString *)from {
+#warning TODO: retrieve email of account using SOGoUserManager, -emailForUID:
+ return @"hh@skyrix.com";
+}
+- (void)setReplyTo:(NSString *)_ignore {
+}
+- (NSString *)replyTo {
+ /* we are here for future extensibility */
+ return @"";
+}
+
- (void)setSubject:(NSString *)_value {
ASSIGNCOPY(self->subject, _value);
}
- (NSString *)subject {
- return self->subject;
+ return self->subject ? self->subject : @"";
}
- (void)setText:(NSString *)_value {
ASSIGNCOPY(self->text, _value);
}
- (NSString *)text {
- return self->text;
+ return [self->text isNotNull] ? self->text : @"";
}
- (void)setTo:(NSArray *)_value {
ASSIGNCOPY(self->to, _value);
}
- (NSArray *)to {
- return self->to;
+ return [self->to isNotNull] ? self->to : [NSArray array];
}
- (void)setCc:(NSArray *)_value {
ASSIGNCOPY(self->cc, _value);
}
- (NSArray *)cc {
- return self->cc;
+ return [self->cc isNotNull] ? self->cc : [NSArray array];
}
- (void)setBcc:(NSArray *)_value {
ASSIGNCOPY(self->bcc, _value);
}
- (NSArray *)bcc {
- return self->bcc;
+ return [self->bcc isNotNull] ? self->bcc : [NSArray array];
+}
+
+/* info loading */
+
+- (void)loadInfo:(NSDictionary *)_info {
+ if (![_info isNotNull]) return;
+ [self debugWithFormat:@"loading info ..."];
+ [self takeValuesFromDictionary:_info];
+}
+- (NSDictionary *)storeInfo {
+ [self debugWithFormat:@"storing info ..."];
+ return [self valuesForKeys:infoKeys];
}
/* requests */
/* actions */
-- (id)saveAction {
-#if 0
- NSException *ex;
+- (id)editAction {
+ [self logWithFormat:@"edit action, load content from: %@",
+ [self clientObject]];
+
+ [self loadInfo:[[self clientObject] fetchInfo]];
+ return self;
+}
- ex = [[self clientObject] saveContentString:content];
- if (ex != nil) {
- [self setErrorText:[ex reason]];
- return self;
+- (id)saveAction {
+ NSDictionary *info;
+
+ if ((info = [self storeInfo]) != nil) {
+ if (![[self clientObject] storeInfo:info]) {
+ [self logWithFormat:@"ERROR: failed to store draft!"];
+ // TODO: improve error handling
+ return nil;
+ }
}
- return [self redirectToLocation:[self _completeURIForMethod:@".."]];
-#else
+ [self logWithFormat:@"save action, store content to: %@",
+ [self clientObject]];
+ return self;
+}
+
+- (id)sendAction {
+ [self logWithFormat:@"send action, store content, send mail, store: %@",
+ [self clientObject]];
+ // if everything is ok, close the window (send a JS closing the Window)
return self;
-#endif
}
@end /* UIxMailEditor */
<a rsrc:href="tbird_073_compose.png">Subject:</a>
</td>
<td width="85%"><input name="subject"
- id="compose_subject_input" type="text" /></td>
+ id="compose_subject_input" type="text"
+ var:value="subject" /></td>
</tr>
</table>
</div>
<!-- separator line -->
<div id="compose_text">
- <textarea name="content" />
+ <textarea name="content" var:value="text" />
</div>
<!-- img rsrc:src="tbird_073_compose.png" alt="screenshot" / -->
# $Id$
-SUBMINOR_VERSION:=44
+SUBMINOR_VERSION:=45
# v0.9.43 requires NGObjWeb v4.3.73
# v0.9.42 requires NGObjWeb v4.3.72
if (!validateEditorInput(sender))
return false;
- alert("SEND");
+ document.pageform.action="send";
+ document.pageform.submit();
// if everything is ok, close the window
+ return true;
}
function clickedEditorAttach(sender) {
- alert("ATTACH");
+ document.pageform.action="save";
+ document.pageform.submit();
+ return true;
}
-
function clickedEditorSave(sender) {
- //field = document.pageform[":method"];
- document.pageform.action="edit";
+ document.pageform.action="save";
document.pageform.submit();
return true;
}
edit = {
protectedBy = "View";
pageName = "UIxMailEditor";
+ actionName = "edit";
+ };
+ save = {
+ protectedBy = "View";
+ pageName = "UIxMailEditor";
+ actionName = "save";
+ };
+ send = {
+ protectedBy = "View";
+ pageName = "UIxMailEditor";
+ actionName = "send";
};
addressbook = {
protectedBy = "View";
font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
letter-spacing: 0pt;
text-decoration: none;
- text-color: #000000;
+ color: #000000;
text-align: center;
vertical-align: middle;
padding-left: 5px;
font-family: Arial, Helvetica, Verdana, Geneva, Tahoma, sans-serif;
letter-spacing: 0pt;
text-decoration: none;
- text-color: #000000;
+ color: #000000;
text-align: center;
vertical-align: middle;
padding-left: 5px;