Macros for SAS Application Developers
https://github.com/sasjs/core
mp_base64copy.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Convert a file to/from base64 format
4  @details Creates a new version of a file either encoded or decoded using
5  Base64. Inspired by this post by Michael Dixon:
6  https://support.selerity.com.au/hc/en-us/articles/223345708-Tip-SAS-and-Base64
7 
8  Usage:
9 
10  filename tmp temp;
11  data _null_;
12  file tmp;
13  put 'base ik ally';
14  run;
15  %mp_base64copy(inref=tmp, outref=myref, action=ENCODE)
16 
17  data _null_;
18  infile myref;
19  input;
20  put _infile_;
21  run;
22 
23  %mp_base64copy(inref=myref, outref=mynewref, action=DECODE)
24 
25  data _null_;
26  infile mynewref;
27  input;
28  put _infile_;
29  run;
30 
31  @param [in] inref= (0) Fileref of the input file (should exist)
32  @param [out] outref= (0) Output fileref. If it does not exist, it is created.
33  @param [in] action= (ENCODE) The action to take. Valid values:
34  @li ENCODE - Convert the file to base64 format
35  @li DECODE - Decode the file from base64 format
36 
37  @version 9.2
38  @author Allan Bowe, source: https://github.com/sasjs/core
39 
40  <h4> SAS Macros </h4>
41  @li mp_abort.sas
42 
43 
44 **/
45 
46 %macro mp_base64copy(
47  inref=0,
48  outref=0,
49  action=ENCODE
50 )/*/STORE SOURCE*/;
51 
52 %let inref=%upcase(&inref);
53 %let outref=%upcase(&outref);
54 %let action=%upcase(&action);
55 %local infound outfound;
56 %let infound=0;
57 %let outfound=0;
58 data _null_;
59  set sashelp.vextfl(where=(fileref="&inref" or fileref="&outref"));
60  if fileref="&inref" then call symputx('infound',1,'l');
61  if fileref="&outref" then call symputx('outfound',1,'l');
62 run;
63 
64 %mp_abort(iftrue= (&infound=0)
65  ,mac=&sysmacroname
66  ,msg=%str(INREF &inref NOT FOUND!)
67 )
68 %mp_abort(iftrue= (&outref=0)
69  ,mac=&sysmacroname
70  ,msg=%str(OUTREF NOT PROVIDED!)
71 )
72 %mp_abort(iftrue= (&action ne ENCODE and &action ne DECODE)
73  ,mac=&sysmacroname
74  ,msg=%str(Invalid action! Should be ENCODE OR DECODE)
75 )
76 
77 %if &outfound=0 %then %do;
78  filename &outref temp lrecl=2097088;
79 %end;
80 
81 %if &action=ENCODE %then %do;
82  data _null_;
83  length b64 $ 76 line $ 57;
84  retain line "";
85  infile &inref recfm=F lrecl= 1 end=eof;
86  input @1 stream $char1.;
87  file &outref recfm=N;
88  substr(line,(_N_-(CEIL(_N_/57)-1)*57),1) = byte(rank(stream));
89  if mod(_N_,57)=0 or EOF then do;
90  if eof then b64=put(trim(line),$base64X76.);
91  else b64=put(line, $base64X76.);
92  put b64 + (-1) @;
93  line="";
94  end;
95  run;
96 %end;
97 %else %if &action=DECODE %then %do;
98  data _null_;
99  length filein 8 fileout 8;
100  filein = fopen("&inref",'I',4,'B');
101  fileout = fopen("&outref",'O',3,'B');
102  char= '20'x;
103  do while(fread(filein)=0);
104  length raw $4;
105  do i=1 to 4;
106  rc=fget(filein,char,1);
107  substr(raw,i,1)=char;
108  end;
109  rc = fput(fileout,input(raw,$base64X4.));
110  rc = fwrite(fileout);
111  end;
112  rc = fclose(filein);
113  rc = fclose(fileout);
114  run;
115 %end;
116 
117 %mend mp_base64copy;