/* Copyright (C) 2003-2004 SKYRIX Software AG This file is part of SOPE. SOPE is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. SOPE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with SOPE; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Note: Its very important that the URLs generated properly match the appname! Otherwise you will get security exceptions in JavaScript on the client side (probably depends on the browser). This also implies, that WOResourcePrefix cannot be used in conjunction with Epoz. */ #include @interface WEEpozEditor : WODynamicElement { // WODynamicElement: extraAttributes // WODynamicElement: otherTagString @protected WOAssociation *name; WOAssociation *value; WOAssociation *disabled; WOAssociation *rows; WOAssociation *cols; WOAssociation *epozCharset; /* def: iso-8859-1 */ WOAssociation *epozButtonStyle; WOAssociation *epozStyle; } @end #include #include #include "common.h" @implementation WEEpozEditor + (int)version { return [super version] + 0 /* v2 */; } + (void)initialize { NSAssert2([super version] == 2, @"invalid superclass (%@) version %i !", NSStringFromClass([self superclass]), [super version]); } - (id)initWithName:(NSString *)_name associations:(NSDictionary *)_config template:(WOElement *)_root { if ((self = [super initWithName:_name associations:_config template:_root])) { self->containsForm = YES; self->name = OWGetProperty(_config, @"name"); self->value = OWGetProperty(_config, @"value"); self->disabled = OWGetProperty(_config, @"disabled"); self->rows = OWGetProperty(_config, @"rows"); self->cols = OWGetProperty(_config, @"cols"); self->epozCharset = OWGetProperty(_config, @"charset"); self->epozStyle = OWGetProperty(_config, @"style"); self->epozButtonStyle = OWGetProperty(_config, @"buttonstyle"); } return self; } - (void)dealloc { [self->epozCharset release]; [self->epozButtonStyle release]; [self->epozStyle release]; [self->rows release]; [self->cols release]; [self->name release]; [self->value release]; [self->disabled release]; [super dealloc]; } /* form support */ static NSString *OWFormElementName(WEEpozEditor *self, WOContext *_ctx) { NSString *name; if (self->name == nil) return [_ctx elementID]; if ((name = [self->name stringValueInComponent:[_ctx component]])) return name; [[_ctx component] logWithFormat: @"WARNING: in element %@, 'name' attribute configured (%@)," @"but no name assigned (using elementID as name) !", self, self->name]; return [_ctx elementID]; } // ******************** responder ******************** - (id)parseFormValue:(id)_value inContext:(WOContext *)_ctx { return _value; } - (void)takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx { NSString *formName; id formValue = nil; if ([self->disabled boolValueInComponent:[_ctx component]]) return; formName = OWFormElementName(self, _ctx); if ((formValue = [_req formValueForKey:formName])) { #if DEBUG && 0 NSLog(@"%s(%@): form=%@ ctx=%@ value=%@ ..", __PRETTY_FUNCTION__, [_ctx elementID], formName, [_ctx contextID], formValue); #endif if ([self->value isValueSettable]) { formValue = [self parseFormValue:formValue inContext:_ctx]; [self->value setStringValue:formValue inComponent:[_ctx component]]; } #if DEBUG else { NSLog(@"%s: form value is not settable: %@", __PRETTY_FUNCTION__, self->value); } #endif } } - (BOOL)isDebuggingEnabled { return NO; } - (BOOL)isEpozBrowserInContext:(WOContext *)_ctx { WEClientCapabilities *cc; if ((cc = [[_ctx request] clientCapabilities]) == nil) { [self debugWithFormat:@"WARNING: missing client capabilities object!"]; return YES; } if ([cc isInternetExplorer]) { if ([cc majorVersion] <= 4) { [self debugWithFormat:@"disable Epoz with IE <5"]; return NO; } if ([cc majorVersion] == 5 && [cc minorVersion] <= 5) { [self debugWithFormat:@"disable Epoz with IE <5.5"]; return NO; } [self debugWithFormat:@"enable Epoz with IE >=5.5"]; return YES; } if ([cc isMozilla] || [cc isNetscape]) { [self debugWithFormat:@"enable Epoz with Mozilla: %@", cc]; return YES; } [self debugWithFormat:@"does not use Epoz with this browser: %@", cc]; return NO; } - (NSString *)stringValueInContext:(WOContext *)_ctx { BOOL removeCR = NO; NSString *ua; NSString *v; v = [[self->value valueInComponent:[_ctx component]] stringValue]; if (![v isNotEmpty]) return v; ua = [[_ctx request] headerForKey:@"user-agent"]; if ([ua rangeOfString:@"Opera"].length > 0) removeCR = YES; if (removeCR) v = [v stringByReplacingString:@"\r" withString:@""]; return v; } - (void)appendTextAreaToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *v; NSString *r, *c; sComponent = [_ctx component]; v = [self stringValueInContext:_ctx]; r = [self->rows stringValueInComponent:sComponent]; c = [self->cols stringValueInComponent:sComponent]; [_response appendContentString:@""]; } - (WOResourceManager *)resourceManagerInContext:(WOContext *)_ctx { WOResourceManager *rm; if ((rm = [[_ctx component] resourceManager]) == nil) rm = [[_ctx application] resourceManager]; return rm; } - (NSString *)urlForEpozResourceNamed:(NSString *)_name inContext:(WOContext *)_ctx { WOResourceManager *rm; NSArray *languages; rm = [self resourceManagerInContext:_ctx]; languages = [_ctx hasSession] ? [[_ctx session] languages] : (NSArray *)nil; return [rm urlForResourceNamed:_name inFramework:nil languages:languages request:[_ctx request]]; } - (void)appendEpozScript:(NSString *)_scriptName toResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { NSString *src; src = [self urlForEpozResourceNamed:_scriptName inContext:_ctx]; [_response appendContentString:@"\n"]; } - (NSString *)epozImageURLInContext:(WOContext *)_ctx { /* Note: Epoz takes the directory where the resources are located, not individual pointers. This also means that you need to have all Epoz resources in the directory which contains the "epoz_button_bold.gif" (which is used as the "reference" point to the active buttons). */ NSString *src; NSRange r; src = [self urlForEpozResourceNamed:@"epoz_button_bold.gif" inContext:_ctx]; r = [src rangeOfString:@"/" options:(NSBackwardsSearch | NSLiteralSearch)]; if (r.length > 0) src = [src substringToIndex:(r.location + r.length)]; return src; } - (NSString *)epozToolboxURLInContext:(WOContext *)_ctx { /* TODO: replace */ // return @"/epoz/WebServerResources/toolbox"; return [self urlForEpozResourceNamed:@"epoz_toolbox.html" inContext:_ctx]; } - (NSString *)epozCSSURLInContext:(WOContext *)_ctx { return [self urlForEpozResourceNamed:@"epoz.css" inContext:_ctx]; } - (void)appendEpozToResponse:(WOResponse *)_r inContext:(WOContext *)_ctx { WOComponent *sComponent; NSString *v, *tmp; sComponent = [_ctx component]; v = [self stringValueInContext:_ctx]; /* first, the background iframe */ [_r appendContentString:@"\n"]; /* the language mappings */ [self appendEpozScript:@"epoz_lang_en.js" toResponse:_r inContext:_ctx]; /* the processing JavaScripts */ [self appendEpozScript:@"epoz_script_widget.js" toResponse:_r inContext:_ctx]; [self appendEpozScript:@"epoz_script_detect.js" toResponse:_r inContext:_ctx]; [self appendEpozScript:@"epoz_script_main.js" toResponse:_r inContext:_ctx]; /* Start Epoz """ Create an Epoz-Wysiwyg-Editor. name : the name of the form-element which submits the data data : the data to edit toolbox : a link to a HTML-Page which delivers additional tools lang: a code for the language-file (en,de,...) path : path to Epoz-Javascript. Needed mainly for Plone (portal_url). widget: You can specify a path to an alternative JavaScript for epoz_script_widget.js style : style-definition for the editor-area button : style-definiton for buttons If Epoz can't create a Rich-Text-Editor, a simple textarea is created. """ */ [_r appendContentString: @""]; /* fallback if scripting is disabled */ [_r appendContentString:@""]; } - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { if ([self isEpozBrowserInContext:_ctx]) [self appendEpozToResponse:_response inContext:_ctx]; else [self appendTextAreaToResponse:_response inContext:_ctx]; } /* description */ - (NSString *)associationDescription { NSMutableString *str = nil; str = [NSMutableString stringWithCapacity:64]; if (self->value) [str appendFormat:@" value=%@", self->value]; if (self->name) [str appendFormat:@" name=%@", self->name]; if (self->disabled) [str appendFormat:@" disabled=%@", self->disabled]; if (self->rows) [str appendFormat:@" rows=%@", self->rows]; if (self->cols) [str appendFormat:@" cols=%@", self->cols]; return str; } @end /* WEEpozEditor */