// B64-IN.VDM - Decode Base64 text, files, etc // // Requires Vedit Version 6.12 minimum // // Date: 05/18/2004 Initial 'Final' Release // // The Starving Hedonist - http://cu2.home.comcast.net // ////////////////////////////// // // COMMAND LINE USAGE // // vedit|vpw|vpw64 [-n1] [-Q] -X b64-in [-A ] // // * If "-A" used w/o filespec output will have ".---" extension // ////////////////////////////// // // OPERATIONAL OPTIONS // // -N nnn 1 = Write benchmark time (milliseconds) - only of use if using // -Q -X also. TImer data written to B64-I-TM.TXT in \user-mac #104 = TRUE // Somewhat automatically managed - Output in New buf / in-place #114 = TRUE // " " " MIME header // ////////////////////////////// // // NUMERIC REGISTERS // // #10 = ID to main buffer // #11 = ID to output buffer when #104 is TRUE // #12 = ID to parsing buffer -- used with @80 // #100 = temp // #101 = temp // #102 = temp // #103 = temp // #104 = FLAG - TRUE for separate output, FALSE for in-place encoding // #105 = output byte 0 | // #106 = output byte 1 | 8 bit (#106 used also at startup prompts) // #107 = output byte 2 | // #108 = secondary decoding counter // #109 = main decoding loop counter // #110 = input byte 0 | // #111 = input byte 1 | 6 bit // #112 = input byte 2 | // #113 = input byte 3 | // #114 = FLAG - create MIME header if TRUE (Total Commander Compatible) // #115 = 'array' to #105, #106, #107 and #110, #111, #112, #113 // #116 = Pad counter // #117 = widget counter // ////////////////////////////// // // TEXT REGISTERS // // @50 = source/input file full path // @51 = source file name only for Benchmark // @52 = macro generated default output file // -@53 = file name from MIME header // TO-DO // @80 = main decode loop parser // @70 = widget 1 // @71 = widget 2 // @72 = widget 3 // @73 = widget 4 // @74 = widget 5 // @90 = in-place decoding output // @99 = benchmark text // @101 = sub-routines // ////////////////////////////// // // PROBLEMS / TO-DO // // - Better detection of actual base64 data boundaries. Especially the end. // - Block marker beginning at begin of file considered as file not block // ..creates separate output buffer // - Decoding binary sources (non command line) output display not optimal // + Add ability to use filename in MIME header for saving output file. // * Maybe add output to clip-board // * Maybe a way to force/offer separate output buffer even with block encoding // ////////////////////////////// #10 = Buf_Num Out_Reg(51) // store input file name Name_Read(NOMSG|NOCR) Out_Reg(CLEAR) if (Is_SaveAs || Block_Begin > 0) { // Command line driven or block encoding #104 = FALSE // Don't use separate output buffer if (! Is_SaveAs) { // If block encode, don't use MIME header #114 = FALSE } else { Overwrite_Mode(0) // Allow overwite for command mode using "-A " } } else { if (#104) { Reg_Set(50,INPUT_FILE) // store source filespec #11 = Buf_Switch(Buf_Free()) Ins_Text(@50) // assemble default output name. Source name with .B64 Search(".|?|?|?|>",BEGIN|NOERR) if (Match(".|?|?|?|>")==0) { Ins_Text(".---",OVERWRITE) Reg_Copy_Block(52,BOL_Pos,EOL_Pos) } else { Reg_Set(52,"|(VEDIT_TEMP)\TEMP.---") // When source is new, un-named buffer/file } Buf_Empty(NOEVENT|OK) File_Open_Write("|@(52)",OVERWRITE|NOEVENT) } else { if (Block_Begin > 0) { // Turn off MIME headers if coding blocks in-place #114 = FALSE } } } Buf_Switch(#10) if (Block_Begin < 0 ) { // No block selected, decode as file If (! Is_Quiet) { // Skip prompts if -Q used Alert() if (OS_TYPE == 1) { #106 = Dialog_Input_1(106,"`Confirmation`,`OK to decode the entire file from base64?\n\nYou cannot undo this.`,`[&Yes]`,`[&No]`",APP+CENTER,0,0) if (#106!=1) { goto DONE } } else { #106 = Get_Key("OK to decode entire base64 file? (You cannot undo this.) [Y]es [N]o ",STATLINE)&95 if (#106!='Y') { goto DONE } } } Block_Begin(0) Block_End(File_Size) } else { if (Block_End < 0) { // block selected, decode block only Block_End(Cur_Pos) } if (Block_Begin > Block_End) { //Ensure BB < BE #106=Block_Begin Block_Begin(Block_End) Block_End(#106) } if ((Block_End-Block_Begin) > 100) { //If block size > 100... Alert() // Get confirmation if (OS_TYPE==1) { #106 = DI1(106,"`Confirmation`,`OK to decode the block from base64?\n\nYou cannot undo this.`,`[&Yes]`,`[&No]`",APP+CENTER,0,0) if (#106!=1) { goto DONE } } else { #106 = Get_Key("OK to decode block from base64? (You cannot undo this.) [Y]es [N]o ",STATLINE)&95 if (#106!='Y') { goto DONE } } } } // Load Widgets Reg_Set(70," || ") Reg_Set(71," |||| ") Reg_Set(72," |||||| ") Reg_Set(73," |||||||| ") Reg_Set(74,"||||||||||") // Load Subroutines into Text Register 101 Reg_Set(101,` :BENCH: Out_Reg(99) Date(NOMSG) Reg_Set(99," - ",APPEND) Version() Reg_Set(99," - ",APPEND) Reg_Set(99,@51,APPEND) Reg_Set(99," : ",APPEND) Time_Tick Reg_Set(99,"ms",APPEND) Out_Reg(CLEAR) Buf_Switch(Buf_Free(EXTRA)) Ins_Text(@99) Replace("|{|N,|L}","",ALL|BEGIN) EOF Ins_Newline(1) BOF Reg_Copy(99,2) Buf_Quit(OK) if (Version_Num >= 612) { Reg_Save(99,"|(USER_MACRO)\B64-I-TM.TXT",OK|APPEND|NOERR) } else { // pre 6.12 Buf_Switch(Buf_Free()) File_Open("|(USER_MACRO)\B64-I-TM.TXT",NOEVENT|NOMSG|OVERWRITE) EOF Ins_Text(@99) Buf_Close(NOMSG|NOEVENT) } Return :D4TO3: #105 = ((#100 << 2) | (#101 >> 4)) #106 = ((#101 << 4) | (#102 >> 2)) #107 = ((#102 << 6) | (#103 & 63)) Return :DBYTE: if (#@115 >= 'A' && #@115 <= 'Z') { #@115 = #@115 - 'A' } else { if (#@115 >= 'a' && #@115 <= 'z') { #@115 = 26 + #@115 - 'a' } else { if (#@115 >= '0' && #@115 <= '9') { #@115 = 52 + #@115 - '0' } else { if (#@115 == '+') { #@115 = 62 } else { if (#@115 == '/') { #@115 = 63 } else { #@115 = #@115 } } } } } Return :FFOUT: if (#104) { // Encode to new buffer Buf_Switch(#11) Ins_Char(#@115) Buf_Switch(#10) } else { // In-place substitutions Out_Reg(90,APPEND) Char_Dump(#@115,NOCR) Out_Reg(CLEAR) } Return :MIME: // TO-DO Return :WIDGET: if ((Block_End-Block_Begin) > 50000 && !Is_Quiet) { if (#117 > 4) { #117 = 0 } else { #117++ } Statline_Message("Deconding |@(#117+70)") } Return `) // Resume main macro Goto_Pos(Block_Begin) // Start at beginning of block/file // Decode byte group(s) while (CP < BE) { #108 = 1 #109 = 4 #116 = 0 Buf_Switch(#10) Reg_Copy_Block(80,Cur_Pos,Cur_Pos + 4,NORESTORE) #12 = Buf_Switch(Buf_Free()) Reg_Ins(80,BEGIN) while (#108 <= 4) { if (Match("|{|F,|043,|047}")==0) { Char(1) #108++ } else { if (Match("|{|N,|L}")==0) { Del_Char(Chars_Matched) #109 = #109 + Chars_Matched Buf_Switch(#10) Reg_Copy_Block(80,Cur_Pos - Chars_Matched, Cur_Pos + Chars_Matched,NORESTORE) Buf_Switch(#12) Reg_Ins(80,BEGIN) } else { if (Match("=")==0) { Del_Char(1) #108++ #116++ Ins_Char(00) } } } } Reg_Empty(80) BOF #110 = Cur_Char(0) #111 = Cur_Char(1) #112 = Cur_Char(2) #113 = Cur_Char(3) Buf_Quit(OK) Buf_Switch(#10) #115 = 110 Call(101,"DBYTE") #100 = #110 #115 = 111 Call(101,"DBYTE") #101 = #111 #115 = 112 Call(101,"DBYTE") #102 = #112 #115 = 113 Call(101,"DBYTE") #103 = #113 Call(101,"D4TO3") #115 = 105 Call(101,"FFOUT") if (#116 != 2) { #115 = 106 Call(101,"FFOUT") } if (#116 == 0) { #115 = 107 Call(101,"FFOUT") } if (!#104) { // In-place substitutions Char(-abs(#109)) Del_Char(#109) Ins_Text(@90) Reg_Empty(90) } Call(101,"WIDGET") } if ((Block_End-Block_Begin) > 100000 && !Is_Quiet) { Alert() Statline_Message("Finished!") } if (#104) { // Decode to new buffer Buf_Switch(#10) Block_Begin(CLEAR) Buf_Switch(#11) } else { // In-place substitutions Block_Begin(CLEAR) } //if (#114) { Call(101,"MIME") } // TO-DO if (N_Option == 1) { // create benchmark information Call(101,"BENCH") } Reg_Empty(51) Reg_Empty(70) Reg_Empty(71) Reg_Empty(72) Reg_Empty(73) Reg_Empty(74) Reg_Empty(80) Reg_Empty(90) Reg_Empty(99) Reg_Empty(101) :DONE: Reg_Empty(50) Reg_Empty(52) Key_Purge() //Purge any pending keystrokes Return(1,DELETE) //Return and empty this T-Reg