// B64-OUT.VDM - Encode text, files, etc to Base64 // // Requires Vedit Version 6.12 minimum // // Date: 05/20/2004 Initial 'Final' Release // // The Starving Hedonist - http://cu2.home.comcast.net // ////////////////////////////// // // COMMAND LINE USAGE // // vedit|vpw|vpw64 [-n1] [-Q] -X b64-out [-A ] // // * If "-A" used w/o filespec output will have ".B64" extension // ////////////////////////////// // // OPERATIONAL OPTIONS // // -N nnn 1 = Write benchmark time (milliseconds) - only of use if using // -Q -X also. TImer data written to B64-O-TM.TXT in \user-mac #103 = 76 // Multiples of 4 is best, 76 is MAX per RFC-2045 pt 6.8 #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 // #103 = output line cut-off length // #104 = FLAG - TRUE for separate output, FALSE for in-place encoding // #105 = input byte 0 | // #106 = input byte 1 | 8 bit (#106 used also at startup prompts) // #107 = input byte 2 | // #108 = output line length counter. Works in conjunction with #103 // #109 = main encoding loop counter // #110 = output byte 0 | // #111 = output byte 1 | 6 bit // #112 = output byte 2 | // #113 = output byte 3 | // #114 = FLAG - create MIME header if TRUE (Total Commander Compatible) // #115 = 'array' to #110, #111, #112, #113 // #116 = n/a // #117 = widget counter // ////////////////////////////// // // TEXT REGISTERS // // @50 = source/input file full path // @51 = source file name only for MIME / Benchmark // @52 = macro generated default output file // @70 = widget 1 // @71 = widget 2 // @72 = widget 3 // @73 = widget 4 // @74 = widget 5 // @90 = in-place encoding output // @99 = benchmark text // @101 = sub-routines // ////////////////////////////// // // PROBLEMS / TO-DO // // - Block marker beginning at begin of file considered as file not block // ..creates separate output buffer // - Block encoding length can become skewed when begin position is not at the // beginning of a line. Extends right beyond the anticpated column, visual // ramifications only. // * Maybe add output to clip-board // * Maybe a way to force/offer separate output buffer even with block encoding // ////////////////////////////// #10 = Buf_Num #108 = 0 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 { 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(".B64",OVERWRITE) Reg_Copy_Block(52,BOL_Pos,EOL_Pos) } else { Reg_Set(52,"|(VEDIT_TEMP)\TEMP.B64") // 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, encode as file If (! Is_Quiet) { // Skip prompts if -Q used Alert() if (OS_TYPE == 1) { #106 = Dialog_Input_1(106,"`Confirmation`,`OK to convert the entire file to base64?\n\nYou cannot undo this.`,`[&Yes]`,`[&No]`",APP+CENTER,0,0) if (#106!=1) { goto DONE } } else { #106 = Get_Key("OK to convert entire 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, encode 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 convert the block to base64?\n\nYou cannot undo this.`,`[&Yes]`,`[&No]`",APP+CENTER,0,0) if (#106!=1) { goto DONE } } else { #106 = Get_Key("OK to convert block to 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 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-O-TM.TXT",OK|APPEND|NOERR) } else { // pre 6.12 Buf_Switch(Buf_Free()) File_Open("|(USER_MACRO)\B64-O-TM.TXT",NOEVENT|NOMSG|OVERWRITE) EOF Ins_Text(@99) Buf_Close(NOMSG|NOEVENT) } Return :E3TO4: #110 = #105 >> 2 & 63 #111 = ((#105 << 4) | (#106 >> 4)) & 63 #112 = ((#106 << 2) | (#107 >> 6)) & 63 #113 = #107 & 63 Return :EBYTE: if ( #@115 >= 0 && #@115 <= 25) { #@115 = 'A' + #@115 } else { if ( #@115 >= 26 && #@115 <= 51 ) { #@115 = 'a' + #@115 - 26 } else { if ( #@115 >= 52 && #@115 <= 61 ) { #@115 = '0' + #@115 - 52 } else { if ( #@115 == 62 ) { #@115 = '+' } else { if ( #@115 == 63 ) { #@115 = '/' } else { #@115 = #@115 } } } } } Return :64OUT: if (#104) { // Encode to new buffer Buf_Switch(#11) Ins_Char(#@115) Buf_Switch(#10) #108++ } else { // In-place substitutions Out_Reg(90,APPEND) Char_Dump(#@115,NOCR) Out_Reg(CLEAR) } Return :CKLEN: if (#103 && #108 >= #103) { if (#104) { // Encode to new buffer Buf_Switch(#11) Ins_Newline() Buf_Switch(#10) } else { // In-place substitutions Ins_Newline() } #108 = 0 } Return :MIME: if (#104) { Buf_Switch(#11) } BOF Ins_Text("MIME-Version: 1.0") Ins_Newline(1) Ins_Text('Content-Type: application/octet-stream; name="') Ins_Text(@51) Ins_Text('"') Ins_Newline(1) Ins_Text("Content-Transfer-Encoding: base64") Ins_Newline(1) Ins_Text('Content-Disposition: attachment; filename="') Ins_Text(@51) Ins_Text('"') Ins_Newline(2) BOF 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 // Encode byte group(s) -- 24 bits present if (((Block_End-Block_Begin) >= 3)==1) { for (#109=(Block_End-Block_Begin)/3;#109!=0;#109--) { #105 = Cur_Char(0) #106 = Cur_Char(1) #107 = Cur_Char(2) Call(101,"E3TO4") #115 = 110 Call(101,"EBYTE") Call(101,"64OUT") #115 = 111 Call(101,"EBYTE") Call(101,"64OUT") #115 = 112 Call(101,"EBYTE") Call(101,"64OUT") #115 = 113 Call(101,"EBYTE") Call(101,"64OUT") Char(3) if (!#104) { // In-place substitutions Char(-3) Del_Char(3) Ins_Text(@90) Reg_Empty(90) #108+=4 } Call(101,"CKLEN") // Check output line length, wrap if needed Call(101,"WIDGET") } } // Encode final byte(s) -- less than 24 bits present if ((Block_End-Block_Begin)%3 != 0) { if ((Block_End-Block_Begin)%3 == 1) { #105 = Cur_Char(0) #106 = 0 #107 = 0 Call(101,"E3TO4") #115 = 110 Call(101,"EBYTE") Call(101,"64OUT") #115 = 111 Call(101,"EBYTE") Call(101,"64OUT") #112 = '=' #115 = 112 Call(101,"64OUT") #113 = '=' #115 = 113 Call(101,"64OUT") } if ((Block_End-Block_Begin)%3 == 2) { #105 = Cur_Char(0) #106 = Cur_Char(1) #107 = 0 Call(101,"E3TO4") #115 = 110 Call(101,"EBYTE") Call(101,"64OUT") #115 = 111 Call(101,"EBYTE") Call(101,"64OUT") #115 = 112 Call(101,"EBYTE") Call(101,"64OUT") #113 = '=' #115 = 113 Call(101,"64OUT") } if (!#104) { // In-place substitutions - Add final byte(s) & "=" pad(s) Del_Char((Block_End-Block_Begin)%3) Ins_Text(@90) Reg_Empty(90) #108+=(Block_End-Block_Begin)%3 } } if ((Block_End-Block_Begin) > 100000 && !Is_Quiet) { Alert() Statline_Message("Finished!") } if (#104) { // Encode to new buffer Buf_Switch(#10) BOF Block_Begin(CLEAR) Buf_Switch(#11) } else { // In-place substitutions Goto_Pos(Block_Begin) Block_Begin(CLEAR) } if (#114) { Call(101,"MIME") } // add MIME header 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(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