Legacy:ProfileImporter - Unreal Wiki

# Legacy:ProfileImporter

### From Unreal Wiki, The Unreal Engine Documentation Site

UT2003 :: Object >> Actor >> Info >> InternetInfo >> InternetLink >> TcpLink >> ProfileImporter (Ladder1.46)

1. //-----------------------------------------------------------
2. // Ladder.ProfileImporter
3. //
4. // Handles all communication with foreign servers containing
5. // exported profile information
6. // Stores remote profile URL locations
7. //-----------------------------------------------------------
8. class ProfileImporter extends TcpLink config(LadderProfiles);
10. const LOGTAG = 'ProfileImport';
12. var enum EImportResult
13. {
14. IMPORT_BadURL, // Incorrect URL format
15. IMPORT_ResolveError, // Couldn't resolve URL
16. IMPORT_BindError, // Couldn't bind port
17. IMPORT_InvalidProfile, // File was not a profile
18. IMPORT_TimeOut, // Timed out waiting
19. IMPORT_ServerError, // Unspecified Foreign Host Error
20. IMPORT_BadRequest, // Receieved 400 Error
21. IMPORT_Unauthorized, // Receieved 401 Error
22. IMPORT_Forbidden, // Receieved 403 Error
23. IMPORT_NotFound, // Receieved 404 Error
24. IMPORT_Success // Profile Successfully Imported
25. } ImportResult;
27. var bool bWaiting; //Waiting for ImportResult
29. struct ZipLocation
30. {
31. var string ProfileURL;
32. var string ZipName;
33. var string ZipURL;
34. };
36. var IpAddr ServerIP;
37. var LadderGameRules LadderRules;
38. var ProfileConfigSet RemoteProfile;
39. var LadderQuery QueryPage;
41. var Session ImportS;
42. var WebRequest QueryRequest;
43. var WebResponse QueryResponse;
45. var string Buffer;
46. var string Header;
47. var string LF; // Line Feed
48. var string CR; // Carriage Return
49. var string Token; // Token Delimiter
51. var string ProfileServerAddress;
52. var string RemoteProfilePath;
54. // Localized strings
55. var localized string BeginImportText;
57. // Localized error messages
58. var localized string ErrorText;
59. var localized string ErrorURLText;
60. var localized string ErrorResolvingText;
61. var localized string ErrorBindingText;
62. var localized string ErrorTimeoutText;
63. var localized string ErrorFNFText;
64. var localized string ErrorBadRequestText;
65. var localized string ErrorUnauthorizedText;
66. var localized string ErrorForbiddenText;
67. var localized string ErrorNoSession;
68. var localized string ErrorNoBuffer;
70. var localized string BadImportURLText;
72. var config array<ZipLocation> RemoteZips; // Remote profile zips locations
74. function PostBeginPlay()
75. {
76. Super.PostBeginPlay();
77. Disable('Tick');
79. LF = Chr(10);
80. CR = Chr(13);
81. Token = Chr(21);
82. }
84. function Tick(float DeltaTime)
85. {
86. Super.Tick(DeltaTime);
88. if (!bWaiting)
89. {
90. // Finish importing profile data, let LadderQuery finish sending page
91. QueryPage.RemoteImport(Self);
92. Disable('Tick');
93. }
94. }
96. function Timer()
97. {
98. log(ErrorTimeoutText @ ProfileServerAddress,LOGTAG);
99. ImportResult = IMPORT_Timeout;
100. bWaiting = False;
102. // Manually close the connection since
103. // we didn't receive a response
104. Close();
105. }
107. // Called from the Management Portal page
108. function bool Connect(string ProfileURL, Session TempS)
109. {
110. local string L, R;
112. bWaiting = True;
113. Enable('Tick');
115. log( BeginImportText @ ProfileURL, LOGTAG);
116. if ( Left(ProfileURL, 7) ~= "http://")
117. ProfileServerAddress = ParseDelimited(ProfileURL,"/",3);
118. else
119. {
120. log( ErrorURLText @ "\"http://\"!", LOGTAG);
121. ImportResult = IMPORT_BadURL;
122. bWaiting = False;
123. return false;
124. }
126. ServerIP.Port = 80;
127. if (InStr(ProfileServerAddress, ":") != -1)
128. {
129. Divide(ProfileServerAddress, ":", L, R);
130. ProfileServerAddress = L;
131. ServerIP.Port = int(R);
132. }
134. RemoteProfilePath = "/" $ ParseDelimited(ProfileURL,"/",4,True);
136. Buffer = "";
137. SetTimer(20.0, False);
138. ImportS = TempS;
139. Resolve( ProfileServerAddress );
140. return true;
141. }
143. event ResolveFailed()
144. {
145. log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
146. ImportResult = IMPORT_ResolveError;
147. bWaiting = False;
148. }
150. event Resolved(IpAddr NumericIP)
151. {
152. if( NumericIP.Addr == 0 )
153. {
154. log( ErrorResolvingText @ ProfileServerAddress, LOGTAG);
155. ImportResult = IMPORT_ResolveError;
156. bWaiting = False;
157. return;
158. }
159. ServerIP.Addr = NumericIP.Addr;
161. // Bind the local port.
162. if( BindPort() == 0 )
163. {
164. log( ErrorBindingText, LOGTAG);
165. ImportResult = IMPORT_BindError;
166. bWaiting = False;
167. return;
168. }
169. // Everything went OK - proceed to open connection
170. Open( ServerIP );
171. }
173. event Opened()
174. {
175. if (LinkMode != MODE_Line)
176. LinkMode = MODE_Line;
178. SetTimer(0.0, False); // Stop timeout counter
180. // Check header of file first, to make sure it's a valid file
181. RequestFile(0);
182. }
184. // Connection was closed by foreign host - Check header for response code
185. event Closed()
186. {
187. local string Result;
189. // First find header and respond accordingly
190. if (SeperateHeaders(Buffer))
191. Result = ProcessHeaders();
192. else
193. {
194. ImportResult = IMPORT_ServerError;
195. bWaiting = False;
196. return;
197. }
199. if (Result == "")
200. {
201. ImportResult = IMPORT_ServerError;
202. bWaiting = False;
203. return;
204. }
206. /* Possible Response Codes:
207. "200" ; OK
208. "201" ; Created
209. "202" ; Accepted
210. "204" ; No Content
211. "301" ; Moved Permanently
212. "302" ; Moved Temporarily
213. "304" ; Not Modified
214. "400" ; Bad Request
215. "401" ; Unauthorized
216. "403" ; Forbidden
217. "404" ; Not Found
218. "500" ; Internal Server Error
219. "501" ; Not Implemented
220. "502" ; Bad Gateway
221. "503" ; Service Unavailable
222. */
223. switch (Result)
224. {
225. case "200":
226. // Buffer should now only contain the actual document
227. // Fill ImportS from document info
228. if (FillSessionInfo())
229. ImportResult = IMPORT_Success;
230. break;
231. case "400":
232. log( ErrorBadRequestText, LOGTAG);
233. ImportResult = IMPORT_BadRequest;
234. break;
235. case "401":
236. log( ErrorUnauthorizedText, LOGTAG);
237. ImportResult = IMPORT_Unauthorized;
238. break;
239. case "403":
240. log( ErrorForbiddenText, LOGTAG);
241. ImportResult = IMPORT_Forbidden;
242. break;
243. default:
244. log( ErrorFNFText, LOGTAG);
245. ImportResult = IMPORT_NotFound;
246. }
247. bWaiting = False;
248. }
250. function bool FillSessionInfo()
251. {
252. local string Line;
253. local string Type;
254. local string Info;
255. local bool bValidProfile;
257. local string Token1, Token2, Token3, Token4, Token5, Token6, Token7;
259. if (ImportS == None)
260. {
261. log( ErrorNoSession, LOGTAG);
262. ImportResult = IMPORT_ServerError;
263. return false;
264. }
266. if (Buffer == "")
267. {
268. log(ErrorNoBuffer, LOGTAG);
269. ImportResult = IMPORT_ServerError;
270. return False;
271. }
272. else
273. {
274. while ( (Left(Buffer,1) ~= CR) || (Left(Buffer,1) ~= LF) )
275. Buffer = Mid(Buffer,1);
276. }
278. while (ReadBufferedLine(Line))
279. {
280. Divide(Line,Chr(58),Type,Info);
282. Token1 = ParseDelimited(Info,Token,1);
283. Token2 = ParseDelimited(Info,Token,2);
284. Token3 = ParseDelimited(Info,Token,3);
285. Token4 = ParseDelimited(Info,Token,4);
286. Token5 = ParseDelimited(Info,Token,5);
287. Token6 = ParseDelimited(Info,Token,6);
288. Token7 = ParseDelimited(Info,Token,7);
290. switch (Type)
291. {
292. case "Profile":
293. ImportS.setValue("ProfileName",Token1,True);
294. ImportS.setValue("GameType",Token2,True);
295. ImportS.setValue("MaxMaps",Token3,True);
296. ImportS.setValue("GameName",Token4,True);
297. ImportS.setValue("ACClass",Token5,True);
298. if (Token6 != "") ImportS.setValue("CustomGameLoc",Token6,True);
299. if (Token7 != "") ImportS.setValue("CustomACLoc",Token7,True);
300. bValidProfile = True;
301. break;
303. case "Map":
304. ImportS.setMap(Token1,int(Token2),True,bool(Token3));
305. if (Token4 != "") AddRemoteZipLocation(Token1,Token4);
306. break;
308. case "Mutator":
309. ImportS.setMutator(Token2,True,bool(Token3));
310. if (Token4 != "") AddRemoteZipLocation(Token2,Token4);
312. case "Data":
313. ImportS.setValue(Token1,Token2,True);
314. break;
315. }
316. }
318. if (bValidProfile)
319. return true;
321. ImportResult = IMPORT_InvalidProfile;
322. return false;
323. }
325. function AddRemoteZipLocation(string PackageName, string PackageLocation)
326. {
327. local int i;
328. local bool ZipFound;
330. local ZipLocation Zip;
332. i = InStr(PackageName, ".");
333. if (i != -1)
334. PackageName = Left(PackageName,i);
336. Zip.ProfileURL = ProfileServerAddress $ RemoteProfilePath;
337. Zip.ZipName = PackageName;
338. Zip.ZipURL = PackageLocation;
340. for (i = 0; i < RemoteZips.Length; i++)
341. {
342. if (RemoteZips[i].ProfileURL ~= Zip.ProfileURL && RemoteZips[i].ZipName ~= Zip.ZipName)
343. {
344. ZipFound = True;
345. break;
346. }
347. }
349. if (ZipFound) RemoteZips[i] = Zip;
350. else RemoteZips[RemoteZips.Length] = Zip;
352. SaveConfig();
353. }
355. function string FindRemoteZipLocation(string PackageName, string ProfileURL, optional bool bAllowOtherLocations)
356. {
357. local int i;
359. i = InStr(PackageName, ".");
360. if (i != -1) PackageName = Left(PackageName,i);
362. for (i = 0;i < RemoteZips.Length; i++)
363. if ((RemoteZips[i].ZipName ~= PackageName) && ((RemoteZips[i].ProfileURL ~= ProfileURL) || (bAllowOtherLocations)) )
364. return RemoteZips[i].ZipURL;
366. return "";
367. }
369. function bool SeperateHeaders(string WebPage)
370. {
371. local int i;
373. //CR$LF$CR$LF seperates header and document
374. i = InStr(WebPage, CR$LF$CR$LF);
376. if (i == -1)
377. return false;
379. Header = Left(WebPage, i);
380. Buffer = Mid(WebPage, i + 3);
381. return true;
382. }
384. function string ProcessHeaders()
385. {
386. if (Header == "")
387. return "";
389. //Remove all CR, leaving only LF
390. Header = RemoveStr(Header,CR);
392. //Parse Response Code from server, ex. HTTP/1.1 200 OK
393. return Mid(ParseDelimited(Header,LF,1),9,3);
394. }
396. event ReceivedText(string Text)
397. {
398. Buffer = Buffer $ Text;
399. }
401. event ReceivedLine(string Line)
402. {
403. local string Result;
405. if (SeperateHeaders(Line))
406. Result = ProcessHeaders();
408. if (Result == "200")
409. {
410. Result = FindContentType(Line);
411. if (Result ~= "text/plain")
412. {
413. RequestFile(1);
414. LinkMode = Mode_Text;
415. }
416. else
417. {
418. ImportResult = IMPORT_InvalidProfile;
419. bWaiting = False;
420. }
421. }
423. else
424. {
425. ImportResult = IMPORT_NotFound;
426. bWaiting = False;
427. }
428. }
430. function string FindContentType(string Text)
431. {
432. local array<string> Lines;
433. local string Tmp;
434. local int i, j;
436. Buffer = Text;
437. while (ReadBufferedLine(Tmp))
438. Lines[Lines.Length] = Tmp;
440. for (i=0;i<Lines.Length;i++)
441. {
442. if (Left(Lines[i],13) ~= "Content-Type:")
443. {
444. Tmp = Mid(Lines[i],14);
445. j = InStr(Tmp,";");
446. if (j >= 0)
447. Tmp = Left(Tmp,j);
448. }
449. }
451. return Tmp;
452. }
454. function RequestFile(int RequestType)
455. {
456. local string RequestMethod, ControlText;
458. if (RequestType == 0)
459. {
460. RequestMethod = "HEAD";
461. ControlText = "Keep-Alive";
462. }
463. else
464. {
465. RequestMethod = "GET";
466. ControlText = "close";
467. }
469. SendText(RequestMethod@RemoteProfilePath@"HTTP/1.1");
470. SendText("Host:"@ProfileServerAddress);
471. SendText("Accept: text/plain"); // Accept only plain txt files
472. SendText("User-agent: ProfileManager; UT2003"@Level.EngineVersion);
473. SendText("Pragma: no-cache"); // Do not allow proxies to send cached information
474. SendText("Cache-control: no-cache");
475. SendText("Connection:"@ControlText); // No further information to be sent
476. SendText("");
477. }
479. function bool ReadBufferedLine(out string Text)
480. {
481. local int i;
483. i = InStr(Buffer, LF);
485. if(i == -1)
486. return False;
488. if (Mid(Buffer, i-1, 1) == CR)
489. Text = Left(Buffer, i-1);
490. else Text = Left(Buffer, i);
492. Buffer = Mid(Buffer, i+1);
493. return True;
494. }
496. // Copied from BufferedTcpLink
497. function string ParseDelimited(string Text, string Delimiter, int Count, optional bool bToEndOfLine)
498. {
499. local string Result;
500. local int Found, i;
501. local string s;
503. Result = "";
504. Found = 1;
506. for(i=0;i<Len(Text);i++)
507. {
508. s = Mid(Text, i, 1);
509. if(InStr(Delimiter, s) != -1)
510. {
511. if(Found == Count)
512. {
513. if(bToEndOfLine)
514. return Result$Mid(Text, i);
515. else
516. return Result;
517. }
519. Found++;
520. }
521. else
522. {
523. if(Found >= Count)
524. Result = Result $ s;
525. }
526. }
528. return Result;
529. }
531. function string RemoveStr(string Source,string mask)
532. {
533. local int i;
534. local string left,right;
536. i = InStr(Source,mask);
537. while (i != -1)
538. {
539. Divide(Source,mask,left,right);
540. Source = Left$Right;
541. i = InStr(Source,Mask);
542. }
544. return Source;
545. }

##### Views

- Legacy
- Discussion
- Current revision

##### Search