adium 5296:56f449db5351: Prevent the messageview from trying to ...
commits at adium.im
commits at adium.im
Tue Feb 5 14:55:19 UTC 2013
details: http://hg.adium.im/adium/rev/56f449db5351
revision: 5296:56f449db5351
branch: (none)
author: mathuaerknedam <adium at ei8ht.us>
date: Tue Feb 05 08:55:02 2013 -0600
Prevent the messageview from trying to load Variants/(null) when a message style has no variant. Thanks to Detmud for the patch. Fixes #16287.
diffs (989 lines):
diff -r ad75d7f54bdc -r 56f449db5351 Plugins/WebKit Message View/AIWebkitMessageViewStyle.m
--- a/Plugins/WebKit Message View/AIWebkitMessageViewStyle.m Mon Feb 04 12:35:14 2013 -0500
+++ b/Plugins/WebKit Message View/AIWebkitMessageViewStyle.m Tue Feb 05 08:55:02 2013 -0600
@@ -1,15 +1,15 @@
-/*
+/*
* Adium is the legal property of its developers, whose names are listed in the copyright file included
* with this source distribution.
- *
+ *
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
- *
+ *
* This program 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 General
* Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License along with this program; if not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@@ -81,7 +81,7 @@
}
@end
-//The old code built the paths itself, which follows the filesystem's case sensitivity, so some noobs named stuff wrong.
+//The old code built the paths itself, which follows the filesystem's case sensitivity, so some noobs named stuff wrong.
//NSBundle is always case sensitive, so those styles broke (they were already broken on case sensitive hfsx)
//These methods only check for the all-lowercase variant, so are not suitable for general purpose use.
@interface NSBundle (StupidCompatibilityHack)
@@ -143,7 +143,7 @@
if ((self = [super init])) {
styleBundle = inBundle;
stylePath = [styleBundle resourcePath];
-
+
if ([self reloadStyle] == FALSE) {
return nil;
}
@@ -155,7 +155,7 @@
- (BOOL) reloadStyle
{
[self releaseResources];
-
+
/* Our styles are versioned so we can change how they work without breaking compatibility.
*
* Version 0: Initial Webkit Version
@@ -173,7 +173,7 @@
* HTML filters in are now supported in Adium's content filter system; filters can assume Version 4 or later.
*/
styleVersion = [[styleBundle objectForInfoDictionaryKey:KEY_WEBKIT_VERSION] integerValue];
-
+
/* Refuse to load a version whose minimum compatible version is greater than the latest version we know about; that
* indicates this is a style FROM THE FUTURE, and we can't risk corrupting our own timeline.
*/
@@ -187,23 +187,23 @@
//Pre-fetch our templates
[self _loadTemplates];
-
+
//Style flags
allowsCustomBackground = ![[styleBundle objectForInfoDictionaryKey:@"DisableCustomBackground"] boolValue];
transparentDefaultBackground = [[styleBundle objectForInfoDictionaryKey:@"DefaultBackgroundIsTransparent"] boolValue];
-
+
combineConsecutive = ![[styleBundle objectForInfoDictionaryKey:@"DisableCombineConsecutive"] boolValue];
-
+
NSNumber *tmpNum = [styleBundle objectForInfoDictionaryKey:@"ShowsUserIcons"];
allowsUserIcons = (tmpNum ? [tmpNum boolValue] : YES);
-
+
//User icon masking
NSString *tmpName = [styleBundle objectForInfoDictionaryKey:KEY_WEBKIT_USER_ICON_MASK];
if (tmpName) userIconMask = [[NSImage alloc] initWithContentsOfFile:[stylePath stringByAppendingPathComponent:tmpName]];
-
+
NSNumber *allowsColorsNumber = [styleBundle objectForInfoDictionaryKey:@"AllowTextColors"];
allowsColors = (allowsColorsNumber ? [allowsColorsNumber boolValue] : YES);
-
+
return YES;
}
@@ -228,10 +228,10 @@
statusHTML = nil;
fileTransferHTML = nil;
topicHTML = nil;
-
+
customBackgroundPath = nil;
customBackgroundColor = nil;
-
+
userIconMask = nil;
}
@@ -239,9 +239,9 @@
* @brief Deallocate
*/
- (void)dealloc
-{
+{
[self releaseResources];
-
+
[[NSDistributedNotificationCenter defaultCenter] removeObserver: self];
}
@@ -261,13 +261,13 @@
if(!checkedSenderColors) {
NSURL *url = [NSURL fileURLWithPath:[stylePath stringByAppendingPathComponent:@"Incoming/SenderColors.txt"]];
NSString *senderColorsFile = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:NULL];
-
+
if(senderColorsFile)
validSenderColors = [senderColorsFile componentsSeparatedByString:@":"];
-
+
checkedSenderColors = YES;
}
-
+
return validSenderColors;
}
@@ -282,7 +282,7 @@
{
NSString *defaultFontFamily = [styleBundle objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_FAMILY];
if (!defaultFontFamily) defaultFontFamily = [[NSFont systemFontOfSize:0] familyName];
-
+
return defaultFontFamily;
}
@@ -291,7 +291,7 @@
NSNumber *defaultFontSize = [styleBundle objectForInfoDictionaryKey:KEY_WEBKIT_DEFAULT_FONT_SIZE];
if (!defaultFontSize) defaultFontSize = [NSNumber numberWithInteger:[[NSFont systemFontOfSize:0] pointSize]];
-
+
return defaultFontSize;
}
@@ -344,7 +344,7 @@
headerContent = headerHTML;
}
}
-
+
//Old styles may be using an old custom 4 parameter baseHTML. Styles version 3 and higher should
//be using the bundled (or a custom) 5 parameter baseHTML.
if ((styleVersion < 3) && usingCustomTemplateHTML) {
@@ -353,7 +353,7 @@
[self pathForVariant:self.activeVariant], //Variant path
headerContent,
(footerHTML ? footerHTML : @"")];
- } else {
+ } else {
templateHTML = [NSMutableString stringWithFormat:baseHTML, //Template
[[NSURL fileURLWithPath:stylePath] absoluteString], //Base path
styleVersion < 3 ? @"" : @"@import url( \"main.css\" );", //Import main.css for new enough styles
@@ -368,7 +368,7 @@
- (NSString *)templateForContent:(AIContentObject *)content similar:(BOOL)contentIsSimilar
{
NSString *template;
-
+
//Get the correct template for what we're inserting
if ([[content type] isEqualToString:CONTENT_MESSAGE_TYPE]) {
if ([content isOutgoing]) {
@@ -376,7 +376,7 @@
} else {
template = (contentIsSimilar ? nextContentInHTML : contentInHTML);
}
-
+
} else if ([[content type] isEqualToString:CONTENT_CONTEXT_TYPE]) {
if ([content isOutgoing]) {
template = (contentIsSimilar ? nextContextOutHTML : contextOutHTML);
@@ -392,17 +392,17 @@
else {
template = statusHTML;
}
-
+
return template;
}
- (NSString *)completedTemplateForContent:(AIContentObject *)content similar:(BOOL)contentIsSimilar
{
NSMutableString *mutableTemplate = [[self templateForContent:content similar:contentIsSimilar] mutableCopy];
-
+
if (mutableTemplate)
[self fillKeywords:mutableTemplate forContent:content similar:contentIsSimilar];
-
+
return mutableTemplate;
}
@@ -412,7 +412,7 @@
* This needs to be called before either baseTemplate or templateForContent is called
*/
- (void)_loadTemplates
-{
+{
//Load the style's templates
//We can't use NSString's initWithContentsOfFile here. HTML files are interpreted in the defaultCEncoding
//(which varies by system) when read that way. We want to always interpret the files as UTF8.
@@ -420,20 +420,20 @@
footerHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Footer" ofType:@"html"]];
topicHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Topic" ofType:@"html"]];
baseHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Template" ofType:@"html"]];
-
- //Starting with version 1, styles can choose to not include template.html. If the template is not included
+
+ //Starting with version 1, styles can choose to not include template.html. If the template is not included
//Adium's default will be used. This is preferred since any future template updates will apply to the style
- if ((!baseHTML || [baseHTML length] == 0) && styleVersion >= 1) {
+ if ((!baseHTML || [baseHTML length] == 0) && styleVersion >= 1) {
baseHTML = [NSString stringWithContentsOfUTF8File:[[NSBundle bundleForClass:[self class]] semiCaseInsensitivePathForResource:@"Template" ofType:@"html"]];
usingCustomTemplateHTML = NO;
} else {
usingCustomTemplateHTML = YES;
-
+
NSAssert(baseHTML != nil, @"The impossible happened!");
-
+
if ([baseHTML rangeOfString:@"function imageCheck()" options:NSLiteralSearch].location != NSNotFound) {
/* This doesn't quite fix image swapping on styles with broken image swapping due to custom HTML templates,
- * but it improves it. For some reason, the result of using our normal template.html functions is that
+ * but it improves it. For some reason, the result of using our normal template.html functions is that
* clicking works once, then the text doesn't allow a return click. This is an improvement compared
* to fully broken behavior in which the return click shows a missing-image placeholder.
*/
@@ -506,50 +506,50 @@
options:NSLiteralSearch];
baseHTML = imageSwapFixedBaseHTML;
}
-
+
}
-
+
//Content Templates
contentHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Content" ofType:@"html"]];
contentInHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Content" ofType:@"html" inDirectory:@"Incoming"]];
nextContentInHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"NextContent" ofType:@"html" inDirectory:@"Incoming"]];
contentOutHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Content" ofType:@"html" inDirectory:@"Outgoing"]];
nextContentOutHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"NextContent" ofType:@"html" inDirectory:@"Outgoing"]];
-
+
//Message history
contextInHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Context" ofType:@"html" inDirectory:@"Incoming"]];
nextContextInHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"NextContext" ofType:@"html" inDirectory:@"Incoming"]];
contextOutHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Context" ofType:@"html" inDirectory:@"Outgoing"]];
nextContextOutHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"NextContext" ofType:@"html" inDirectory:@"Outgoing"]];
-
+
//Fall back to Resources/Content.html if Incoming isn't present
if (!contentInHTML) contentInHTML = contentHTML;
-
+
//Fall back to Content if NextContent doesn't need to use different HTML
if (!nextContentInHTML) nextContentInHTML = contentInHTML;
-
+
//Fall back to Content if Context isn't present
if (!nextContextInHTML) nextContextInHTML = nextContentInHTML;
if (!contextInHTML) contextInHTML = contentInHTML;
-
+
//Fall back to Content if Context isn't present
if (!nextContextOutHTML && nextContentOutHTML) nextContextOutHTML = nextContentOutHTML;
if (!contextOutHTML && contentOutHTML) contextOutHTML = contentOutHTML;
-
+
//Fall back to Content if Context isn't present
if (!nextContextOutHTML) nextContextOutHTML = nextContextInHTML;
if (!contextOutHTML) contextOutHTML = contextInHTML;
-
+
//Fall back to Incoming if Outgoing doesn't need to be different
if (!contentOutHTML) contentOutHTML = contentInHTML;
if (!nextContentOutHTML) nextContentOutHTML = nextContentInHTML;
-
+
//Status
statusHTML = [NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"Status" ofType:@"html"]];
-
+
//Fall back to Resources/Incoming/Content.html if Status isn't present
if (!statusHTML) statusHTML = contentInHTML;
-
+
//TODO: make a generic Request message, rather than having this ft specific one
NSMutableString *fileTransferHTMLTemplate;
fileTransferHTMLTemplate = [[NSString stringWithContentsOfUTF8File:[styleBundle semiCaseInsensitivePathForResource:@"FileTransferRequest" ofType:@"html"]] mutableCopy];
@@ -568,13 +568,13 @@
{
NSMutableString *newHTML;
NSString *script;
-
+
//If combining of consecutive messages has been disabled, we treat all content as non-similar
if (!combineConsecutive) contentIsSimilar = NO;
-
+
//Fetch the correct template and substitute keywords for the passed content
newHTML = [[self completedTemplateForContent:content similar:contentIsSimilar] mutableCopy];
-
+
//BOM scripts vary by style version
if (!usingCustomTemplateHTML && styleVersion >= 4) {
/* If we're using the built-in template HTML, we know that it supports our most modern scripts */
@@ -585,7 +585,7 @@
} else {
script = (contentIsSimilar ? APPEND_NEXT_MESSAGE : APPEND_MESSAGE);
}
-
+
} else if (styleVersion >= 3) {
if (willAddMoreContentObjects) {
script = (contentIsSimilar ? APPEND_NEXT_MESSAGE_NO_SCROLL : APPEND_MESSAGE_NO_SCROLL);
@@ -594,10 +594,10 @@
}
} else if (styleVersion >= 1) {
script = (contentIsSimilar ? APPEND_NEXT_MESSAGE : APPEND_MESSAGE);
-
+
} else {
if (usingCustomTemplateHTML && [content isKindOfClass:[AIContentStatus class]]) {
- /* Old styles with a custom template.html had Status.html files without 'insert' divs coupled
+ /* Old styles with a custom template.html had Status.html files without 'insert' divs coupled
* with a APPEND_NEXT_MESSAGE_WITH_SCROLL script which assumes one exists.
*/
script = APPEND_MESSAGE_WITH_SCROLL;
@@ -605,8 +605,8 @@
script = (contentIsSimilar ? APPEND_NEXT_MESSAGE_WITH_SCROLL : APPEND_MESSAGE_WITH_SCROLL);
}
}
-
- return [NSString stringWithFormat:script, [self _escapeStringForPassingToScript:newHTML]];
+
+ return [NSString stringWithFormat:script, [self _escapeStringForPassingToScript:newHTML]];
}
- (NSString *)scriptForChangingVariant
@@ -627,22 +627,22 @@
* @brief Escape a string for passing to our BOM scripts
*/
- (NSMutableString *)_escapeStringForPassingToScript:(NSMutableString *)inString
-{
+{
// We need to escape a few things to get our string to the javascript without trouble
- [inString replaceOccurrencesOfString:@"\\"
- withString:@"\\\\"
- options:NSLiteralSearch];
-
- [inString replaceOccurrencesOfString:@"\""
- withString:@"\\\""
- options:NSLiteralSearch];
-
- [inString replaceOccurrencesOfString:@"\n"
- withString:@""
+ [inString replaceOccurrencesOfString:@"\\"
+ withString:@"\\\\"
options:NSLiteralSearch];
- [inString replaceOccurrencesOfString:@"\r"
- withString:@"<br>"
+ [inString replaceOccurrencesOfString:@"\""
+ withString:@"\\\""
+ options:NSLiteralSearch];
+
+ [inString replaceOccurrencesOfString:@"\n"
+ withString:@""
+ options:NSLiteralSearch];
+
+ [inString replaceOccurrencesOfString:@"\r"
+ withString:@"<br>"
options:NSLiteralSearch];
return inString;
@@ -653,7 +653,7 @@
- (NSArray *)availableVariants
{
NSMutableArray *availableVariants = [NSMutableArray array];
-
+
//Build an array of all variant names
for (NSString *path in [styleBundle pathsForResourcesOfType:@"css" inDirectory:@"Variants"]) {
[availableVariants addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
@@ -664,21 +664,30 @@
if (styleVersion < 3) {
[availableVariants addObject:[self noVariantName]];
}
-
+
//Alphabetize the variants
[availableVariants sortUsingSelector:@selector(localizedStandardCompare:)];
-
+
return availableVariants;
}
- (NSString *)pathForVariant:(NSString *)variant
{
+ //mvv > 2 and (variant exists and not nil)
+ if (styleVersion > 2 && (![variant isEqualToString:[self noVariantName]] && variant != nil )) { return [NSString stringWithFormat:@"Variants/%@.css",variant];
+ }
+ // mvv > 2 and variant does not exist
+ else if (styleVersion > 2 && ([variant isEqualToString:[self noVariantName]] || variant == nil )) {
+ return @"";
+ }
+
//Styles before version 3 stored the default variant in main.css, and not in the variants folder.
- if (styleVersion < 3 && [variant isEqualToString:[self noVariantName]]) {
+ else if (styleVersion < 3 && [variant isEqualToString:[self noVariantName]]) {
return @"main.css";
- } else {
- return [NSString stringWithFormat:@"Variants/%@.css",variant];
}
+
+ // Secure Return
+ return @"";
}
/*!
@@ -693,7 +702,7 @@
+ (NSString *)noVariantNameForBundle:(NSBundle *)inBundle
{
NSString *noVariantName = [inBundle objectForInfoDictionaryKey:@"DisplayNameForNoVariant"];
- return noVariantName ? noVariantName : AILocalizedString(@"Normal","Normal style variant menu item");
+ return noVariantName ? noVariantName : AILocalizedString(@"Normal","Normal style variant menu item");
}
- (NSString *)defaultVariant
@@ -703,8 +712,8 @@
+ (NSString *)defaultVariantForBundle:(NSBundle *)inBundle
{
- return [[inBundle objectForInfoDictionaryKey:KEY_WEBKIT_VERSION] integerValue] < 3 ?
- [self noVariantNameForBundle:inBundle] :
+ return [[inBundle objectForInfoDictionaryKey:KEY_WEBKIT_VERSION] integerValue] < 3 ?
+ [self noVariantNameForBundle:inBundle] :
[inBundle objectForInfoDictionaryKey:@"DefaultVariant"];
}
@@ -722,10 +731,10 @@
/*
htmlEncodedMessage is only encoded correctly for AIContentMessages
but we do it up here so that we can check for RTL/LTR text below without
- having to encode the message twice. This is less than ideal
+ having to encode the message twice. This is less than ideal
*/
NSString *htmlEncodedMessage = [AIHTMLDecoder encodeHTML:[content message]
- headers:NO
+ headers:NO
fontTags:showIncomingFonts
includingColorTags:(allowsColors && showIncomingColors)
closeFontTags:YES
@@ -739,7 +748,7 @@
simpleTagsOnly:NO
bodyBackground:NO
allowJavascriptURLs:NO];
-
+
if (styleVersion >= 4)
htmlEncodedMessage = [adium.contentController filterHTMLString:htmlEncodedMessage
direction:[content isOutgoing] ? AIFilterOutgoing : AIFilterIncoming
@@ -748,16 +757,16 @@
//date
if ([content respondsToSelector:@selector(date)])
date = [(AIContentMessage *)content date];
-
+
//Replacements applicable to any AIContentObject
- [inString replaceKeyword:@"%time%"
+ [inString replaceKeyword:@"%time%"
withString:(date ? [timeStampFormatter stringFromDate:date] : @"")];
__block NSString *shortTimeString;
[NSDateFormatter withLocalizedDateFormatterShowingSeconds:NO showingAMorPM:NO perform:^(NSDateFormatter *dateFormatter){
shortTimeString = (date ? [dateFormatter stringFromDate:date] : @"");
}];
-
+
[inString replaceKeyword:@"%shortTime%"
withString:shortTimeString];
@@ -766,7 +775,7 @@
[inString replaceKeyword:@"%senderStatusIcon%"
withString:[self statusIconPathForListObject:theSource]];
}
-
+
//Replaces %localized{x}% with a a localized version of x, searching the style's localizations, and then Adium's localizations
do{
range = [inString rangeOfString:@"%localized{"];
@@ -775,7 +784,7 @@
endRange = [inString rangeOfString:@"}%" options:NSLiteralSearch range:NSMakeRange(NSMaxRange(range), [inString length] - NSMaxRange(range))];
if (endRange.location != NSNotFound && endRange.location > NSMaxRange(range)) {
NSString *untranslated = [inString substringWithRange:NSMakeRange(NSMaxRange(range), (endRange.location - NSMaxRange(range)))];
-
+
NSString *translated = [styleBundle localizedStringForKey:untranslated
value:untranslated
table:nil];
@@ -789,9 +798,9 @@
table:nil];
}
}
-
-
- [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
+
+
+ [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
withString:translated];
}
}
@@ -802,16 +811,16 @@
[inString replaceKeyword:@"%messageClasses%"
withString:[(contentIsSimilar ? @"consecutive " : @"") stringByAppendingString:[[content displayClasses] componentsJoinedByString:@" "]]];
-
+
[inString replaceKeyword:@"%senderColor%"
withString:[NSColor representedColorForObject:contentSource.UID withValidColors:self.validSenderColors]];
-
+
//HAX. The odd conditional here detects the rtl html that our html parser spits out.
BOOL isRTL = ([htmlEncodedMessage rangeOfString:@"<div dir=\"rtl\">"
options:(NSCaseInsensitiveSearch | NSLiteralSearch)].location != NSNotFound);
[inString replaceKeyword:@"%messageDirection%"
withString:(isRTL ? @"rtl" : @"ltr")];
-
+
//Replaces %time{x}% with a timestamp formatted like x (using NSDateFormatter)
do{
range = [inString rangeOfString:@"%time{"];
@@ -826,7 +835,7 @@
[[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(flushTimeFormatterCache:) name:@"AppleTimePreferencesChangedNotification" object:nil];
}
NSString *timeFormat = [inString substringWithRange:NSMakeRange(NSMaxRange(range), (endRange.location - NSMaxRange(range)))];
-
+
NSDateFormatter *dateFormatter = [timeFormatterCache objectForKey:timeFormat];
if (!dateFormatter) {
if ([timeFormat rangeOfString:@"%"].location != NSNotFound) {
@@ -838,44 +847,44 @@
}
[timeFormatterCache setObject:dateFormatter forKey:timeFormat];
}
-
- [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
+
+ [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
withString:[dateFormatter stringFromDate:date]];
-
+
} else
[inString deleteCharactersInRange:NSUnionRange(range, endRange)];
-
+
}
}
} while (range.location != NSNotFound);
-
+
do{
range = [inString rangeOfString:@"%userIconPath%"];
if (range.location != NSNotFound) {
NSString *userIconPath;
NSString *replacementString;
-
+
userIconPath = [theSource valueForProperty:KEY_WEBKIT_USER_ICON];
if (!userIconPath) {
userIconPath = [theSource valueForProperty:@"UserIconPath"];
}
-
+
if (showUserIcons && userIconPath) {
replacementString = [NSString stringWithFormat:@"file://%@", userIconPath];
-
+
} else {
replacementString = ([content isOutgoing]
- ? @"Outgoing/buddy_icon.png"
+ ? @"Outgoing/buddy_icon.png"
: @"Incoming/buddy_icon.png");
}
-
+
[inString safeReplaceCharactersInRange:range withString:replacementString];
}
} while (range.location != NSNotFound);
-
- [inString replaceKeyword:@"%service%"
+
+ [inString replaceKeyword:@"%service%"
withString:[content.chat.account.service shortDescription]];
-
+
[inString replaceKeyword:@"%serviceIconPath%"
withString:[AIServiceIcons pathForServiceIconForServiceID:content.chat.account.service.serviceID
type:AIServiceIconLarge]];
@@ -888,7 +897,7 @@
//message stuff
if ([content isKindOfClass:[AIContentMessage class]]) {
-
+
//Use [content source] directly rather than the potentially-metaContact theSource
NSString *formattedUID = nil;
if (content.chat.isGroupChat && [(AIGroupChat *)content.chat aliasForContact:contentSource]) {
@@ -898,24 +907,24 @@
}
NSString *displayName;
-
+
if (content.chat.isGroupChat)
displayName = [(AIGroupChat *)content.chat displayNameForContact:contentSource];
else
displayName = content.source.displayName;
-
+
[inString replaceKeyword:@"%status%"
withString:@""];
- [inString replaceKeyword:@"%senderScreenName%"
+ [inString replaceKeyword:@"%senderScreenName%"
withString:[(formattedUID ?
formattedUID :
displayName) stringByEscapingForXMLWithEntities:nil]];
-
-
+
+
[inString replaceKeyword:@"%senderPrefix%"
withString:((AIContentMessage *)content).senderPrefix];
-
+
do{
range = [inString rangeOfString:@"%sender%"];
if (range.location != NSNotFound) {
@@ -952,7 +961,7 @@
if (!senderDisplay) {
AILog(@"XXX we don't have a sender for %@ (%@)", content, [content message]);
NSLog(@"Enormous error: we don't have a sender for %@ (%@)", content, [content message]);
-
+
// This shouldn't happen.
senderDisplay = @"(unknown)";
}
@@ -961,15 +970,15 @@
} else {
senderDisplay = displayName;
}
-
+
if ([(AIContentMessage *)content isAutoreply]) {
senderDisplay = [NSString stringWithFormat:@"%@ %@",senderDisplay,AILocalizedString(@"(Autoreply)","Short word inserted after the sender's name when displaying a message which was an autoresponse")];
}
-
+
[inString safeReplaceCharactersInRange:range withString:[senderDisplay stringByEscapingForXMLWithEntities:nil]];
}
} while (range.location != NSNotFound);
-
+
do {
range = [inString rangeOfString:@"%senderDisplayName%"];
if (range.location != NSNotFound) {
@@ -979,7 +988,7 @@
if (!serversideDisplayName) {
serversideDisplayName = theSource.displayName;
}
-
+
[inString safeReplaceCharactersInRange:range
withString:[serversideDisplayName stringByEscapingForXMLWithEntities:nil]];
}
@@ -994,12 +1003,12 @@
if (endRange.location != NSNotFound && endRange.location > NSMaxRange(range)) {
NSString *transparency = [inString substringWithRange:NSMakeRange(NSMaxRange(range),
(endRange.location - NSMaxRange(range)))];
-
+
if (allowTextBackgrounds && showIncomingColors) {
NSString *thisIsATemporaryString;
unsigned rgb = 0, red, green, blue;
NSScanner *hexcode;
- thisIsATemporaryString = [AIHTMLDecoder encodeHTML:[content message] headers:NO
+ thisIsATemporaryString = [AIHTMLDecoder encodeHTML:[content message] headers:NO
fontTags:NO
includingColorTags:NO
closeFontTags:NO
@@ -1030,8 +1039,8 @@
} else if (endRange.location == NSMaxRange(range)) {
if (allowTextBackgrounds && showIncomingColors) {
NSString *thisIsATemporaryString;
-
- thisIsATemporaryString = [AIHTMLDecoder encodeHTML:[content message] headers:NO
+
+ thisIsATemporaryString = [AIHTMLDecoder encodeHTML:[content message] headers:NO
fontTags:NO
includingColorTags:NO
closeFontTags:NO
@@ -1045,17 +1054,17 @@
simpleTagsOnly:NO
bodyBackground:YES
allowJavascriptURLs:NO];
- [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
+ [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
withString:[NSString stringWithFormat:@"#%@", thisIsATemporaryString]];
} else {
[inString deleteCharactersInRange:NSUnionRange(range, endRange)];
- }
+ }
}
}
} while (range.location != NSNotFound);
if ([content isKindOfClass:[ESFileTransfer class]]) { //file transfers are an AIContentMessage subclass
-
+
ESFileTransfer *transfer = (ESFileTransfer *)content;
NSString *fileName = [[transfer remoteFilename] stringByEscapingForXMLWithEntities:nil];
NSString *fileTransferID = [[transfer uniqueID] stringByEscapingForXMLWithEntities:nil];
@@ -1073,13 +1082,13 @@
[inString replaceKeyword:@"%fileName%"
withString:fileName];
-
+
[inString replaceKeyword:@"%saveFileHandler%"
withString:[NSString stringWithFormat:@"client.handleFileTransfer('Save', '%@')", fileTransferID]];
-
+
[inString replaceKeyword:@"%saveFileAsHandler%"
withString:[NSString stringWithFormat:@"client.handleFileTransfer('SaveAs', '%@')", fileTransferID]];
-
+
[inString replaceKeyword:@"%cancelRequestHandler%"
withString:[NSString stringWithFormat:@"client.handleFileTransfer('Cancel', '%@')", fileTransferID]];
}
@@ -1092,24 +1101,24 @@
options:NSLiteralSearch
range:NSMakeRange(range.location + htmlEncodedMessage.length,
inString.length - range.location - htmlEncodedMessage.length)];
- }
-
+ }
+
// Topic replacement (if applicable)
if ([content isKindOfClass:[AIContentTopic class]]) {
range = [inString rangeOfString:@"%topic%"];
-
+
if (range.location != NSNotFound) {
[inString safeReplaceCharactersInRange:range withString:[NSString stringWithFormat:TOPIC_INDIVIDUAL_WRAPPER, htmlEncodedMessage]];
}
- }
+ }
} else if ([content isKindOfClass:[AIContentStatus class]]) {
NSString *statusPhrase;
BOOL replacedStatusPhrase = NO;
-
- [inString replaceKeyword:@"%status%"
+
+ [inString replaceKeyword:@"%status%"
withString:[[(AIContentStatus *)content status] stringByEscapingForXMLWithEntities:nil]];
-
- [inString replaceKeyword:@"%statusSender%"
+
+ [inString replaceKeyword:@"%statusSender%"
withString:[theSource.displayName stringByEscapingForXMLWithEntities:nil]];
[inString replaceKeyword:@"%senderScreenName%"
@@ -1125,13 +1134,13 @@
do{
range = [inString rangeOfString:@"%statusPhrase%"];
if (range.location != NSNotFound) {
- [inString safeReplaceCharactersInRange:range
+ [inString safeReplaceCharactersInRange:range
withString:[statusPhrase stringByEscapingForXMLWithEntities:nil]];
replacedStatusPhrase = YES;
}
} while (range.location != NSNotFound);
}
-
+
//Message (must do last)
range = [inString rangeOfString:@"%message%"];
if (range.location != NSNotFound) {
@@ -1142,7 +1151,7 @@
messageString = @"";
} else {
messageString = [AIHTMLDecoder encodeHTML:[content message]
- headers:NO
+ headers:NO
fontTags:NO
includingColorTags:NO
closeFontTags:YES
@@ -1157,7 +1166,7 @@
bodyBackground:NO
allowJavascriptURLs:NO];
}
-
+
[inString safeReplaceCharactersInRange:range withString:messageString];
}
}
@@ -1168,7 +1177,7 @@
- (NSMutableString *)fillKeywordsForBaseTemplate:(NSMutableString *)inString chat:(AIChat *)chat
{
NSRange range;
-
+
[inString replaceKeyword:@"%chatName%"
withString:[chat.displayName stringByEscapingForXMLWithEntities:nil]];
@@ -1176,46 +1185,46 @@
if(!sourceName) sourceName = @" ";
[inString replaceKeyword:@"%sourceName%"
withString:sourceName];
-
+
NSString *destinationName = chat.listObject.displayName;
if (!destinationName) destinationName = chat.displayName;
[inString replaceKeyword:@"%destinationName%"
withString:destinationName];
-
+
NSString *serversideDisplayName = chat.listObject.serversideDisplayName;
if (!serversideDisplayName) serversideDisplayName = chat.displayName;
[inString replaceKeyword:@"%destinationDisplayName%"
withString:[serversideDisplayName stringByEscapingForXMLWithEntities:nil]];
-
+
AIListContact *listObject = chat.listObject;
NSString *iconPath = nil;
-
+
[inString replaceKeyword:@"%incomingColor%"
withString:[NSColor representedColorForObject:listObject.UID withValidColors:self.validSenderColors]];
-
+
[inString replaceKeyword:@"%outgoingColor%"
withString:[NSColor representedColorForObject:chat.account.UID withValidColors:self.validSenderColors]];
-
+
if (listObject) {
iconPath = [listObject valueForProperty:KEY_WEBKIT_USER_ICON];
if (!iconPath)
iconPath = [listObject valueForProperty:@"UserIconPath"];
-
+
/* We couldn't get an icon... but perhaps we can for a parent contact */
if (!iconPath &&
[listObject isKindOfClass:[AIListContact class]] &&
([(AIListContact *)listObject parentContact] != listObject)) {
iconPath = [[(AIListContact *)listObject parentContact] valueForProperty:KEY_WEBKIT_USER_ICON];
if (!iconPath)
- iconPath = [[(AIListContact *)listObject parentContact] valueForProperty:@"UserIconPath"];
- }
+ iconPath = [[(AIListContact *)listObject parentContact] valueForProperty:@"UserIconPath"];
+ }
}
[inString replaceKeyword:@"%incomingIconPath%"
withString:(iconPath ? iconPath : @"incoming_icon.png")];
AIListObject *account = chat.account;
iconPath = nil;
-
+
if (account) {
iconPath = [account valueForProperty:KEY_WEBKIT_USER_ICON];
if (!iconPath)
@@ -1226,21 +1235,21 @@
NSString *serviceIconPath = [AIServiceIcons pathForServiceIconForServiceID:account.service.serviceID
type:AIServiceIconLarge];
-
+
NSString *serviceIconTag = [NSString stringWithFormat:@"<img class=\"serviceIcon\" src=\"%@\" alt=\"%@\" title=\"%@\">", serviceIconPath ? serviceIconPath : @"outgoing_icon.png", [account.service shortDescription], [account.service shortDescription]];
-
- [inString replaceKeyword:@"%service%"
+
+ [inString replaceKeyword:@"%service%"
withString:[account.service shortDescription]];
-
+
[inString replaceKeyword:@"%serviceIconImg%"
withString:serviceIconTag];
-
+
[inString replaceKeyword:@"%serviceIconPath%"
withString:serviceIconPath];
-
+
[inString replaceKeyword:@"%timeOpened%"
withString:[timeStampFormatter stringFromDate:[chat dateOpened]]];
-
+
//Replaces %time{x}% with a timestamp formatted like x (using NSDateFormatter)
do{
range = [inString rangeOfString:@"%timeOpened{"];
@@ -1248,9 +1257,9 @@
NSRange endRange;
endRange = [inString rangeOfString:@"}%" options:NSLiteralSearch range:NSMakeRange(NSMaxRange(range), [inString length] - NSMaxRange(range))];
- if (endRange.location != NSNotFound && endRange.location > NSMaxRange(range)) {
+ if (endRange.location != NSNotFound && endRange.location > NSMaxRange(range)) {
NSString *timeFormat = [inString substringWithRange:NSMakeRange(NSMaxRange(range), (endRange.location - NSMaxRange(range)))];
-
+
NSDateFormatter *dateFormatter;
if ([timeFormat rangeOfString:@"%"].location != NSNotFound) {
/* Support strftime-style format strings, which old message styles may use */
@@ -1259,28 +1268,28 @@
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:timeFormat];
}
-
- [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
+
+ [inString safeReplaceCharactersInRange:NSUnionRange(range, endRange)
withString:[dateFormatter stringFromDate:[chat dateOpened]]];
}
}
} while (range.location != NSNotFound);
-
+
[NSDateFormatter withLocalizedDateFormatterPerform:^(NSDateFormatter *dateFormatter){
[inString replaceKeyword:@"%dateOpened%"
withString:[dateFormatter stringFromDate:[chat dateOpened]]];
}];
-
+
//Background
{
range = [inString rangeOfString:@"==bodyBackground=="];
-
+
if (range.location != NSNotFound) { //a backgroundImage tag is not required
NSMutableString *bodyTag = nil;
- if (allowsCustomBackground && (customBackgroundPath || customBackgroundColor)) {
+ if (allowsCustomBackground && (customBackgroundPath || customBackgroundColor)) {
bodyTag = [[NSMutableString alloc] init];
-
+
if (customBackgroundPath) {
if ([customBackgroundPath length]) {
switch (customBackgroundType) {
@@ -1310,18 +1319,18 @@
[bodyTag appendString:[NSString stringWithFormat:@"background-color: rgba(%ld, %ld, %ld, %f); ", (NSInteger)(red * 255.0), (NSInteger)(green * 255.0), (NSInteger)(blue * 255.0), alpha]];
}
}
-
+
//Replace the body background tag
[inString safeReplaceCharactersInRange:range withString:(bodyTag ? (NSString *)bodyTag : @"")];
}
}
-
+
if ([inString rangeOfString:@"%variant%"].location != NSNotFound) {
/* Per #12702, don't allow spaces in the variant name, as otherwise it becomes multiple css classes */
[inString replaceKeyword:@"%variant%"
withString:[self.activeVariant stringByReplacingOccurrencesOfString:@" " withString:@"_"]];
}
-
+
return inString;
}
More information about the commits
mailing list