376137_219716018098056_119264868143172_499051_609147412_n

The king is dead, long live the king

0

Well, by now you have probably already heard the news about Adobe canceling flash plugin for mobile devices. Great news for mac addicts, late Steve’o was right once again, for the wrong reasons, but still. Now just to see the big picture lets forward the time to 2-3 years in future. There are couple of things happening in the mobile browsing experience. First of all there are no flash banners, w00t for users, bad for marketing, that means web campaigns are extremely not effective, less money gets invested in advertising, less money in the market of web development, so developers are shifting towards apps. Casual browser gaming is back to 2005, text based Omerta style games for core gamers. Less visual appeal = smaller market = less money = less developer focusing on these solutions. And so on and so forth.

Now you might object by saying that HTML5 can do all of those things that flash can, and i respond- bullshit. HTML5 is pretty and blinking and no plugins, bla bla bla. At the end of the day, you are still stuck with JavaScript, a DOM type language that should have not survived the crossover to the new millennium. You might also object that banners can be made with HTML5, but you would be missing the security issue. Most banners are hosted off the website servers, meaning if you embed HTML5 banner, you ember a cross site script, good luck with sandboxing that. HTML5 got to where it is because Apple decided to ban flash plugin so Apple had to push browser engines really hard because it needed to catch up with flash and HTML5 nowhere near that point. I just hope that new Macromedia pops up very soon to cover the gap, and this time they wont sell out.

376137_219716018098056_119264868143172_499051_609147412_n

Custom dynamic hit-zones for flash objects

0

Lets say you need a hit-zone for a transparent bitmap that matches the images non transparent pixels. What do you do? The answer is quite simple, you find all those pixels that you need and draw a square on top of it. Or so i thought, turns out if you draw a square using

1
shape.graphics.drawSquare(x,y,w,h)

You create a bunch of squares inside shape object and they are not merged, so when ever you move your mouse on top of the hit zone, performance peaks for hit test calculations. The solution i came to use was in Marching squares algorithm. The goal of the algorithm is to provide you with a set of shape outline coordinates that you can use with shape.graphics.lineTo(x,y) to draw the outline you need and fill it.
The library i used is located here
and the code is here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public static function getOutline(b : BitmapData, xpos : int = 0, ypos : int = 0, zone : Shape = null) : DisplayObject {
      if (!zone) {
        zone = new Shape();
      }
      var points:Vector.<Point>=MarchingSquares.getBlobOutlinePointsClockwise(b);
      zone.graphics.beginFill(0, 1);
      zone.graphics.moveTo(points[0].x, points[0].y);
      for (var i:int = 1; i < points.length;++i) {
        zone.graphics.lineTo(points[i].x, points[i].y);
      }
      zone.graphics.endFill();
      return zone;

    }

Now once you have the shape, there is one more trick you need to do

1
2
3
4
5
6
var result:DisplayObject = FieldUtils.getOutline(_bitmapData, 0, 0, null);
// create a SimpleButton instance to contain the shape
var simpleButton:SimpleButton = new SimpleButton(null, null, null, result);
// add the simple button to sprite so that flash understands the presence of the hit zone and reacts to mouse input
_hitBoxContainer.addChild(simpleButton);
_bitmapData.dispose();

if you simply add hit zone to display list and try to listen for events they will not fire, you need to go inception on the button, putting it one level deeper and adding event listeners on the sprite containing the SimpleButton instance

376137_219716018098056_119264868143172_499051_609147412_n

Strategy pattern

0

Couple of months ago i joined a high complexity project that a team of multiple developers were working on. This required some adjusting to my usual workflow, but it was for the better. I learned a lot and one of those things is a strategy pattern. This pattern goes well with pureMVC and definitely produces reusable code in the project. The core concept behind the pattern is to use a strategy object for every interface method that covers some group of actions. For example your object needs to flip on Y axis every click. This is how you would do this action in strategy pattern.

1
2
3
4
5
6
7
8
9
10
11
12
package  
{
  /**
   * ...
   * @author Martynas Bajoraitis
   */

  public interface IFlip
  {
    function flip():void;
  }
 
}

now the strategy interface:

1
2
3
4
5
6
7
8
9
10
11
12
package  
{
  /**
   * ...
   * @author Martynas Bajoraitis
   */

  public interface IFlipStrategy
  {
    function flip():void;
  }
 
}

now the strategy class itself

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package
{
  import flash.display.DisplayObject;
 
  /**
   * ...
   * @author Martynas Bajoraitis
   */

  public class FlipStrategy implements IFlipStrategy
  {
    private var _target:DisplayObject;
    public function FlipStrategy(target:DisplayObject) {
      _target = target;
    }
    public function flip():void {
      _target.scaleY *= -1;
    }
  }
 
}

and finally the implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package
{
  import flash.display.Sprite;
 
  /**
   * ...
   * @author Martynas Bajoraitis
   */

  public class Flipper extends Sprite implements IFlip
  {
    private var _flipStrategy:IFlipStrategy;
    public function Flipper() {
      _flipStrategy = new FlipSptrategy(this);
    }
    public function flip():void {
      _flipStrategy.flip();
    }
  }
 
}

this example very crude and basic, but it shows the usability of strategy pattern. Using the strategy class i can extend every display object and make it to have the same action just by passing the right parameter to the strategy constructor

376137_219716018098056_119264868143172_499051_609147412_n

Tips’n'Tricks for pureMVC on Titanium

0

Howdy people, its been a while. Anyway, here are some useful info on pureMVC framework. Titanium is not really meant for OOP, classes are not really welcome inside this framework. Most of the files are meant to be included as if they were AS2 #include somefile.as with procedural code instead of real OOP. This has its own advantages and drawback, main advantage is that newbies can quickly set up something that they later name as “Application”. Reminds me the times of flash 7 where designers used to tweak code directly on timeline and later they would say “i fixed it”. However the drawback is that you cant control the display tree and the whole structure application goes through the window. That is not how a real professional app should be built. pureMVC comes in to save the day with the encapsulation of most views and windows and a strong event based UI interaction. But lets get to the point here.

Heres tip #1:
All of your windows should be at least a viewComponent of a mediator. Even better is to use a separate component to wrap the window inside a class and just attach simple events to the component. Usually any outcome of UI interaction with the window is either open another window or close the window and go back to the previous one. Surely there are a lot of things you do inside a window, like input text, move stuff around etc, but at the end of it all ist still a back or next action. pureMVC has a good control on its components and if you remove a mediator or a component from memory, its is gone for good, no memory leaks at all.

Tip #2:
Use commands, A LOT, they will save your butt, its your best friend. Don’t be afraid of huge amount of classes, its normal, and the more classes you have the more localized your bug is and easier to find/resolve

Tip #3:
Remove unused mediators, reinitiating a mediator requires very little time, event if you have a huge table component, dont be affraid of killing it.

Tip #4:
If you have any piece of code that is similar to something you used before, write a wrapper component class for it. A good example is a custom title bar on the head of the window.
instead of using this piece of code in every window you create

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    var backBTN=Ti.UI.createImageView({
      image:'images/components/back_btn.png',
      width:65,
      height:24,
      top:0.5*(57-25),
      left:10
    });
    var title=Ti.UI.createView({
      width:'100%',
      height:57,
      backgroundImage:'images/components/title_background.png',
      top:0
    });
    title.add(backBTN);
    backBTN.addEventListener('click',this.doBackClick.bind(this));
   
                var titleLabel= Ti.UI.createLabel({
      text:'Some title',
      width:200,
      height:24,
      textAlign:'center',
      color:'#FFFFFF',
      top:0.5*(57-25)
    });
    titleLabel.font={fontWeight:'bold',fontSize:16};
    title.add(titleLabel);
    this.view.add(title);

You can use component and save yourself a lot of time by doing this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
TitleBarComponent=new Class({
  Extends: Events,
    view:null,
    initialize:function(title,hasBack){
    this.view=Ti.UI.createView({
          width:'100%',
          height:57,
          backgroundImage:'images/components/title_background.png',
          top:0
        });
    if(hasBack){
      var backBTN=Ti.UI.createImageView({
        image:'images/components/back_btn.png',
        width:65,
        height:24,
        top:0.5*(57-25),
        left:10
      });
      this.view.add(backBTN);
      backBTN.addEventListener('click',this.doBackClick.bind(this));
    }
    var titleLabel= Ti.UI.createLabel({
          text:title,
          width:200,
          height:24,
          textAlign:'center',
          color:'#FFFFFF',
          top:0.5*(57-25)
    });
    titleLabel.font={fontWeight:'bold',fontSize:16};
    this.view.add(titleLabel);
  },
    getView:function(){
    return this.view;
  },
  doBackClick:function(){
    this.fireEvent('back');
  }
});

and once you have this, simply create a class

1
this.window.add(new TitleBarComponent('Some Title').getView() );
376137_219716018098056_119264868143172_499051_609147412_n

Titanium + Aptana a match made in heaven

0

This is like bread and butter. I could not have imagined a better merge of two companies. Aptana is the best IDE based on Eclipse, however they were not going anywhere. Aptana studio is good, and that’s it, no direction, no really big goals or anything. Its just stands there being good. Titanium, on the other hands has everything except a proper IDE, it has funding like crazy, army of developers using it(~100000) who are also debuggers at the same time, the appeal of open source and so on. What it lacks is something that Aptana has and that something is best free IDE out there.

From this merge 2 things will definitely happen, #1 JavaScript debugger with strong code hinting, that should be the main focus for both of the companies. #2 Aptana will become even stronger in IDE market and hopefully remain free.

While I do have high hopes for the new version of IDE, i doubt that its going to come close to FlashDevelop in capabilities, which is hands down the best tool for Actionscript developers out there (even though Adobe has their own eclipse based IDE). If anyone from Aptana is reading this: don’t take an example from eclipse based IDE’s, take an example from the best

376137_219716018098056_119264868143172_499051_609147412_n

Titanium SDK, hangover after first crush

4

So, Ive been messing around with titanium SDK for 2 weeks and it is horrible. Bye bye to the love at first sight and welcome to marriage in a trailer park with 7 kids and no job. That is exactly how i feel right now. To start off, Titanium is most stable on windows, but who cares bout that? On windows you can only build android apps, and if i would build only android apps, I’d rather go for Java then some poorly knitted interpreter/compiler hybrid. I had my basic app running in 20 min and its great that you can do that so fast. Launching the emulator for android takes forever, but that’s not for titanium guys to solve. Still debugging is a pain in the butt when working like that. But never mind android, the real fun starts when you try to run the same app on iPhone emulator. First of all there are inconsistencies in the docs, and not just in some in depth communication with GPU or something, no no, something as basic as width or height requires to use this:

1
top:usernameTXT.top + (usernameTXT.size.height || usernameTXT.height) + 3

one height is for iPhone and the other one for android.

But wait, there’s more. Sometimes Titanium forgets that Titanium.API.info(‘some debug message’); is actually a part of Titanium API. Then you need to go to /build/iphone/build and delete all of the content there. Then there are mobile SDK issues, like, if you set your SDK to 1.5.1 (which is beta) and for some unimaginable reason you switch to stable SDK, compiling things for iPhone becomes not possible at all, as Titanium cant even load the list of available iPhone SDK’s, without picking one you cant compile.

Now lets say you did managed to get it running on emulator, both android and iPhone, and they actually look alike when put side by side. Which is where i was yesterday. Next step was to try it out on a device, just to see how it works, reasonable, right? Well guess what, there are gazillion of certificates you need to have and approve from apple. And even if you manage to get them, Titanium cant tell you if you have them or not. I am not kidding, this is their actual message on the screen:

We cannot verify all steps, so once you've completed them all, click "Package"

One guy on the Q & A page has started a topic: Spent 4 hours writing my iPhone app, and another 48 hours trying to get it to run on my phone, the part that surprises me the most, is that it took him 48 hours to cry out for help. Patience like that deserves a medal.

To sum up, almost every point that makes Titanium great compared to writing native app is actually worse than writing a native app, it is not faster, it is not more stable, it is not cross platform, its unusable most of the time, its undeveloped, support is slow to respond and even if they do, usually its not correct. I looked up their prices and for professional support they charge 200$/month. My guess is that for those 200 bucks, some dude in China or India actually writes you two native apps and just gives them to you.

376137_219716018098056_119264868143172_499051_609147412_n

pureMVC port to Javascript + Titanium appcelerator

5

My last post was about rewriting pureMVC port with syntax suggested in mootools. The reasons behind this were not mentioned, so now i will post more information on this topic. One of my projects requires me to develop a multi-platform mobile application to work on all iOS devices plus android phones. Now since i cant code in objective C and Java is also not really appealing to me, the obvious choice was to use flash on all of the systems, as packager is available for iPhone/iPad and android already runs flash and AIR. Woohooo i thought to myself, peace of cake. However after a week of testing on iPod touch i figured that even with heavy optimization of the code and UI elements, the end product is just not good enough. So after scraping flash idea, Googling around found Titanium SDK by Appcelerator. Unbelievable tool when developing hand held device applications. Support all of the current devices, development language is JavaScript and the best part is, that all of the compiled applications are actually native apps.

Being a pureMVC fan-boy i immediately started experimenting with android emulators. Getting basic app to run was pretty easy and my emulator was loading twitter trends in no time. However, a big problem came around when i tried to compile the same application for iPhone, it was just not happening, after launching the emulator, right after loading screen, an error in ApplicationFacade.js, ‘The method “parent” cannot be called.’ and in facade constructor it is vital to call this.parent(); My first guess was that i missed some mootols components when building a file for myself (pureMVC JS port is mootools based). Ive tried to get it running for 2 hours, but that was not the problem. Second guess was, that the problem came from how the port was written, and that’s where my last blog post comes in. However, that was not the case either. Failed attempts to run the app have brought me to google yet again. And it turns out, there are some deprecated methods in webkit that handle $caller. Solution for the problem is not to use the latest mootools library which is 1.3.x but rather use 1.2.5 which you can find here. To run pureMVC you will need these components: Core, Array, Function, Number, String, Hash, Class, Class.Extras.

As for my port of pureMVC, you can stick with the official one or use mine. One is a bit faster the other one is in compliance with mootools Class syntax, your choice. Thanx for reading

376137_219716018098056_119264868143172_499051_609147412_n

Propper pureMVC port to JavaScript with MooTools

3

Long story short, documentation has to match, even if its across multiple sites. Current official pureMVC JavaScript port is messy and definitely does not match the documentation at MooTools.

Simply put:
Here’s how mootools show their Class usage example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var Animal = new Class({
  initialize: function(options){
    this.options = options;
    this.isAlive = true;
  }
});
 
var Mammal = new Class({
  Extends: Animal,
  initialize: function(options){
    this.parent(options);
    this.isWarmBlooded = true;
    this.hasFur = true;
    this.producesMilk = true;
  },
  sleep: function() {
    this.isAsleep = true;
  },
  awake: function(){
    this.isAsleep = false;
  }
});

Implementation at pureMVC_JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var SimpleCommand = function(){
    this.Extends = Notifier;
    /**
     * @ignore
     */

    this.initialize = function()
    {
  this.parent();
    }
    /**
     * Fulfill the use-case initiated by the given <code>Notification</code>.
     *
     * <P>
     * In the Command Pattern, an application use-case typically
     * begins with some user action, which results in a <code>Notification</code> being broadcast, which
     * is handled by business logic in the <code>execute</code> method of an
     * <code>ICommand</code>.</P>
     *
     * @param {Notification} notification the <code>Notification</code> to handle.
     */

    this.execute = function(notification /* Notification */){}
}
SimpleCommand = new Class(new SimpleCommand());

My implementation pureMVC-oop.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
SimpleCommand = new Class({
    Extends : Notifier,

    /**
     * @ignore
     */

    initialize : function(){
    this.parent();
    },
   
    /**
     * Fulfill the use-case initiated by the given <code>Notification</code>.
     *
     * <P>
     * In the Command Pattern, an application use-case typically
     * begins with some user action, which results in a <code>Notification</code> being broadcast, which
     * is handled by business logic in the <code>execute</code> method of an
     * <code>ICommand</code>.</P>
     *
     * @param {Notification} notification the <code>Notification</code> to handle.
     */

    execute : function(notification /* Notification */){
  }
});

I have adapted the syntax suggested in MooTools for this port. Why this was not done in the beginning I have no clue. Sure, I had to use a hack here and there when using pureMVC, specially with “static” values, but still its cleaner than the current official version

file-comparison

Securing flash games

0

This is a topic Ive covered in a flash mail group once thoroughly, however it was in Lithuanian and in a closed group, so i guess it makes sense to translate and update.

First of all, lets identify the problems. Flash application is executed on user machine, it is living in users RAM and there it is vulnerable to manipulation. RAM can be written in to and locked or unlocked, because thats what applications do. Any smart kid can use a program called tsearch to find any value in RAM, overwrite it, and lock it, after that its just a matter of getting to the form screen and posting values.

Posting to server side is another vulnerable point in your application. No matter how many tricks you use, how confusing you make it look, at the end of it, its a call to a server side script with a score.

To solve these problems or at least make it too difficult for noobs here are some steps you can take.

Encrypt your application, I cant stress enough the necessity of this action. There is a very strong encryption tool called secureSWF by kindisoft.

This tool encrypts your swf in such a way that it is not decompileable any more in to readable code. To illustrate, I have decompiled same secured and unsecured application.

Below is the folder structure

And here is the comparison of the code, first unencrypted

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package
{
    import flash.display.*;

    dynamic public class GroundPNG extends BitmapData
    {

        public function GroundPNG(param1:int = 64, param2:int = 63)
        {
            super(param1, param2);
            return;
        }// end function

    }
}

And now encrypted

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
package true
{
    import break.*;

    public class include extends Object
    {
        public static const _-0W:Number = 6.03;
        public static const _-0r:int = 0;
        public static const for:int = 1;
        public static const var20:int = 2;
        public static const _-0t:int = 3;
        public static const _-c:int = 4;
        public static const _20do:int = 5;
        public static var mode:int;
        public static var enabled:Boolean;

        public function include()
        {
            var _loc_1:Boolean;
            ;
            if (!((null is null * null[false]++) &lt;= null)--)
            {
            }
            return;
        }// end function

        public static function _-j(param1:int = 2) : int
        {
            ;
            var _loc_2:Boolean;
            _loc_2--;
            _loc_2--;
            _loc_2--;
            _loc_2 = ~true--;
            var _loc_3:String;
            if (!(_loc_2 &amp;&amp; param1))
            {
                ;
                _loc_2 = _loc_2;
                _loc_2++;
                _loc_2++;
                _loc_2++;
            }
            throw new Error("Warning: Your TweenLite class needs to be updated to work with OverwriteManager (or you may need to clear your ASO files). Please download and install the latest version from http://www.tweenlite.com.");
            if (_loc_3)
            {
                each20.static = include;
                if (_loc_3 || param1)
                {
                    ;
                    mode = param1;
                }
                enabled = true;
            }
            return mode;
        }// end function

        public static function manageOverwrites(param1:each20, param2:Object, param3:Array, param4:uint) : Boolean
        {
            ;
            _loc_12--;
            var _loc_20:* = true &lt;&lt; (typeof(false))++;
            var _loc_21:* = true &lt;&lt; (typeof(false))++;
            var _loc_5:int;
            var _loc_6:Boolean;
            var _loc_7:each20;
            var _loc_13:uint;
            var _loc_14:Number;
            var _loc_15:Number;
            var _loc_16:continue;
            var _loc_17:Number;
            var _loc_18:_20null;
            if (!(_loc_20 &amp;&amp; _loc_2))
            {
            }
            _loc_13 = param3.length;
            if (_loc_21)
            {
                _loc_5 = 0;
            }
            while (_loc_5 &lt; _loc_13)             {                                  _loc_7 = param3[_loc_5];                 if (_loc_7 != param1)                 {                     if (_loc_21)                     {                     }                     _loc_6 = true;                 }                 else if (param4 == 5)                 {                     break;                 }                 _loc_5++;                 if (!_loc_20)                 {                 }                 return _loc_6;             }             var _loc_8:* = param1._-a + 1e-010;             var _loc_9:Array;             var _loc_10:Array;             var _loc_11:uint;             var _loc_12:uint;             if (!(_loc_20 &amp;&amp; _loc_2))             {                 _loc_5 = param3.length;                 do                 {                                      }                 _loc_7 = param3[_loc_5];                 if (_loc_21)                 {                     if (_loc_7 != param1)                     {                     }                     if (_loc_7.gc)                     {                     }                     if (_loc_7.timeline != param1.timeline)                     {                         if (!get20(_loc_7))                         {                             _loc_10[++_loc_11] = _loc_7;                         }                     }                     if (_loc_21)                     {                     }                 }                 if (_loc_7._-a + _loc_7.for20 + 1e-010 &gt; _loc_8)
                {
                    if (!(_loc_20 &amp;&amp; _loc_2))
                    {
                    }
                }
                if (!get20(_loc_7))
                {
                    if (!(_loc_20 &amp;&amp; param1))
                    {
                        _loc_9[++_loc_12] = _loc_7;
                    }
                }
                if (!_loc_20)
                {
                    if (!(_loc_20 &amp;&amp; param1))
                    {
                    }while (--_loc_5 &gt; -1)
                    if (_loc_21)
                    {
                        if (_loc_11 != 0)
                        {
                            if (_loc_21)
                            {
                                _loc_14 = param1._-04;
                            }
                            _loc_15 = _loc_8;
                            _loc_18 = param1.timeline;
                            if (!_loc_20)
                            {
                                while (_loc_18)
                                {

                                    if (!_loc_20)
                                    {
                                        _loc_14 = _loc_14 * _loc_18._-04;
                                    }
                                    _loc_15 = _loc_15 + _loc_18._-a;
                                    _loc_18 = _loc_18.timeline;
                                }
                            }
                            _loc_8 = _loc_14 * _loc_15;
                            if (!_loc_20)
                            {
                                ;
                                _loc_2++;
                                _loc_2--;
                                var _loc_2:* = null / (_loc_11 &lt; _loc_21);                                 if (null || param3)                                 {                                     --_loc_5 = null;                                     do                                     {                                                                                  _loc_16 = _loc_10[--_loc_5];                                         if (!_loc_20)                                         {                                             if (_loc_21)                                             {                                                 _loc_14 = _loc_16._-04;                                             }                                         }                                         _loc_15 = _loc_16._-a;                                         _loc_18 = _loc_16.timeline;                                         if (!_loc_20)                                         {                                             while (_loc_18)                                             {                                                                                                  if (_loc_21 || this)                                                 {                                                     _loc_14 = _loc_14 * _loc_18._-04;                                                 }                                                 _loc_15 = _loc_15 + _loc_18._-a;                                                 _loc_18 = _loc_18.timeline;                                             }                                         }                                         if (!_loc_20)                                         {                                         }                                         if (!_loc_20)                                         {                                             _loc_17 = _loc_14 * _loc_15;                                             if (_loc_21 || this)                                             {                                             }                                         }                                         if (_loc_21 || param3)                                         {                                             if (_loc_21 || param3)                                             {                                             }                                         }                                         if (_loc_16._-m == 0)                                         {                                             if (!_loc_20)                                             {                                                 _loc_9[++_loc_12] = _loc_16;                                             }                                         }                                         if (_loc_21)                                         {                                         }                                         if (!_loc_20)                                         {                                         }                                     }                                 }while (--_loc_5 &gt; -1)
                            }
                        }
                    }
                    if (_loc_12 == 0)
                    {
                        return _loc_6;
                    }
                }
                --_loc_5 = _loc_12;
                if (_loc_21 || this)
                {
                }
                do
                {

                    _loc_7 = _loc_9[--_loc_5];
                    if (_loc_21 || this)
                    {
                        if (_loc_7._-0l(_loc_2))
                        {
                            var _loc_6:Boolean;
                        }
                        if (_loc_21)
                        {
                            if (_loc_7.case20 == null)
                            {
                                if (_loc_21 || param3)
                                {
                                }
                            }
                        }
                    }
                    if (_loc_7.dynamic)
                    {
                        if (_loc_21 || param1)
                        {
                            _loc_7.setEnabled(false, false);
                        }
                    }
                }
                if (_loc_21)
                {
                }
                if (_loc_21 || param3)
                {
                }while (--_loc_5 &gt; -1)
                if (_loc_21)
                {
                    ;
                    while (--_loc_5 &gt; -1)
                    {

                    }
                    ;
                    _loc_11--;
                    _loc_14--;
                    _loc_6 = true as true;
                }
            }
            return _loc_6;
        }// end function

        public static function get20(param1:continue) : Boolean
        {
            ;
            _loc_2--;
            var _loc_3:* = null[(false - _loc_3)-- == true];
            var _loc_4:String;
            var _loc_2:Boolean;
            while (param1)
            {

                if (!(_loc_3 &amp;&amp; _loc_3))
                {
                    continue;
                    _loc_3 = param1.else20;
                    _loc_2++;
                    _loc_2--;
                    if (_loc_4 || _loc_3)
                    {
                        continue;
                        if (_loc_3)
                        {
                        }
                    }
                }
            }
            return _loc_2;
        }// end function

        ;
        var _loc_1:* = (true * false)--[_loc_2];
        var _loc_2:String;
        if (!_loc_1)
        {
            ;
            null.for = this;
        }
        if (_loc_1)
        {
        }
        else
        {
        }
        if (!new activation)
        {
        }
    }
}

Good luck figuring that one out. The purpose of the encryption is to remove hackers ability to see how your score hash is formed, but we will get to this later.

First the RAM problem.
RAM search programs look for a specific set of conditions, like numbers that have increased, decreased, not changed, equal to, greater than, less than, not equal to and other logical comparison operations. To make this method pretty much unusable, all you need to do is make your score (which is visually a number) not to be a number inside memory. Here is my way of doing just that

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package {
  import com.dynamicflash.util.Base64;
  public class SafeNumber {
    private var _currentScore:String;
    private static var _instance:SafeNumber;
    private static var _allowInit:Boolean = false;
    public static function get instance():SafeNumber {
      if (!_instance) {
        _allowInit = true;
        _instance = new SafeNumber();
        _allowInit = false;
      }
      return _instance;
    }
    public function SafeNumber() {
      if(_allowInit){
        _currentScore = Base64.encode("0");
      }else {
        throw new Error("Use SafeNumber.instance");
      }
    }
    public function get currentScore():Number {
      return Base64.decode(_currentScore);
    }
    public function set currentScore(parValue:Number):void {
      _currentScore = Base64.encode(String(parValue));
    }
  }
}

What I do here is covert a number to base64 hash, this way the score, or any other value that you need to save, never exist as a number in the memory, it exist as a base64 hash. Going back to encryption topic, unless swf file is encrypted, hacker can look up how your hash is generated, write a script of his own and search for the value he needs.

Next is the problem of securing the post. Since your application is encrypted, things are a lot easier. All you need to do is send to server your score and checksum hash, chesum hash is generated by using

1
MD5.encode(score+"Some secret key");

In server side, you perform check

1
2
3
4
5
6
7
8
  $score= $_POST['score'];
  $secret_key='Some secret key';
  $hash= $_POST['hash'];
  if(md5($score . $secret_key)===$hash){
    // save score
  }else{
    // error message or some other handler
  }

Simple and effective. These steps are no way 100% secure, however they are very tricky to go around and hack. From my personal experience, hackers give up after 50 minutes of hack fail. And this can definitely hold longer than that

376137_219716018098056_119264868143172_499051_609147412_n

PHP pseudo streams

0

Couple of minutes ago one of my friends has asked me do i know anything that can be used for pseudo streams and flash. This is somewhat an old topic, but still quite interesting.

Pseudo streams are a solution of skipping the play-head of the stream to your desired position on timeline. It is called pseudo stream because its not really skipping to that position, rather to the closest key-frame available. Reason for using this method is simple, unless you have a flash media server or red5 installed on your machine, you cant skip to the time that is not yet loaded.

Heres a basic story behind pseudo streaming:

  • Adding metadata to your flv along with a bunch of key-frames
  • put the flv on a server supporting PHP
  • Instead of using myvideo.flv as a path parameter, you use a PHP script with param, usually a key-frame number and in some cases a path to the flv on the server
  • PHP script uses fopen function to skip to the key-frame specified and starts throwing content as if it was a normal flv file only starting from your key-frame rather than beginning

This method is very popular in adult content websites as they have some legal issues with licensing servers.

So, that was a small intro to the method, and to see multiple implementations follow this link

Go to Top