LegitStack Posted November 18, 2016 Share Posted November 18, 2016 (edited) I wanted some kind of a plugin system for a project I'm working on. So naturally I decided to write my own from scratch. Stupid. I actually know of better ways to do this such as... ...But I thought, since I spent several days on this, and it does technically work for my purposes I may as well post it up and maybe some part of it might help someone someday. expandcollapse popup;#NoTrayIcon #include <Math.au3> #include <File.au3> #include <Misc.au3> #include <Crypt.au3> #include <Array.au3> #include <FileConstants.au3> #include <MsgboxConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #Include <GDIPlus.au3> Global $procs[256][256] Global $loops[256][256] Global $v[65000] Global $a[256][256] Global $hotkey[100] Global $hotproc[100] Func HotkeyPlugin() for $hki = 0 to ubound($hotkey)-1 if @HotKeyPressed == $hotkey[$hki] then ExecuteProc($hotproc[$hki]) endif next EndFunc Func ImportPlugin() local $path = "c:\plugin.au3p" local $file = FileOpen($path, $FO_READ) local $read = FileRead($file) FileClose($file) local $nread = Stringsplit($read, @CRLF, 2) if Stringleft($nread[0],1) == "'" then $nread = stringtrimleft($nread[0],1) $nread = stringtrimright($nread,1) Else $nread = $nread[0] endif $read = BinaryToString(_Crypt_DecryptData($nread, "a", $CALG_AES_256)) $read = Stringsplit($read, @CRLF, 2) AnalyzePlugin($read) EndFunc Func AnalyzePlugin($read) local $procnum = 0 local $loopnum = -1 local $temp local $temp1 local $ln = 0 local $lnloop[256] local $embedded = -1 local $hki = 0 for $r in $read $temp = Stringsplit($r, " ", 2) $temp1= stringleft($r, 4) ;msgbox(64,"temp1",$temp1) if $temp1 == "proc" Or $temp1 == "Proc" then $procnum = $temp[1] $embedded = -1 $ln = 0 elseif $temp1 == "endp" Or $temp1 == "Endp" then ;msgbox(64,"r",$r) $procs[$procnum][$ln] = $r $procnum = "" $embedded = -1 elseif $temp1 == "hkps" Or $temp1 == "Hkps" then ;hot key pressed set $hotkey[$hki] = $temp[1] $hotproc[$hki] = $temp[2] $hki = $hki + 1 HotKeySet($temp[1],"HotkeyPlugin") elseif StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) == "loop" Or StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) == "Loop" then $oldloopnum = $loopnum $loopnum = $loopnum + 1 $embedded = $embedded + 1 $lnloop[$embedded] = 0 if $embedded == 0 then $procs[$procnum][$ln] = "loop " & $loopnum $ln = $ln + 1 else ;msgbox(64,"loop found," & $loopnum, $embedded & " " & $lnloop[$embedded]) $loops[$oldloopnum][$lnloop[$embedded-1]] = "loop " & $loopnum $lnloop[$embedded-1] = $lnloop[$embedded-1] + 1 ;_arraydisplay($loops) endif elseif StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) == "endl" Or StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) == "Endl" then $loops[$loopnum][$lnloop[$embedded]] = StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) $embedded = $embedded - 1 if $embedded > -1 then $loopnum = $loopnum - 1 endif else ; regular code if $procnum <> "" then if $r <> "" then if $embedded == -1 then $procs[$procnum][$ln] = StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) $ln = $ln + 1 else $loops[$loopnum][$lnloop[$embedded]] = StringStripWS($r, $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) $lnloop[$embedded] = $lnloop[$embedded] + 1 endif endif endif endif next ;_arraydisplay($procs) ;_arraydisplay($loops) ExecuteProc(0) EndFunc Func ExecuteProc($number, $arg1 = "", $arg2 = "") local $temp local $temp1 local $return local $ift = "" local $embeddedif = 0 local $command = "" for $pcount = 0 to 255 ;put loops in the right places! $read = $procs[$number][$pcount] ;msgbox(64,"readsays "& $pcount,$read) $r = Stringsplit($read, " ", 2) $command = stringleft($read, 4) ExecuteCode($read, $r, $arg1, $arg2, $temp, $temp1, $return, $ift, $embeddedif, $command) next return $return EndFunc Func ExecuteLoop($number, Byref $arg1, Byref $arg2, Byref $temp, Byref $temp1, Byref $return, Byref $command) local $embeddedif = 0 local $ift = "" ;_arraydisplay($procs) while 1 For $pcount = 0 to 255 ;put loops in the right places! $read = $loops[$number][$pcount] $r = Stringsplit($read, " ", 2) $command = stringleft($read, 4) ;msgbox(64,"readsays " & $pcount,$read & " " & $embeddedif & " " & $ift) $ret = ExecuteCode($read, $r, $arg1, $arg2, $temp, $temp1, $return, $ift, 0, $command) if $ret == 300 then $pcount = 300 elseif $ret == "bklp" then exitloop 2 endif next wend EndFunc Func ExecuteCode(Byref $read, Byref $r, Byref $arg1, Byref $arg2, Byref $temp, Byref $temp1, Byref $return, Byref $ift, Byref $embeddedif, Byref $command) local $tempread1 local $tempread2 local $tempread3 local $execute1 = false local $execute2 = false local $execute3 = false if ($command == "goto" Or $command == "Goto") And ($ift == "" Or stringright($ift, 1) == "t") then if StringLeft($r[1], 1) == "'" or StringLeft($r[1], 1) == '"' then ; 1 is text $tempread1 = StringTrimLeft(StringTrimRight($r[1], 1), 1) elseif StringIsDigit(Stringleft($r[1], 1)) == 1 then ; 1 is number $tempread1 = $r[1] else ; its code so we're going to execute it. $execute1 = true endif if Ubound($r) == 4 then if StringLeft($r[2], 1) == "'" or StringLeft($r[2], 1) == '"' then ; 2 is text $tempread2 = StringTrimLeft(StringTrimRight($r[2], 1), 1) elseif StringIsDigit(Stringleft($r[2], 1)) == 1 then ; 2 is number $tempread2 = $r[2] else ; its code so we're going to execute it. $execute2 = true endif if StringLeft($r[3], 1) == "'" or StringLeft($r[3], 1) == '"' then ; 3 is text $tempread3 = StringTrimLeft(StringTrimRight($r[3], 1), 1) elseif StringIsDigit(Stringleft($r[3], 1)) == 1 then ; 3 is number $tempread3 = $r[3] else ; its code so we're going to execute it. $execute3 = true endif if $execute1 And $execute2 And $execute3 then $return = ExecuteProc(execute($tempread1), execute($tempread2), execute($tempread3)) elseif $execute1 And $execute2 then $return = ExecuteProc(execute($tempread1), execute($tempread2), $tempread3 ) elseif $execute1 And $execute3 then $return = ExecuteProc(execute($tempread1), $tempread2 , execute($tempread3)) elseif $execute2 And $execute3 then $return = ExecuteProc( $tempread1 , execute($tempread2), execute($tempread3)) elseif $execute1 then $return = ExecuteProc(execute($tempread1), $tempread2 , $tempread3 ) elseif $execute2 then $return = ExecuteProc( $tempread1 , execute($tempread2), $tempread3 ) elseif $execute3 then $return = ExecuteProc( $tempread1 , $tempread2 , execute($tempread3)) else $return = ExecuteProc( $tempread1 , $tempread2 , $tempread3 ) endif elseif Ubound($r) == 3 then if StringLeft($r[2], 1) == "'" or StringLeft($r[2], 1) == '"' then ; 2 is text $tempread2 = StringTrimLeft(StringTrimRight($r[2], 1), 1) elseif StringIsDigit(Stringleft($r[2], 1)) == 1 then ; 2 is number $tempread2 = $r[2] else ; its code so we're going to execute it. $execute2 = true endif elseif $execute1 And $execute2 then $return = ExecuteProc(execute($tempread1), execute($tempread2)) elseif $execute1 then $return = ExecuteProc(execute($tempread1), $tempread2 ) elseif $execute2 then $return = ExecuteProc( $tempread1 , execute($tempread2)) else $return = ExecuteProc( $tempread1 , $tempread2 ) endif elseif Ubound($r) == 2 then if $execute1 then $return = ExecuteProc(execute($tempread1)) else $return = ExecuteProc( $tempread1 ) endif endif elseif ($command == "set " Or $command == "Set ") And ($ift == "" Or stringright($ift, 1) == "t") then if UBound($r) == 3 then if StringLeft($r[1], 1) == "'" or StringLeft($r[1], 1) == '"' then ; 1 is text $tempread1 = StringTrimLeft(StringTrimRight($r[1], 1), 1) elseif StringIsDigit(Stringleft($r[1], 1)) == 1 then ; 1 is number $tempread1 = $r[1] else ; its code so we're going to execute it. $execute1 = true endif if StringLeft($r[2], 1) == "'" or StringLeft($r[2], 1) == '"' then ; 2 is text $tempread2 = StringTrimLeft(StringTrimRight($r[2], 1), 1) elseif StringIsDigit(Stringleft($r[2], 1)) == 1 then ; 2 is number $tempread2 = $r[2] else ; its code so we're going to execute it. $execute2 = true endif if $execute1 And $execute2 then $v[execute($tempread1)] = execute($tempread2) elseif $execute1 then $v[execute($tempread1)] = $tempread2 elseif $execute2 then $v[$tempread1] = execute($tempread2) else $v[$tempread1] = $tempread2 endif elseif ubound($r) > 3 then for $temp = 2 to ubound($r)-1 $a[$r[1]][$temp-2] = $r[$temp] next endif elseif ($command == "loop" Or $command == "Loop") And ($ift == "" Or stringright($ift, 1) == "t") then ExecuteLoop($r[1], $arg1, $arg2, $temp, $temp1, $return, $command) elseif ($command == "endl" or $command == "Endl") And ($ift == "" Or stringright($ift, 1) == "t") then return 300 elseif ($command == "bklp" or $command == "Bklp") And ($ift == "" Or stringright($ift, 1) == "t") then ;$ift = "" return "bklp" elseif $command == "ift " Or $command == "Ift " then if $ift == "" Or stringright($ift, 1) == "t" then if execute(stringtrimleft($read, 4)) then $ift = $ift & "t" $embeddedif = $embeddedif + 1 else $ift = $ift & "f" endif endif elseif $command == "elif" Or $command == "Elif" then if $ift == "f" Or stringright($ift, 2) == "tf" then if execute(stringtrimleft($read, 4)) then $ift = stringtrimright($ift, 1) $ift = $ift & "t" $embeddedif = $embeddedif + 1 else $ift = stringtrimright($ift, 1) $ift = $ift & "f" endif endif elseif $command == "else" Or $command == "Else" then if $ift == "f" Or stringright($ift, 2) == "tf" then $ift = stringtrimright($ift, 1) $ift = $ift & "t" $embeddedif = $embeddedif + 1 else $ift = stringtrimright($ift, 1) $ift = $ift & "f" endif elseif ($command == "endi" Or $command == "Endi") then if $ift == "" Or stringright($ift, 1) == "t" then $ift = stringtrimright($ift, 1) $embeddedif = $embeddedif - 1 elseif stringright($ift, 1) == "f" then $ift = stringtrimright($ift, 1) $embeddedif = $embeddedif - 1 endif elseif ($command == "endp" Or $command == "Endp") And ($ift == "" Or stringright($ift, 1) == "t")then if Ubound($r) == 2 then if stringleft($r[1], 1) == "$" then $return = ExecuteProc(execute($r[1])) else $return = $r[1] endif else $return = "" endif $pcount =300 elseif ($read == "exit" Or $read == "Exit") And ($ift == "" Or stringright($ift, 1) == "t") then Exit else if $ift == "" Or stringright($ift, 1) == "t" then Execute($read) endif endif EndFunc ImportPlugin() ;METHOD 3 (special Raw Execute) ;at least 3 arrays: ;1. proc code, arguments of procs = 2d array p[] ;2. variables (public) g[] ;3. variables (private) v[] ;this script loads the entire plugin. ;as it loads it it fills up the arrays. ;no returns, args ;everything is separated by spaces ;encoding of Functions: ;proc 0 - tells you which i to put it in. ;args 1 2 - array 1 1-99 ; - array 1 first, ;endp - none ;encoding calling functions ;goto 2 - start loading each line from p[2] into execution ;encoding of variables: ;set 1 [code] - v[1] = Execute($restofline) ;set 1 puts 2 - v[1] = v[2] ;we may use set as setv for arrays and let them use assign for regular variables ;so first we analyze it to separate it out, ;then the very last line of the code should be only number ;thats when we switch over to run mode ;and starting with the numbered proc we being to execute each line of code. ;limitations: ; we could make arrays of 1000 or something like a1-10 ; no includes ; no switches or anything else other than If statement. ; clunky. but basically func becomes proc args call becomes goto and local becomes set, while becomes loop, if becomes ift ;how to prepare plugins ;1. create a plugin script ;2. encrypt the data, replace code ;3. encryptfile, put in the plugins folder in scriptdir. ;plugin requirements: ;1. cannot have a function called "ImportPlugin" ;2. cannot have a function called "ExecutePlugin" ;3. cannot have a variable called "$__R__" ;4. cannot have a variable called "$__READ__" ;5. you must load everything into Memory before you being to execute. ;6. Your plugin cannot have more than 30k lines of code. ;7. cannot #include anything. ;8. cannot assign variables the normal way. you must use Assign("message", "world") (Assign, Call, Eval) ;9. convention suggests you use RMPlugin_ at the beginning of all function and variables in order to avoid duplicates because all the includes have to be That's the actual script that acts as the plugin-executor. I basically had to recreate flow-control inside the context of the autoit flow-control. Which means I had to make a sudo-language. Hobby: masochist. Here's an example script I created to show how it works. expandcollapse popup;how to set a hotkey key procnumber - must be first thing you do. hkps {END} 3 ;proc 0 is the natural entry point to the program. ;If you want it to constantly run, and wait for user hotkey then make proc 0 look like this: ;proc 0 ; loop ; endl ;endp ;here's a sudo-function. only numbers (as the name) allowed. No need to specify arguments proc 0 ; this how you make comment ; ; make a call: goto 1 ; reference a variable msgbox(64,"01","hello " & $v[1] ) ; reference elements in an array msgbox(64,"01","hello " & $a[1][1] & $a[1][2] & $a[1][3] ) goto 4 ;end sudo function endp proc 1 ; make a variable - use number as variable name set 1 "world" msgbox(64,"1","hello " & $v[1]) ; variable substitution available on name or value. set 9 1 set $v[9] "world!" msgbox(64,"1","hello " & $v[1]) ; make an array - substitution not not allowed when creating these, its litteral set 1 "a" b "c" d "e" f ; make some regular autoit code msgbox(64,"1","hello world") ; 2 max arguments allowed. arguments only allow single words or numbers or variables goto 2 hello $v[1] ; how to access the return msgbox(64,"1-returned",$return) Endp proc 2 args are ignored if you write them in here. ; here's how to use args, 1 or 2 args allowed msgbox(64, "2", $arg1 & " " & $arg2) ; if you want to return a value simply add it onto the end of this line Endp goodbyeworld proc 3 called from hotkey msgbox(64, "3", "called from hotkey") Endp code outside procs are ignored, like comments proc 4 if statements are ift statments NO then ift $v[1] == "hello" msgbox(64,"4","this is false and wont be executed!") elif $v[1] == "world" msgbox(64,"4","hello ift statement! this is elif") endi ift $v[1] == "goodbye" msgbox(64,"4","this is false and wont be executed!") else msgbox(64,"4","Hello else statement!") endi msgbox(64,"4","This code is not in an if statement.") set 1 0 goto 5 endp proc 5 for small loops recursion should work fine ift $v[1] == 3 msgbox(64,"5","done with loop! please press the END key after you press ok. " & $v[1]) ;wait so we can test the hotkey command sleep(5000) goto 6 else msgbox(64,"5",$v[1]) set 1 $v[1]+1 goto 5 endi endp proc 6 but for large loops or embedded loops "loop" might work best. set 2 0 loop set 2 $v[2]+1 tooltip($v[2]) sleep(1000) ift $v[2] >= 2 bklp endi endl set 3 0 set 4 0 loop loop set 3 $v[3]+1 tooltip($v[3]) sleep(1000) ift $v[3] >= 2 bklp endi endl set 4 $v[4]+1 tooltip($v[4]) sleep(1000) ift $v[4] >= 2 bklp endi endl msgbox(64,"6","This concludes our tour of the au3p language!") endp Edited November 18, 2016 by LegitStack Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now