├── LICENSE ├── README.md ├── demo.gif └── installation files ├── 10application_changes.txt ├── 10application_example.jsx ├── 1337jsxbinconverter.jsx └── converter └── runner.cmd /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrin Meier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction to ExtendScript Toolkit JSXBIN to JSX converter plugin 2 | [JSXBIN to JSX converter](https://github.com/autoboosh/jsxbin-to-jsx-converter) allows you to decode .jsxbin to .jsx files using the command line. This gets tedious after a while if you have many scripts to decode. That is why this little plugin was born which allows you to open .jsxbin files directly inside of ExtendScript Toolkit as if they had always been in cleartext. 3 | 4 | # Demo 5 | ![Plugin Demo](demo.gif) 6 | 7 | # Installation 8 | 1. Grab and extract the [latest release somewhere on your PC](https://github.com/autoboosh/extendscript-toolkit-jsxbintojsx-plugin/releases) 9 | 2. Copy the converter directory to somewhere on your PC where you have read/write permissions 10 | 3. Grab and extract the latest [JSXBIN to JSX converter](https://github.com/autoboosh/jsxbin-to-jsx-converter/releases) and put it inside of the converter directory 11 | 4. As administrator: Change C:\Program Files (x86)\Adobe\Adobe ExtendScript Toolkit CC\Required\10application.jsx as described in the 10application_changes.txt file. The 10application_example.txt file shows you how it is supposed to look in the end but since there may be different versions of the file in the wild it is important that you apply the changes manually. 12 | 5. As administrator: Open 1337jsxbinconverter.jsx and change CONVERTER_FOLDER to the path where you put the converter directory 13 | 6. Copy 1337jsxbinconverter.jsx to C:\Program Files (x86)\Adobe\Adobe ExtendScript Toolkit CC\Required\ 14 | 7. Start ExtendScript Toolkit and use File->Open as you usually would. Only this time open a .jsxbin file. It should be automatically converted in the background with the decoded file being created in the same folder as the .jsxbin file 15 | 16 | # Feedback 17 | If you encounter any problems, please create an issue. -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sror/extendscript-toolkit-jsxbintojsx-plugin/ebc1cc81c5e02443811e16d2b8389bdaac6ff32e/demo.gif -------------------------------------------------------------------------------- /installation files/10application_changes.txt: -------------------------------------------------------------------------------- 1 | // STEP 1 2 | // Replace 3 | var files = f.openDlg (localize ("$$$/ESToolkit/FileDlg/Open=Open"), 4 | lang.buildFileTypes(), true); 5 | // With 6 | var filetypes = lang.buildFileTypes(); 7 | filetypes = filetypes.replace("*.jsx;", "*.jsx;*.jsxbin;"); 8 | var files = f.openDlg (localize ("$$$/ESToolkit/FileDlg/Open=Open"), 9 | filetypes, true); 10 | 11 | // STEP 2 12 | // Before 13 | var doc = docMgr.find( f.absoluteURI ); 14 | // Add 15 | f = app.convertJsxbinToJsx(f); 16 | -------------------------------------------------------------------------------- /installation files/10application_example.jsx: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | * 3 | * @@@BUILDINFO@@@ 10application-2.jsx 3.5.0.46 07-December-2009 4 | * ADOBE SYSTEMS INCORPORATED 5 | * Copyright 2010 Adobe Systems Incorporated 6 | * All Rights Reserved. 7 | * 8 | * NOTICE: Adobe permits you to use, modify, and distribute this file in 9 | * accordance with the terms of the Adobe license agreement accompanying it. 10 | * If you have received this file from a source other than Adobe, then your 11 | * use, modification, or distribution of it requires the prior written 12 | * permission of Adobe. 13 | * 14 | **************************************************************************/ 15 | 16 | // The current folder to use for open/save dialogs 17 | app.currentFolder = Folder.myDocuments.absoluteURI; 18 | // file watches 19 | app.fileWatches = []; 20 | 21 | app.onNotify = function( reason, shift ) 22 | { 23 | switch( reason ) 24 | { 25 | case 'shutdown': 26 | { 27 | globalBroadcaster.unregisterClient( this ); 28 | 29 | if( !arguments[1] ) 30 | this.writePrefs(); 31 | } 32 | break; 33 | 34 | case 'preferencesDialog': 35 | { 36 | openPreferencesDialog( arguments[1] ); 37 | } 38 | break; 39 | 40 | case 'reqNewDoc': 41 | { 42 | docMgr.create(); 43 | } 44 | break; 45 | 46 | case 'reqOpenDoc': 47 | { 48 | app.open(); 49 | } 50 | break; 51 | 52 | case 'appFrameChanged': 53 | { 54 | if( !_win ) 55 | { 56 | if( workspace.appbar.btn ) 57 | workspace.appbar.btn.update(); 58 | } 59 | } 60 | break; 61 | } 62 | } 63 | 64 | app.onIdle = function() 65 | { 66 | globalBroadcaster.notifyClients( 'IDLE' ); 67 | } 68 | 69 | app.open = function() 70 | { 71 | var f = File (this.currentFolder); 72 | var filetypes = lang.buildFileTypes(); 73 | filetypes = filetypes.replace("*.jsx;", "*.jsx;*.jsxbin;"); 74 | var files = f.openDlg (localize ("$$$/ESToolkit/FileDlg/Open=Open"), 75 | filetypes, true); 76 | if (files) 77 | { 78 | if( files.length > 1 ) 79 | { 80 | docMgr.showProgress (true); 81 | docMgr.setProgress( 0, files.length ); 82 | } 83 | 84 | for (var i = 0; i < files.length; i++) 85 | { 86 | f = files [i]; 87 | 88 | docMgr.setProgressText( f.name ); 89 | docMgr.incProgress(1); 90 | 91 | // remember the folder 92 | this.currentFolder = f.parent ? f.parent.absoluteURI : "/"; 93 | // resolve any alias 94 | if (f.alias) 95 | { 96 | var resolved = f.resolve(); 97 | if (!resolved) 98 | { 99 | errorBox( localize( "$$$/ESToolkit/FileDlg/CannotResolve=Cannot resolve alias to file %1", decodeURIComponent( f.name ) ) ); 100 | return false; 101 | } 102 | f = resolved; 103 | } 104 | 105 | f = app.convertJsxbinToJsx(f); 106 | 107 | // user selected a file; test if the file has been loaded 108 | var doc = docMgr.find( f.absoluteURI ); 109 | 110 | if (doc) 111 | doc.activate(); 112 | else if (!docMgr.load( f )) 113 | { 114 | docMgr.showProgress( false ); 115 | 116 | return false; 117 | } 118 | } 119 | 120 | docMgr.showProgress( false ); 121 | } 122 | return true; 123 | } 124 | 125 | app.loadPrefs = function() 126 | { 127 | if( prefs.app.currentFolder.hasValue( Preference.STRING ) != '' ) 128 | this.currentFolder = prefs.app.currentFolder.getValue( Preference.STRING ); 129 | 130 | if( prefs.app.scriptsFolder.hasValue( Preference.STRING ) != '' ) 131 | this.scriptsFolder = prefs.app.scriptsFolder.getValue( Preference.STRING ); 132 | if( !this.scriptsFolder.exists ) 133 | this.scriptsFolder = Folder.current.absoluteURI; 134 | } 135 | 136 | app.writePrefs = function() 137 | { 138 | prefs.app.currentFolder = this.currentFolder; 139 | } 140 | 141 | app.toFront = function() 142 | { 143 | // 144 | // ask the target to bring myself to front 145 | // 146 | var currTarget = targetMgr.getActiveTarget(); 147 | 148 | if( currTarget && currTarget.getFeature( Feature.TO_FRONT ) ) 149 | { 150 | try 151 | { 152 | var job = currTarget.cdic.toFront( currTarget.address ); 153 | job.hostID = app.id; 154 | 155 | job.onResult = function() 156 | { 157 | if( !this.result[0] ) 158 | // try it by myself 159 | app.bringToFront(); 160 | } 161 | 162 | job.onError = job.onTimeout = function() 163 | { 164 | // try it by myself 165 | app.bringToFront(); 166 | } 167 | 168 | job.submit(); 169 | } 170 | catch( exc ) 171 | {} 172 | } 173 | else 174 | // try it by myself 175 | app.bringToFront(); 176 | } 177 | 178 | app.targetAppRunning = function( target ) 179 | { 180 | var ret = false; 181 | 182 | if( target.cdic ) 183 | { 184 | try 185 | { 186 | var res = cdicMgr.callSynchronous( target.cdic.isTargetRunning( target.address ) ); 187 | 188 | // 189 | // first res entry is the actuall result array, if there're more entries 190 | // then an error or a timeout occurred 191 | // 192 | if( res.length <= 1 ) 193 | ret = res[0][0]; 194 | } 195 | catch( exc ) 196 | { 197 | // TODO 198 | } 199 | } 200 | 201 | return ret; 202 | } 203 | 204 | app.launchTargetAppSynchronous = function( target, launchMsg, connectIfLaunched ) 205 | { 206 | var ret = false; 207 | var finished = false; 208 | 209 | function check( state ) 210 | { 211 | ret = state; 212 | finished = true; 213 | } 214 | 215 | var cb = new Callback( check ); 216 | 217 | app.launchTargetApp( target, launchMsg, cb ); 218 | 219 | while( !finished ) 220 | cdi.pump(); 221 | 222 | if( ret && connectIfLaunched && target ) 223 | target.connect( true, undefined, undefined, true ); 224 | 225 | return ret; 226 | } 227 | 228 | app.launchTargetApp = function( target, launchMsg, callback, errorInfo ) 229 | { 230 | // 231 | // OK if the target is myself or running 232 | // 233 | if( target.address.target == 'estoolkit-4.0' ) 234 | { 235 | if( callback ) 236 | callback.call( true ); 237 | } 238 | 239 | if( !launchMsg ) 240 | launchMsg = "$$$/ESToolkit/Alerts/Launch=Target %1 is not running.^nDo you want to launch %1?"; 241 | 242 | if( !dsaQueryBox( 'app2', launchMsg, target.getTitle() ) ) 243 | { 244 | if( callback ) 245 | callback.call( false ); 246 | 247 | return; 248 | } 249 | 250 | // 251 | // initiate launch 252 | // 253 | if( target.cdic ) 254 | { 255 | try 256 | { 257 | var job = target.cdic.launchTarget( target.address ); 258 | job.target = target; 259 | job.cb = callback; 260 | job.errorInfo = errorInfo; 261 | 262 | job.onResult = function() 263 | { 264 | if( this.result[0] ) 265 | { 266 | // 267 | // target app is about to launch, now wait until the app finished launching 268 | // 269 | // 270 | // display a non-modal dialog 271 | // 272 | var dlg = new Window ( 273 | "palette { \ 274 | properties: { closeOnKey:'Escape' }, \ 275 | text: '" + app.title + "', \ 276 | orientation:'column', \ 277 | msg: StaticText { text:'$$$/ESToolkit/Status/Sleeping=Waiting; press ESC to abort...' },\ 278 | cancelBtn: Button { text:'$$$/CT/ExtendScript/UI/Cancel=&Cancel', properties:{name:'cancel'} } \ 279 | } \ 280 | }"); 281 | 282 | dlg.cancel.onClick = function() 283 | { 284 | //this.parent.aborted = true; 285 | this.parent.close(); 286 | } 287 | 288 | dlg.onClose = function() 289 | { 290 | this.aborted = true; 291 | } 292 | 293 | dlg.aborted = false; 294 | dlg.toClose = false; 295 | dlg.center(); 296 | dlg.show(); 297 | 298 | // 299 | // wait until launched, timeout after 5 Min. 300 | // 301 | const kLaunchTimeout = 300000; // 5 min. 302 | var startTime = new Date(); 303 | 304 | while( !dlg.aborted && !dlg.toClose ) 305 | { 306 | try 307 | { 308 | var task = this.target.cdic.isTargetRunning( this.target.address ); 309 | var res = CDICManager.getSynchronousResult( cdicMgr.callSynchronous( task ) ); 310 | 311 | if( res && res.length && res[0] ) 312 | { 313 | // app is running 314 | dlg.toClose = true; 315 | } 316 | 317 | // 318 | // pump application event loop several times to 319 | // receive UI events 320 | // 321 | var abortIm = false; 322 | 323 | for( var pumpLoop=0; pumpLoop<10 && !abortIm; pumpLoop++ ) 324 | abortIm = !app.pumpEventLoop(); 325 | 326 | if( abortIm ) 327 | { 328 | // abort 329 | dlg.aborted = true; 330 | dlg.close(); 331 | 332 | if( abortIm ) 333 | { 334 | // 335 | // estk is quitting 336 | // 337 | return; 338 | } 339 | } 340 | } 341 | catch( exc ) 342 | { 343 | // abort 344 | dlg.aborted = true; 345 | dlg.close(); 346 | } 347 | 348 | var now = new Date(); 349 | 350 | dlg.aborted = ( dlg.aborted ? dlg.aborted : ( ( now - startTime ) > kLaunchTimeout ) ); 351 | } 352 | 353 | dlg.onClose = null; 354 | dlg.close(); 355 | var dlgaborted = dlg.aborted; 356 | dlg = null; // force deletion of core Window element 357 | 358 | if( this.cb ) 359 | this.cb.call( !dlgaborted ); 360 | } 361 | else 362 | { 363 | app.launchError( this ); 364 | } 365 | } 366 | 367 | job.onError = job.onTimeout = function() 368 | { 369 | app.launchError( this ); 370 | } 371 | 372 | job.submit(); 373 | } 374 | catch( exc ) 375 | { 376 | if( this.cb ) 377 | this.cb.call( false ); 378 | } 379 | } 380 | else if( this.cb ) 381 | this.cb.call( false ); 382 | } 383 | 384 | app.launchError = function( targetOrJob ) 385 | { 386 | var target = targetOrJob; 387 | var cb = null; 388 | var error = null; 389 | 390 | if( target.target ) 391 | { 392 | // 393 | // parameter is a Job object 394 | // 395 | target = targetOrJob.target; 396 | cb = targetOrJob.cb; 397 | error = targetOrJob.errorInfo; 398 | } 399 | 400 | var errorMsg = localize( "$$$/ESToolkit/Alerts/CannotLaunch=Cannot launch target %1!", target.getTitle() ); 401 | 402 | if( error ) 403 | error.push( errorMsg ); 404 | else 405 | new ErrorInfo( errorMsg ).display(); 406 | 407 | if( cb ) 408 | cb.call( false ); 409 | } 410 | 411 | /////////////////////////////////////////////////////////////////////////////// 412 | // 413 | // file watches 414 | // 415 | 416 | app.onFilesChanged = function( files ) 417 | { 418 | for( var i=0; i 0; 574 | } 575 | catch( exc ) 576 | { 577 | delete __busyPlaceholder__[busyID]; 578 | } 579 | 580 | return ret; 581 | } 582 | } 583 | 584 | app.initBusyPlaceholderImage = function( imageObj ) 585 | { 586 | imageObj.visible = false; 587 | imageObj.currentIdx = 0; 588 | imageObj.timer = -1; 589 | imageObj.icons = new Array; 590 | imageObj.instance = 0; 591 | 592 | for( var i=1; i<9; i++ ) 593 | imageObj.icons.push( '#Busyan0' + i ); 594 | 595 | __busyID__++; 596 | __busyPlaceholder__[__busyID__] = imageObj; 597 | 598 | return __busyID__; 599 | } 600 | 601 | app.__busystep__ = function( id ) 602 | { 603 | var imgObj = __busyPlaceholder__[id]; 604 | 605 | try 606 | { 607 | if( imgObj && imgObj.icons ) 608 | { 609 | imgObj.currentIdx++; 610 | 611 | if( imgObj.currentIdx > 8 ) 612 | imgObj.currentIdx = 1; 613 | 614 | var nextImg = imgObj.icons[imgObj.currentIdx-1]; 615 | imgObj.icon = nextImg; 616 | } 617 | } 618 | catch( exc ) 619 | { 620 | delete __busyPlaceholder__[busyID]; 621 | } 622 | } 623 | -------------------------------------------------------------------------------- /installation files/1337jsxbinconverter.jsx: -------------------------------------------------------------------------------- 1 | var CONVERTER_FOLDER = "C:/Temp/converter"; 2 | 3 | 4 | /* Do not edit below this line */ 5 | var CONVERTER_FILEPATH = CONVERTER_FOLDER + "/runner.cmd"; 6 | var CONVERTER_ENCODED_FILEPATH = CONVERTER_FOLDER + "/encoded.jsxbin"; 7 | var CONVERTER_DECODED_FILEPATH = CONVERTER_FOLDER + "/decoded.jsx"; 8 | var CONVERTER_IPC_FILEPATH = CONVERTER_FOLDER + "/converter.ipc"; 9 | app.convertJsxbinToJsx = function(jsxbinFile) { 10 | var f = jsxbinFile; 11 | var converter = File(CONVERTER_FILEPATH); 12 | if (f.fullName.indexOf(".jsxbin", f.fullName.length - ".jsxbin".length) !== -1) { 13 | ipc = File(CONVERTER_IPC_FILEPATH); 14 | ipc.open('w', undefined, undefined); 15 | ipc.write("lock"); 16 | ipc.close(); 17 | f.copy(CONVERTER_ENCODED_FILEPATH); 18 | converter.execute(); 19 | var tries = 10; 20 | while (ipc.exists) { 21 | ipc = File(CONVERTER_IPC_FILEPATH); 22 | $.sleep(500); 23 | ipc.close(); 24 | tries--; 25 | // Don't hang application if something went wrong. 26 | if (tries == 0) { 27 | return jsxbinFile; 28 | } 29 | } 30 | decoded = File(CONVERTER_DECODED_FILEPATH); 31 | var pos = f.fsName.lastIndexOf ('.'); 32 | var dest = f.fsName.substr(0, pos) + ".jsx"; 33 | decoded.copy(dest); 34 | f = File(dest); 35 | converter.close(); 36 | decoded.close(); 37 | } 38 | return f; 39 | } -------------------------------------------------------------------------------- /installation files/converter/runner.cmd: -------------------------------------------------------------------------------- 1 | SET mypath=%~dp0 2 | %mypath%jsxbin_to_jsx.exe %mypath%encoded.jsxbin %mypath%decoded.jsx 3 | del %mypath%converter.ipc --------------------------------------------------------------------------------