mirror of
https://github.com/SASPAC/gsm.git
synced 2026-03-10 01:28:14 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8963f189e |
@@ -8,7 +8,7 @@ to create secured macros stored in SAS Proc FCMP functions.
|
|||||||
The dataset with functions can be shared between different operating systems
|
The dataset with functions can be shared between different operating systems
|
||||||
and allows to generate macros on site without showing their code.
|
and allows to generate macros on site without showing their code.
|
||||||
|
|
||||||
SHA256 digest for the latest version of `GSM`: F*7A4FEC410DEB921613A33F154FBBE332D7EC4C4DAC1351A4E611D986489EE848
|
SHA256 digest for the latest version of `GSM`: F*411452E8388C181800023A01A3B7DC7904A80A915D506D9606638F27CBC282B1
|
||||||
|
|
||||||
[**Documentation for GSM**](./gsm.md "Documentation for GSM")
|
[**Documentation for GSM**](./gsm.md "Documentation for GSM")
|
||||||
|
|
||||||
|
|||||||
14
gsm.md
14
gsm.md
@@ -9,23 +9,21 @@
|
|||||||
### Version information:
|
### Version information:
|
||||||
|
|
||||||
- Package: GSM
|
- Package: GSM
|
||||||
- Version: 0.22.2
|
- Version: 0.22.3
|
||||||
- Generated: 2026-01-26T16:44:38
|
- Generated: 2026-02-17T12:08:56
|
||||||
- Author(s): Bartosz Jablonski (yabwon@gmail.com)
|
- Author(s): Bartosz Jablonski (yabwon@gmail.com)
|
||||||
- Maintainer(s): Bartosz Jablonski (yabwon@gmail.com)
|
- Maintainer(s): Bartosz Jablonski (yabwon@gmail.com)
|
||||||
- License: MIT
|
- License: MIT
|
||||||
- File SHA256: `F*7A4FEC410DEB921613A33F154FBBE332D7EC4C4DAC1351A4E611D986489EE848` for this version
|
- File SHA256: `F*411452E8388C181800023A01A3B7DC7904A80A915D506D9606638F27CBC282B1` for this version
|
||||||
- Content SHA256: `C*99444DE5A473D3F92374ACE917E29E77C1F94BF77E06436695B06B85705606C7` for this version
|
- Content SHA256: `C*1955721DDAAE32A631A8071BEE3BC6CF83761C2280DA5F823D4E4CFD96838FD3` for this version
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# The `GSM` package, version: `0.22.2`;
|
# The `GSM` package, version: `0.22.3`;
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
# The GSM package [ver. 0.22.2] <a name="gsm-package"></a> ###############################################
|
|
||||||
|
|
||||||
The **GSM** (a.k.a. *Generate Secure Macros*) package allows
|
The **GSM** (a.k.a. *Generate Secure Macros*) package allows
|
||||||
to create secured macros stored in SAS Proc FCMP functions.
|
to create secured macros stored in SAS Proc FCMP functions.
|
||||||
The dataset with functions can be shared and allows to generate
|
The dataset with functions can be shared and allows to generate
|
||||||
@@ -122,7 +120,7 @@ localization (only if additional content was deployed during the installation pr
|
|||||||
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
*SAS package generated by SAS Package Framework, version `20260126`,*
|
*SAS package generated by SAS Package Framework, version `20260216`,*
|
||||||
*under `WIN`(`X64_10PRO`) operating system,*
|
*under `WIN`(`X64_10PRO`) operating system,*
|
||||||
*using SAS release: `9.04.01M9P06042025`.*
|
*using SAS release: `9.04.01M9P06042025`.*
|
||||||
|
|
||||||
|
|||||||
386
hist/0.22.3/gsm.md
Normal file
386
hist/0.22.3/gsm.md
Normal file
@@ -0,0 +1,386 @@
|
|||||||
|
# Documentation for the `GSM` package.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
*Generate Secure Macros - to keep your code secret*
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
### Version information:
|
||||||
|
|
||||||
|
- Package: GSM
|
||||||
|
- Version: 0.22.3
|
||||||
|
- Generated: 2026-02-17T12:08:56
|
||||||
|
- Author(s): Bartosz Jablonski (yabwon@gmail.com)
|
||||||
|
- Maintainer(s): Bartosz Jablonski (yabwon@gmail.com)
|
||||||
|
- License: MIT
|
||||||
|
- File SHA256: `F*411452E8388C181800023A01A3B7DC7904A80A915D506D9606638F27CBC282B1` for this version
|
||||||
|
- Content SHA256: `C*1955721DDAAE32A631A8071BEE3BC6CF83761C2280DA5F823D4E4CFD96838FD3` for this version
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# The `GSM` package, version: `0.22.3`;
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
The **GSM** (a.k.a. *Generate Secure Macros*) package allows
|
||||||
|
to create secured macros stored in SAS Proc FCMP functions.
|
||||||
|
The dataset with functions can be shared and allows to generate
|
||||||
|
macros without showing their code.
|
||||||
|
|
||||||
|
[Recording of presentation with "how it works" description (in Polish)](https://www.youtube.com/watch?v=LtaWPe2sgRY&t=1s "YouTube").
|
||||||
|
|
||||||
|
[The WUSS 2023 Conference article describing the idea](https://www.wuss.org/wuss-2023-conference-proceedings/ "Article about the idea GSM")
|
||||||
|
|
||||||
|
The GSM package is basically an automated version of the following:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
proc fcmp outlib = work.gsm.secure ENCRYPT;
|
||||||
|
function generateMacro() $;
|
||||||
|
rc = RESOLVE('
|
||||||
|
%macro secretMacro(x) / SECURE;
|
||||||
|
data test;
|
||||||
|
a = "&x.";
|
||||||
|
run;
|
||||||
|
%mend;
|
||||||
|
');
|
||||||
|
return (rc);
|
||||||
|
endsub;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* share work.gsm dataset */
|
||||||
|
options cmplib = work.gsm;
|
||||||
|
data _null_;
|
||||||
|
rc = generateMacro();
|
||||||
|
put rc=;
|
||||||
|
run;
|
||||||
|
|
||||||
|
/* enjoy */
|
||||||
|
%secretMacro(42)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
See examples for more details.
|
||||||
|
|
||||||
|
|
||||||
|
*How to use it:*
|
||||||
|
- Copy all files with your secured macros code into a directory.
|
||||||
|
Best approach is to have one file for one macro.
|
||||||
|
- Copy a path to the directory.
|
||||||
|
- Run the following code:
|
||||||
|
```
|
||||||
|
%GSM(<the path to directory>, cmplib=<name of the dataset>)
|
||||||
|
```
|
||||||
|
- Share generated `ZIP` file (unzip and run the code).
|
||||||
|
|
||||||
|
|
||||||
|
**Limitations:**
|
||||||
|
- Single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
- Multiline text variable. Consider the following code text file:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
%macro~test()/SECURE;~#@
|
||||||
|
data~test;~#@
|
||||||
|
a~=~"abc~#@
|
||||||
|
~#@
|
||||||
|
def";~#@
|
||||||
|
put~a~hex20.;~#@
|
||||||
|
run;~#@
|
||||||
|
%mend~test;~#@
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
where `~` symbols the space character,
|
||||||
|
`#` symbols the carriage return (`0D`),
|
||||||
|
and `@` symbols the line feed (`0A`).
|
||||||
|
The code file is scanned and inserted into
|
||||||
|
the `resolve()` function argument in a "byte by byte"
|
||||||
|
fashion hence also the "end of line" characters are included.
|
||||||
|
As the result value of variable `a` will be:
|
||||||
|
|
||||||
|
`a = "abc~#@~#@def"`.
|
||||||
|
|
||||||
|
If you want to use the `GSM` package avoid
|
||||||
|
such "style" of coding in your macros.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Required SAS Components:
|
||||||
|
- Base SAS Software
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Package contains additional content, run: `%loadPackageAddCnt(GSM)` to load it
|
||||||
|
or look for the `gsm_AdditionalContent` directory in the `packages` fileref
|
||||||
|
localization (only if additional content was deployed during the installation process).
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
*SAS package generated by SAS Package Framework, version `20260216`,*
|
||||||
|
*under `WIN`(`X64_10PRO`) operating system,*
|
||||||
|
*using SAS release: `9.04.01M9P06042025`.*
|
||||||
|
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
# The `GSM` package content
|
||||||
|
The `GSM` package consists of the following content:
|
||||||
|
|
||||||
|
1. [`%gsm()` macro ](#gsm-macro-1 )
|
||||||
|
2. [`%gsmpck_makefcmpcode()` macro ](#gsmpckmakefcmpcode-macro-2 )
|
||||||
|
|
||||||
|
|
||||||
|
3. [License note](#license)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `%gsm()` macro <a name="gsm-macro-1"></a> ######
|
||||||
|
|
||||||
|
## >>> `%GSM()` macro: <<< <a name="gsm-macro"></a> #######################
|
||||||
|
|
||||||
|
The `%GSM()` macro is the main macro of
|
||||||
|
the **GSM** (a.k.a. *Generate Secure Macros*) package.
|
||||||
|
|
||||||
|
It converts a list of macros provided by the user into
|
||||||
|
a data set of the Proc FCMP functions. The macros are stored
|
||||||
|
as encrypted code which allow to share the macros
|
||||||
|
without showing their code.
|
||||||
|
|
||||||
|
*Important* thing is that macros provided by the user *has* to
|
||||||
|
be "secure", i.e. the `secure` option has to be added to the
|
||||||
|
macro definition and th emacro code has to be written properly.
|
||||||
|
See the example:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%macro secretMacro(x) / SECURE; %* <- the secure option *;
|
||||||
|
<... secure code ...>
|
||||||
|
%mend secretMacro;
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
As a result a zip file, containing dataset with functions and
|
||||||
|
code to be executed on site, is generated.
|
||||||
|
|
||||||
|
Since encrypted code is stored in a SAS dataset it has
|
||||||
|
no limitation in sharing between operating systems (like catalogs have).
|
||||||
|
|
||||||
|
*Limitation:* Due to the `Resolve()` function limitations
|
||||||
|
a single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
*Notes:*
|
||||||
|
- All macros have to have the `secure` option added, i.e. `%macro aMacroname(...) / SECURE ;`.
|
||||||
|
- During the execution a test macro, named `%GSMpck_dummyMacroForTests()`, is generated.
|
||||||
|
- The `%GSM()` macro calls the `%GSMpck_makeFCMPcode(...)` macro internally.
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%GSM(
|
||||||
|
path
|
||||||
|
<,trim=0>
|
||||||
|
<,cmplib=work.generateMacros>
|
||||||
|
<,source2=>
|
||||||
|
<,outpath=>
|
||||||
|
<,encodingRestricted=>
|
||||||
|
<,secret=>
|
||||||
|
<,lineEnd=>
|
||||||
|
<,encrypt=>
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `path` - *Required*, indicates a directory which contains files with macros.
|
||||||
|
Only files with `sas` extension are used.
|
||||||
|
|
||||||
|
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||||
|
Names the dataset which will contain generated functions.
|
||||||
|
|
||||||
|
* `source2=` - *Optional*, the default value is null.
|
||||||
|
Indicate if `%includ`-ed files are printed out.
|
||||||
|
Any value other than null enables printing.
|
||||||
|
|
||||||
|
* `outpath=` - *Optional*, the default value is set the same as the `path`.
|
||||||
|
Points a directory in which a result (a zip file) is generated.
|
||||||
|
|
||||||
|
* `encodingRestricted=` - *Optional*, the default value is `0`.
|
||||||
|
If set to 1 then if User session encoding is different from
|
||||||
|
encoding of the session which generates the dataset then
|
||||||
|
the generateMacros() function will not execute macro code.
|
||||||
|
|
||||||
|
* `secret=` - *Optional*, the default value is null, in such case the
|
||||||
|
secret is generated from the `sha256(datetime(), hex32.)` function
|
||||||
|
and is printed in the log. When not null then should be
|
||||||
|
alphanumerical constant. Non-alphanumerical characters are removed.
|
||||||
|
Required to execute the `resolve()` function.
|
||||||
|
User who do not know the value will not be able
|
||||||
|
to run the `_maxro_XX_()` function.
|
||||||
|
|
||||||
|
* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of:
|
||||||
|
line feed, carriage return, or both, or a space be inserted
|
||||||
|
at the end of line in the intermediate code file that is generated.
|
||||||
|
Value has to be hexadecimal code (_NOT_ null),
|
||||||
|
since the value is resolved as `"&lineEnd."x`, so use e.g.
|
||||||
|
`0A` for line feed, `0D` for carriage return,
|
||||||
|
`0D0A` for both, and `20` for space.
|
||||||
|
|
||||||
|
* `encrypt=` - *Optional*, the default value is `ENCRYPT`.
|
||||||
|
Indicate if `FCMP` functions generated by the package
|
||||||
|
are encrypted. Value has to be either empty or `ENCRYPT`,
|
||||||
|
all other are converted to default. The option is
|
||||||
|
dedicated for debugging, keep the default value
|
||||||
|
for production use.
|
||||||
|
|
||||||
|
* `trim=` - *Deprecated*, the default value is `0`.
|
||||||
|
*Kept for backward compatibility.*
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
### Example: ###################################################################
|
||||||
|
|
||||||
|
Example 1. Prepare 2 files: `f1.sas` and `f2.sas` and use the `%GSM()` macro.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%let path = %sysfunc(pathname(work))/path2files;
|
||||||
|
|
||||||
|
%put &=path.;
|
||||||
|
options dlcreatedir;
|
||||||
|
libname path "&path.";
|
||||||
|
filename path "&path.";
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file path(f1.sas);
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
cards4;
|
||||||
|
%macro abc(x) / SECURE;
|
||||||
|
data test;
|
||||||
|
do i = 1 to &x.;
|
||||||
|
put i=;
|
||||||
|
end;
|
||||||
|
run;
|
||||||
|
%mend;
|
||||||
|
;;;;
|
||||||
|
run;
|
||||||
|
|
||||||
|
data _null_;
|
||||||
|
file path(f2.sas);
|
||||||
|
input;
|
||||||
|
put _infile_;
|
||||||
|
cards4;
|
||||||
|
%macro xyz(x) / SECURE;
|
||||||
|
%do i = 1 %to &x.;
|
||||||
|
%put &=i;
|
||||||
|
%end;
|
||||||
|
%mend;
|
||||||
|
;;;;
|
||||||
|
run;
|
||||||
|
|
||||||
|
%GSM(&path., cmplib=work.myMacros)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## `%gsmpck_makefcmpcode()` macro <a name="gsmpckmakefcmpcode-macro-2"></a> ######
|
||||||
|
|
||||||
|
## >>> `%GSMpck_makeFCMPcode()` macro: <<< <a name="GSMpck-makeFCMPcode-macro"></a> #######################
|
||||||
|
|
||||||
|
The `%GSMpck_makeFCMPcode()` macro is an internal macro of
|
||||||
|
the **GSM** (a.k.a. *Generate Secure Macros*) package.
|
||||||
|
|
||||||
|
It executes a process of converting
|
||||||
|
a macro provided by the user into
|
||||||
|
a Proc FCMP function.
|
||||||
|
|
||||||
|
Since encrypted code is stored in a SAS dataset it has
|
||||||
|
no limitation in sharing between operating systems (like catalogs have).
|
||||||
|
|
||||||
|
*Limitation:* Single macro file cannot be longer than 32760 bytes.
|
||||||
|
|
||||||
|
### SYNTAX: ###################################################################
|
||||||
|
|
||||||
|
The basic syntax is the following, the `<...>` means optional parameters:
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas
|
||||||
|
%GSMpck_makeFCMPcode(
|
||||||
|
path
|
||||||
|
,number
|
||||||
|
<,outlib=work.generateMacros.secure>
|
||||||
|
<,source2=>
|
||||||
|
<,fileNameCode=FNC>
|
||||||
|
<,secret=123456789>
|
||||||
|
<,lineEnd=0A>
|
||||||
|
)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**Arguments description**:
|
||||||
|
|
||||||
|
1. `path` - *Required*, indicates a directory which contains files with macros.
|
||||||
|
Only files with `sas` extension are used.
|
||||||
|
|
||||||
|
2. `number` - *Required*, a sequential number.
|
||||||
|
|
||||||
|
|
||||||
|
* `cmplib=` - *Optional*, the default value is `work.generateMacros`.
|
||||||
|
Names the dataset which will contain generated functions.
|
||||||
|
|
||||||
|
* `source2=` - *Optional*, the default value is null.
|
||||||
|
Indicate if `%includ`-ed files are printed out.
|
||||||
|
Any value other than null enables printing.
|
||||||
|
|
||||||
|
* `fileNameCode=` - *Optional*, the default value is `FNC`.
|
||||||
|
Internal fileref.
|
||||||
|
|
||||||
|
* `secret=` - *Optional*, internal, the default value is `1234567890`.
|
||||||
|
Alphanumerical constant required to execute the `resolve()`
|
||||||
|
function. User who do not know the value will not be able
|
||||||
|
to run the `_maxro_XX_()` function.
|
||||||
|
|
||||||
|
* `lineEnd=` - *Optional*, the default value is `0D0A`, indicates which of:
|
||||||
|
line feed, carriage return, or both, or a space be inserted
|
||||||
|
at the end of line in the intermediate code file that is generated.
|
||||||
|
Value has to be hexadecimal code (_NOT_ null),
|
||||||
|
since the value is resolved as `"&lineEnd."x`, so use e.g.
|
||||||
|
`0A` for line feed, `0D` for carriage return,
|
||||||
|
`0D0A` for both, and `20` for space.
|
||||||
|
|
||||||
|
* `trim=` - *Deprecated*, the default value is `0`.
|
||||||
|
*Kept for backward compatibility.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# License <a name="license"></a> ######
|
||||||
|
|
||||||
|
Copyright (c) Bartosz Jablonski, since 2021 onward
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
BIN
hist/0.22.3/gsm.zip
Normal file
BIN
hist/0.22.3/gsm.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user