Converted these images to PNG, saving a handful of bytes per image
[adiumx.git] / Plugins / Translation / AITranslatorRequestDelegate.m
blob7f4d2ffe020ac42a51010f79b91850864b124c40
1 //
2 //  AITranslatorRequestDelegate.m
3 //  Adium
4 //  Created by Evan Schoenberg on 3/12/06.
6 /* Response decoding based on:
7  * TranslationEngine.m
8  * Fire
9  *
10  * Created by Alan Humpherys on Wed Mar 19 2003.
11  * Copyright (c) 2003. All rights reserved.
12  * 
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
28 #import "AITranslatorRequestDelegate.h"
29 #import "TranslationEngine.h"
30 #import "AITranslatorPlugin.h"
31 #import <AIUtilities/AIStringAdditions.h>
33 @interface AITranslatorRequestDelegate (PRIVATE)
34 - (id)initWithDict:(NSDictionary *)inDict notifyingTarget:(id)inTarget;
35 @end
37 @implementation AITranslatorRequestDelegate
38 + (id)translatorRequestDelegateForDict:(NSDictionary *)inDict notifyingTarget:(id)inTarget
40         return [[[self alloc] initWithDict:inDict notifyingTarget:inTarget] autorelease];
43 - (id)initWithDict:(NSDictionary *)inDict notifyingTarget:(id)inTarget
45         if ((self = [super init])) {
46                 messageDict = [inDict retain];
47                 target = [inTarget retain];
48                 state = Translator_SearchForTextArea;
49                 response = [[NSMutableString alloc] init];
50                 targetRange = NSMakeRange(0,0);
51                 
52         }
53         
54         return self;
57 - (void)dealloc
59         [messageDict release];
60         [target release];
61         [response release];
63         [super dealloc];
66 - (void)searchCompletedWithLocation:(int)location
68         NSString        *translation;
70         // Reset the Range to reflect the returned translation
71         targetRange = NSMakeRange(0, location);
73         // We may have some newlines and spaces at the beginning of the range.  If we do, let's
74     // skip past those.
75     while ([response characterAtIndex:(targetRange.location)] == '\n' ||
76            [response characterAtIndex:(targetRange.location)] == '\r' ||
77            [response characterAtIndex:(targetRange.location)] == ' ') {
78         targetRange.location++;
79         targetRange.length--;
80     }
81         
82     // Now we might have some extra newlines and spaces at the end of our range.  Let's
83     // fix that, too.
84     while ([response characterAtIndex:(targetRange.location+targetRange.length-1)] == '\n' ||
85            [response characterAtIndex:(targetRange.location+targetRange.length-1)] == '\r' ||
86            [response characterAtIndex:(targetRange.location+targetRange.length-1)] == ' ') {
87         targetRange.length--;
88     }
89         
90     translation = [response substringWithRange:targetRange];
91         
92     if (!translation || [translation length] == 0) {
93         TRANSLATION_ERROR(TE_UNKNOWN_ERROR);
94         return;
95     }
96         
97     // The worldlingo website may add a meta tag to the start of the returned string.  We must delete this
98     // tag because the clients do not understand it.
99     targetRange = [translation rangeOfString:@"<meta "];
100     if (targetRange.location != NSNotFound) {
101         NSRange endRange = [translation rangeOfString:@">" 
102                                                                                           options:NSLiteralSearch
103                                                                                                 range:NSMakeRange(targetRange.location + targetRange.length,
104                                                                                                                                   [translation length] - targetRange.location - targetRange.length)];
105         
106         if (endRange.location != NSNotFound) {
107             response = [NSMutableString stringWithString:translation];
108             [response deleteCharactersInRange:NSMakeRange(targetRange.location,endRange.location - targetRange.location + 1)];
110                         // Make a copy to ensure type integrity
111             translation = [NSString stringWithString:response];
112         }
113     }
114         
115         [target translatedString:translation forMessageDict:messageDict];               
118 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
120         //      The target looks like:
121     //  <textarea name="wl_result"...>This is what we're looking for.</textarea>
122     //  Receive characters from the server.  We'll keep going as long as
123     //  we haven't found the closing </textarea>
124         if (state != Translator_SearchCompleted) {
125                 NSString *retrievedData = [NSString stringWithData:data encoding:NSUTF8StringEncoding];
126                 if (retrievedData && [retrievedData length]) {
127                         [response appendString:retrievedData];
128                 } else {
129                         AILog(@"Null new data.. %@ so far...",response);
130                 }
131                 
132         switch (state) {
133             case Translator_SearchForTextArea:
134                         {
135                 targetRange = [response rangeOfString:@"<textarea name=\"wl_result\""];
136                 if (targetRange.location == NSNotFound) {
137                     break;
138                 } else {
139                     // found textarea beginning
140                     state = Translator_SearchForEndOfTag;
141                     // Throw away all preamble data
142                     targetRange.length = targetRange.location + targetRange.length;
143                     targetRange.location = 0;
144                     [response deleteCharactersInRange:targetRange];
145                     // fall through to next state
146                 }
147                         }
148                         case Translator_SearchForEndOfTag:
149                         {
150                                 targetRange = [response rangeOfString:@">"];
151                                 if (targetRange.location == NSNotFound) {
152                                         break;
153                                 } else {
154                                         // found closing of <textarea *> tag
155                                         state = Translator_SearchForTextAreaClose;
156                                         // Throw away all preamble data
157                                         targetRange.length = targetRange.location + targetRange.length;
158                                         targetRange.location = 0;
159                                         [response deleteCharactersInRange:targetRange];
160                                         // fall through to next state
161                                 }
162                         }
163                         case Translator_SearchForTextAreaClose:
164                         {
165                                 targetRange = [response rangeOfString:@"</textarea>"];
166                                 if (targetRange.location != NSNotFound) {
167                                         // found closing of </textarea> tag
168                                         state = Translator_SearchCompleted;
169                                 }
170                                 break;
171                         }
172                         case Translator_SearchCompleted:
173                                 break;
174         }
175                 
176                 if (!response || [response length] == 0) {
177                         TRANSLATION_ERROR(TE_NO_RESPONSE);
178                         return;
179                 }
180         }
181         
182         if (state == Translator_SearchCompleted) {
183                 if (targetRange.location == 0) {
184                         TRANSLATION_ERROR(TE_EMPTY_RESPONSE);
185                         return;
186                 }
188                 [self searchCompletedWithLocation:targetRange.location];
189                 [connection cancel];
190         }
193 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
195         AILog(@"Translation failed: %@", [error localizedDescription]);
198 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
200     if (state != Translator_SearchCompleted) {
201         TRANSLATION_ERROR(TE_CANT_DECODE);
202     }
205 @end