From vszocs at redhat.com Tue Aug 28 06:17:30 2012 Content-Type: multipart/mixed; boundary="===============5583118577201118657==" MIME-Version: 1.0 From: Vojtech Szocs To: devel at ovirt.org Subject: [Engine-devel] Update on UI Plugins: Improved plugin API Date: Tue, 28 Aug 2012 06:17:29 -0400 Message-ID: <1302819559.14447954.1346149049849.JavaMail.root@redhat.com> In-Reply-To: 455300925.14438202.1346146868031.JavaMail.root@redhat.com --===============5583118577201118657== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable ------=3D_Part_14447953_781921536.1346149049848 Content-Type: text/plain; charset=3Dutf-8 Content-Transfer-Encoding: 7bit Hi guys, = I was thinking about improving JavaScript plugin API so that each time a pl= ugin calls WebAdmin, the plugin name will be part of the call. This way, Pl= uginManager (WebAdmin) can validate the call before doing any further actio= ns, e.g. "plugin invocation must be allowed && plugin must be initialized".= In other words, this is just to ensure consistent behavior for "plugin -> = WebAdmin" calls. = Here's a draft of new JavaScript API in action: http://jsfiddle.net/tHk5n/ = (see the code below the comment saying "ACTUAL TEST CODE") = (I took my inspiration from jQuery source code, even though I don't fully u= nderstand JavaScript prototype OOP concept, seems a bit weird to me.) = For comparison, here's some plugin code that uses current plugin API: = // Register our plugin object (containing event handler functions) into plu= ginApi.plugins = pluginApi.plugins['myPlugin'] =3D { = UiInit: function() { = pluginApi.ui.addMainTab('Custom Tab', 'custom-tab', 'http://www.example.com= /'); = } = }; = // Tell WebAdmin that we are ready, we need the plugin name to identify thi= s plugin = pluginApi.ready('myPlugin'); = And here's an equivalent plugin code that uses new plugin API: = // Plugin API instance for our plugin = var myPlugin =3D pluginApi('myPlugin'); = // Register our plugin object (containing event handler functions) into myP= lugin = myPlugin.register({ = UiInit: function() { = myPlugin.ui.addMainTab('Custom Tab', 'custom-tab', 'http://www.example.com/= '); = } = }); = // Tell WebAdmin that we are ready , plugin name is already part of myPlugi= n = myPlugin.ready(); = // Note: the above line is equivalent to: pluginApi('myPlugin').ready() ; = Let me know what you think. = Cheers, = Vojtech = ------=3D_Part_14447953_781921536.1346149049848 Content-Type: text/html; charset=3Dutf-8 Content-Transfer-Encoding: quoted-printable <=3D div style=3D3D'font-family: times new roman,new york,times,serif; font-size= : =3D 12pt; color: #000000'>Hi guys,

I was thinking about improving JavaSc= =3D ript plugin API so that each time a plugin calls WebAdmin, the plugin name = =3D will be part of the call. This way, PluginManager (WebAdmin) can v= =3D alidate the call before doing any further actions, e.g. "plugin invocation = =3D must be allowed && plugin must be initialized". In other words, thi= =3D s is just to ensure consistent behavior for "plugin -> WebAdmin" calls.<= =3D br>
Here's a draft of new JavaScript API in action: http://jsfiddle.net/= =3D tHk5n/ (see the code below the comment saying "ACTUAL TEST CODE")
(I too= =3D k my inspiration from jQuery source code, even though I don't fully underst= =3D and JavaScript prototype OOP concept, seems a bit weird to me.)



For comparison, here's some plugi= n =3D code that uses current plugin API:

// Register our plugin object = =3D (containing event handler functions) into pluginApi.plugins
plu= gi=3D nApi.plugins['myPlugin'] =3D3D {
  UiInit: function() {
    pluginApi.ui.addMainTab('Custom Tab', 'custom-t= =3D ab', 'http://www.example.com/');
  }
};

// Tell WebAdmin that we are ready, we need the plugin name to identi= =3D fy this plugin
pluginApi.ready('myPlugin');



And here's an equivalent plugin code t= ha=3D t uses new plugin API:

// Plugin API instance for our plugin
var myPlugin =3D3D pluginApi('myPlugin');

// Register our pl= =3D ugin object (containing event handler functions) into myPlugin
= my=3D Plugin.register({

  UiInit: function() {
&n= bs=3D p;   myPlugin.ui.addMainTab('Custom Tab', 'custom-tab', 'http://w= =3D ww.example.com/');

  }
});

// = Te=3D ll WebAdmin that we are ready, plugin name is already part of myPlugin
myPlugin.ready();
// Note: the above line is equivalent to:= =3D pluginApi('myPlugin').ready();



Let me know what you think.

Cheers,
Vojtech

------=3D_Part_14447953_781921536.1346149049848-- --===============5583118577201118657== Content-Type: multipart/alternative MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="attachment.bin" LS0tLS0tPV9QYXJ0XzE0NDQ3OTUzXzc4MTkyMTUzNi4xMzQ2MTQ5MDQ5ODQ4CkNvbnRlbnQtVHlw ZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiA3 Yml0CgpIaSBndXlzLCAKCkkgd2FzIHRoaW5raW5nIGFib3V0IGltcHJvdmluZyBKYXZhU2NyaXB0 IHBsdWdpbiBBUEkgc28gdGhhdCBlYWNoIHRpbWUgYSBwbHVnaW4gY2FsbHMgV2ViQWRtaW4sIHRo ZSBwbHVnaW4gbmFtZSB3aWxsIGJlIHBhcnQgb2YgdGhlIGNhbGwuIFRoaXMgd2F5LCBQbHVnaW5N YW5hZ2VyIChXZWJBZG1pbikgY2FuIHZhbGlkYXRlIHRoZSBjYWxsIGJlZm9yZSBkb2luZyBhbnkg ZnVydGhlciBhY3Rpb25zLCBlLmcuICJwbHVnaW4gaW52b2NhdGlvbiBtdXN0IGJlIGFsbG93ZWQg JiYgcGx1Z2luIG11c3QgYmUgaW5pdGlhbGl6ZWQiLiBJbiBvdGhlciB3b3JkcywgdGhpcyBpcyBq dXN0IHRvIGVuc3VyZSBjb25zaXN0ZW50IGJlaGF2aW9yIGZvciAicGx1Z2luIC0+IFdlYkFkbWlu IiBjYWxscy4gCgpIZXJlJ3MgYSBkcmFmdCBvZiBuZXcgSmF2YVNjcmlwdCBBUEkgaW4gYWN0aW9u OiBodHRwOi8vanNmaWRkbGUubmV0L3RIazVuLyAoc2VlIHRoZSBjb2RlIGJlbG93IHRoZSBjb21t ZW50IHNheWluZyAiQUNUVUFMIFRFU1QgQ09ERSIpIAooSSB0b29rIG15IGluc3BpcmF0aW9uIGZy b20galF1ZXJ5IHNvdXJjZSBjb2RlLCBldmVuIHRob3VnaCBJIGRvbid0IGZ1bGx5IHVuZGVyc3Rh bmQgSmF2YVNjcmlwdCBwcm90b3R5cGUgT09QIGNvbmNlcHQsIHNlZW1zIGEgYml0IHdlaXJkIHRv IG1lLikgCgoKCkZvciBjb21wYXJpc29uLCBoZXJlJ3Mgc29tZSBwbHVnaW4gY29kZSB0aGF0IHVz ZXMgY3VycmVudCBwbHVnaW4gQVBJOiAKCi8vIFJlZ2lzdGVyIG91ciBwbHVnaW4gb2JqZWN0IChj b250YWluaW5nIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb25zKSBpbnRvIHBsdWdpbkFwaS5wbHVnaW5z IApwbHVnaW5BcGkucGx1Z2luc1snbXlQbHVnaW4nXSA9IHsgClVpSW5pdDogZnVuY3Rpb24oKSB7 IApwbHVnaW5BcGkudWkuYWRkTWFpblRhYignQ3VzdG9tIFRhYicsICdjdXN0b20tdGFiJywgJ2h0 dHA6Ly93d3cuZXhhbXBsZS5jb20vJyk7IAp9IAp9OyAKCi8vIFRlbGwgV2ViQWRtaW4gdGhhdCB3 ZSBhcmUgcmVhZHksIHdlIG5lZWQgdGhlIHBsdWdpbiBuYW1lIHRvIGlkZW50aWZ5IHRoaXMgcGx1 Z2luIApwbHVnaW5BcGkucmVhZHkoJ215UGx1Z2luJyk7IAoKCgpBbmQgaGVyZSdzIGFuIGVxdWl2 YWxlbnQgcGx1Z2luIGNvZGUgdGhhdCB1c2VzIG5ldyBwbHVnaW4gQVBJOiAKCi8vIFBsdWdpbiBB UEkgaW5zdGFuY2UgZm9yIG91ciBwbHVnaW4gCnZhciBteVBsdWdpbiA9IHBsdWdpbkFwaSgnbXlQ bHVnaW4nKTsgCgovLyBSZWdpc3RlciBvdXIgcGx1Z2luIG9iamVjdCAoY29udGFpbmluZyBldmVu dCBoYW5kbGVyIGZ1bmN0aW9ucykgaW50byBteVBsdWdpbiAKbXlQbHVnaW4ucmVnaXN0ZXIoeyAK VWlJbml0OiBmdW5jdGlvbigpIHsgCm15UGx1Z2luLnVpLmFkZE1haW5UYWIoJ0N1c3RvbSBUYWIn LCAnY3VzdG9tLXRhYicsICdodHRwOi8vd3d3LmV4YW1wbGUuY29tLycpOyAKfSAKfSk7IAoKLy8g VGVsbCBXZWJBZG1pbiB0aGF0IHdlIGFyZSByZWFkeSAsIHBsdWdpbiBuYW1lIGlzIGFscmVhZHkg cGFydCBvZiBteVBsdWdpbiAKbXlQbHVnaW4ucmVhZHkoKTsgCi8vIE5vdGU6IHRoZSBhYm92ZSBs aW5lIGlzIGVxdWl2YWxlbnQgdG86IHBsdWdpbkFwaSgnbXlQbHVnaW4nKS5yZWFkeSgpIDsgCgoK CkxldCBtZSBrbm93IHdoYXQgeW91IHRoaW5rLiAKCkNoZWVycywgClZvanRlY2ggCgoKLS0tLS0t PV9QYXJ0XzE0NDQ3OTUzXzc4MTkyMTUzNi4xMzQ2MTQ5MDQ5ODQ4CkNvbnRlbnQtVHlwZTogdGV4 dC9odG1sOyBjaGFyc2V0PXV0Zi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IHF1b3RlZC1w cmludGFibGUKCjxodG1sPjxoZWFkPjxzdHlsZSB0eXBlPTNEJ3RleHQvY3NzJz5wIHsgbWFyZ2lu OiAwOyB9PC9zdHlsZT48L2hlYWQ+PGJvZHk+PD0KZGl2IHN0eWxlPTNEJ2ZvbnQtZmFtaWx5OiB0 aW1lcyBuZXcgcm9tYW4sbmV3IHlvcmssdGltZXMsc2VyaWY7IGZvbnQtc2l6ZTogPQoxMnB0OyBj b2xvcjogIzAwMDAwMCc+SGkgZ3V5cyw8YnI+PGJyPkkgd2FzIHRoaW5raW5nIGFib3V0IGltcHJv dmluZyBKYXZhU2M9CnJpcHQgcGx1Z2luIEFQSSBzbyB0aGF0IGVhY2ggdGltZSBhIHBsdWdpbiBj YWxscyBXZWJBZG1pbiwgdGhlIHBsdWdpbiBuYW1lID0Kd2lsbCBiZSBwYXJ0IG9mIHRoZSBjYWxs LiBUaGlzIHdheSwgPGVtPlBsdWdpbk1hbmFnZXI8L2VtPiAoV2ViQWRtaW4pIGNhbiB2PQphbGlk YXRlIHRoZSBjYWxsIGJlZm9yZSBkb2luZyBhbnkgZnVydGhlciBhY3Rpb25zLCBlLmcuICJwbHVn aW4gaW52b2NhdGlvbiA9Cm11c3QgYmUgYWxsb3dlZCAmYW1wOyZhbXA7IHBsdWdpbiBtdXN0IGJl IGluaXRpYWxpemVkIi4gSW4gb3RoZXIgd29yZHMsIHRoaT0KcyBpcyBqdXN0IHRvIGVuc3VyZSBj b25zaXN0ZW50IGJlaGF2aW9yIGZvciAicGx1Z2luIC0mZ3Q7IFdlYkFkbWluIiBjYWxscy48PQpi cj48YnI+SGVyZSdzIGEgZHJhZnQgb2YgbmV3IEphdmFTY3JpcHQgQVBJIGluIGFjdGlvbjogaHR0 cDovL2pzZmlkZGxlLm5ldC89CnRIazVuLyAoc2VlIHRoZSBjb2RlIGJlbG93IHRoZSBjb21tZW50 IHNheWluZyAiQUNUVUFMIFRFU1QgQ09ERSIpPGJyPihJIHRvbz0KayBteSBpbnNwaXJhdGlvbiBm cm9tIGpRdWVyeSBzb3VyY2UgY29kZSwgZXZlbiB0aG91Z2ggSSBkb24ndCBmdWxseSB1bmRlcnN0 PQphbmQgSmF2YVNjcmlwdCBwcm90b3R5cGUgT09QIGNvbmNlcHQsIHNlZW1zIGEgYml0IHdlaXJk IHRvIG1lLik8YnI+PGJyPjxociA9CnN0eWxlPTNEIndpZHRoOiAxMDAlOyBoZWlnaHQ6IDJweDsi Pjxicj5Gb3IgY29tcGFyaXNvbiwgaGVyZSdzIHNvbWUgcGx1Z2luID0KY29kZSB0aGF0IHVzZXMg Y3VycmVudCBwbHVnaW4gQVBJOjxicj48YnI+PHNwYW4gc3R5bGU9M0QiZm9udC1mYW1pbHk6IGNv dXJpPQplciBuZXcsY291cmllcixtb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij4vLyBSZWdp c3RlciBvdXIgcGx1Z2luIG9iamVjdCA9Cihjb250YWluaW5nIGV2ZW50IGhhbmRsZXIgZnVuY3Rp b25zKSBpbnRvIHBsdWdpbkFwaS5wbHVnaW5zPC9zcGFuPjxiciBzdHlsZT0KPTNEImZvbnQtZmFt aWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxz cGFuIHN0PQp5bGU9M0QiZm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1v bm9zcGFjZSxzYW5zLXNlcmlmOyI+cGx1Z2k9Cm5BcGkucGx1Z2luc1snbXlQbHVnaW4nXSA9M0Qg ezwvc3Bhbj48YnIgc3R5bGU9M0QiZm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LD0KY291cmllcixt b25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij48c3BhbiBzdHlsZT0zRCJmb250LWZhbWlseTog Y291cmllciBuPQpldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPiZuYnNw OyZuYnNwO1VpSW5pdDogZnVuY3Rpb24oKSB7PC89CnNwYW4+PGJyIHN0eWxlPTNEImZvbnQtZmFt aWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZT0KcmlmOyI+ PHNwYW4gc3R5bGU9M0QiZm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1v bm9zcGFjZSxzYW5zPQotc2VyaWY7Ij4mbmJzcDsmbmJzcDsgJm5ic3A7cGx1Z2luQXBpLnVpLmFk ZE1haW5UYWIoJ0N1c3RvbSBUYWInLCAnY3VzdG9tLXQ9CmFiJywgJ2h0dHA6Ly93d3cuZXhhbXBs ZS5jb20vJyk7PC9zcGFuPjxiciBzdHlsZT0zRCJmb250LWZhbWlseTogY291cmllciBuZT0Kdyxj b3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPTNEImZvbnQt ZmFtaWx5OiBjb3VyaWVyPQogbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlm OyI+Jm5ic3A7Jm5ic3A7fTwvc3Bhbj48YnIgc3R5bGU9M0Q9CiJmb250LWZhbWlseTogY291cmll ciBuZXcsY291cmllcixtb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij48c3BhbiBzdHlsZT0K PTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fu cy1zZXJpZjsiPn07PC9zcGFuPQo+PGJyIHN0eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5l dyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjs9CiI+PGJyIHN0eWxlPTNEImZv bnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJp Zj0KOyI+PHNwYW4gc3R5bGU9M0QiZm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9u YWNvLG1vbm9zcGFjZSxzYW5zLXNlPQpyaWY7Ij4vLyBUZWxsIFdlYkFkbWluIHRoYXQgd2UgYXJl IHJlYWR5LCB3ZSBuZWVkIHRoZSBwbHVnaW4gbmFtZSB0byBpZGVudGk9CmZ5IHRoaXMgcGx1Z2lu PC9zcGFuPjxiciBzdHlsZT0zRCJmb250LWZhbWlseTogY291cmllciBuZXcsY291cmllcixtb25h Y28sbT0Kb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPTNEImZvbnQtZmFtaWx5OiBj b3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjPQpvLG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+cGx1Z2lu QXBpLnJlYWR5KCdteVBsdWdpbicpOzwvc3Bhbj48YnIgc3R5bGU9M0QiZm89Cm50LWZhbWlseTog Y291cmllciBuZXcsY291cmllcixtb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij48YnI+PGhy IHN0eWxlPQo9M0Qid2lkdGg6IDEwMCU7IGhlaWdodDogMnB4OyI+PGJyPkFuZCBoZXJlJ3MgYW4g ZXF1aXZhbGVudCBwbHVnaW4gY29kZSB0aGE9CnQgdXNlcyBuZXcgcGx1Z2luIEFQSTo8YnI+PGJy PjxzcGFuIHN0eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaT0KZXIsbW9uYWNv LG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+Ly8gUGx1Z2luIEFQSSBpbnN0YW5jZSBmb3Igb3VyIHBs dWdpbjwvc3BhPQpuPjxiciBzdHlsZT0zRCJmb250LWZhbWlseTogY291cmllciBuZXcsY291cmll cixtb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY9CjsiPjxzcGFuIHN0eWxlPTNEImZvbnQtZmFt aWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZT0KcmlmOyI+ dmFyIG15UGx1Z2luID0zRCBwbHVnaW5BcGkoJ215UGx1Z2luJyk7PC9zcGFuPjxiciBzdHlsZT0z RCJmb250LWZhbWlsPQp5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fu cy1zZXJpZjsiPjxiciBzdHlsZT0zRCJmb250LWZhbWk9Cmx5OiBjb3VyaWVyIG5ldyxjb3VyaWVy LG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPTNEImZvbnQtZj0KYW1p bHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+Ly8g UmVnaXN0ZXIgb3VyIHBsPQp1Z2luIG9iamVjdCAoY29udGFpbmluZyBldmVudCBoYW5kbGVyIGZ1 bmN0aW9ucykgaW50byBteVBsdWdpbjwvc3Bhbj48YnIgc3Q9CnlsZT0zRCJmb250LWZhbWlseTog Y291cmllciBuZXcsY291cmllcixtb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij48c3Bhbj0K IHN0eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25vc3Bh Y2Usc2Fucy1zZXJpZjsiPm15PQpQbHVnaW4ucmVnaXN0ZXIoezwvc3Bhbj48YnIgc3R5bGU9M0Qi Zm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWM9Cm8sbW9ub3NwYWNlLHNhbnMt c2VyaWY7Ij48c3BhbiBzdHlsZT0zRCJmb250LWZhbWlseTogY291cmllciBuZXcsY291cmllcixt bz0KbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPiZuYnNwOyZuYnNwO1VpSW5pdDogZnVuY3Rp b24oKSB7PC9zcGFuPjxiciBzdHlsPQplPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3Vy aWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHM9CnR5bGU9M0QiZm9udC1m YW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+ Jm5icz0KcDsmbmJzcDsgJm5ic3A7bXlQbHVnaW4udWkuYWRkTWFpblRhYignQ3VzdG9tIFRhYics ICdjdXN0b20tdGFiJywgJ2h0dHA6Ly93PQp3dy5leGFtcGxlLmNvbS8nKTs8L3NwYW4+PGJyIHN0 eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmE9CmNvLG1vbm9zcGFj ZSxzYW5zLXNlcmlmOyI+PHNwYW4gc3R5bGU9M0QiZm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNv dXJpZXIsbT0Kb25hY28sbW9ub3NwYWNlLHNhbnMtc2VyaWY7Ij4mbmJzcDsmbmJzcDt9PC9zcGFu PjxiciBzdHlsZT0zRCJmb250LWZhbWlseTogPQpjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxt b25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHN0eWxlPTNEImZvbnQtZmFtaWw9Cnk6IGNvdXJp ZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+fSk7PC9zcGFuPjxi ciBzdHlsZT0zRD0KImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyaWVyLG1vbmFjbyxtb25v c3BhY2Usc2Fucy1zZXJpZjsiPjxiciBzdHlsZT0KPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5l dyxjb3VyaWVyLG1vbmFjbyxtb25vc3BhY2Usc2Fucy1zZXJpZjsiPjxzcGFuIHN0PQp5bGU9M0Qi Zm9udC1mYW1pbHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNl cmlmOyI+Ly8gVGU9CmxsIFdlYkFkbWluIHRoYXQgd2UgYXJlIHJlYWR5LCBwbHVnaW4gbmFtZSBp cyBhbHJlYWR5IHBhcnQgb2YgbXlQbHVnaW48L3NwYT0Kbj48YnIgc3R5bGU9M0QiZm9udC1mYW1p bHk6IGNvdXJpZXIgbmV3LGNvdXJpZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlmPQo7Ij48 c3BhbiBzdHlsZT0zRCJmb250LWZhbWlseTogY291cmllciBuZXcsY291cmllcixtb25hY28sbW9u b3NwYWNlLHNhbnMtc2U9CnJpZjsiPm15UGx1Z2luLnJlYWR5KCk7PC9zcGFuPjxiciBzdHlsZT0z RCJmb250LWZhbWlseTogY291cmllciBuZXcsY291cmllcj0KLG1vbmFjbyxtb25vc3BhY2Usc2Fu cy1zZXJpZjsiPjxzcGFuIHN0eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldyxjb3VyPQpp ZXIsbW9uYWNvLG1vbm9zcGFjZSxzYW5zLXNlcmlmOyI+Ly8gTm90ZTogdGhlIGFib3ZlIGxpbmUg aXMgZXF1aXZhbGVudCB0bzo9CiBwbHVnaW5BcGkoJ215UGx1Z2luJykucmVhZHkoKTs8L3NwYW4+ PGJyIHN0eWxlPTNEImZvbnQtZmFtaWx5OiBjb3VyaWVyIG5ldz0KLGNvdXJpZXIsbW9uYWNvLG1v bm9zcGFjZSxzYW5zLXNlcmlmOyI+PGJyPjxociBzdHlsZT0zRCJ3aWR0aDogMTAwJTsgaGVpZ2h0 PQo6IDJweDsiPjxicj5MZXQgbWUga25vdyB3aGF0IHlvdSB0aGluay48YnI+PGJyPkNoZWVycyw8 YnI+Vm9qdGVjaDxicj48YnI+PC89CmRpdj48L2JvZHk+PC9odG1sPgotLS0tLS09X1BhcnRfMTQ0 NDc5NTNfNzgxOTIxNTM2LjEzNDYxNDkwNDk4NDgtLQo= --===============5583118577201118657==--