Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bas64 #2

Merged
merged 4 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ titles_from_headings:
strip_title: true
collections: true

show_excerpts: true

defaults:
- scope:
path: ""
Expand Down
5 changes: 1 addition & 4 deletions _includes/sharelinks.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
#share-buttons > div.twitter > svg {height: 20px; margin-top: 8px;}
#share-buttons > div.linkedin > svg {height: 19px; margin-top: 7px;}
#share-buttons > div.pinterest > svg {height: 20px; margin-top: 9px;}
#share-buttons > div.gplus > svg {height: 17px; margin-top: 9px; position: relative; left: 1px;}
#share-buttons > div.mail > svg {height: 14px; margin-top: 11px;}
</style>

Expand All @@ -25,12 +24,10 @@
<span style="color: silver;">Share on: </span><div id="share-buttons">
<div class="facebook" title="Share this on Facebook" onclick="window.open('http://www.facebook.com/share.php?u={{ safeurl }}','popup','width=600,height=600'); return false;">
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1343 12v264h-157q-86 0-116 36t-30 108v189h293l-39 296h-254v759h-306v-759h-255v-296h255v-218q0-186 104-288.5t277-102.5q147 0 228 12z"/></svg></div>
<div class="twitter" title="Share this on Twitter" onclick="window.open('https://twitter.com/intent/tweet?url={{ safeurl }}&text={{ safetitle }}&via={{ site.twitter_username }}','popup','width=600,height=600'); return false;">
<div class="twitter" title="Share this on X (formerly Twitter)" onclick="window.open('https://twitter.com/intent/tweet?url={{ safeurl }}&text={{ safetitle }}&via={{ site.twitter_username }}','popup','width=600,height=600'); return false;">
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1684 408q-67 98-162 167 1 14 1 42 0 130-38 259.5t-115.5 248.5-184.5 210.5-258 146-323 54.5q-271 0-496-145 35 4 78 4 225 0 401-138-105-2-188-64.5t-114-159.5q33 5 61 5 43 0 85-11-112-23-185.5-111.5t-73.5-205.5v-4q68 38 146 41-66-44-105-115t-39-154q0-88 44-163 121 149 294.5 238.5t371.5 99.5q-8-38-8-74 0-134 94.5-228.5t228.5-94.5q140 0 236 102 109-21 205-78-37 115-142 178 93-10 186-50z"/></svg></div>
<div class="linkedin" title="Share this on Linkedin" onclick="window.open('https://www.linkedin.com/sharing/share-offsite/?url={{ safeurl }}','popup','width=600,height=600'); return false;">
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M477 625v991h-330v-991h330zm21-306q1 73-50.5 122t-135.5 49h-2q-82 0-132-49t-50-122q0-74 51.5-122.5t134.5-48.5 133 48.5 51 122.5zm1166 729v568h-329v-530q0-105-40.5-164.5t-126.5-59.5q-63 0-105.5 34.5t-63.5 85.5q-11 30-11 81v553h-329q2-399 2-647t-1-296l-1-48h329v144h-2q20-32 41-56t56.5-52 87-43.5 114.5-15.5q171 0 275 113.5t104 332.5z"/></svg></div>
<div class="gplus" title="Share this on Google Plus" onclick="window.open('https://plus.google.com/share?url={{ safeurl }}','popup','width=600,height=600'); return false;">
<svg viewBox="0 0 2304 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1437 913q0 208-87 370.5t-248 254-369 91.5q-149 0-285-58t-234-156-156-234-58-285 58-285 156-234 234-156 285-58q286 0 491 192l-199 191q-117-113-292-113-123 0-227.5 62t-165.5 168.5-61 232.5 61 232.5 165.5 168.5 227.5 62q83 0 152.5-23t114.5-57.5 78.5-78.5 49-83 21.5-74h-416v-252h692q12 63 12 122zm867-122v210h-209v209h-210v-209h-209v-210h209v-209h210v209h209z"/></svg></div>
<div class="mail" title="Share this through Email" onclick="window.open('mailto:?&body={{ safeurl }}&subject={{ safetitlepre }}{{ safetitle }}','popup','width=600,height=600'); return false;">
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1792 710v794q0 66-47 113t-113 47h-1472q-66 0-113-47t-47-113v-794q44 49 101 87 362 246 497 345 57 42 92.5 65.5t94.5 48 110 24.5h2q51 0 110-24.5t94.5-48 92.5-65.5q170-123 498-345 57-39 100-87zm0-294q0 79-49 151t-122 123q-376 261-468 325-10 7-42.5 30.5t-54 38-52 32.5-57.5 27-50 9h-2q-23 0-50-9t-57.5-27-52-32.5-54-38-42.5-30.5q-91-64-262-182.5t-205-142.5q-62-42-117-115.5t-55-136.5q0-78 41.5-130t118.5-52h1472q65 0 112.5 47t47.5 113z"/></svg></div>
</div>
18 changes: 17 additions & 1 deletion _posts/2023-05-11-RPG-CICD-Setting-up-local-development.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ VSCODE automatically prompts you to download and install it the first time you c

![Install GIT](/assets/images/VSCODE_Install_GIT_2.gif)

#### Configure Git

The first time you use Git, you must configure some settings. Open up a bash terminal in VSCODE and run the following 2 commands:

```
git config --global user.name "xx xxxx"
git config --global user.email "[email protected]"
```
![Configure GIT](/assets/images/Git_Config.gif)

These settings will be used to identify you on every commit you make.

#### Set up SSH keys in Gitlab
We need to generate an SSH key pair on your local PC, then enter the public key in your gitlab profile. This allows easy, secure ability to push and pull content from your PC to Gitlab. All of the following instructions are pretty much the same if you use another SCM like Github instead of Gitlab.

1.

#### Install VSCODE extensions

There are a multitude of extensions available for VSCODE. They are available to install in the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/VSCode), or you can access the same marketplace from within the VSCODE in the extensions sidebar view:
Expand All @@ -67,7 +84,6 @@ There are two approaches to getting a project to sync to online source control.
2. Copy the project SSH clone URL and clone it

5. Set your deploy IFS target directory - do this in the IFS
6. Set up your

### Setting up your IBM i profile
The first work we need to do is to set up your IBM i profile for open source development
Expand Down
163 changes: 163 additions & 0 deletions _posts/2023-10-12-Base64-encode-decode.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
layout: post
title: "Base 64 Encoding and Decoding with DB2"
date: 2023-10-12
---

## Base64 Encoding and Decoding on IBM i

Base64 encoding is a method for converting binary data into ASCII text. It's designed to prevent communication errors when transferring binary information.

The IBM i operating system provides two DB2 services that allow you to BASE64 encode and decode.

In this post we will discuss how to use these DB2 services, and why CCSID is an important consideration. The examples given will utilize embedded SQL in an SQLRPGLE program. We will make use of a service program exported procedure named 'print_this' that will be discussed in future post about service programs.

### The IBM i DB2 services for base64 encoding and decoding

[BASE64_ENCODE](https://www.ibm.com/docs/en/i/7.5?topic=functions-base64-encode) - returns the Base64 encoded version of a binary value.

[BASE64_DECODE](https://www.ibm.com/docs/en/i/7.5?topic=functions-base64-decode) - returns a character string that has been Base64 decoded

### Trying it out

First lets encode a string 'MyText' in base64 using a simple SQLRPGLE program. As mentioned above, we will make use of service program sub-procedure named 'print_this' that simply prints 2 strings passed as parameters to a spoolfile.

``` text
**free
ctl-opt actgrp(*new) bnddir('BNDUTIL');

// Start of Main Procedure
// Declare some stand-alone fields
Dcl-S PlainText VARCHAR(100) INZ('MyText');
Dcl-S EncodedText VARCHAR(100);

/copy ./qptypesrc/printer.rpgleinc

// Print headings
print_this('Field Name' : 'Value');
print_this('---------------------' : '-----------------------------------------------------------');

print_this('PlainText' : %Trim(PlainText));

// Encode the text into a VARCHAR field
Exec SQL Values QSYS2.BASE64_ENCODE(:PlainText) Into :EncodedText;
print_this('EncodedText' : %trim(EncodedText));

return;
```

Spoolfile Output:

``` text
Field Name Value
--------------------- --------------------------------------------------------
PlainText MyText
EncodedText 1Kjjhaej
```

Now, lets check that against a base64 encoder on the web: [https://www.base64encode.org/](https://www.base64encode.org/)

> ![bas64encode.org screen grab](/assets/images/base64-1.png)

The encoded value from our RPG program doesn't match the encoded value from www.base64encode.org. The reason they don't match, is because of CCSID. CCSID, or Coded Character Set Identitifier, is what uniquely identifies the specific encoding of a code page.

If you read the documentation for base64_encode, it gives examples of base64 encodeing for both the system default EBCDIC code page and UTF-8 (code page 1208) CCSID. ON IBM i, the default character set is EBCDIC, with the specific code page varying by region.

> On IBM i, ebcdic is the default character set.

The code page for your machine is stored in a system value called QCCSID. When your IBM i was delivered, it came with value 65535 - which isn't a real code page. 65535 is something IBM i uses to specify all character data tagging support support is turned off. IBM recommends this value be changed. In North America, the standard ebcdic code page for IBM i is 37. For more information, read up on QCCSID [here](https://www.ibm.com/docs/en/i/7.5?topic=values-coded-character-set-identifier-qccsid-system-value).

With that understanding, if you want to base64 encode / decode like the rest of the world, and you probably do, you need to make a CCSID adjustments to your code:

``` text
**free
ctl-opt actgrp(*new) bnddir('BNDUTIL');

// Start of Main Procedure
// Declare some stand-alone fields
Dcl-S PlainText VARCHAR(100) INZ('MyText') CCSID(1208);
Dcl-S EncodedText VARCHAR(100);

/copy ./qptypesrc/printer.rpgleinc

// Print headings
print_this('Field Name' : 'Value');
print_this('---------------------' : '-----------------------------------------------------------');

print_this('PlainText' : %Trim(PlainText));

// Encode the text into a VARCHAR field
Exec SQL Values QSYS2.BASE64_ENCODE(:PlainText) Into :EncodedText;
print_this('EncodedText' : %trim(EncodedText));

return;
```

Spoolfile Output:

``` text
Field Name Value
--------------------- --------------------------------------------------------
PlainText MyText
EncodedText TXlUZXh0
```

In the code above, the only modification needed was to add the CCSID keyword to the definition for `PlainText`. I used the specific value of `1208`, but could also have used `*UTF8`. IBM's documentation suggests another method, which is to CAST the CCSID inline:

```
VALUES QSYS2.BASE64_ENCODE (CAST(EncodedText AS VARCHAR(10) CCSID 1208)) Into :EncodedText;
```

### And Now to Decode

Lets add a few more lines to our example that decode the now encoded message.

``` text
**free
ctl-opt actgrp(*new) bnddir('BNDUTIL');

// Start of Main Procedure
// Declare some stand-alone fields
Dcl-S PlainText VARCHAR(100) INZ('MyText') CCSID(1208);
Dcl-S EncodedText VARCHAR(100);
Dcl-S DecodedTextVarBinary sqltype(VARBINARY:100);
Dcl-S TranslatedTextVarChar VARCHAR(100) CCSID(1208);

/copy ./qptypesrc/printer.rpgleinc

// Print headings
print_this('Field Name' : 'Value');
print_this('---------------------' : '-----------------------------------------------------------');

print_this('PlainText' : %Trim(PlainText));

// Encode the text into a VARCHAR field
Exec SQL Values QSYS2.BASE64_ENCODE(:PlainText) Into :EncodedText;
print_this('EncodedText' : %trim(EncodedText));

// Decode the encoded text into an EBCDIC VarBinary field
Exec SQL Values QSYS2.BASE64_DECODE(:EncodedText) Into :DecodedTextVarBinary;
print_this('DecodedTextVarBinary' : %trim(DecodedTextVarBinary));

// Translate binary data in EBCDIC to UTF-8
TranslatedTextVarChar = DecodedTextVarBinary;
print_this('TranslatedTextVarChar' : %trim(TranslatedTextVarChar));

return;
```

Spoolfile Output:

``` text
Field Name Value
--------------------- --------------------------------------------------------
PlainText MyText
EncodedText TXlUZXh0
DecodedTextVarBinary (`èÁÌÈ
TranslatedTextVarChar MyText
```

In the code above, we first define a field of type `sqltype(VARBINARY:100)` to recieve the decoded text. We define another field of type `VARCHAR(100) CCSID(1208)` which allows us to translate the binary ebcdic data back to UTF-8 text. Unfortunately I haven't found a way to do this in one step. If you know of a better way, please mention it in the comments below.

In summary, while care must be given when defining fields with the correct CCSID values and field types, the IBM i operating system does give us the features we need to encode and decode in base64 just like the rest of the world.

Binary file added assets/images/Git_Config.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/base64-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.