open-tibia-tools 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +29 -0
  2. package/effectFramesGenerator.html +42 -0
  3. package/effectFramesGenerator.ts +95 -0
  4. package/itemImageFramesGenerator.html +45 -0
  5. package/itemImageFramesGenerator.ts +140 -0
  6. package/itemImageGenerator.html +40 -0
  7. package/itemImageGenerator.ts +161 -0
  8. package/missileFramesGenerator.html +42 -0
  9. package/missileFramesGenerator.ts +95 -0
  10. package/otbEditor.html +21 -0
  11. package/otbEditor.ts +106 -0
  12. package/outfitImageGenerator.html +38 -0
  13. package/outfitImageGenerator.ts +109 -0
  14. package/outfitImagePhpGeneratorCode.ts +19 -0
  15. package/package.json +28 -0
  16. package/tests.html +29 -0
  17. package/tests.ts +218 -0
  18. package/tools/colored-outfit-images-generator/README.md +7 -0
  19. package/tools/colored-outfit-images-generator/abuse_warning.png +0 -0
  20. package/tools/colored-outfit-images-generator/animoutfit.php +103 -0
  21. package/tools/colored-outfit-images-generator/cacheGenerator.php +40 -0
  22. package/tools/colored-outfit-images-generator/config.php +25 -0
  23. package/tools/colored-outfit-images-generator/filesAsJson.php +22 -0
  24. package/tools/colored-outfit-images-generator/index.php +21 -0
  25. package/tools/colored-outfit-images-generator/libs/gifCreator.php +343 -0
  26. package/tools/colored-outfit-images-generator/libs/outfitter.php +312 -0
  27. package/tools/colored-outfit-images-generator/outfit.php +77 -0
  28. package/tools/colored-outfit-images-generator/release.php +40 -0
  29. package/tools/item-image-frames-to-animated-gif-converter/1-10/1.gif +0 -0
  30. package/tools/item-image-frames-to-animated-gif-converter/1-10/1.png +0 -0
  31. package/tools/item-image-frames-to-animated-gif-converter/1-10/10.gif +0 -0
  32. package/tools/item-image-frames-to-animated-gif-converter/1-10/10.png +0 -0
  33. package/tools/item-image-frames-to-animated-gif-converter/1-10/2.gif +0 -0
  34. package/tools/item-image-frames-to-animated-gif-converter/1-10/2.png +0 -0
  35. package/tools/item-image-frames-to-animated-gif-converter/1-10/3.gif +0 -0
  36. package/tools/item-image-frames-to-animated-gif-converter/1-10/3.png +0 -0
  37. package/tools/item-image-frames-to-animated-gif-converter/1-10/4.gif +0 -0
  38. package/tools/item-image-frames-to-animated-gif-converter/1-10/4.png +0 -0
  39. package/tools/item-image-frames-to-animated-gif-converter/1-10/5.gif +0 -0
  40. package/tools/item-image-frames-to-animated-gif-converter/1-10/5.png +0 -0
  41. package/tools/item-image-frames-to-animated-gif-converter/1-10/6.gif +0 -0
  42. package/tools/item-image-frames-to-animated-gif-converter/1-10/6.png +0 -0
  43. package/tools/item-image-frames-to-animated-gif-converter/1-10/7.gif +0 -0
  44. package/tools/item-image-frames-to-animated-gif-converter/1-10/7.png +0 -0
  45. package/tools/item-image-frames-to-animated-gif-converter/1-10/8.gif +0 -0
  46. package/tools/item-image-frames-to-animated-gif-converter/1-10/8.png +0 -0
  47. package/tools/item-image-frames-to-animated-gif-converter/1-10/9.gif +0 -0
  48. package/tools/item-image-frames-to-animated-gif-converter/1-10/9.png +0 -0
  49. package/tools/item-image-frames-to-animated-gif-converter/README.md +20 -0
  50. package/tools/item-image-frames-to-animated-gif-converter/cli_convert.php +42 -0
  51. package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/.gitignore +3 -0
  52. package/tools/item-image-frames-to-animated-gif-converter/generated-zip-archives/index.html +1 -0
  53. package/tools/item-image-frames-to-animated-gif-converter/index.php +97 -0
  54. package/tools/item-image-frames-to-animated-gif-converter/lib/abstractPngConverterAnimation.php +87 -0
  55. package/tools/item-image-frames-to-animated-gif-converter/lib/apngCreator.php +247 -0
  56. package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToApngAnimation.php +93 -0
  57. package/tools/item-image-frames-to-animated-gif-converter/lib/converterPngToGifAnimation.php +90 -0
  58. package/tools/item-image-frames-to-animated-gif-converter/lib/gifCreator.php +339 -0
  59. package/tsconfig.json +12 -0
  60. package/webpack.config.js +53 -0
  61. package/websiteImageGeneratorBase.ts +156 -0
@@ -0,0 +1,95 @@
1
+ import {DatManager, DatThingCategory, GameFeature, ImageGenerator, OtbManager, SpriteManager} from "@gesior/open-tibia-library";
2
+ import {WebsiteImageGeneratorBase} from "./websiteImageGeneratorBase";
3
+
4
+ class MissileFramesGenerator extends WebsiteImageGeneratorBase {
5
+ private forceEnableExtendedSpritesCheckbox: HTMLInputElement;
6
+ private enableTransparencyCheckbox: HTMLInputElement;
7
+ private enableEnhancedAnimationsCheckbox: HTMLInputElement;
8
+ private enableIdleAnimationsCheckbox: HTMLInputElement;
9
+
10
+ init() {
11
+ this.otbRequired = false;
12
+ super.init();
13
+ this.forceEnableExtendedSpritesCheckbox = <HTMLInputElement>document.getElementById('forceEnableExtendedSprites');
14
+ this.enableTransparencyCheckbox = <HTMLInputElement>document.getElementById('enableTransparency');
15
+ this.enableEnhancedAnimationsCheckbox = <HTMLInputElement>document.getElementById('enableEnhancedAnimations');
16
+ this.enableIdleAnimationsCheckbox = <HTMLInputElement>document.getElementById('enableIdleAnimations');
17
+ }
18
+
19
+ afterSetClientVersion() {
20
+ if (this.forceEnableExtendedSpritesCheckbox.checked) {
21
+ this.client.enableFeature(GameFeature.GameSpritesU32);
22
+ }
23
+ if (this.enableTransparencyCheckbox.checked) {
24
+ this.client.enableFeature(GameFeature.GameSpritesAlphaChannel);
25
+ }
26
+ if (this.enableEnhancedAnimationsCheckbox.checked) {
27
+ this.client.enableFeature(GameFeature.GameEnhancedAnimations);
28
+ }
29
+ if (this.enableIdleAnimationsCheckbox.checked) {
30
+ this.client.enableFeature(GameFeature.GameIdleAnimations);
31
+ }
32
+ }
33
+
34
+ startImageGenerator(imageGenerator: ImageGenerator, otbManager: OtbManager, datManager: DatManager, spriteManager: SpriteManager, zip) {
35
+ this.generateMissileImage(imageGenerator, datManager, zip, 0);
36
+ }
37
+
38
+ generateMissileImage(imageGenerator: ImageGenerator, datManager: DatManager, zip, missileId: number) {
39
+ const self = this;
40
+ this.progressValue(missileId, datManager.getCategory(DatThingCategory.ThingCategoryMissile).length);
41
+ if (missileId > datManager.getCategory(DatThingCategory.ThingCategoryMissile).length) {
42
+ this.progressText('Packing images to ZIP file, please wait (it may take a while)');
43
+ zip.generateAsync({type: "blob"}).then(function (blob: Blob) {
44
+ console.log('zip size', blob.size);
45
+ self.progressText('ZIP generated, it should start download now.');
46
+ self.downloadBlob('missiles.zip', blob);
47
+ });
48
+ return;
49
+ }
50
+
51
+ let missileThingType = this.datManager.getMissile(missileId);
52
+ if (!missileThingType) {
53
+ console.log('dat ID not found in dat file', missileId);
54
+ setTimeout(function () {
55
+ self.generateMissileImage(imageGenerator, datManager, zip, missileId + 1);
56
+ }, 1);
57
+ return;
58
+ }
59
+
60
+ const missileSprites = imageGenerator.generateMissileImagesById(missileId);
61
+ if (!missileSprites || missileSprites.length == 0) {
62
+ setTimeout(function () {
63
+ self.generateMissileImage(imageGenerator, datManager, zip, missileId + 1);
64
+ }, 1);
65
+ return;
66
+ }
67
+
68
+ const firstMissileSprite = missileSprites[0];
69
+ const canvas = <HTMLCanvasElement>document.createElement('canvas');
70
+ canvas.width = firstMissileSprite.getWidth() * missileSprites.length;
71
+ canvas.height = firstMissileSprite.getHeight();
72
+ document.getElementsByTagName('body')[0].appendChild(canvas);
73
+ const ctx = canvas.getContext("2d");
74
+
75
+ for (let animationFrame = 0; animationFrame < missileSprites.length; animationFrame++) {
76
+ const palette = ctx.getImageData(firstMissileSprite.getWidth() * animationFrame, 0, firstMissileSprite.getWidth(), firstMissileSprite.getHeight());
77
+ const missileSprite = missileSprites[animationFrame];
78
+ palette.data.set(new Uint8ClampedArray(missileSprite.getPixels().m_buffer.buffer));
79
+ ctx.putImageData(palette, firstMissileSprite.getWidth() * animationFrame, 0);
80
+ }
81
+
82
+ const callback = function (blob) {
83
+ canvas.remove();
84
+ zip.file('missiles/' + missileId + '_' + missileSprites.length + '.png', blob);
85
+ setTimeout(function () {
86
+ self.generateMissileImage(imageGenerator, datManager, zip, missileId + 1);
87
+ }, 1);
88
+
89
+ };
90
+ canvas.toBlob(callback);
91
+ }
92
+ }
93
+
94
+ const missileFramesGenerator = new MissileFramesGenerator();
95
+ missileFramesGenerator.init();
package/otbEditor.html ADDED
@@ -0,0 +1,21 @@
1
+ <html>
2
+ <head>
3
+ <title>OTB editor example - OpenTibiaLibrary</title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
5
+ </head>
6
+ <body>
7
+ <h2>OTB editor example</h2>
8
+ Client Version: <input type="number" id="clientversion" value="860"/> (format 860, NOT 8.60, clients: 740 - 1099, type <b>1099</b> for latest .dat+.spr version [ex. from 12+])<br/>
9
+ Otb file: <input type="file" id="otb"/><br/>
10
+ <br/>
11
+ <button id="loadFile">LOAD FILE</button>
12
+ <br/>
13
+ <br/>
14
+ <button id="generateFile">GENERATE PROCESSED FILE</button>
15
+ <br/>
16
+ <br/>
17
+ <b>Progress:</b> <span id="progressBar">Not running</span><br/>
18
+ <script src="js/vendor.js"></script>
19
+ <script src="js/otbEditor.js"></script>
20
+ </body>
21
+ </html>
package/otbEditor.ts ADDED
@@ -0,0 +1,106 @@
1
+ import {Client, InputFile, OtbManager} from "@gesior/open-tibia-library";
2
+
3
+ /**
4
+ * Simple items.otb file editor example. Edit OTB file using TypeScript code!
5
+ * All it does is:
6
+ * - load .otb file
7
+ * - remove items with Client ID (Tibia.dat ID) higher than 5090
8
+ * - save new .otb file
9
+ *
10
+ * All logic is in function 'processOtbFile'
11
+ */
12
+
13
+ class OtbEditor {
14
+ protected clientVersionInput: HTMLInputElement;
15
+ protected otbPicker: HTMLInputElement;
16
+ protected loadFileButton: HTMLButtonElement;
17
+ protected generateFileButton: HTMLButtonElement;
18
+
19
+ protected otbManager: OtbManager;
20
+ protected client: Client;
21
+
22
+ init() {
23
+ this.clientVersionInput = <HTMLInputElement>document.getElementById('clientversion');
24
+ this.otbPicker = <HTMLInputElement>document.getElementById('otb');
25
+ this.loadFileButton = <HTMLButtonElement>document.getElementById('loadFile');
26
+ this.generateFileButton = <HTMLButtonElement>document.getElementById('generateFile');
27
+ const self = this;
28
+ this.loadFileButton.onclick = function () {
29
+ self.loadFiles();
30
+ };
31
+ this.generateFileButton.onclick = function () {
32
+ if (!self.otbManager) {
33
+ self.progressText('Cannot generate. Load file first.');
34
+ return;
35
+ }
36
+
37
+ self.processOtbFile();
38
+
39
+ let otbFile = self.otbManager.saveOtb();
40
+ self.downloadBlob('items.otb', new Blob(new Array(otbFile.getUint8Array())));
41
+ };
42
+ }
43
+
44
+ processOtbFile() {
45
+ for (let serverItemId = 0; serverItemId <= this.otbManager.getLastId(); serverItemId++) {
46
+ if (this.otbManager.isValidOtbId(serverItemId)) {
47
+ let item = this.otbManager.getItem(serverItemId)
48
+ if (item.getClientId() > 5090) {
49
+ console.log('removing item from .otb, server ID', item.getServerId(), 'client ID', item.getClientId());
50
+ this.otbManager.removeItemType(item)
51
+ }
52
+ }
53
+ }
54
+ }
55
+
56
+ loadFiles() {
57
+ let clientVersion = parseInt(this.clientVersionInput.value);
58
+ this.progressText('Loading client version ' + clientVersion);
59
+ this.client = new Client();
60
+ this.client.setClientVersion(clientVersion);
61
+ this.progressText('Loading OTB file');
62
+ const self = this;
63
+ setTimeout(function () {
64
+ self.loadOtb()
65
+ }, 10);
66
+ }
67
+
68
+ loadOtb() {
69
+ if (this.otbPicker.files.length > 0) {
70
+ this.otbManager = new OtbManager(this.client);
71
+ const file = this.otbPicker.files[0];
72
+ var reader = new FileReader();
73
+ reader.readAsArrayBuffer(file);
74
+ const self = this;
75
+ reader.onload = function (event: any) {
76
+ const otbLoaded = self.otbManager.loadOtb(InputFile.fromUint8Array(new Uint8Array(event.target.result)));
77
+ if (otbLoaded) {
78
+ self.progressText('Data loaded. You can click "Generate processed file" now.');
79
+ } else {
80
+ self.otbManager = null;
81
+ self.progressText('ERROR: Failed to load OTB file');
82
+ }
83
+ }
84
+ } else {
85
+ this.progressText('ERROR: Please select OTB file');
86
+ }
87
+ }
88
+
89
+ downloadBlob(filename: string, blob: Blob) {
90
+ const a = document.createElement('a');
91
+ const url = window.URL.createObjectURL(blob);
92
+ a.href = url;
93
+ a.download = filename;
94
+ a.click();
95
+ window.URL.revokeObjectURL(url);
96
+ a.remove();
97
+ }
98
+
99
+ progressText(text: string) {
100
+ document.getElementById('progressBar').innerText = text;
101
+ }
102
+
103
+ }
104
+
105
+ const otbEditor = new OtbEditor();
106
+ otbEditor.init();
@@ -0,0 +1,38 @@
1
+ <html>
2
+ <head>
3
+ <title>Outfit Image Generator - OpenTibiaLibrary</title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
5
+ </head>
6
+ <body>
7
+ <h2>Outfit images generator</h2>
8
+ <blockquote>
9
+ How to use:<br/><br/>
10
+ 1. Type version of Tibia client.<br/>
11
+ 2. Select SPR and DAT files.<br/>
12
+ 3. Click "LOAD FILES", watch "Progress".<br/>
13
+ 4. Click "GENERATE IMAGES", wait for ZIP file download.<br/>
14
+ <br/>
15
+ <b>FILES ARE NOT SEND TO SERVER! EVERYTHING IS GENERATED ON YOUR COMPUTER.</b><br/>
16
+ <br/>
17
+ (Enable Developer console in webbrowser to get more information about problems/progress)
18
+ </blockquote>
19
+ Client Version: <input type="number" id="clientversion" value="860"/> (format 860, NOT 8.60, clients: 740 - 1099, type <b>1099</b> for latest .dat+.spr version [ex. from 12+])<br/>
20
+ Sprite file: <input type="file" id="spr"/><br/>
21
+ Dat file: <input type="file" id="dat"/><br/>
22
+ Load idle animation when possible: <input type="checkbox" id="idleAnimation" checked/><br/>
23
+ Force enable extended sprites: <input type="checkbox" id="forceEnableExtendedSprites"/> (OTC feature 'GameSpritesU32')<br/>
24
+ Enable transparency: <input type="checkbox" id="enableTransparency"/> (OTC feature 'GameSpritesAlphaChannel')<br/>
25
+ Enable improved animations: <input type="checkbox" id="enableEnhancedAnimations"/> (OTC feature 'GameEnhancedAnimations')<br/>
26
+ Enable frame groups: <input type="checkbox" id="enableIdleAnimations"/> (OTC feature 'GameIdleAnimations')<br/>
27
+ <br/>
28
+ <button id="loadFiles">LOAD FILES</button>
29
+ <br/>
30
+ <br/>
31
+ <button id="generateImages">GENERATE IMAGES</button>
32
+ <br/>
33
+ <br/>
34
+ <b>Progress:</b> <span id="progressBar">Not running</span><br/>
35
+ <script src="js/vendor.js"></script>
36
+ <script src="js/outfitImageGenerator.js"></script>
37
+ </body>
38
+ </html>
@@ -0,0 +1,109 @@
1
+ import {DatManager, DatThingCategory, FrameGroupType, GameFeature, ImageGenerator, OtbManager, SpriteManager} from "@gesior/open-tibia-library";
2
+ import {WebsiteImageGeneratorBase} from "./websiteImageGeneratorBase";
3
+ import {OutfitImagePhpGeneratorCode} from "./outfitImagePhpGeneratorCode";
4
+
5
+ class OutfitImageGenerator extends WebsiteImageGeneratorBase {
6
+ private idleAnimationCheckbox: HTMLInputElement;
7
+ private forceEnableExtendedSpritesCheckbox: HTMLInputElement;
8
+ private enableTransparencyCheckbox: HTMLInputElement;
9
+ private enableEnhancedAnimationsCheckbox: HTMLInputElement;
10
+ private enableIdleAnimationsCheckbox: HTMLInputElement;
11
+
12
+ private idleAnimation = true;
13
+
14
+ init() {
15
+ this.otbRequired = false;
16
+ super.init();
17
+ this.idleAnimationCheckbox = <HTMLInputElement>document.getElementById('idleAnimation');
18
+ this.forceEnableExtendedSpritesCheckbox = <HTMLInputElement>document.getElementById('forceEnableExtendedSprites');
19
+ this.enableTransparencyCheckbox = <HTMLInputElement>document.getElementById('enableTransparency');
20
+ this.enableEnhancedAnimationsCheckbox = <HTMLInputElement>document.getElementById('enableEnhancedAnimations');
21
+ this.enableIdleAnimationsCheckbox = <HTMLInputElement>document.getElementById('enableIdleAnimations');
22
+ }
23
+
24
+ afterSetClientVersion() {
25
+ if (this.forceEnableExtendedSpritesCheckbox.checked) {
26
+ this.client.enableFeature(GameFeature.GameSpritesU32);
27
+ }
28
+ if (this.enableTransparencyCheckbox.checked) {
29
+ this.client.enableFeature(GameFeature.GameSpritesAlphaChannel);
30
+ }
31
+ if (this.enableEnhancedAnimationsCheckbox.checked) {
32
+ this.client.enableFeature(GameFeature.GameEnhancedAnimations);
33
+ }
34
+ if (this.enableIdleAnimationsCheckbox.checked) {
35
+ this.client.enableFeature(GameFeature.GameIdleAnimations);
36
+ }
37
+ }
38
+
39
+ startImageGenerator(imageGenerator: ImageGenerator, otbManager: OtbManager, datManager: DatManager, spriteManager: SpriteManager, zip) {
40
+ this.idleAnimation = this.idleAnimationCheckbox.checked;
41
+ this.generateOutfitImage(imageGenerator, otbManager, datManager, zip, 0);
42
+ }
43
+
44
+ generateOutfitImage(imageGenerator: ImageGenerator, otbManager: OtbManager, datManager: DatManager, zip, outfitId: number) {
45
+ const self = this;
46
+ this.progressValue(outfitId, datManager.getCategory(DatThingCategory.ThingCategoryCreature).length);
47
+ if (outfitId > datManager.getCategory(DatThingCategory.ThingCategoryCreature).length) {
48
+ this.progressText('Packing images to ZIP file, please wait (it may take a while)');
49
+
50
+ const outfitImagePhpGeneratorCode = new OutfitImagePhpGeneratorCode();
51
+ outfitImagePhpGeneratorCode.addFilesToZip(zip);
52
+
53
+ zip.generateAsync({type: "blob"}).then(function (blob: Blob) {
54
+ console.log('zip size', blob.size);
55
+ self.progressText('ZIP generated, it should start download now.');
56
+ self.downloadBlob('outfits.zip', blob);
57
+ });
58
+ return;
59
+ }
60
+
61
+ let outfitSprites;
62
+ if (this.idleAnimation) {
63
+ outfitSprites = imageGenerator.generateOutfitAnimationImages(outfitId, FrameGroupType.FrameGroupIdle);
64
+ }
65
+ if (!outfitSprites || outfitSprites.length == 0) {
66
+ outfitSprites = imageGenerator.generateOutfitAnimationImages(outfitId, FrameGroupType.FrameGroupMoving);
67
+ }
68
+ if (!outfitSprites || outfitSprites.length == 0) {
69
+ setTimeout(function () {
70
+ self.generateOutfitImage(imageGenerator, otbManager, datManager, zip, outfitId + 1);
71
+ }, 1);
72
+ return;
73
+ }
74
+
75
+ let outfitThingType = this.datManager.getOutfit(outfitId);
76
+ if (outfitThingType && outfitThingType.hasBones()) {
77
+ zip.file('outfits_anim/' + outfitId + '/bones.json', JSON.stringify(outfitThingType.getBones()));
78
+ }
79
+
80
+ let spritesToProcess = outfitSprites.length;
81
+ for (let outfitSprite of outfitSprites) {
82
+ const canvas = <HTMLCanvasElement>document.createElement('canvas');
83
+ canvas.width = outfitSprite.sprite.getWidth();
84
+ canvas.height = outfitSprite.sprite.getHeight();
85
+ document.getElementsByTagName('body')[0].appendChild(canvas);
86
+ const ctx = canvas.getContext("2d");
87
+ const palette = ctx.getImageData(0, 0, outfitSprite.sprite.getWidth(), outfitSprite.sprite.getHeight());
88
+ palette.data.set(new Uint8ClampedArray(outfitSprite.sprite.getPixels().m_buffer.buffer));
89
+ ctx.putImageData(palette, 0, 0);
90
+ if (self.imageFormat == 'png') {
91
+ const callback = function (blob) {
92
+ canvas.remove();
93
+ zip.file(outfitSprite.file + '.png', blob);
94
+ spritesToProcess--;
95
+ if (spritesToProcess == 0) {
96
+ setTimeout(function () {
97
+ self.generateOutfitImage(imageGenerator, otbManager, datManager, zip, outfitId + 1);
98
+ }, 1);
99
+ }
100
+ };
101
+ canvas.toBlob(callback);
102
+ }
103
+ }
104
+
105
+ }
106
+ }
107
+
108
+ const outfitImageGenerator = new OutfitImageGenerator();
109
+ outfitImageGenerator.init();
@@ -0,0 +1,19 @@
1
+ export class OutfitImagePhpGeneratorCode {
2
+ public version = '0.2.1';
3
+ private files = {
4
+ "libs\/gifCreator.php": "PD9waHANCg0KLyoqDQogKiBDcmVhdGUgYW4gYW5pbWF0ZWQgR0lGIGZyb20gbXVsdGlwbGUgaW1hZ2VzDQogKg0KICogQHVwZGF0ZSBieSBnZXNpb3IsIHBocCA4LjAgY29tcGF0aWJpbGl0eQ0KICoNCiAqIEB2ZXJzaW9uIDEuMA0KICogQGxpbmsgaHR0cHM6Ly9naXRodWIuY29tL1N5YmlvL0dpZkNyZWF0b3INCiAqIEBhdXRob3IgU3liaW8gKENsw6ltZW50IEd1aWxsZW1haW4gIC8gQFN5YmlvMDEpDQogKiBAbGljZW5zZSBodHRwOi8vb3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvZ3BsLWxpY2Vuc2UucGhwIEdOVSBQdWJsaWMgTGljZW5zZQ0KICogQGNvcHlyaWdodCBDbMOpbWVudCBHdWlsbGVtYWluDQogKi8NCmNsYXNzIEdpZkNyZWF0b3INCnsNCiAgICAvKioNCiAgICAgKiBAdmFyIHN0cmluZyBUaGUgZ2lmIHN0cmluZyBzb3VyY2UgKG9sZDogdGhpcy0+R0lGKQ0KICAgICAqLw0KICAgIHByaXZhdGUgJGdpZjsNCg0KICAgIC8qKg0KICAgICAqIEB2YXIgc3RyaW5nIEVuY29kZXIgdmVyc2lvbiAob2xkOiB0aGlzLT5WRVIpDQogICAgICovDQogICAgcHJpdmF0ZSAkdmVyc2lvbjsNCg0KICAgIC8qKg0KICAgICAqIEB2YXIgYm9vbGVhbiBDaGVjayB0aGUgaW1hZ2UgaXMgYnVpbGQgb3Igbm90IChvbGQ6IHRoaXMtPklNRykNCiAgICAgKi8NCiAgICBwcml2YXRlICRpbWdCdWlsdDsNCg0KICAgIC8qKg0KICAgICAqIEB2YXIgYXJyYXkgRnJhbWVzIHN0cmluZyBzb3VyY2VzIChvbGQ6IHRoaXMtPkJVRikNCiAgICAgKi8NCiAgICBwcml2YXRlICRmcmFtZVNvdXJjZXM7DQoNCiAgICAvKioNCiAgICAgKiBAdmFyIGludGVnZXIgR2lmIGxvb3AgKG9sZDogdGhpcy0+TE9QKQ0KICAgICAqLw0KICAgIHByaXZhdGUgJGxvb3A7DQoNCiAgICAvKioNCiAgICAgKiBAdmFyIGludGVnZXIgR2lmIGRpcyAob2xkOiB0aGlzLT5ESVMpDQogICAgICovDQogICAgcHJpdmF0ZSAkZGlzOw0KDQogICAgLyoqDQogICAgICogQHZhciBpbnRlZ2VyIEdpZiBjb2xvciAob2xkOiB0aGlzLT5DT0wpDQogICAgICovDQogICAgcHJpdmF0ZSAkY29sb3VyOw0KDQogICAgLyoqDQogICAgICogQHZhciBhcnJheSAob2xkOiB0aGlzLT5FUlIpDQogICAgICovDQogICAgcHJpdmF0ZSAkZXJyb3JzOw0KDQogICAgLy8gTWV0aG9kcw0KICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiAgICAvKioNCiAgICAgKiBDb25zdHJ1Y3Rvcg0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBfX2NvbnN0cnVjdCgpDQogICAgew0KICAgICAgICAkdGhpcy0+cmVzZXQoKTsNCg0KICAgICAgICAvLyBTdGF0aWMgZGF0YQ0KICAgICAgICAkdGhpcy0+dmVyc2lvbiA9ICdHaWZDcmVhdG9yOiBVbmRlciBkZXZlbG9wbWVudCc7DQogICAgICAgICR0aGlzLT5lcnJvcnMgPSBhcnJheSgNCiAgICAgICAgICAgICdFUlIwMCcgPT4gJ0RvZXMgbm90IHN1cHBvcnRlZCBmdW5jdGlvbiBmb3Igb25seSBvbmUgaW1hZ2UuJywNCiAgICAgICAgICAgICdFUlIwMScgPT4gJ1NvdXJjZSBpcyBub3QgYSBHSUYgaW1hZ2UuJywNCiAgICAgICAgICAgICdFUlIwMicgPT4gJ1lvdSBoYXZlIHRvIGdpdmUgcmVzb3VyY2UgaW1hZ2UgdmFyaWFibGVzLCBpbWFnZSBVUkwgb3IgaW1hZ2UgYmluYXJ5IHNvdXJjZXMgaW4gJGZyYW1lcyBhcnJheS4nLA0KICAgICAgICAgICAgJ0VSUjAzJyA9PiAnRG9lcyBub3QgbWFrZSBhbmltYXRpb24gZnJvbSBhbmltYXRlZCBHSUYgc291cmNlLicsDQogICAgICAgICk7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQ3JlYXRlIHRoZSBHSUYgc3RyaW5nIChvbGQ6IEdJRkVuY29kZXIpDQogICAgICoNCiAgICAgKiBAcGFyYW0gYXJyYXkgJGZyYW1lcyBBbiBhcnJheSBvZiBmcmFtZTogY2FuIGJlIGZpbGUgcGF0aHMsIHJlc291cmNlIGltYWdlIHZhcmlhYmxlcywgYmluYXJ5IHNvdXJjZXMgb3IgaW1hZ2UgVVJMcw0KICAgICAqIEBwYXJhbSBhcnJheSAkZHVyYXRpb25zIEFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIGR1cmF0aW9uIG9mIGVhY2ggZnJhbWUNCiAgICAgKiBAcGFyYW0gaW50ZWdlciAkbG9vcCBOdW1iZXIgb2YgR0lGIGxvb3BzIGJlZm9yZSBzdG9wcGluZyBhbmltYXRpb24gKFNldCAwIHRvIGdldCBhbiBpbmZpbml0ZSBsb29wKQ0KICAgICAqDQogICAgICogQHJldHVybiBzdHJpbmcgVGhlIEdJRiBzdHJpbmcgc291cmNlDQogICAgICovDQogICAgcHVibGljIGZ1bmN0aW9uIGNyZWF0ZSgkZnJhbWVzID0gYXJyYXkoKSwgJGR1cmF0aW9ucyA9IGFycmF5KCksICRsb29wID0gMCkNCiAgICB7DQogICAgICAgIGlmICghaXNfYXJyYXkoJGZyYW1lcykgJiYgIWlzX2FycmF5KCRkdXJhdGlvbnMpKSB7DQogICAgICAgICAgICB0aHJvdyBuZXcgXEV4Y2VwdGlvbigkdGhpcy0+dmVyc2lvbiAuICc6ICcgLiAkdGhpcy0+ZXJyb3JzWydFUlIwMCddKTsNCiAgICAgICAgfQ0KDQogICAgICAgICR0aGlzLT5sb29wID0gKCRsb29wID4gLTEpID8gJGxvb3AgOiAwOw0KICAgICAgICAkdGhpcy0+ZGlzID0gMjsNCg0KICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCBjb3VudCgkZnJhbWVzKTsgJGkrKykgew0KICAgICAgICAgICAgaWYgKCRmcmFtZXNbJGldIGluc3RhbmNlb2YgR2RJbWFnZSB8fCBpc19yZXNvdXJjZSgkZnJhbWVzWyRpXSkpIHsgLy8gUmVzb3VyY2UgdmFyDQoNCiAgICAgICAgICAgICAgICAkcmVzb3VyY2VJbWcgPSAkZnJhbWVzWyRpXTsNCg0KICAgICAgICAgICAgICAgIG9iX3N0YXJ0KCk7DQogICAgICAgICAgICAgICAgaW1hZ2VnaWYoJGZyYW1lc1skaV0pOw0KICAgICAgICAgICAgICAgICR0aGlzLT5mcmFtZVNvdXJjZXNbXSA9IG9iX2dldF9jb250ZW50cygpOw0KICAgICAgICAgICAgICAgIG9iX2VuZF9jbGVhbigpOw0KICAgICAgICAgICAgfSBlbHNlaWYgKGlzX3N0cmluZygkZnJhbWVzWyRpXSkpIHsgLy8gRmlsZSBwYXRoIG9yIFVSTCBvciBCaW5hcnkgc291cmNlIGNvZGUNCg0KICAgICAgICAgICAgICAgIGlmIChmaWxlX2V4aXN0cygkZnJhbWVzWyRpXSkgfHwgZmlsdGVyX3ZhcigkZnJhbWVzWyRpXSwgRklMVEVSX1ZBTElEQVRFX1VSTCkpIHsgLy8gRmlsZSBwYXRoDQoNCiAgICAgICAgICAgICAgICAgICAgJGZyYW1lc1skaV0gPSBmaWxlX2dldF9jb250ZW50cygkZnJhbWVzWyRpXSk7DQogICAgICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAgICAgJHJlc291cmNlSW1nID0gaW1hZ2VjcmVhdGVmcm9tc3RyaW5nKCRmcmFtZXNbJGldKTsNCg0KICAgICAgICAgICAgICAgIG9iX3N0YXJ0KCk7DQogICAgICAgICAgICAgICAgaW1hZ2VnaWYoJHJlc291cmNlSW1nKTsNCiAgICAgICAgICAgICAgICAkdGhpcy0+ZnJhbWVTb3VyY2VzW10gPSBvYl9nZXRfY29udGVudHMoKTsNCiAgICAgICAgICAgICAgICBvYl9lbmRfY2xlYW4oKTsNCiAgICAgICAgICAgIH0gZWxzZSB7IC8vIEZhaWwNCg0KICAgICAgICAgICAgICAgIHRocm93IG5ldyBcRXhjZXB0aW9uKCR0aGlzLT52ZXJzaW9uIC4gJzogJyAuICR0aGlzLT5lcnJvcnNbJ0VSUjAyJ10pOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoJGkgPT0gMCkgew0KICAgICAgICAgICAgICAgICR0cmFuc3BhcmVudEluZGV4ID0gaW1hZ2Vjb2xvcnRyYW5zcGFyZW50KCRyZXNvdXJjZUltZyk7DQogICAgICAgICAgICAgICAgaWYgKCR0cmFuc3BhcmVudEluZGV4ID49IDAgJiYgKGltYWdlaXN0cnVlY29sb3IoJHJlc291cmNlSW1nKSB8fCAkdHJhbnNwYXJlbnRJbmRleCA8IGltYWdlY29sb3JzdG90YWwoJHJlc291cmNlSW1nKSkpIHsNCiAgICAgICAgICAgICAgICAgICAgJGNvbG9ycyA9IGltYWdlY29sb3JzZm9yaW5kZXgoJHJlc291cmNlSW1nLCAkdHJhbnNwYXJlbnRJbmRleCk7DQogICAgICAgICAgICAgICAgICAgICRjb2xvdXIgPSAoJGNvbG9yc1sncmVkJ10gPDwgMTYpIHwgKCRjb2xvcnNbJ2dyZWVuJ10gPDwgOCkgfCAkY29sb3JzWydibHVlJ107DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoc3Vic3RyKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldLCAwLCA2KSAhPSAnR0lGODdhJyAmJiBzdWJzdHIoDQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5mcmFtZVNvdXJjZXNbJGldLA0KICAgICAgICAgICAgICAgICAgICAwLA0KICAgICAgICAgICAgICAgICAgICA2DQogICAgICAgICAgICAgICAgKSAhPSAnR0lGODlhJykgew0KICAgICAgICAgICAgICAgIHRocm93IG5ldyBcRXhjZXB0aW9uKCR0aGlzLT52ZXJzaW9uIC4gJzogJyAuICRpIC4gJyAnIC4gJHRoaXMtPmVycm9yc1snRVJSMDEnXSk7DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIGZvciAoJGogPSAoMTMgKyAzICogKDIgPDwgKG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWyRpXSBbMTBdKSAmIDB4MDcpKSksICRrID0gdHJ1ZTsgJGs7ICRqKyspIHsNCiAgICAgICAgICAgICAgICBzd2l0Y2ggKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldIFskal0pIHsNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnISc6DQoNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgoc3Vic3RyKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldLCAoJGogKyAzKSwgOCkpID09ICdORVRTQ0FQRScpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgXEV4Y2VwdGlvbigNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMtPnZlcnNpb24gLiAnOiAnIC4gJHRoaXMtPmVycm9yc1snRVJSMDMnXSAuICcgKCcgLiAoJGkgKyAxKSAuICcgc291cmNlKS4nDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIH0NCg0KICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7DQoNCiAgICAgICAgICAgICAgICAgICAgY2FzZSAnOyc6DQoNCiAgICAgICAgICAgICAgICAgICAgICAgICRrID0gZmFsc2U7DQogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQoNCiAgICAgICAgICAgIHVuc2V0KCRyZXNvdXJjZUltZyk7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAoaXNzZXQoJGNvbG91cikpIHsNCiAgICAgICAgICAgICR0aGlzLT5jb2xvdXIgPSAkY29sb3VyOw0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgJHJlZCA9ICRncmVlbiA9ICRibHVlID0gMDsNCiAgICAgICAgICAgICR0aGlzLT5jb2xvdXIgPSAoJHJlZCA+IC0xICYmICRncmVlbiA+IC0xICYmICRibHVlID4gLTEpID8gKCRyZWQgfCAoJGdyZWVuIDw8IDgpIHwgKCRibHVlIDw8IDE2KSkgOiAtMTsNCiAgICAgICAgfQ0KDQogICAgICAgICR0aGlzLT5naWZBZGRIZWFkZXIoKTsNCg0KICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCBjb3VudCgkdGhpcy0+ZnJhbWVTb3VyY2VzKTsgJGkrKykgew0KICAgICAgICAgICAgJHRoaXMtPmFkZEdpZkZyYW1lcygkaSwgJGR1cmF0aW9uc1skaV0pOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRoaXMtPmdpZkFkZEZvb3RlcigpOw0KDQogICAgICAgIHJldHVybiAkdGhpcy0+Z2lmOw0KICAgIH0NCg0KICAgIC8vIEludGVybmFscw0KICAgIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCiAgICAvKioNCiAgICAgKiBBZGQgdGhlIGhlYWRlciBnaWYgc3RyaW5nIGluIGl0cyBzb3VyY2UgKG9sZDogR0lGQWRkSGVhZGVyKQ0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBnaWZBZGRIZWFkZXIoKQ0KICAgIHsNCiAgICAgICAgJGNtYXAgPSAwOw0KDQogICAgICAgIGlmIChvcmQoJHRoaXMtPmZyYW1lU291cmNlc1swXSBbMTBdKSAmIDB4ODApIHsNCiAgICAgICAgICAgICRjbWFwID0gMyAqICgyIDw8IChvcmQoJHRoaXMtPmZyYW1lU291cmNlc1swXSBbMTBdKSAmIDB4MDcpKTsNCg0KICAgICAgICAgICAgJHRoaXMtPmdpZiAuPSBzdWJzdHIoJHRoaXMtPmZyYW1lU291cmNlc1swXSwgNiwgNyk7DQogICAgICAgICAgICAkdGhpcy0+Z2lmIC49IHN1YnN0cigkdGhpcy0+ZnJhbWVTb3VyY2VzWzBdLCAxMywgJGNtYXApOw0KICAgICAgICAgICAgJHRoaXMtPmdpZiAuPSAiIVwzNzdcMTNORVRTQ0FQRTIuMFwzXDEiIC4gJHRoaXMtPmVuY29kZUFzY2lpVG9DaGFyKCR0aGlzLT5sb29wKSAuICJcMCI7DQogICAgICAgIH0NCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBBZGQgdGhlIGZyYW1lIHNvdXJjZXMgdG8gdGhlIEdJRiBzdHJpbmcgKG9sZDogR0lGQWRkRnJhbWVzKQ0KICAgICAqDQogICAgICogQHBhcmFtIGludGVnZXIgJGkNCiAgICAgKiBAcGFyYW0gaW50ZWdlciAkZA0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBhZGRHaWZGcmFtZXMoJGksICRkKQ0KICAgIHsNCiAgICAgICAgJExvY2Fsc19zdHIgPSAxMyArIDMgKiAoMiA8PCAob3JkKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldIFsxMF0pICYgMHgwNykpOw0KDQogICAgICAgICRMb2NhbHNfZW5kID0gc3RybGVuKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldKSAtICRMb2NhbHNfc3RyIC0gMTsNCiAgICAgICAgJExvY2Fsc190bXAgPSBzdWJzdHIoJHRoaXMtPmZyYW1lU291cmNlc1skaV0sICRMb2NhbHNfc3RyLCAkTG9jYWxzX2VuZCk7DQoNCiAgICAgICAgJEdsb2JhbF9sZW4gPSAyIDw8IChvcmQoJHRoaXMtPmZyYW1lU291cmNlc1swXSBbMTBdKSAmIDB4MDcpOw0KICAgICAgICAkTG9jYWxzX2xlbiA9IDIgPDwgKG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWyRpXSBbMTBdKSAmIDB4MDcpOw0KDQogICAgICAgICRHbG9iYWxfcmdiID0gc3Vic3RyKCR0aGlzLT5mcmFtZVNvdXJjZXNbMF0sIDEzLCAzICogKDIgPDwgKG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWzBdIFsxMF0pICYgMHgwNykpKTsNCiAgICAgICAgJExvY2Fsc19yZ2IgPSBzdWJzdHIoJHRoaXMtPmZyYW1lU291cmNlc1skaV0sIDEzLCAzICogKDIgPDwgKG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWyRpXSBbMTBdKSAmIDB4MDcpKSk7DQoNCiAgICAgICAgJExvY2Fsc19leHQgPSAiIVx4RjlceDA0IiAuIGNocigoJHRoaXMtPmRpcyA8PCAyKSArIDApIC4gY2hyKCgkZCA+PiAwKSAmIDB4RkYpIC4gY2hyKA0KICAgICAgICAgICAgICAgICgkZCA+PiA4KSAmIDB4RkYNCiAgICAgICAgICAgICkgLiAiXHgwXHgwIjsNCg0KICAgICAgICBpZiAoJHRoaXMtPmNvbG91ciA+IC0xICYmIG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWyRpXSBbMTBdKSAmIDB4ODApIHsNCiAgICAgICAgICAgIGZvciAoJGogPSAwOyAkaiA8ICgyIDw8IChvcmQoJHRoaXMtPmZyYW1lU291cmNlc1skaV0gWzEwXSkgJiAweDA3KSk7ICRqKyspIHsNCiAgICAgICAgICAgICAgICBpZiAob3JkKCRMb2NhbHNfcmdiIFszICogJGogKyAwXSkgPT0gKCgkdGhpcy0+Y29sb3VyID4+IDE2KSAmIDB4RkYpICYmDQogICAgICAgICAgICAgICAgICAgIG9yZCgkTG9jYWxzX3JnYiBbMyAqICRqICsgMV0pID09ICgoJHRoaXMtPmNvbG91ciA+PiA4KSAmIDB4RkYpICYmDQogICAgICAgICAgICAgICAgICAgIG9yZCgkTG9jYWxzX3JnYiBbMyAqICRqICsgMl0pID09ICgoJHRoaXMtPmNvbG91ciA+PiAwKSAmIDB4RkYpDQogICAgICAgICAgICAgICAgKSB7DQogICAgICAgICAgICAgICAgICAgICRMb2NhbHNfZXh0ID0gIiFceEY5XHgwNCIgLiBjaHIoKCR0aGlzLT5kaXMgPDwgMikgKyAxKSAuIGNocigoJGQgPj4gMCkgJiAweEZGKSAuIGNocigNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoJGQgPj4gOCkgJiAweEZGDQogICAgICAgICAgICAgICAgICAgICAgICApIC4gY2hyKCRqKSAuICJceDAiOw0KICAgICAgICAgICAgICAgICAgICBicmVhazsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICBzd2l0Y2ggKCRMb2NhbHNfdG1wIFswXSkgew0KICAgICAgICAgICAgY2FzZSAnISc6DQoNCiAgICAgICAgICAgICAgICAkTG9jYWxzX2ltZyA9IHN1YnN0cigkTG9jYWxzX3RtcCwgOCwgMTApOw0KICAgICAgICAgICAgICAgICRMb2NhbHNfdG1wID0gc3Vic3RyKCRMb2NhbHNfdG1wLCAxOCwgc3RybGVuKCRMb2NhbHNfdG1wKSAtIDE4KTsNCg0KICAgICAgICAgICAgICAgIGJyZWFrOw0KDQogICAgICAgICAgICBjYXNlICcsJzoNCg0KICAgICAgICAgICAgICAgICRMb2NhbHNfaW1nID0gc3Vic3RyKCRMb2NhbHNfdG1wLCAwLCAxMCk7DQogICAgICAgICAgICAgICAgJExvY2Fsc190bXAgPSBzdWJzdHIoJExvY2Fsc190bXAsIDEwLCBzdHJsZW4oJExvY2Fsc190bXApIC0gMTApOw0KDQogICAgICAgICAgICAgICAgYnJlYWs7DQogICAgICAgIH0NCg0KICAgICAgICBpZiAob3JkKCR0aGlzLT5mcmFtZVNvdXJjZXNbJGldIFsxMF0pICYgMHg4MCAmJiAkdGhpcy0+aW1nQnVpbHQpIHsNCiAgICAgICAgICAgIGlmICgkR2xvYmFsX2xlbiA9PSAkTG9jYWxzX2xlbikgew0KICAgICAgICAgICAgICAgIGlmICgkdGhpcy0+Z2lmQmxvY2tDb21wYXJlKCRHbG9iYWxfcmdiLCAkTG9jYWxzX3JnYiwgJEdsb2JhbF9sZW4pKSB7DQogICAgICAgICAgICAgICAgICAgICR0aGlzLT5naWYgLj0gJExvY2Fsc19leHQgLiAkTG9jYWxzX2ltZyAuICRMb2NhbHNfdG1wOw0KICAgICAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgICAgICRieXRlID0gb3JkKCRMb2NhbHNfaW1nIFs5XSk7DQogICAgICAgICAgICAgICAgICAgICRieXRlIHw9IDB4ODA7DQogICAgICAgICAgICAgICAgICAgICRieXRlICY9IDB4Rjg7DQogICAgICAgICAgICAgICAgICAgICRieXRlIHw9IChvcmQoJHRoaXMtPmZyYW1lU291cmNlc1swXSBbMTBdKSAmIDB4MDcpOw0KICAgICAgICAgICAgICAgICAgICAkTG9jYWxzX2ltZyBbOV0gPSBjaHIoJGJ5dGUpOw0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+Z2lmIC49ICRMb2NhbHNfZXh0IC4gJExvY2Fsc19pbWcgLiAkTG9jYWxzX3JnYiAuICRMb2NhbHNfdG1wOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGJ5dGUgPSBvcmQoJExvY2Fsc19pbWcgWzldKTsNCiAgICAgICAgICAgICAgICAkYnl0ZSB8PSAweDgwOw0KICAgICAgICAgICAgICAgICRieXRlICY9IDB4Rjg7DQogICAgICAgICAgICAgICAgJGJ5dGUgfD0gKG9yZCgkdGhpcy0+ZnJhbWVTb3VyY2VzWyRpXSBbMTBdKSAmIDB4MDcpOw0KICAgICAgICAgICAgICAgICRMb2NhbHNfaW1nIFs5XSA9IGNocigkYnl0ZSk7DQogICAgICAgICAgICAgICAgJHRoaXMtPmdpZiAuPSAkTG9jYWxzX2V4dCAuICRMb2NhbHNfaW1nIC4gJExvY2Fsc19yZ2IgLiAkTG9jYWxzX3RtcDsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICAgICR0aGlzLT5naWYgLj0gJExvY2Fsc19leHQgLiAkTG9jYWxzX2ltZyAuICRMb2NhbHNfdG1wOw0KICAgICAgICB9DQoNCiAgICAgICAgJHRoaXMtPmltZ0J1aWx0ID0gdHJ1ZTsNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBBZGQgdGhlIGdpZiBzdHJpbmcgZm9vdGVyIGNoYXIgKG9sZDogR0lGQWRkRm9vdGVyKQ0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBnaWZBZGRGb290ZXIoKQ0KICAgIHsNCiAgICAgICAgJHRoaXMtPmdpZiAuPSAnOyc7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogQ29tcGFyZSB0d28gYmxvY2sgYW5kIHJldHVybiB0aGUgdmVyc2lvbiAob2xkOiBHSUZCbG9ja0NvbXBhcmUpDQogICAgICoNCiAgICAgKiBAcGFyYW0gc3RyaW5nICRnbG9iYWxCbG9jaw0KICAgICAqIEBwYXJhbSBzdHJpbmcgJGxvY2FsQmxvY2sNCiAgICAgKiBAcGFyYW0gaW50ZWdlciAkbGVuZ3RoDQogICAgICoNCiAgICAgKiBAcmV0dXJuIGludGVnZXINCiAgICAgKi8NCiAgICBwdWJsaWMgZnVuY3Rpb24gZ2lmQmxvY2tDb21wYXJlKCRnbG9iYWxCbG9jaywgJGxvY2FsQmxvY2ssICRsZW5ndGgpDQogICAgew0KICAgICAgICBmb3IgKCRpID0gMDsgJGkgPCAkbGVuZ3RoOyAkaSsrKSB7DQogICAgICAgICAgICBpZiAoJGdsb2JhbEJsb2NrIFszICogJGkgKyAwXSAhPSAkbG9jYWxCbG9jayBbMyAqICRpICsgMF0gfHwNCiAgICAgICAgICAgICAgICAkZ2xvYmFsQmxvY2sgWzMgKiAkaSArIDFdICE9ICRsb2NhbEJsb2NrIFszICogJGkgKyAxXSB8fA0KICAgICAgICAgICAgICAgICRnbG9iYWxCbG9jayBbMyAqICRpICsgMl0gIT0gJGxvY2FsQmxvY2sgWzMgKiAkaSArIDJdKSB7DQogICAgICAgICAgICAgICAgcmV0dXJuIDA7DQogICAgICAgICAgICB9DQogICAgICAgIH0NCg0KICAgICAgICByZXR1cm4gMTsNCiAgICB9DQoNCiAgICAvKioNCiAgICAgKiBFbmNvZGUgYW4gQVNDSUkgY2hhciBpbnRvIGEgc3RyaW5nIGNoYXIgKG9sZDogR0lGV29yZCkNCiAgICAgKg0KICAgICAqICRwYXJhbSBpbnRlZ2VyICRjaGFyIEFTQ0lJIGNoYXINCiAgICAgKg0KICAgICAqIEByZXR1cm4gc3RyaW5nDQogICAgICovDQogICAgcHVibGljIGZ1bmN0aW9uIGVuY29kZUFzY2lpVG9DaGFyKCRjaGFyKQ0KICAgIHsNCiAgICAgICAgcmV0dXJuIChjaHIoJGNoYXIgJiAweEZGKSAuIGNocigoJGNoYXIgPj4gOCkgJiAweEZGKSk7DQogICAgfQ0KDQogICAgLyoqDQogICAgICogUmVzZXQgYW5kIGNsZWFuIHRoZSBjdXJyZW50IG9iamVjdA0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiByZXNldCgpDQogICAgew0KICAgICAgICAkdGhpcy0+ZnJhbWVTb3VyY2VzOw0KICAgICAgICAkdGhpcy0+Z2lmID0gJ0dJRjg5YSc7IC8vIHRoZSBHSUYgaGVhZGVyDQogICAgICAgICR0aGlzLT5pbWdCdWlsdCA9IGZhbHNlOw0KICAgICAgICAkdGhpcy0+bG9vcCA9IDA7DQogICAgICAgICR0aGlzLT5kaXMgPSAyOw0KICAgICAgICAkdGhpcy0+Y29sb3VyID0gLTE7DQogICAgfQ0KDQogICAgLy8gR2V0dGVyIC8gU2V0dGVyDQogICAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCg0KICAgIC8qKg0KICAgICAqIEdldCB0aGUgZmluYWwgR0lGIGltYWdlIHN0cmluZyAob2xkOiBHZXRBbmltYXRpb24pDQogICAgICoNCiAgICAgKiBAcmV0dXJuIHN0cmluZw0KICAgICAqLw0KICAgIHB1YmxpYyBmdW5jdGlvbiBnZXRHaWYoKQ0KICAgIHsNCiAgICAgICAgcmV0dXJuICR0aGlzLT5naWY7DQogICAgfQ0KfQ0K",
5
+ "libs\/outfitter.php": "PD9waHANCi8qKg0KICogQGF1dGhvciBLYW1pbCBLYXJrdXMgPGtha2VyQHdwLmV1Pg0KICogQGF1dGhvciBHZXNpb3IucGwgPHBob293bmVkQHdwLnBsPg0KICogQGNvcHlyaWdodCBDb3B5cmlnaHQgKGMpIDIwMTIsIEthbWlsIEthcmt1cw0KICogQHZlcnNpb24gNiAtIGZpeGVkIGJhY2tncm91bmQgdHJhbnNwYXJlbmN5IGluIEdJRnMNCiAqLw0KDQpjbGFzcyBPdXRmaXR0ZXIgew0KCXByb3RlY3RlZCBzdGF0aWMgJGluc3RhbmNlID0gbnVsbDsNCglwcm90ZWN0ZWQgc3RhdGljICRvdXRmaXRDb2xvcnMgPSBhcnJheSgNCgkJMHhGRkZGRkYsIDB4RkZENEJGLCAweEZGRTlCRiwgMHhGRkZGQkYsIDB4RTlGRkJGLCAweEQ0RkZCRiwNCgkJMHhCRkZGQkYsIDB4QkZGRkQ0LCAweEJGRkZFOSwgMHhCRkZGRkYsIDB4QkZFOUZGLCAweEJGRDRGRiwNCgkJMHhCRkJGRkYsIDB4RDRCRkZGLCAweEU5QkZGRiwgMHhGRkJGRkYsIDB4RkZCRkU5LCAweEZGQkZENCwNCgkJMHhGRkJGQkYsIDB4REFEQURBLCAweEJGOUY4RiwgMHhCRkFGOEYsIDB4QkZCRjhGLCAweEFGQkY4RiwNCgkJMHg5RkJGOEYsIDB4OEZCRjhGLCAweDhGQkY5RiwgMHg4RkJGQUYsIDB4OEZCRkJGLCAweDhGQUZCRiwNCgkJMHg4RjlGQkYsIDB4OEY4RkJGLCAweDlGOEZCRiwgMHhBRjhGQkYsIDB4QkY4RkJGLCAweEJGOEZBRiwNCgkJMHhCRjhGOUYsIDB4QkY4RjhGLCAweEI2QjZCNiwgMHhCRjdGNUYsIDB4QkZBRjhGLCAweEJGQkY1RiwNCgkJMHg5RkJGNUYsIDB4N0ZCRjVGLCAweDVGQkY1RiwgMHg1RkJGN0YsIDB4NUZCRjlGLCAweDVGQkZCRiwNCgkJMHg1RjlGQkYsIDB4NUY3RkJGLCAweDVGNUZCRiwgMHg3RjVGQkYsIDB4OUY1RkJGLCAweEJGNUZCRiwNCgkJMHhCRjVGOUYsIDB4QkY1RjdGLCAweEJGNUY1RiwgMHg5MTkxOTEsIDB4QkY2QTNGLCAweEJGOTQzRiwNCgkJMHhCRkJGM0YsIDB4OTRCRjNGLCAweDZBQkYzRiwgMHgzRkJGM0YsIDB4M0ZCRjZBLCAweDNGQkY5NCwNCgkJMHgzRkJGQkYsIDB4M0Y5NEJGLCAweDNGNkFCRiwgMHgzRjNGQkYsIDB4NkEzRkJGLCAweDk0M0ZCRiwNCgkJMHhCRjNGQkYsIDB4QkYzRjk0LCAweEJGM0Y2QSwgMHhCRjNGM0YsIDB4NkQ2RDZELCAweEZGNTUwMCwNCgkJMHhGRkFBMDAsIDB4RkZGRjAwLCAweEFBRkYwMCwgMHg1NEZGMDAsIDB4MDBGRjAwLCAweDAwRkY1NCwNCgkJMHgwMEZGQUEsIDB4MDBGRkZGLCAweDAwQTlGRiwgMHgwMDU1RkYsIDB4MDAwMEZGLCAweDU1MDBGRiwNCgkJMHhBOTAwRkYsIDB4RkUwMEZGLCAweEZGMDBBQSwgMHhGRjAwNTUsIDB4RkYwMDAwLCAweDQ4NDg0OCwNCgkJMHhCRjNGMDAsIDB4QkY3RjAwLCAweEJGQkYwMCwgMHg3RkJGMDAsIDB4M0ZCRjAwLCAweDAwQkYwMCwNCgkJMHgwMEJGM0YsIDB4MDBCRjdGLCAweDAwQkZCRiwgMHgwMDdGQkYsIDB4MDAzRkJGLCAweDAwMDBCRiwNCgkJMHgzRjAwQkYsIDB4N0YwMEJGLCAweEJGMDBCRiwgMHhCRjAwN0YsIDB4QkYwMDNGLCAweEJGMDAwMCwNCgkJMHgyNDI0MjQsIDB4N0YyQTAwLCAweDdGNTUwMCwgMHg3RjdGMDAsIDB4NTU3RjAwLCAweDJBN0YwMCwNCgkJMHgwMDdGMDAsIDB4MDA3RjJBLCAweDAwN0Y1NSwgMHgwMDdGN0YsIDB4MDA1NDdGLCAweDAwMkE3RiwNCgkJMHgwMDAwN0YsIDB4MkEwMDdGLCAweDU0MDA3RiwgMHg3RjAwN0YsIDB4N0YwMDU1LCAweDdGMDAyQSwNCgkJMHg3RjAwMDAsDQoJKTsNCglwdWJsaWMgc3RhdGljICRtb3VudHNURlMgPSBbDQoJICAgIDEgPT4gMzY4LCAyID0+IDM2OSwgMyA9PiAzNzAsIDQgPT4gMzcxLCA1ID0+IDM3MiwgNiA9PiAzNzMsIDcgPT4gMzc0LCA4ID0+IDM3NSwNCiAgICAgICAgOSA9PiAzNzYsIDEwID0+IDM3NywgMTEgPT4gMzc4LCAxMiA9PiAzNzksIDEzID0+IDM4NywgMTQgPT4gMzg4LCAxNSA9PiAzODksIDE2ID0+IDM5MCwgMTcgPT4gMzkyLA0KICAgICAgICAxOCA9PiA0MDEsIDE5ID0+IDQwMiwgMjAgPT4gNDA1LCAyMSA9PiA0MDYsIDIyID0+IDQyMSwgMjMgPT4gNDI2LCAyNCA9PiA0MjcsIDI1ID0+IDQzNywgMjYgPT4gNDM4LA0KICAgICAgICAyNyA9PiA0NDcsIDI4ID0+IDQ1MCwgMjkgPT4gNTAyLCAzMCA9PiA1MDMsIDMxID0+IDUwNiwgMzIgPT4gNTE1LCAzMyA9PiA1MjEsIDM0ID0+IDUyMiwgMzUgPT4gNTI2LA0KICAgICAgICAzNiA9PiA1NDYsIDM3ID0+IDU0NywgMzggPT4gNTQ4LCAzOSA9PiA1NTksIDQwID0+IDU3MSwgNDEgPT4gNTcyLCA0MiA9PiA1ODAsIDQzID0+IDYwNiwgNDQgPT4gNjIxLA0KICAgICAgICA0NSA9PiA2MjIsIDQ2ID0+IDYyNCwgNDcgPT4gNjI2LCA0OCA9PiA2MjcsIDQ5ID0+IDYyOCwgNTAgPT4gNjI5LCA1MSA9PiA2MzAsIDUyID0+IDYzMSwgNTMgPT4gNjQ0LA0KICAgICAgICA1NCA9PiA2NDcsIDU1ID0+IDY0OCwgNTYgPT4gNjQ5LCA1NyA9PiA2NTAsIDU4ID0+IDY1MSwgNTkgPT4gNjY5LCA2MCA9PiA2NzAsIDYxID0+IDY3MSwgNjIgPT4gNjcyLA0KICAgICAgICA2MyA9PiA2NzMsIDY0ID0+IDY3NCwgNjUgPT4gNjg4LCA2NiA9PiA2ODksIDY3ID0+IDY5MCwgNjggPT4gNjkxLCA2OSA9PiA2OTIsIDcwID0+IDY5MywgNzEgPT4gNjgyLA0KICAgICAgICA3MiA9PiA2ODUsIDczID0+IDY4NiwgNzQgPT4gNjg3LCA3NSA9PiA3MjYsIDc2ID0+IDcyNywgNzcgPT4gNzI4LCA3OCA9PiA3MzQsIDc5ID0+IDczNSwgODAgPT4gNzM2LA0KICAgICAgICA4MSA9PiA3MzgsIDgyID0+IDczOSwgODMgPT4gNzQwLCA4NCA9PiA3NjEsIDg1ID0+IDc2MiwgODYgPT4gNzYzLCA4NyA9PiA4NDgsIDg4ID0+IDg0OSwgODkgPT4gODUwLA0KICAgICAgICA5MCA9PiA4NTEsIDkxID0+IDg2OCwgOTIgPT4gODY5LCA5MyA9PiA4NzAsIDk0ID0+IDg4MywgOTUgPT4gODg2LCA5NiA9PiA4ODcsIDk3ID0+IDg4OCwgOTggPT4gODg5LA0KICAgICAgICA5OSA9PiA4OTAsIDEwMCA9PiA5MDEsIDEwMSA9PiA5MDIsIDEwMiA9PiA5MDMsIDEwMyA9PiA5MDUsIDEwNCA9PiA5MDYsIDEwNSA9PiA5MDcsIDEwNiA9PiA5MzcsDQogICAgICAgIDEwNyA9PiA5NTAsIDEwOCA9PiA5NTEsIDEwOSA9PiA5NTIsIDExMCA9PiA5NTksIDExMSA9PiA5NjAsIDExMiA9PiA5NjEsIDExMyA9PiAxMDE3LCAxMTQgPT4gMTAxOCwNCiAgICAgICAgMTE1ID0+IDEwMTksIDExNiA9PiAxMDI1LCAxMTcgPT4gMTAyNiwgMTE4ID0+IDEwMjcsIDExOSA9PiAxMDQ5LCAxMjAgPT4gMTA1MiwgMTIxID0+IDEwNTMsDQogICAgICAgIDEyMiA9PiAxMDU0LCAxMjMgPT4gMTA5MSwgMTI0ID0+IDEwOTIsIDEyNSA9PiAxMDkzLCAxMjYgPT4gMTEwMSwgMTI3ID0+IDExMDQsIDEyOCA9PiAxMTA1LA0KICAgICAgICAxMjkgPT4gMTEwNiwgMTMwID0+IDExNTAsIDEzMSA9PiAxMTUxLCAxMzIgPT4gMTE2MywgMTMzID0+IDExNjQsIDEzNCA9PiAxMTY1LCAxMzUgPT4gMTE2NywNCiAgICAgICAgMTM2ID0+IDExNjgsIDEzNyA9PiAxMTY5LCAxMzggPT4gMTE3OSwgMTM5ID0+IDExODAsIDE0MCA9PiAxMTgxLCAxNDEgPT4gMTE4MywgMTQyID0+IDExODQsDQogICAgICAgIDE0MyA9PiAxMTg1LCAxNDQgPT4gMTE5MSwgMTQ1ID0+IDEyMDgsIDE0NiA9PiAxMjA5LCAxNDcgPT4gMTIyOSwgMTQ4ID0+IDEyMzAsIDE0OSA9PiAxMjMxLA0KICAgICAgICAxNTAgPT4gMTIzMiwgMTUxID0+IDEyMzMsIDE1MiA9PiAxMjM0LCAxNTMgPT4gMTI0NywgMTU0ID0+IDEyNDgsIDE1NSA9PiAxMjQ5LCAxNTYgPT4gMTI1NywNCiAgICAgICAgMTU3ID0+IDEyNTgsIDE1OCA9PiAxMjU5LCAxNTkgPT4gMTI2NCwgMTYwID0+IDEyNjUsIDE2MSA9PiAxMjY2LCAxNjIgPT4gMTI2OSwgMTYzID0+IDEyODEsDQogICAgICAgIDE2NCA9PiAxMjg0LCAxNjUgPT4gMTI4NSwgMTY2ID0+IDEyODYsIDE2NyA9PiAxMzIxLCAxNjggPT4gMTMyNCwgMTY5ID0+IDEzMjUsIDE3MCA9PiAxMzI2LA0KICAgICAgICAxNzEgPT4gMTMzMywgMTcyID0+IDEzMzQsIDE3MyA9PiAxMzM1LCAxNzQgPT4gMTMzNiwgMTc1ID0+IDEzNjMsIDE3NiA9PiAxMzc5LCAxNzcgPT4gMTM4MCwNCiAgICAgICAgMTc4ID0+IDEzODEsIDE3OSA9PiAxMzg5LCAxODAgPT4gMTM5MCwgMTgxID0+IDEzOTEsIDE4MiA9PiAxNDE3LCAxODMgPT4gMTQzMCwgMTg0ID0+IDE0MzEsDQogICAgICAgIDE4NSA9PiAxNDM5LCAxODYgPT4gMTQ0MCwgMTg3ID0+IDE0NDENCiAgICBdOw0KDQoJcHVibGljIHN0YXRpYyAkZGF0YSA9IFtdOw0KCXByaXZhdGUgc3RhdGljICR0cmFuc3BhcmVudEJhY2tncm91bmRDb2xvciA9IGFycmF5KDI1NSwgMjU1LCAyNTUsIDEyNyk7DQoJcHVibGljIHN0YXRpYyAkb3V0Zml0UGF0aDsNCglwdWJsaWMgc3RhdGljICRyZXNpemVBbGxPdXRmaXRzVG82NHB4ID0gZmFsc2U7DQoNCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGluc3RhbmNlKCkgew0KCQlpZiAoIWlzc2V0KHNlbGY6OiRpbnN0YW5jZSkpDQoJCQlzZWxmOjokaW5zdGFuY2UgPSBuZXcgc2VsZigpOw0KCQlyZXR1cm4gc2VsZjo6JGluc3RhbmNlOw0KCX0NCg0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gc2V0UmVzaXplQWxsT3V0Zml0c1RvNjRweCgkdmFsdWUpIHsNCgkJc2VsZjo6JHJlc2l6ZUFsbE91dGZpdHNUbzY0cHggPSAoYm9vbCkkdmFsdWU7DQoJfQ0KDQoJcHVibGljIHN0YXRpYyBmdW5jdGlvbiBsb2FkRGF0YSgkb3V0Zml0SWQsICRpc01vdW50ID0gZmFsc2UpDQoJew0KCQlpZigkaXNNb3VudCkNCgkJew0KCQkJJG1vdW50ID0gJG91dGZpdElkOw0KCQkJaWYoJG1vdW50ID09IDAgfHwgJG1vdW50ID49IDY1NTM1KQ0KCQkJew0KICAgICAgICAgICAgICAgICRvdXRmaXRJZCA9ICgkbW91bnQgJiAweEZGRkYpOw0KCQkJfQ0KCQkJZWxzZWlmKCRtb3VudCA8IDMwMCkNCgkJCXsNCgkJCQkvLyB0ZnMgMS54IG1vdW50IHN5c3RlbQ0KICAgICAgICAgICAgICAgICRvdXRmaXRJZCA9IHNlbGY6OiRtb3VudHNURlNbJG1vdW50XTsNCgkJCX0NCgkJfQ0KCQlpZihmaWxlX2V4aXN0cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXRJZCAuICcvb3V0Zml0LmRhdGEudHh0JykpDQoJCXsNCgkJCWlmKCRpc01vdW50KQ0KCQkJew0KCQkJCSR0bXAgPSB1bnNlcmlhbGl6ZShmaWxlX2dldF9jb250ZW50cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXRJZCAuICcvb3V0Zml0LmRhdGEudHh0JykpOw0KCQkJCXNlbGY6OiRkYXRhWydmaWxlcyddID0gYXJyYXlfbWVyZ2Uoc2VsZjo6JGRhdGFbJ2ZpbGVzJ10sICR0bXBbJ2ZpbGVzJ10pOw0KCQkJCXNlbGY6OiRkYXRhWydtb3VudEZyYW1lc051bWJlciddID0gJHRtcFsnZnJhbWVzTnVtYmVyJ107DQoJCQl9DQoJCQllbHNlDQoJCQl7DQoJCQkJc2VsZjo6JGRhdGEgPSB1bnNlcmlhbGl6ZShmaWxlX2dldF9jb250ZW50cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXRJZCAuICcvb3V0Zml0LmRhdGEudHh0JykpOw0KCQkJCXNlbGY6OiRkYXRhWydtb3VudEZyYW1lc051bWJlciddID0gMTsNCgkJCX0NCgkJCXJldHVybiB0cnVlOw0KCQl9DQoJCXJldHVybiBmYWxzZTsNCgl9DQoNCglwdWJsaWMgc3RhdGljIGZ1bmN0aW9uIGdldE91dGZpdEZyYW1lc051bWJlcigpDQoJew0KCQlyZXR1cm4gc2VsZjo6JGRhdGFbJ2ZyYW1lc051bWJlciddOw0KCX0NCg0KCXB1YmxpYyBzdGF0aWMgZnVuY3Rpb24gZmlsZV9leGlzdHMoJGZpbGVQYXRoKQ0KCXsNCgkJcmV0dXJuIGluX2FycmF5KHRyaW0odHJpbShzdHJfcmVwbGFjZSgnXFwnLCAnLycsICRmaWxlUGF0aCksICcuJyksICcvJyksIHNlbGY6OiRkYXRhWydmaWxlcyddKTsNCgl9DQoNCglwdWJsaWMgZnVuY3Rpb24gb3V0Zml0KCRvdXRmaXQsICRhZGRvbnMsICRoZWFkLCAkYm9keSwgJGxlZ3MsICRmZWV0LCAkbW91bnQsICRkaXJlY3Rpb24gPSAzLCAkYW5pbWF0aW9uID0gMSkgew0KCQlpZigkbW91bnQgPT0gMCB8fCAkbW91bnQgPj0gNjU1MzUpDQoJCXsNCgkJCS8vIG9sZCBtb3VudCBzeXN0ZW0NCgkJCSRtb3VudElkID0gKCRtb3VudCAmIDB4RkZGRik7DQoJCQkkbW91bnRTdGF0ZSA9ICgoJG1vdW50ICYgMHhGRkZGMDAwMCkgIT0gMCkgPyAyIDogMTsNCgkJfQ0KCQllbHNlaWYoJG1vdW50IDwgMzAwKQ0KCQl7DQoJCQkvLyB0ZnMgMS54IG1vdW50IHN5c3RlbQ0KCQkJJG1vdW50SWQgPSBzZWxmOjokbW91bnRzVEZTWyRtb3VudF07DQoJCQkkbW91bnRTdGF0ZSA9IDI7DQoJCX0NCgkJZWxzZQ0KCQl7DQoJCQkkbW91bnRJZCA9ICRtb3VudDsNCgkJCSRtb3VudFN0YXRlID0gMjsNCgkJfQ0KDQogICAgICAgIGlmIChzZWxmOjpmaWxlX2V4aXN0cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycuJGFuaW1hdGlvbi4nXycgLiAkbW91bnRTdGF0ZSAuICdfMV8nLiRkaXJlY3Rpb24uJy5wbmcnKSkgew0KICAgICAgICAgICAgJGltYWdlX291dGZpdCA9IGltYWdlY3JlYXRlZnJvbXBuZyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycgLiAkYW5pbWF0aW9uIC4gJ18nIC4gJG1vdW50U3RhdGUgLiAnXzFfJyAuICRkaXJlY3Rpb24gLiAnLnBuZycpOw0KICAgICAgICAgICAgaWYgKGZpbGVfZXhpc3RzKHNlbGY6OiRvdXRmaXRQYXRoIC4gJG91dGZpdCAuICcvJyAuICRhbmltYXRpb24gLiAnXycgLiAkbW91bnRTdGF0ZSAuICdfMV8nIC4gJGRpcmVjdGlvbiAuICdfdGVtcGxhdGUucG5nJykpIHsNCiAgICAgICAgICAgICAgICAkaW1hZ2VfdGVtcGxhdGUgPSBpbWFnZWNyZWF0ZWZyb21wbmcoc2VsZjo6JG91dGZpdFBhdGggLiAkb3V0Zml0IC4gJy8nIC4gJGFuaW1hdGlvbiAuICdfJyAuICRtb3VudFN0YXRlIC4gJ18xXycgLiAkZGlyZWN0aW9uIC4gJ190ZW1wbGF0ZS5wbmcnKTsNCiAgICAgICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgICAgICAgJGltYWdlX3RlbXBsYXRlID0gaW1hZ2VjcmVhdGV0cnVlY29sb3IoaW1hZ2VzeCgkaW1hZ2Vfb3V0Zml0KSwgaW1hZ2VzeSgkaW1hZ2Vfb3V0Zml0KSk7DQogICAgICAgICAgICAgICAgJGJnY29sb3IgPSBpbWFnZWNvbG9yYWxsb2NhdGVhbHBoYSgkaW1hZ2VfdGVtcGxhdGUsIHNlbGY6OiR0cmFuc3BhcmVudEJhY2tncm91bmRDb2xvclswXSwgc2VsZjo6JHRyYW5zcGFyZW50QmFja2dyb3VuZENvbG9yWzFdLCBzZWxmOjokdHJhbnNwYXJlbnRCYWNrZ3JvdW5kQ29sb3JbMl0sIHNlbGY6OiR0cmFuc3BhcmVudEJhY2tncm91bmRDb2xvclszXSk7DQogICAgICAgICAgICAgICAgaW1hZ2VmaWxsKCRpbWFnZV90ZW1wbGF0ZSwgMCwgMCwgJGJnY29sb3IpOw0KICAgICAgICAgICAgICAgIGltYWdlY29sb3J0cmFuc3BhcmVudCgkaW1hZ2VfdGVtcGxhdGUsICRiZ2NvbG9yKTsNCg0KICAgICAgICAgICAgICAgIGltYWdlYWxwaGFibGVuZGluZygkaW1hZ2VfdGVtcGxhdGUsIGZhbHNlKTsNCiAgICAgICAgICAgICAgICBpbWFnZXNhdmVhbHBoYSgkaW1hZ2VfdGVtcGxhdGUsIHRydWUpOw0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICBpZiAoJGFkZG9ucyA9PSAxIHx8ICRhZGRvbnMgPT0gMykgew0KICAgICAgICAgICAgICAgIGlmIChzZWxmOjpmaWxlX2V4aXN0cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycgLiAkYW5pbWF0aW9uIC4gJ18nIC4gJG1vdW50U3RhdGUgLiAnXzJfJyAuICRkaXJlY3Rpb24gLiAnLnBuZycpKSB7DQogICAgICAgICAgICAgICAgICAgICRpbWFnZV9maXJzdCA9IGltYWdlY3JlYXRlZnJvbXBuZyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycgLiAkYW5pbWF0aW9uIC4gJ18nIC4gJG1vdW50U3RhdGUgLiAnXzJfJyAuICRkaXJlY3Rpb24gLiAnLnBuZycpOw0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+YWxwaGFPdmVybGF5KCRpbWFnZV9vdXRmaXQsICRpbWFnZV9maXJzdCwgNjQsIDY0KTsNCiAgICAgICAgICAgICAgICAgICAgaW1hZ2VkZXN0cm95KCRpbWFnZV9maXJzdCk7DQogICAgICAgICAgICAgICAgICAgIGlmIChzZWxmOjpmaWxlX2V4aXN0cyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycgLiAkYW5pbWF0aW9uIC4gJ18nIC4gJG1vdW50U3RhdGUgLiAnXzJfJyAuICRkaXJlY3Rpb24gLiAnX3RlbXBsYXRlLnBuZycpKSB7DQogICAgICAgICAgICAgICAgICAgICAgICAkaW1hZ2VfZmlyc3RfdGVtcGxhdGUgPSBpbWFnZWNyZWF0ZWZyb21wbmcoc2VsZjo6JG91dGZpdFBhdGggLiAkb3V0Zml0IC4gJy8nIC4gJGFuaW1hdGlvbiAuICdfJyAuICRtb3VudFN0YXRlIC4gJ18yXycgLiAkZGlyZWN0aW9uIC4gJ190ZW1wbGF0ZS5wbmcnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5hbHBoYU92ZXJsYXkoJGltYWdlX3RlbXBsYXRlLCAkaW1hZ2VfZmlyc3RfdGVtcGxhdGUsIDY0LCA2NCk7DQogICAgICAgICAgICAgICAgICAgICAgICBpbWFnZWRlc3Ryb3koJGltYWdlX2ZpcnN0X3RlbXBsYXRlKTsNCiAgICAgICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgIH0NCiAgICAgICAgICAgIGlmICgkYWRkb25zID09IDIgfHwgJGFkZG9ucyA9PSAzKSB7DQogICAgICAgICAgICAgICAgaWYgKHNlbGY6OmZpbGVfZXhpc3RzKHNlbGY6OiRvdXRmaXRQYXRoIC4gJG91dGZpdCAuICcvJyAuICRhbmltYXRpb24gLiAnXycgLiAkbW91bnRTdGF0ZSAuICdfM18nIC4gJGRpcmVjdGlvbiAuICcucG5nJykpIHsNCiAgICAgICAgICAgICAgICAgICAgJGltYWdlX3NlY29uZCA9IGltYWdlY3JlYXRlZnJvbXBuZyhzZWxmOjokb3V0Zml0UGF0aCAuICRvdXRmaXQgLiAnLycgLiAkYW5pbWF0aW9uIC4gJ18nIC4gJG1vdW50U3RhdGUgLiAnXzNfJyAuICRkaXJlY3Rpb24gLiAnLnBuZycpOw0KICAgICAgICAgICAgICAgICAgICAkdGhpcy0+YWxwaGFPdmVybGF5KCRpbWFnZV9vdXRmaXQsICRpbWFnZV9zZWNvbmQsIDY0LCA2NCk7DQogICAgICAgICAgICAgICAgICAgIGltYWdlZGVzdHJveSgkaW1hZ2Vfc2Vjb25kKTsNCiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGY6OmZpbGVfZXhpc3RzKHNlbGY6OiRvdXRmaXRQYXRoIC4gJG91dGZpdCAuICcvJyAuICRhbmltYXRpb24gLiAnXycgLiAkbW91bnRTdGF0ZSAuICdfM18nIC4gJGRpcmVjdGlvbiAuICdfdGVtcGxhdGUucG5nJykpIHsNCiAgICAgICAgICAgICAgICAgICAgICAgICRpbWFnZV9zZWNvbmRfdGVtcGxhdGUgPSBpbWFnZWNyZWF0ZWZyb21wbmcoc2VsZjo6JG91dGZpdFBhdGggLiAkb3V0Zml0IC4gJy8nIC4gJGFuaW1hdGlvbiAuICdfJyAuICRtb3VudFN0YXRlIC4gJ18zXycgLiAkZGlyZWN0aW9uIC4gJ190ZW1wbGF0ZS5wbmcnKTsNCiAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLT5hbHBoYU92ZXJsYXkoJGltYWdlX3RlbXBsYXRlLCAkaW1hZ2Vfc2Vjb25kX3RlbXBsYXRlLCA2NCwgNjQpOw0KICAgICAgICAgICAgICAgICAgICAgICAgaW1hZ2VkZXN0cm95KCRpbWFnZV9zZWNvbmRfdGVtcGxhdGUpOw0KICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfQ0KICAgICAgICAgICAgfQ0KDQogICAgICAgICAgICAkdGhpcy0+Y29sb3JpemUoJGltYWdlX3RlbXBsYXRlLCAkaW1hZ2Vfb3V0Zml0LCAkaGVhZCwgJGJvZHksICRsZWdzLCAkZmVldCk7DQogICAgICAgIH0NCg0KCQkkbW91bnRBbmltYXRpb25GcmFtZSA9ICRhbmltYXRpb247DQoJCXdoaWxlICgkbW91bnRBbmltYXRpb25GcmFtZSA+IHNlbGY6OiRkYXRhWydtb3VudEZyYW1lc051bWJlciddKSB7DQoJCQkkbW91bnRBbmltYXRpb25GcmFtZSAtPSBzZWxmOjokZGF0YVsnbW91bnRGcmFtZXNOdW1iZXInXTsNCgkJfQ0KDQoJCWlmICgkbW91bnRTdGF0ZSA9PSAyICYmIHNlbGY6OmZpbGVfZXhpc3RzKHNlbGY6OiRvdXRmaXRQYXRoIC4gJG1vdW50SWQgLiAnLycuJG1vdW50QW5pbWF0aW9uRnJhbWUuJ18xXzFfJy4kZGlyZWN0aW9uLicucG5nJykpIHsNCgkJCSRtb3VudCA9IGltYWdlY3JlYXRlZnJvbXBuZyhzZWxmOjokb3V0Zml0UGF0aCAuICRtb3VudElkIC4gJy8nLiRtb3VudEFuaW1hdGlvbkZyYW1lLidfMV8xXycuJGRpcmVjdGlvbi4nLnBuZycpOw0KCQkJJHRoaXMtPmFscGhhT3ZlcmxheSgkbW91bnQsICRpbWFnZV9vdXRmaXQsIDY0LCA2NCk7DQogICAgICAgICAgICBpZiAoJGltYWdlX291dGZpdCkgew0KICAgICAgICAgICAgICAgIGltYWdlZGVzdHJveSgkaW1hZ2Vfb3V0Zml0KTsNCiAgICAgICAgICAgIH0NCgkJCSRpbWFnZV9vdXRmaXQgPSAkbW91bnQ7DQoJCX0NCg0KCQkkd2lkdGggPSBpbWFnZXN4KCRpbWFnZV9vdXRmaXQpOw0KCQkkaGVpZ2h0ID0gaW1hZ2VzeSgkaW1hZ2Vfb3V0Zml0KTsNCgkJaWYgKHNlbGY6OiRyZXNpemVBbGxPdXRmaXRzVG82NHB4KSB7DQoJCQkkaW1hZ2Vfb3V0Zml0VCA9IGltYWdlY3JlYXRldHJ1ZWNvbG9yKDY0LCA2NCk7DQoJCX0gZWxzZSB7DQoJCQkkaW1hZ2Vfb3V0Zml0VCA9IGltYWdlY3JlYXRldHJ1ZWNvbG9yKCR3aWR0aCwgJGhlaWdodCk7DQoJCX0NCgkJDQoJCS8vIFVzZSBhIHNwZWNpZmljIGNvbG9yIGZvciB0cmFuc3BhcmVuY3kgKE1hZ2VudGE6IDI1NSwgMCwgMjU1KQ0KCQkkYmdjb2xvciA9IGltYWdlY29sb3JhbGxvY2F0ZSgkaW1hZ2Vfb3V0Zml0VCwgMjU1LCAwLCAyNTUpOw0KCQlpbWFnZWZpbGwoJGltYWdlX291dGZpdFQsIDAsIDAsICRiZ2NvbG9yKTsNCg0KCQlpbWFnZWNvcHlyZXNhbXBsZWQoJGltYWdlX291dGZpdFQsICRpbWFnZV9vdXRmaXQsIGltYWdlc3goJGltYWdlX291dGZpdFQpLSR3aWR0aCwgaW1hZ2VzeSgkaW1hZ2Vfb3V0Zml0VCktJGhlaWdodCwgMCwgMCwgJHdpZHRoLCAkaGVpZ2h0LCAkd2lkdGgsICRoZWlnaHQpOw0KDQoJCS8vIENvbnZlcnQgdHJ1ZWNvbG9yIGltYWdlIHRvIHBhbGV0dGUgdG8gZml4IEdJRiB0cmFuc3BhcmVuY3kgbG9zcyBpc3N1ZQ0KCQlpbWFnZXRydWVjb2xvcnRvcGFsZXR0ZSgkaW1hZ2Vfb3V0Zml0VCwgZmFsc2UsIDI1NSk7DQoJCQ0KCQkvLyBHZXQgdGhlIGV4YWN0IHRyYW5zcGFyZW50IGluZGV4IGFuZCBhc3NpZ24gaXQNCgkJJHRyYW5zcGFyZW50SW5kZXggPSBpbWFnZWNvbG9yY2xvc2VzdCgkaW1hZ2Vfb3V0Zml0VCwgMjU1LCAwLCAyNTUpOw0KCQlpbWFnZWNvbG9ydHJhbnNwYXJlbnQoJGltYWdlX291dGZpdFQsICR0cmFuc3BhcmVudEluZGV4KTsNCg0KCQlpbWFnZWRlc3Ryb3koJGltYWdlX291dGZpdCk7DQoJCWlmIChpc3NldCgkaW1hZ2VfdGVtcGxhdGUpICYmICRpbWFnZV90ZW1wbGF0ZSkgew0KCQkJaW1hZ2VkZXN0cm95KCRpbWFnZV90ZW1wbGF0ZSk7DQoJCX0NCgkJcmV0dXJuICRpbWFnZV9vdXRmaXRUOw0KCX0NCg0KCXByb3RlY3RlZCBmdW5jdGlvbiBjb2xvcml6ZVBpeGVsKCRfY29sb3IsICYkX3IsICYkX2csICYkX2IpIHsNCgkJaWYgKCRfY29sb3IgPCBjb3VudChzZWxmOjokb3V0Zml0Q29sb3JzKSkNCgkJCSR2YWx1ZSA9IHNlbGY6OiRvdXRmaXRDb2xvcnNbJF9jb2xvcl07DQoJCWVsc2UNCgkJCSR2YWx1ZSA9IDA7DQoJCSRybyA9ICgkdmFsdWUgJiAweEZGMDAwMCkgPj4gMTY7IC8vIHJnYiBvdXRmaXQNCgkJJGdvID0gKCR2YWx1ZSAmIDB4RkYwMCkgPj4gODsNCgkJJGJvID0gKCR2YWx1ZSAmIDB4RkYpOw0KCQkkX3IgPSAoaW50KSAoJF9yICogKCRybyAvIDI1NSkpOw0KCQkkX2cgPSAoaW50KSAoJF9nICogKCRnbyAvIDI1NSkpOw0KCQkkX2IgPSAoaW50KSAoJF9iICogKCRibyAvIDI1NSkpOw0KCX0NCg0KCXByb3RlY3RlZCBmdW5jdGlvbiBjb2xvcml6ZSgmJF9pbWFnZV90ZW1wbGF0ZSwgJiRfaW1hZ2Vfb3V0Zml0LCAkX2hlYWQsICRfYm9keSwgJF9sZWdzLCAkX2ZlZXQpIHsNCiAgICAgICAgaWYgKCEkX2ltYWdlX3RlbXBsYXRlKSB7DQogICAgICAgICAgICByZXR1cm47DQogICAgICAgIH0NCg0KCQlmb3IgKCRpID0gMDsgJGkgPCBpbWFnZXN5KCRfaW1hZ2VfdGVtcGxhdGUpOyAkaSsrKSB7DQoJCQlmb3IgKCRqID0gMDsgJGogPCBpbWFnZXN4KCRfaW1hZ2VfdGVtcGxhdGUpOyAkaisrKSB7DQoJCQkJJHRlbXBsYXRlcGl4ZWwgPSBpbWFnZWNvbG9yYXQoJF9pbWFnZV90ZW1wbGF0ZSwgJGosICRpKTsNCgkJCQkkb3V0Zml0ID0gaW1hZ2Vjb2xvcmF0KCRfaW1hZ2Vfb3V0Zml0LCAkaiwgJGkpOw0KDQoJCQkJaWYgKCR0ZW1wbGF0ZXBpeGVsID09ICRvdXRmaXQpDQoJCQkJCWNvbnRpbnVlOw0KDQoJCQkJJHJ0ID0gKCR0ZW1wbGF0ZXBpeGVsID4+IDE2KSAmIDB4RkY7DQoJCQkJJGd0ID0gKCR0ZW1wbGF0ZXBpeGVsID4+IDgpICYgMHhGRjsNCgkJCQkkYnQgPSAkdGVtcGxhdGVwaXhlbCAmIDB4RkY7DQoJCQkJJHJvID0gKCRvdXRmaXQgPj4gMTYpICYgMHhGRjsNCgkJCQkkZ28gPSAoJG91dGZpdCA+PiA4KSAmIDB4RkY7DQoJCQkJJGJvID0gJG91dGZpdCAmIDB4RkY7DQoNCgkJCQlpZiAoJHJ0ICYmICRndCAmJiAhJGJ0KSB7IC8vIHllbGxvdyA9PSBoZWFkDQoJCQkJCSR0aGlzLT5jb2xvcml6ZVBpeGVsKCRfaGVhZCwgJHJvLCAkZ28sICRibyk7DQoJCQkJfSBlbHNlIGlmICgkcnQgJiYgISRndCAmJiAhJGJ0KSB7IC8vIHJlZCA9PSBib2R5DQoJCQkJCSR0aGlzLT5jb2xvcml6ZVBpeGVsKCRfYm9keSwgJHJvLCAkZ28sICRibyk7DQoJCQkJfSBlbHNlIGlmICghJHJ0ICYmICRndCAmJiAhJGJ0KSB7IC8vIGdyZWVuID09IGxlZ3MNCgkJCQkJJHRoaXMtPmNvbG9yaXplUGl4ZWwoJF9sZWdzLCAkcm8sICRnbywgJGJvKTsNCgkJCQl9IGVsc2UgaWYgKCEkcnQgJiYgISRndCAmJiAkYnQpIHsgLy8gYmx1ZSA9PSBmZWV0DQoJCQkJCSR0aGlzLT5jb2xvcml6ZVBpeGVsKCRfZmVldCwgJHJvLCAkZ28sICRibyk7DQoJCQkJfSBlbHNlIHsNCgkJCQkJY29udGludWU7IC8vIGlmIG5vdGhpbmcgY2hhbmdlZCwgc2tpcCB0aGUgY2hhbmdlIG9mIHBpeGVsDQoJCQkJfQ0KDQoJCQkJaW1hZ2VzZXRwaXhlbCgkX2ltYWdlX291dGZpdCwgJGosICRpLCBpbWFnZWNvbG9yYWxsb2NhdGUoJF9pbWFnZV9vdXRmaXQsICRybywgJGdvLCAkYm8pKTsNCgkJCX0NCgkJfQ0KCX0NCg0KCXByb3RlY3RlZCBmdW5jdGlvbiBhbHBoYU92ZXJsYXkoJiRkZXN0SW1nLCAmJG92ZXJsYXlJbWcsICRpbWdXLCAkaW1nSCkgew0KICAgICAgICBpZiAoISRvdmVybGF5SW1nKSB7DQogICAgICAgICAgICByZXR1cm4gJGRlc3RJbWc7DQogICAgICAgIH0NCg0KCQlmb3IgKCR5ID0gMDsgJHkgPCAkaW1nSDsgJHkrKykgew0KCQkJZm9yICgkeCA9IDA7ICR4IDwgJGltZ1c7ICR4KyspIHsNCgkJCQkkb3ZyQVJHQiA9IGltYWdlY29sb3JhdCgkb3ZlcmxheUltZywgJHgsICR5KTsNCgkJCQkkb3ZyQSA9ICgkb3ZyQVJHQiA+PiAyNCkgPDwgMTsNCgkJCQkkb3ZyUiA9ICRvdnJBUkdCID4+IDE2ICYgMHhGRjsNCgkJCQkkb3ZyRyA9ICRvdnJBUkdCID4+IDggJiAweEZGOw0KCQkJCSRvdnJCID0gJG92ckFSR0IgJiAweEZGOw0KDQoJCQkJJGNoYW5nZSA9IGZhbHNlOw0KCQkJCWlmICgkb3ZyQSA9PSAwKSB7DQoJCQkJCSRkc3RSID0gJG92clI7DQoJCQkJCSRkc3RHID0gJG92ckc7DQoJCQkJCSRkc3RCID0gJG92ckI7DQoJCQkJCSRjaGFuZ2UgPSB0cnVlOw0KCQkJCX0gZWxzZWlmICgkb3ZyQSA8IDI1NCkgew0KCQkJCQkkZHN0QVJHQiA9IGltYWdlY29sb3JhdCgkZGVzdEltZywgJHgsICR5KTsNCgkJCQkJJGRzdFIgPSAkZHN0QVJHQiA+PiAxNiAmIDB4RkY7DQoJCQkJCSRkc3RHID0gJGRzdEFSR0IgPj4gOCAmIDB4RkY7DQoJCQkJCSRkc3RCID0gJGRzdEFSR0IgJiAweEZGOw0KDQoJCQkJCSRkc3RSID0gKCgkb3ZyUiAqICgweEZGIC0gJG92ckEpKSA+PiA4KSArICgoJGRzdFIgKiAkb3ZyQSkgPj4gOCk7DQoJCQkJCSRkc3RHID0gKCgkb3ZyRyAqICgweEZGIC0gJG92ckEpKSA+PiA4KSArICgoJGRzdEcgKiAkb3ZyQSkgPj4gOCk7DQoJCQkJCSRkc3RCID0gKCgkb3ZyQiAqICgweEZGIC0gJG92ckEpKSA+PiA4KSArICgoJGRzdEIgKiAkb3ZyQSkgPj4gOCk7DQoJCQkJCSRjaGFuZ2UgPSB0cnVlOw0KCQkJCX0NCgkJCQlpZiAoJGNoYW5nZSkgew0KCQkJCQkkZHN0UkdCID0gaW1hZ2Vjb2xvcmFsbG9jYXRlYWxwaGEoJGRlc3RJbWcsICRkc3RSLCAkZHN0RywgJGRzdEIsIDApOw0KCQkJCQlpbWFnZXNldHBpeGVsKCRkZXN0SW1nLCAkeCwgJHksICRkc3RSR0IpOw0KCQkJCX0NCgkJCX0NCgkJfQ0KCQlyZXR1cm4gJGRlc3RJbWc7DQoJfQ0KfQ0K",
6
+ "abuse_warning.png": "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAHNUlEQVR4nO1aa0gUXRh+VlPJtFJTK6y8ddEiyLRar7URlCRURiCWEEFE2YWUkOyKEYT2I6W0+48uGCVGBIWk4nYzLYlUFLppWomUt+6mvd+P9xvGaXbH2f1Wp+\/79oFhds57zpn3PHvmnPc85+iIiPA\/hoPWDmgNOwFaO6A17ARo7YDWUEdATQ2wdi0weTLg4gKMHg2EhwP79wPt7WK+xkZApzN\/VVYCGRnKeYSrsHCImiyFbtBpsKAASE0FgoOBdev4\/uMHUF0NXLoETJvGDQOYgJAQYMMGYOlSeV0GA\/DuHecTUFrK7zhyBAgMFNMXLAD8\/GzQxEFASqisJHJ0JFq1iqi3V27v6iLKyRGfGxqIAKK8PMVqJTh9mstUV6svY0MofwLZ2YCzM3DqFODkJLePGQOkpQ3RXzM8GKFoLS0FoqIALy\/Lav32DejqkqbpdEzYHwbzPeDLF26Ev7\/c9vmz9Pp9GNm1C\/DwkF6+vrb13EYw3wPMjY3fvwPu7tK0lhbpgLVtG7BypTSPw58545onwM0NGDsWaG6Wpru4AHfv8u\/CQuD4cXnZqVOBhQtt5+UQQnkMMBiAW7eAjg7A05PTdDogOpp\/C9PfvxjK\/TI9nef8jRuBnz+HyaXhhXIP0OuBY8eA7duB2bOlgdCLF8CFCxwVjhwpLff0KXDtmry+efM4mvyToCpaqKoiSkoi8vMjcnIicncnmjuXaN8+orY2MZ8QCJm7LlyQ161xIDR4KPwfx585Nw0j7ARo7YDWsBOgtQNaw06AqlwVFUBCAjBuHK8FAgN5wdPWJs03cyYQGysvv3Urh9C5uXLbhAnAihX8e6Ck9vChPG9wMLB6tSqX1WJwAnJzgUWLWPvLygIuXwZSUlgOmzMHaGgQ88bGAlVVHCkOhNEIuLryfSCeP2cSTZG2Z48VzbECimFSZSWRgwNLYn19UturV0QeHkQzZ4q2y5c5qquoEPN1dnId27cT+fhI6zhzhvM\/fszPQiS5ZAnfy8qk+YOCiBITLY72lKBMwOrVRC4uRO3tpu2HDrGj16\/z89u3\/JyVJea5cYPI1ZXo9Wu2NTSItpQUDqsFAgUCzp4lmjWLKDJS+r4hIED5Eygt5aWvt7dp+5o1fC8r4\/vEiUBQkLSrG42s8Pr78\/W7LSoKcHSU1uvgABw8CDx4wMvxIYSyJNbZCQQEmC89ZQo729IipsXG8gDW18fPRiMQE8O\/Y2JEAlpbgaYmIC7OdN2rVgFhYcDevepbYwXME2DtGikujnXCmhomsaZGJCA6WiSgooLvpgZAAVlZwJMnQHGxdb6ogHkCBEns9WvzpZubgV+\/gEmTxDShQUYjd2GAPwGAiWhp4X\/eaGQdITzcfP3x8UBkJLBvH79nCKA8BixeDNy7B3z4YNp+9SrfDQYxLSCACTEa+QoLA0aNYltICMcSgk2v530HJWRlAXV1wJUrKptkGZQJSEtjKWzzZvk\/0NwMHD0KhIYCy5dLbbGxTFxFhdj9BURFAUVFHPQodX8BBgPHIQcOAP39g+e3FIPOE0eP8tQ0fz5RQQFRURHRwYNEXl5Evr5EtbXyMidPchmdTpwiBeTkcLqpeV6YBs+fl6bfvy+qSsMaBwgoKyOKjyfy9CRydiby9ydKTSV69850\/sZGkYAPH6S2R4\/Y5uxM9PWr1GaOACKiZcuGhAC7JKa1A1rDToDWDmgNOwFaO6A17AQoWgsKWJ6qq5Pb2trYduiQ3KZWQgN453nXLmDGDFaNvL15DzE9nc8i3L6t7lTZpk1cX1cXP6tUlJQ3R61Bbi6wYwcQEcFxvI8PUFsL5OXx2qGsjNcEAEtn0dG8NN6yhSW2nh7g2TPeeM3I4DRhzQEwiVu3siyXkCCmBwVZ569imJSfz9GXqXD3\/Xu5+mOphFZczHVcvCiv\/+dPov5+efrz51wmO9u0z52dbM\/MVGyaANuOATk5fJqsoECu8gQE8OKqvh64eZPThINUpv69ESOG5ViNujd8+sTODrx6euT5LJXQ5s3jRu7YAZSXA729VjThn0EdAZGR8lNf06dL81gjoYWGAvn53CsMBj5sERkJHD4MdHdb1yJBXxhMZ\/gb6gbBc+fkDevoABITxWdr11QbNwJJSUBJCYsk5eVAZiYTU1XFGyeWwNWVP7\/Ro1VlV0dARAQwa5Y07fcpzVoJDeBjd4mJIqGXLvHh7MOHefawFH5+PAWrgG1HGWskNFNITubps77eOj+amphAFbAtAZZKaK2tPMD+jtZW4ONHYPx4m7pnCrYNhPR6PmCdlga8eQOsX88zQl0dB0hOTixuClPknTt8Ai05mZVjNzfg5UvgxAkeLFNTLfehu5vPNmdm8ubKILB9JLhzJ0dvOTnA7t28RzBxIg90u3dLB7XFi5mAkhI+ViccyNTreRNWr7f8\/UQsnqoUUO2SmNYOaA07AVo7oDXsBGjtgNawE6C1A1rjL0YmFdDSaDn+AAAAAElFTkSuQmCC",
7
+ "animoutfit.php": "PD9waHANCg0KcmVxdWlyZV9vbmNlKCcuL2NvbmZpZy5waHAnKTsNCg0KaWYgKCFmaWxlX2V4aXN0cygnLi9jYWNoZS5nZW5lcmF0ZWQudHh0JykpIHsNCiAgICByZXF1aXJlX29uY2UoJy4vY2FjaGVHZW5lcmF0b3IucGhwJyk7DQogICAgZXhpdDsNCn0NCg0KaGVhZGVyKCdDYWNoZS1jb250cm9sOiBtYXgtYWdlPScgLiAoNjAgKiA2MCAqIDI0ICogMzY1KSk7DQpoZWFkZXIoJ0V4cGlyZXM6ICcgLiBnbWRhdGUoREFURV9SRkMxMTIzLCB0aW1lKCkgKyA2MCAqIDYwICogMjQgKiAzNjUpKTsNCmhlYWRlcignTGFzdC1Nb2RpZmllZDogJyAuIGdtZGF0ZSgnRCwgZCBNIFkgSDppOnMnLCAxMzM3KSAuICcgR01UJyk7DQppZiAoaXNzZXQoJF9TRVJWRVJbJ0hUVFBfSUZfTU9ESUZJRURfU0lOQ0UnXSkpIHsNCiAgICBoZWFkZXIoJ0hUVFAvMS4wIDMwNCBOb3QgTW9kaWZpZWQnKTsNCiAgICBoZWFkZXIoJ0NhY2hlLUNvbnRyb2w6IHB1YmxpYycpOw0KICAgIGhlYWRlcignUHJhZ21hOiBjYWNoZScpOw0KICAgIGV4aXQ7DQp9DQoNCi8vIEJsb2NrIHNpdGVzIHRoYXQgaG90bGluayB5b3VyIGhvc3QgYW5kIG92ZXJsb2FkIGl0DQokYWJ1c2Vyc0xpc3QgPSBhcnJheSgnYXVyZXJhLWdsb2JhbC5jb20nLCAnYmFkLXNlcnZlci5jb20nKTsNCmlmIChpc3NldCgkX1NFUlZFUlsnSFRUUF9SRUZFUkVSJ10pICYmIChpbl9hcnJheShwYXJzZV91cmwoJF9TRVJWRVJbJ0hUVFBfUkVGRVJFUiddLCBQSFBfVVJMX0hPU1QpLCAkYWJ1c2Vyc0xpc3QpIHx8DQogICAgICAgIGluX2FycmF5KHN1YnN0cihwYXJzZV91cmwoJF9TRVJWRVJbJ0hUVFBfUkVGRVJFUiddLCBQSFBfVVJMX0hPU1QpLCA0KSwgJGFidXNlcnNMaXN0KSkNCikgew0KICAgIGhlYWRlcignQ29udGVudC1UeXBlOiBpbWFnZS9wbmcnKTsNCiAgICByZWFkZmlsZSgnYWJ1c2Vfd2FybmluZy5wbmcnKTsNCiAgICBleGl0Ow0KfQ0KDQpyZXF1aXJlKCdsaWJzL291dGZpdHRlci5waHAnKTsNCnJlcXVpcmUoJ2xpYnMvZ2lmQ3JlYXRvci5waHAnKTsNCg0KT3V0Zml0dGVyOjokb3V0Zml0UGF0aCA9ICRvdXRmaXRJbWFnZXNQYXRoOw0KT3V0Zml0dGVyOjpzZXRSZXNpemVBbGxPdXRmaXRzVG82NHB4KCRyZXNpemVBbGxPdXRmaXRzVG82NHB4KTsNCg0KJGlkID0gMDsNCmlmIChpc3NldCgkX0dFVFsnaWQnXSkpIHsNCiAgICAkaWQgPSAoaW50KSRfR0VUWydpZCddOw0KfQ0KaWYgKCFPdXRmaXR0ZXI6OmxvYWREYXRhKCRpZCwgZmFsc2UpKSB7DQogICAgZXhpdCgnT3V0Zml0IGRvZXMgbm90IGV4aXN0IG9yIGZpbGUgY2FjaGUgaXMgbm90IGdlbmVyYXRlZC4nKTsNCn0NCg0KJG1vdW50ID0gMDsNCmlmIChpc3NldCgkX0dFVFsnbW91bnQnXSkpIHsNCiAgICAkbW91bnQgPSAoaW50KSRfR0VUWydtb3VudCddOw0KfQ0KaWYgKCRtb3VudCA+IDAgJiYgIU91dGZpdHRlcjo6bG9hZERhdGEoJG1vdW50LCB0cnVlKSkgew0KICAgIGV4aXQoJ01vdW50IG91dGZpdCBkb2VzIG5vdCBleGlzdCBvciBmaWxlIGNhY2hlIGlzIG5vdCBnZW5lcmF0ZWQuJyk7DQp9DQoNCiRoZWFkID0gMDsNCmlmIChpc3NldCgkX0dFVFsnaGVhZCddKSkgew0KICAgICRoZWFkID0gKGludCkkX0dFVFsnaGVhZCddOw0KfQ0KJGJvZHkgPSAwOw0KaWYgKGlzc2V0KCRfR0VUWydib2R5J10pKSB7DQogICAgJGJvZHkgPSAoaW50KSRfR0VUWydib2R5J107DQp9DQokbGVncyA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ2xlZ3MnXSkpIHsNCiAgICAkbGVncyA9IChpbnQpJF9HRVRbJ2xlZ3MnXTsNCn0NCiRmZWV0ID0gMDsNCmlmIChpc3NldCgkX0dFVFsnZmVldCddKSkgew0KICAgICRmZWV0ID0gKGludCkkX0dFVFsnZmVldCddOw0KfQ0KJGFkZG9ucyA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ2FkZG9ucyddKSkgew0KICAgICRhZGRvbnMgPSAoaW50KSRfR0VUWydhZGRvbnMnXTsNCn0NCiRkaXJlY3Rpb24gPSAzOw0KaWYgKGlzc2V0KCRfR0VUWydkaXJlY3Rpb24nXSkpIHsNCiAgICAkZGlyZWN0aW9uID0gKGludCkkX0dFVFsnZGlyZWN0aW9uJ107DQp9DQoNCiRmcmFtZXMgPSBbXTsNCiRkdXJhdGlvbnMgPSBbXTsNCg0KJG1vdmVBbmltRnJhbWVzID0gT3V0Zml0dGVyOjpnZXRPdXRmaXRGcmFtZXNOdW1iZXIoKTsNCg0KLy8gcm90YXRlIHBsYXllciwgQklHIElNQUdFUywgMjAtODAgS0IgcGVyIG91dGZpdCENCi8vZm9yKCRkaXJlY3Rpb24gPSAxOyAkZGlyZWN0aW9uIDw9IDQ7ICRkaXJlY3Rpb24rKykgDQpmb3IgKCRtb3ZlQW5pbUZyYW1lID0gMTsgJG1vdmVBbmltRnJhbWUgPD0gJG1vdmVBbmltRnJhbWVzOyArKyRtb3ZlQW5pbUZyYW1lKSB7DQogICAgJGZyYW1lc1tdID0gT3V0Zml0dGVyOjppbnN0YW5jZSgpLT5vdXRmaXQoDQogICAgICAgICRpZCwNCiAgICAgICAgJGFkZG9ucywNCiAgICAgICAgJGhlYWQsDQogICAgICAgICRib2R5LA0KICAgICAgICAkbGVncywNCiAgICAgICAgJGZlZXQsDQogICAgICAgICRtb3VudCwNCiAgICAgICAgJGRpcmVjdGlvbiwNCiAgICAgICAgJG1vdmVBbmltRnJhbWUNCiAgICApOw0KICAgICRkdXJhdGlvbnNbXSA9ICR3YWxrU3BlZWRzWyRtb3ZlQW5pbUZyYW1lc107DQp9DQokZ2MgPSBuZXcgR2lmQ3JlYXRvcigpOw0KJGdjLT5jcmVhdGUoJGZyYW1lcywgJGR1cmF0aW9ucywgMCk7DQokZ2lmQmluYXJ5ID0gJGdjLT5nZXRHaWYoKTsNCg0KaGVhZGVyKCdDb250ZW50LXR5cGU6IGltYWdlL2dpZicpOw0KZWNobyAkZ2lmQmluYXJ5Ow0K",
8
+ "cacheGenerator.php": "PD9waHANCg0KcmVxdWlyZV9vbmNlKCcuL2NvbmZpZy5waHAnKTsNCg0KJGRpckl0ZXJhdG9yID0gbmV3IFJlY3Vyc2l2ZURpcmVjdG9yeUl0ZXJhdG9yKCRvdXRmaXRJbWFnZXNQYXRoLCBGaWxlc3lzdGVtSXRlcmF0b3I6OlVOSVhfUEFUSFMpOw0KJGl0ZXJhdG9yID0gbmV3IFJlY3Vyc2l2ZUl0ZXJhdG9ySXRlcmF0b3IoJGRpckl0ZXJhdG9yLCBSZWN1cnNpdmVJdGVyYXRvckl0ZXJhdG9yOjpTRUxGX0ZJUlNUKTsNCg0KJG91dGZpdHMgPSBbXTsNCiRpID0gMDsNCmZvcmVhY2ggKCRpdGVyYXRvciBhcyAkZmlsZSkNCnsNCglpZiAoJGZpbGUtPmlzRmlsZSgpKQ0KCXsNCiAgICAgICAgJGZpbGVQYXRoID0gdHJpbSgkZmlsZS0+Z2V0UGF0aCgpLCAnLicpOw0KICAgICAgICAkZmlsZVBhdGggPSB0cmltKCRmaWxlUGF0aCwgJy8nKTsNCgkJJG91dGZpdElkRGF0YSA9IGV4cGxvZGUoJy8nLCAkZmlsZVBhdGgpOw0KCQkkb3V0Zml0SWQgPSAkb3V0Zml0SWREYXRhWzFdOw0KCQkkb3V0Zml0c1skb3V0Zml0SWRdWydmaWxlcyddW10gPSAkZmlsZVBhdGggLiAnLycgLiAkZmlsZS0+Z2V0RmlsZW5hbWUoKTsNCgkJaWYoaXNzZXQoJG91dGZpdHNbJG91dGZpdElkXVsnZnJhbWVzTnVtYmVyJ10pKQ0KCQkJJG91dGZpdHNbJG91dGZpdElkXVsnZnJhbWVzTnVtYmVyJ10gPSBtYXgoJG91dGZpdHNbJG91dGZpdElkXVsnZnJhbWVzTnVtYmVyJ10sIChpbnQpIHN1YnN0cigkZmlsZS0+Z2V0RmlsZW5hbWUoKSwgMCwgMSkpOw0KCQllbHNlDQoJCQkkb3V0Zml0c1skb3V0Zml0SWRdWydmcmFtZXNOdW1iZXInXSA9IChpbnQpIHN1YnN0cigkZmlsZS0+Z2V0RmlsZW5hbWUoKSwgMCwgMSk7DQogICAgfQ0KfQ0KDQovLyBDT0RFIFRPIENIRUNLIFdIQVQgVkFMVUVTIE9GICdmcmFtZXNOdW1iZXInIEFSRSBQT1NTSUJMRSBGT1IgWU9VUiBPVVRGSVRTDQokZnJhbWVOdW1iZXJzID0gWzAsMCwwLDAsMCwwLDAsMCwwLDBdOw0KZm9yZWFjaCgkb3V0Zml0cyBhcyAkb3V0Zml0SWQgPT4gJG91dGZpdCkNCnsNCglpZiAoIWZpbGVfcHV0X2NvbnRlbnRzKCRvdXRmaXRJbWFnZXNQYXRoIC4gJy8nIC4gJG91dGZpdElkIC4gJy9vdXRmaXQuZGF0YS50eHQnLCBzZXJpYWxpemUoJG91dGZpdCkpKSB7DQoJICAgIGV4aXQoJ1BIUCBjYW5ub3Qgd3JpdGUgdG86ICInIC4gJG91dGZpdEltYWdlc1BhdGggLiAnLycgLiAkb3V0Zml0SWQgLiAnL291dGZpdC5kYXRhLnR4dCIsIGNoZWNrIGRpcmVjdG9yeSBhY2Nlc3MgcmlnaHRzJyk7DQogICAgfQ0KCSRmcmFtZU51bWJlcnNbJG91dGZpdFsnZnJhbWVzTnVtYmVyJ11dKys7DQp9DQoNCmlmICghZmlsZV9wdXRfY29udGVudHMoJy4vY2FjaGUuZ2VuZXJhdGVkLnR4dCcsICdjYWNoZSBnZW5lcmF0ZWQnKSkgew0KICAgIGV4aXQoJ1BIUCBjYW5ub3Qgd3JpdGUgdG86ICIuL2NhY2hlLmdlbmVyYXRlZC50eHQiLCBjaGVjayBkaXJlY3RvcnkgYWNjZXNzIHJpZ2h0cycpOw0KfQ0KZWNobyAnRklMRSBTWVNURU0gQ0FDSEUgR0VORVJBVEVEPGJyIC8+QW5pbWF0aW9uIGZyYW1lcyBjb3VudCBpbiBsb2FkZWQgb3V0Zml0czonOw0KdmFyX2R1bXAoJGZyYW1lTnVtYmVycyk7DQo=",
9
+ "config.php": "PD9waHANCg0KJG91dGZpdEltYWdlc1BhdGggPSAnLi9vdXRmaXRzX2FuaW0vJzsNCi8vIHJlc2l6ZSBhbGwgb3V0Zml0cyB0byA2NHg2NCBwaXhlbHMsIHBsYWNlIHNtYWxsZXIgb3V0Zml0cyBpbiBib3R0b20tcmlnaHQgY29ybmVyDQokcmVzaXplQWxsT3V0Zml0c1RvNjRweCA9IHRydWU7DQoNCi8vIGFuaW1hdGlvbiBzcGVlZHM6IG51bWJlciBvZiBhbmltYXRpb24gZnJhbWVzID0+IHRpbWUgaW4gMC4wMSBvZiBzZWNvbmQNCiR3YWxrU3BlZWRzID0gWw0KICAgIDEgPT4gNTAsDQogICAgMiA9PiAzNSwNCiAgICAzID0+IDMwLA0KICAgIDQgPT4gMTUsDQogICAgNSA9PiAxNSwNCiAgICA2ID0+IDE1LA0KICAgIDcgPT4gMTUsDQogICAgOCA9PiAxMCwNCiAgICA5ID0+IDgNCl07DQoNCi8qDQpzb21lIHNlcnZlciBjb25maWd1cmF0aW9ucyBtYXkgcHJpbnQgd2FybmluZ3MgZnJvbSBncmFwaGljcyBsaWJyYXJ5DQp0aGVzZSB3YXJuaW5ncyBhcmUgaW50ZXJwcmV0ZWQgYXMgcGFydCBvZiBpbWFnZSBhbmQgbWFrZSBpbWFnZSB1bnJlYWRhYmxlIGZvciB3ZWIgYnJvd3NlcnMNCmlmIHlvdSBnZXQgYmxhY2svZW1wdHkgaW1hZ2UsIHlvdSBjYW4gdHJ5IHRvIHVuY29tbWVudCBsaW5lIGJlbG93IHRvIGRpc2FibGUgYWxsIHdhcm5pbmdzDQoqLw0KLy8gZXJyb3JfcmVwb3J0aW5nKDApOw0K",
10
+ "index.php": "PGh0bWwgbGFuZz0iZW4iPg0KPGhlYWQ+DQogICAgPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeXBlIiBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgiPg0KICAgIDx0aXRsZT5UaWJpYSBPdXRmaXQgSW1hZ2VzIEdlbmVyYXRvciAwLjIuMTwvdGl0bGU+DQo8L2hlYWQ+DQo8Ym9keT4NCgk8c3BhbiBzdHlsZT0iZm9udC1zaXplOjIwcHgiPg0KICAgICAgICBUaGlzIGlzIGluZGV4IGZpbGUuPGJyLz4NCiAgICAgICAgT3BlbiA8Yj5hbmltb3V0Zml0LnBocDwvYj4gd2l0aCB2YWxpZCBwYXJhbWV0ZXJzIHRvIGdlbmVyYXRlIGFuaW1hdGVkIG91dGZpdCBpbWFnZS4gRm9yIGV4YW1wbGU6PGJyLz4NCiAgICAgICAgPGEgaHJlZj0iYW5pbW91dGZpdC5waHA\/aWQ9MTI4JmFkZG9ucz0zJmhlYWQ9MTIzJmJvZHk9MTImbGVncz0yMyZmZWV0PTMxJm1vdW50PTAmZGlyZWN0aW9uPTIiPg0KICAgICAgICAgICAgYW5pbW91dGZpdC5waHA\/aWQ9MTI4JmFkZG9ucz0zJmhlYWQ9MTIzJmJvZHk9MTImbGVncz0yMyZmZWV0PTMxJm1vdW50PTAmZGlyZWN0aW9uPTINCiAgICAgICAgPC9hPjxici8+DQogICAgICAgIDxici8+DQogICAgICAgIE9wZW4gPGI+b3V0Zml0LnBocDwvYj4gd2l0aCB2YWxpZCBwYXJhbWV0ZXJzIHRvIGdlbmVyYXRlIHN0YXRpYyBvdXRmaXQgaW1hZ2UuIEZvciBleGFtcGxlOjxici8+DQogICAgICAgIDxhIGhyZWY9Im91dGZpdC5waHA\/aWQ9MTI4JmFkZG9ucz0zJmhlYWQ9MTIzJmJvZHk9MTImbGVncz0yMyZmZWV0PTMxJm1vdW50PTAmZGlyZWN0aW9uPTIiPg0KICAgICAgICAgICAgb3V0Zml0LnBocD9pZD0xMjgmYWRkb25zPTMmaGVhZD0xMjMmYm9keT0xMiZsZWdzPTIzJmZlZXQ9MzEmbW91bnQ9MCZkaXJlY3Rpb249Mg0KICAgICAgICA8L2E+PGJyLz4NCiAgICA8L3NwYW4+DQo8L2JvZHk+DQo8L2hlYWQ+DQo8L2h0bWw+DQo=",
11
+ "outfit.php": "PD9waHANCg0KcmVxdWlyZV9vbmNlKCcuL2NvbmZpZy5waHAnKTsNCg0KaWYgKCFmaWxlX2V4aXN0cygnLi9jYWNoZS5nZW5lcmF0ZWQudHh0JykpIHsNCiAgICByZXF1aXJlX29uY2UoJy4vY2FjaGVHZW5lcmF0b3IucGhwJyk7DQogICAgZXhpdDsNCn0NCg0KaGVhZGVyKCdDYWNoZS1jb250cm9sOiBtYXgtYWdlPScgLiAoNjAgKiA2MCAqIDI0ICogMzY1KSk7DQpoZWFkZXIoJ0V4cGlyZXM6ICcgLiBnbWRhdGUoREFURV9SRkMxMTIzLCB0aW1lKCkgKyA2MCAqIDYwICogMjQgKiAzNjUpKTsNCmhlYWRlcignTGFzdC1Nb2RpZmllZDogJyAuIGdtZGF0ZSgnRCwgZCBNIFkgSDppOnMnLCAxMzM3KSAuICcgR01UJyk7DQppZiAoaXNzZXQoJF9TRVJWRVJbJ0hUVFBfSUZfTU9ESUZJRURfU0lOQ0UnXSkpIHsNCiAgICBoZWFkZXIoJ0hUVFAvMS4wIDMwNCBOb3QgTW9kaWZpZWQnKTsNCiAgICBoZWFkZXIoJ0NhY2hlLUNvbnRyb2w6IHB1YmxpYycpOw0KICAgIGhlYWRlcignUHJhZ21hOiBjYWNoZScpOw0KICAgIGV4aXQ7DQp9DQoNCi8vIEJsb2NrIHNpdGVzIHRoYXQgaG90bGluayB5b3VyIGhvc3QgYW5kIG92ZXJsb2FkIGl0DQokYWJ1c2Vyc0xpc3QgPSBhcnJheSgnYXVyZXJhLWdsb2JhbC5jb20nLCAnYmFkLXNlcnZlci5jb20nKTsNCmlmIChpc3NldCgkX1NFUlZFUlsnSFRUUF9SRUZFUkVSJ10pICYmIChpbl9hcnJheShwYXJzZV91cmwoJF9TRVJWRVJbJ0hUVFBfUkVGRVJFUiddLCBQSFBfVVJMX0hPU1QpLCAkYWJ1c2Vyc0xpc3QpIHx8DQogICAgICAgIGluX2FycmF5KHN1YnN0cihwYXJzZV91cmwoJF9TRVJWRVJbJ0hUVFBfUkVGRVJFUiddLCBQSFBfVVJMX0hPU1QpLCA0KSwgJGFidXNlcnNMaXN0KSkNCikgew0KICAgIGhlYWRlcignQ29udGVudC1UeXBlOiBpbWFnZS9wbmcnKTsNCiAgICByZWFkZmlsZSgnYWJ1c2Vfd2FybmluZy5wbmcnKTsNCiAgICBleGl0Ow0KfQ0KDQpyZXF1aXJlKCdsaWJzL291dGZpdHRlci5waHAnKTsNCk91dGZpdHRlcjo6JG91dGZpdFBhdGggPSAkb3V0Zml0SW1hZ2VzUGF0aDsNCk91dGZpdHRlcjo6c2V0UmVzaXplQWxsT3V0Zml0c1RvNjRweCgkcmVzaXplQWxsT3V0Zml0c1RvNjRweCk7DQoNCiRpZCA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ2lkJ10pKSB7DQogICAgJGlkID0gKGludCkkX0dFVFsnaWQnXTsNCn0NCmlmICghT3V0Zml0dGVyOjpsb2FkRGF0YSgkaWQsIGZhbHNlKSkgew0KICAgIGV4aXQoJ091dGZpdCBkb2VzIG5vdCBleGlzdCBvciBmaWxlIGNhY2hlIGlzIG5vdCBnZW5lcmF0ZWQuJyk7DQp9DQoNCiRtb3VudCA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ21vdW50J10pKSB7DQogICAgJG1vdW50ID0gKGludCkkX0dFVFsnbW91bnQnXTsNCn0NCmlmICgkbW91bnQgPiAwICYmICFPdXRmaXR0ZXI6OmxvYWREYXRhKCRtb3VudCwgdHJ1ZSkpIHsNCiAgICBleGl0KCdNb3VudCBvdXRmaXQgZG9lcyBub3QgZXhpc3Qgb3IgZmlsZSBjYWNoZSBpcyBub3QgZ2VuZXJhdGVkLicpOw0KfQ0KDQokaGVhZCA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ2hlYWQnXSkpIHsNCiAgICAkaGVhZCA9IChpbnQpJF9HRVRbJ2hlYWQnXTsNCn0NCiRib2R5ID0gMDsNCmlmIChpc3NldCgkX0dFVFsnYm9keSddKSkgew0KICAgICRib2R5ID0gKGludCkkX0dFVFsnYm9keSddOw0KfQ0KJGxlZ3MgPSAwOw0KaWYgKGlzc2V0KCRfR0VUWydsZWdzJ10pKSB7DQogICAgJGxlZ3MgPSAoaW50KSRfR0VUWydsZWdzJ107DQp9DQokZmVldCA9IDA7DQppZiAoaXNzZXQoJF9HRVRbJ2ZlZXQnXSkpIHsNCiAgICAkZmVldCA9IChpbnQpJF9HRVRbJ2ZlZXQnXTsNCn0NCiRhZGRvbnMgPSAwOw0KaWYgKGlzc2V0KCRfR0VUWydhZGRvbnMnXSkpIHsNCiAgICAkYWRkb25zID0gKGludCkkX0dFVFsnYWRkb25zJ107DQp9DQokZGlyZWN0aW9uID0gMzsNCmlmIChpc3NldCgkX0dFVFsnZGlyZWN0aW9uJ10pKSB7DQogICAgJGRpcmVjdGlvbiA9IChpbnQpJF9HRVRbJ2RpcmVjdGlvbiddOw0KfQ0KDQokYW5pbWF0aW9uRnJhbWUgPSAxOw0KaGVhZGVyKCdDb250ZW50LXR5cGU6IGltYWdlL2dpZicpOw0KaW1hZ2VnaWYoT3V0Zml0dGVyOjppbnN0YW5jZSgpLT5vdXRmaXQoJGlkLCAkYWRkb25zLCAkaGVhZCwgJGJvZHksICRsZWdzLCAkZmVldCwgJG1vdW50LCAkZGlyZWN0aW9uLCAkYW5pbWF0aW9uRnJhbWUpKTsNCg=="
12
+ };
13
+
14
+ addFilesToZip(zip) {
15
+ for (const fileName in this.files) {
16
+ zip.file(fileName, this.files[fileName], { base64: true });
17
+ }
18
+ }
19
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "open-tibia-tools",
3
+ "version": "0.2.1",
4
+ "description": "Browser tools for DAT, SPR and OTB files, built on open-tibia-library",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1",
7
+ "build": "webpack --config webpack.config.js",
8
+ "watch": "webpack --config webpack.config.js --watch"
9
+ },
10
+ "author": "Gesior.pl (Jerzy Skalski)",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git://github.com/gesior/open-tibia-tools.git"
15
+ },
16
+ "devDependencies": {
17
+ "copy-webpack-plugin": "^14.0.0",
18
+ "ts-loader": "^9.5.4",
19
+ "typescript": "^5.9.2",
20
+ "webpack": "^5.101.3",
21
+ "webpack-cli": "^6.0.1"
22
+ },
23
+ "dependencies": {
24
+ "@gesior/open-tibia-library": "^0.2.1",
25
+ "gif.js": "^0.2.0",
26
+ "jszip": "^3.10.1"
27
+ }
28
+ }
package/tests.html ADDED
@@ -0,0 +1,29 @@
1
+ <html>
2
+ <head>
3
+ <title>OTEdit</title>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
5
+ <style>
6
+ * {
7
+ image-rendering: pixelated;
8
+ image-rendering: -moz-crisp-edges;
9
+ image-rendering: crisp-edges;
10
+ }
11
+ </style>
12
+ </head>
13
+ <body>
14
+ Client Version: <input type="number" id="clientversion" value="860" /><br />
15
+ Sprite file: <input type="file" id="spr" /><br />
16
+ Dat file: <input type="file" id="dat" /><br />
17
+ Otb file: <input type="file" id="otb" /><br />
18
+ Item id: <input type="number" id="itemid" /><br />
19
+ <br />
20
+ Images generator progress: <span id="progressBar">Not running</span><br />
21
+ Item view:<br />
22
+ <canvas id="view" width="100" height="100" style="width:200px;height:200px"></canvas>
23
+ <script src="node_modules/jszip/dist/jszip.js"></script>
24
+ <script src="node_modules/gif.js/dist/gif.js"></script>
25
+ <script src="js/vendor.js"></script>
26
+ <script src="js/tests.js"></script>
27
+
28
+ </body>
29
+ </html>