Sunday, May 03, 2009

Base64 Encoding for PeopleSoft

This week on the ittoolbox peopeltools-I forum, I ran across a question on base64 encoding binary data using PeopleCode. There are a couple of ways to base64 encode data, none of which are delivered. Before deciding which method to use, we first have to answer two questions:

  1. Where is the data (file, database, text string)?
  2. Is the data in binary or plain text format?

If the data resides in the database, then we can select it out using the following SQL:

SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW('Hello World'))) FROM DUAL;

In fact, rewrite that as:

SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(%TextIn(:1)))) FROM DUAL;

And, if you are an Oracle database user, then you have a generic SQL statement you can use to base64 encode any plain text. If you name the SQL definition BASE_64_ENCODE, then you can call that SQL definition as follows:

Local string &source = "Hello World";
Local string &encoded;
Local number &i;

SQLExec(SQL.BASE_64_ENCODE, &source, &encoded);
MessageBox(0, "", 0, 0, "base64: " | &encoded);

The PeopleCode and SQL above will work for any text string as long as you are using an Oracle database. Now, what if you want to base64 encode binary data? If the binary data is in the database, then modify the SQL accordingly.

Did you notice the %TextIn Meta-SQL I sneaked into the SQL above? Use it whenever you are sending large amounts of text to the database. For a string as short as "Hello World," you don't need it, but if you are trying to base64 encode an entire XML document, then you might.

What if you are not using Oracle database? Perhaps T-SQL has a base64 encoding routine? If so, great. If not, then the following code provides a Java/PeopleCode solution. Unfortunately, the 2 common Java base64 encoding algorithms use method and constructor overloads in a manner that requires some ugly Java reflection PeopleCode.

REM ** create an instance of the Java base64 encoder;
Local JavaObject &encoder = CreateJavaObject("sun.misc.BASE64Encoder");

REM ** get a reference to a Java class instance for the primitive byte array;
Local JavaObject &arrayClass = GetJavaClass("java.lang.reflect.Array");
Local JavaObject &bytArrClass = &arrayClass.newInstance(GetJavaClass("java.lang.Byte").TYPE, 0);

REM ** use reflection to get a reference to the method we want to call;
Local JavaObject &encodeArgTypes = CreateJavaObject("java.lang.Class[]", &bytArrClass.getClass());
Local JavaObject &encodeMethod = &encoder.getClass().getMethod("encode", &encodeArgTypes);

REM ** call the method;
Local JavaObject &bytes = CreateJavaObject("java.lang.String", "Hello World").getBytes();
Local JavaObject &result = &encodeMethod.invoke(&encoder, CreateJavaObject("java.lang.Object[]", &bytes));

REM ** print the result;
MessageBox(0, "", 0, 0, "Result: " | &result.toString());

If you know enough about Java to compile a wrapper class and you have access to your app server's class directory, then you can eliminate the Java reflection code in favor of a wrapper:

package com.blogspot.jjmpsj;

import java.io.IOException;

import sun.misc.BASE64Encoder;

public class Base64Coder {
public static String encodeString(String data) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data.getBytes());
}

public static String encodeBytes(byte[] data) {
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
}

... and call it like so:

Local JavaObject &encoder = GetJavaClass("com.blogspot.jjmpsj.Base64Coder");
Local string &result = &encoder.encodeString("Hello World");

MessageBox(0, "", 0, 0, &result);

As you can see from this final example, when working with overloaded constructors and methods, Java wrappers dramatically simplify PeopleCode.

Each of the examples above uses "Hello World" as the text string. What is "Hello World" in base64? SGVsbG8gV29ybGQ=. You can find an online base64 encoder/decoder here.

I will have to leave the question of base64 encoding binary files for another day. I am on the East coast attending Collaborate '09 and I need to get some rest so I can be right as rain for the conference tomorrow morning.

Update May 4th, 2009 at 4:09 AM: In the comments to this post, devwfb suggests that developers use org.apache.commons.codec.binary.Base64
rather than sun.misc.BASE64Encoder because classes in the sun package are undocumented and unsupported. devwfb is right and I should have mentioned this fact in my original post. I chose to use sun's base64 encoder because it is delivered and doesn't require customers to add more jars to the $PS_HOME/class directory. I will post the commons-codec example and link to it from here. See Sun's FAQ for more information.

67 comments:

devwfb said...

sun.misc.BASE64Encoder is sun's internal class which may be deprecated later. So better use a 3rd party one, such as org.apache.commons.codec.binary.Base64

Jim Marion said...

@devwfb, you are exactly right. The difference between sun.misc.BASE64Encoder and org.apache.commons.codec.binary.Base64 is that the sun class returns a String and the Apache class returns a byte array. Once the result is returned to PeopleCode, the Apache byte array needs to be converted to a String. Creating a String from a byte array requires you to use the overloaded String(byte[]) constructor. I started down the Apache path, but switched to the Sun path because:

1. Both required Java reflection
2. The Sun class is delivered whereas the Apache commons jar file needs to be added to $PS_HOME/class

I should have pointed this out. Thank you for mentioning it as Sun's support policy may have an impact on a developer's base64 encoding method selection. I'll post the Apache commons version next. I'm a big fan of Apache commons, but have found that customers prefer to use the delivered Java API because it doesn't require them to add additional files to the $PS_HOME/class directory

Jim Marion said...

@devfwb, I moved your comment up into the body of the post as it is very important. I have the code written for the commons-codec case. I'll try to post it tonight.

Chris Heller said...

There is a delivered method - PCODE_BASE64_DECODE_STRING is a supported crypto type in the PeopleSoft Pluggable Encryption stuff.

Look at the PTAF_EMC.Utils appclass for an example of it's use.

Bauke Gehem said...

Several delivered java classes provide Base64 encoding and decoding:

PS_HOME/class/com.peoplesoft.tools.keystore.jar
com.peoplesoft.tools.util.Base64
public static String encodeAndFormat(byte raw[])
public static String encode(byte raw[])
public static byte[] decode(String base64)

PS_HOME/class/psjoa.jar
psft.pt8.oreilly.Base64
public static String encode(byte raw[])
public static byte[] decode(String base64)

Jim Marion said...

Wow! Great responses! I am going to look into some of those alternatives. @devwfb, I haven't forgotten about commons-codec. From a support and documentation perspective, that is definitely the right choice.

Jim Marion said...

@Chris, I did some looking into the Crypt class in the PeopleCode API PeopleBook. It appears that base64 encryption is delivered and documented using the SSL encryption library. The code you reference uses the PCODE_BASE64_DECODE_STRING encryption profile. Encryption Profiles are documented in the Security Administration PeopleBook. Following the documentation in the PeopleBook, I looked up my existing profiles and don't see the base64 profiles. The algorithms exist so it should be possible to create a profile that uses the algorithm. It looks like a blog post offering a little more documentation is in order.

It also appears that the UpdateData method only works for base64 encoding strings so I'm wondering if it can be used to encrypt binary data. Definitely worth pursuing!

Jim Marion said...

@Chris, after creating an algorithm chain and an encryption profile as documented in the security administration PeopleBook, I was able to base64 encode "Hello World" with 3 lines of PeopleCode. Pretty Simple! I copied the 3DES CBC B64 ENCRYPT algorithm chain, but removed the 3des_ks168_cbc_encrypt entry. The Defining Algorithm Chains PeopleBook says input data must be in ASCII format so that definitely rules out binary base64 encoding, but it definitely works for strings!

EonYun Admin said...

hi,jim:

it's glad to c u here , and now i face a problem about " approve transactions straight from the email notification" , it's said that a book named " Email Collaboration Framework implementation guide" can helped , but i did not find it anywhere . do u have one or have some suggestion about my problem?

thx
jarden.cheung

Jim Marion said...

@jarden, I know what you are referring to, but I have never implemented it. Did you look in PeopleBooks and MetaLink?

Charlie said...

Doc ID 645462.1 in metalink3 mentions: "The standard PeopleSoft API for handling messaging will convert the binary data to Base64 and insert in the
corresponding XML data tag. In otherwords sending image type data is no different than any other messaging."

It does not, however, mention decoding. :)

Jim Marion said...

@Charlie, have you tested this? I'm wondering how you would get binary data into a message in the first place.

Bauke Gehem said...

I've done a quick test on tools 8.49 using a message based on the EMPL_PHOTO rowset. I can both extract and insert base64 encoded photos using this message. This can come in handy in all kinds of integration scenerios. Thanks Charlie.

Jim Marion said...

@Charlie, @Bauke, Ah! That makes sense. Thanks Charlie and Bauke. OK, so if I understand correctly, if binary data is in the database (employee photos) then you can select it into a Rowset based message. When you publish that message, Integration Broker will automatically base64 encode the LONG field's data.

Bauke Gehem said...

Exactly! And it works the other way round. If you send a rowset based message containing a base64 encoded image field, it will be decoded and stored in your database. A function sorely missing from the File class.

Jim Marion said...

@Bauke, I absolutely agree with you regarding the sorely missing binary methods in the File object. I know you can get this functionality using java.io.File and wrap it in a Java class to base64 encode the contents of the file prior to returning it to PeopleSoft. I have it on my list, I just haven't created it yet.

Cool. Thanks again Bauke and Charlie for sharing.

Unknown said...

Jim,
Can you please provide the code for encoding a File to base64 bit file and decoding back a base64 bit file.
Thank you,
Naren.

Jim Marion said...

I posted how to base64 encode a binary file: Base64 Encoding Binary Files. Decoding is very similar.

jb said...

Jim, I am trying to decode a string using

Local object &oDecoder = CreateJavaObject("sun.misc.BASE64Decoder");
Local object &dOut = &oDecoder.decodeBuffer(&Fld_Str);
Local object &oDecoded = CreateJavaObject("java.lang.String", &dOut, 0, &dOut.length, "UTF8");
&DecodeResult = &oDecoded.toString();

This is a file I am trying to download and decrypt back into, in this case a Word document. I don't know if the string is ascii or unicode or something else (I don't know the difference).

Do I need to do anything to the string before I decode? I can't get the file to open in Word after decrypting.

Jim Marion said...

@Joseph, Your code looks good. I think the problem is what you are doing with the result. Assuming that &Fld_Str is a base64 encoded string, the result of decodeBuffer should be a binary array. You are then converting the binary array to a string. I believe that is where the problem begins. If your Word document is HTML, RTF or one of the text based Word formats, then converting it to a string is fine. If it is one of the older OLE compound binary documents, then converting it to a string is incorrect. Converting the binary data to a string would corrupt the data. Rather than try to deal with this in PeopleCode, I recommend using a language that supports binary data, like Java. If you are writing the data to a file, then you can create a static Java helper method that uses the decodeBuffer version that takes an InputStream and OutputStream.

Working with binary files in PeopleCode is very tricky because PeopleCode has no support for binary files.

Another option rather than creating your own Java helper is to use an existing Java helper. org.apache.commons.codec.binary.Base64OutputStream is an example. I show how to use the Base64InputStream in my post Base64 Encoding Binary Files (which I saw you already read). The output stream version is very similar. Just wrap the Base64OutputStream in an OutputStreamWriter and BufferedWriter or maybe even just a PrintWriter.

Dealing with binary input/transfers is actually the next item in my series on dealing with binary data.

jb said...

FYI...
In regard to my earlier post, I have developed a way to process a binary file in PeopleCode. Here is the code snipet:

REM &Fld_Str holds the encrypted binary file data (in this case, from a soap message);
&Fld_Str = &Rslts_Node.NodeValue;

rem &PrintFlName is the path and file name (in this case, from a soap message);
&PrintFlName = &Sav_Dir | &Resp_NameVal;


Local object &oDecoder = CreateJavaObject("sun.misc.BASE64Decoder");
Local object &dOut = &oDecoder.decodeBuffer(&Fld_Str);
Local object &fstream2 = CreateJavaObject("java.io.FileOutputStream", &PrintFlName);


&fstream2.write(&dOut);


&fstream2.close();

Jim Marion said...

@Joseph, Brilliant! Well done. Thank you for sharing.

Jim Marion said...

@Joseph, One comment though... instead of using Local Object, I recommend using Local JavaObject. I don't know if it will change anything, but the return value of a Java method is technically a JavaObject, so it is worth noting that in the declaration.

Raj said...

Hi Jim,
Great Book.
I wanted to check how to URLENCODE a link in peoplecode.
I tried endcodeurl builtin function, but when I send it across a webservice, it errors out. I
Is there any other way?

Jim Marion said...

@Raj, I'm glad you like the book.

Before you search for a different solution, I suggest you look at the EncodeURL output and EncodeURLForQueryString output to see what they are generating. Then you can determine why your web service is failing. If you find that the problem really is with the two PeopleCode functions, then I suggest you log a case to have the issue with the functions resolved. Next, you can look to Java for URL Encoding (really known as www-form-urlencoded). The java.net.URLEncoder and org.apache.commons.codec.net.URLCodec both urlencode URL's.

Kris said...

Jim, we ran into problems with the reflection involved in this code and either PTools 8.51 or JDK 1.6 (I'm not sure exactly which one is the culprit but I suspect the latter). Removing some of the reflection solve it for us.

rem Local JavaObject &arrayClass =
GetJavaClass("java.lang.reflect.Array");
rem Local JavaObject &bytArrClass =
&arrayClass.newInstance(GetJavaClass("java.lang.Byte").TYPE, 0);

rem - ke 7-20-2011 Local JavaObject &digestArgTypes =
CreateJavaObject("java.lang.Class[]", &bytArrClass.getClass());

Local JavaObject &ka = CreateJavaArray("byte[]", 0);
Local JavaObject &digestArgTypes = CreateJavaObject("java.lang.Class[]",
&ka.getClass());
Local JavaObject &digestMethod = &jMsgDigest.getClass().getMethod("digest",
&digestArgTypes);

Jim Marion said...

@Kris, thank you for sharing. I ran into the same thing last week while reading bytes from files to write into a ZipEntry for creating zip files. It appears that you can't create a byte[] using the Array.newInstance method anymore. the CreateJavaArray method is a much better way to create the byte array.

Tom said...

Jim,

I have the following code.

Local string &out;
Local JavaObject &javaString1, &javaString2;

&javaString1 = CreateJavaObject("java.lang.String", "test.doc");
&javaString2 = CreateJavaObject("java.lang.String", ".");

&out = &javaString1.lastIndexOf(&javaString2);

I was expecting a "more than one overload matches" error since lastIndexOf() method in String class is overloaded. But this code worked fine. Any clues? I'm on PT 8.50, Java 6.

Jim Marion said...

@Tom, You only see the "More than one overload matches" error when the PeopleCode runtime can't determine which overload to match based on parameter count and type. Some overloads with the same parameter count can be matched based on parameter type. java.io.FileInputStream's constructor is a great example of an overloaded Java method that PeopleCode is able to resolve. In your case, lastIndexOf's matching overloads can either be an integer (char) or a string and PeopleCode was able to determine the difference.

The way I approach this is to first try without reflection. If it fails, then I go the long hand reflection route.

Ganesh said...

Local JavaObject &iparrayClass = GetJavaClass("java.lang.reflect.Array");
Local JavaObject &ipbytArrClass = &iparrayClass.newInstance(GetJavaClass("java.lang.Byte").TYPE, 0);

I am getting the error.

Calling Java java.lang.reflect.Array.newInstance: more than one overload matches. (2,742)


Need your help - how I can fix it. I am using 8.51.11 PeopleTools

Jim Marion said...

@JCook, How you proceed depends on your tools release. If you have PT 8.52+, you can use the File.WriteBase64StringToBinary() method (see base64 in PT 8.52). If you are on a prior release, then you will use one of the other base64 methods described in this blog to write to a binary file. If the received base64 data is not binary, then you can convert it directly to a string. Regardless of how you get the base64 data into a file, once you have it in a file, use the PutAttachment function to move the file into a file attachment record.

Now, with that said, there are other options. File attachment records are just database records. You can insert into and select from them just like any other record. If I were writing this, though, I would get the base64 data into a file (either using PT 8.52 or commons-codec Base64OutputStream and then use PutAttachment to import it.

JCook said...

Jim,

Thanks so much I will get to a file and use putattachment as suggested.

:)

Jim Marion said...

@Ganesh, the array approach demonstrated here worked in 8.49, but no longer works. I documented a much better approach here: Creating Binary Arrays

BMWMOTOS said...

Hi Jim,

We are trying to take an image from Oracle 11 and passed to BASE64Encoder function and embedding the text result to an Html Email.

It looks easy your explanation 'till we found the words "then modify the SQL accordingly"

Please can you help us to understand what its means?

Thnks you for your help!!

Jim Marion said...

@BMWMOTOS, good question. I believe the difference is the CAST_TO_RAW required when working with text strings. Depending on the size of the files you are processing, you may have size limitations as well. Here is a great example of the proper PL/SQL on stack overflow. Since you are sending these images in an email embedded in base64, I suspect they aren't that big. Are you using HTML e-mail with base64 encoded data URL's?

BMWMOTOS said...

Jim,
We're using People Tools 8.49, for that reason we have not chance to use functions like WriteBase64StringToBinary.
Till now using package UTL_RAW don't help us much.
Our apparently simple plan was: :)
1) Read a Picture from a Table.Field ORACLE, then encode it BASE64 and pass it TO an PS variable.
But CASTING values between packages, Oracle and PS it's a really nightmare.
We worked before with JavaObjects but we still don't have any clean or certain clue about how to implement it for our need.

Jim Marion said...

@BMWMOTO, getting the image into base64 and then into a PeopleCode string variable is a reasonable task. If it can't be done with plain SQL, then you might need a little PL/SQL, but once you have a function defined, you should be able to select that function to get the base64 into a column, and then into a PeopleCode variable. I'm not sure what you mean by casting values between PeopleSoft and Oracle. Once you have the string variable in PeopleCode, are then planning to convert it back to binary? I'm not sure if that is even possible. Even if you did, I don't know what you would do with it since none of the PeopleCode methods work with binary data.

The WriteBase64StringToBinary file method creates a file on your app server (or process scheduler server). If that is suitable, and you have the attachment in the database, then just use the GetAttachment function. It creates a file from a database attachment, skipping the whole base64 step.

The original requirement was to place the image in an e-mail. If you are using an e-mail attachment, then using GetAttachment with the SendMail function seems reasonable. Just make sure you consider file security for attachments copied to the file system. An alternative would be to use HTML e-mail and embed the images in base64 in data URL's using img tag or background images. This would just require the extraction of the binary image in base64, but no conversion back to binary.

BMWMOTOS said...

1) Data actually is into a PS Record BLOB type
2) Data is binary (Pictures files)
3) Destination: As a string to be embedded into a mail with HTML format to avoid to have an Public directory to publish our emails pictures.

May be it'll easier to read the content from that image from a File Server instead of reading it from Oracle.

Jim we're asking for your help 'cause we'd run out ideas:
¿There is any method to read a picture file content into a PSoft string variable and then format the result string with base64 Encoding in order to embbed it?

Jim Marion said...

@BMWMOTOS, you may want to post your question on the OTN PeopleSoft General Discussion forum, which has a wider audience.

Vikas Bhartiya said...

Hi Jim, our requirement is integration with a cloud based application which uses SAML 2.0 and hence we need to create a signed XML document which then needs to be base64 encoded and sent using HTML POST (Iscript).

What we are struggling with currently is a way in PeopleCode to create a signed xml document. Is it possible?
Thanks a ton for your help!

Vikas

Jim Marion said...

@Vikas, You may need to use Java to sign your document. This blog contains plenty of examples of using GetJavaClass and CreateJavaObject.

Unknown said...

Hi Jim,

Can you suggest us a way to encrypt specific columns in some tables in oracle database and should be automatically decrypted in application(PIA).

Thanks in advance.

Jim Marion said...

@Vinod, I have no experience with column encryption. You will get better answers to this question if you post it on the OTN PeopleSoft General Discussion forum.

Unknown said...

Hi Jim I am new to Java and the like. There is a delivered piece in BAC030 AE that calls for FileInputStream. The code is as below. I understand that the overload in this case is at fileinputstream. I am just stuck not knowing how to get past. Would you know a simple fix.

Local JavaObject &jFile = CreateJavaObject("java.io.File", &1094C_FullPath);
Local JavaObject &jFileReader = CreateJavaObject("java.io.FileInputStream", &jFile);
Local JavaObject &messageDigest = GetJavaClass("java.security.MessageDigest").getInstance("MD5");
Local JavaObject &jByteArray = CreateJavaArray("byte[]", 1024);
/* Read Input File Byte by Byte */
Local number &jByteCount = &jFileReader.read(&jByteArray);
While &jByteCount > 0
&messageDigest.update(&jByteArray, 0, &jByteCount);
&jByteCount = &jFileReader.read(&jByteArray);
End-While;

Jim Marion said...

I do not have an easy fix. If you look through the posts on this site and other sites, you will see samples of Java reflection in PeopleCode as well as an example of using JavaScript to avoid reflection.

Jim Marion said...

I do not have an easy fix. If you look through the posts on this site and other sites, you will see samples of Java reflection in PeopleCode as well as an example of using JavaScript to avoid reflection.

Naveen said...

Hi Jim,
If have been trying to extract the contents form a pdf documents using the jar file itextpdf-5.1.0.jar and the class

com.itextpdf.text.pdf.parser.pdfTextExtractor , but whenever i use this class it throws the message as matching constructor is not public .

if i user getjavaclass(com.itextpdf.text.pdf.parser.pdfTextExtractor) and use the getTextFromPage it throws the message as no overload matches.

can you help me in bypassing and understanding this errorrs.

Iam able to read the file with PDFREader but extraction is creating a problem.

Need ur advise in how to overcome this problem

Jim Marion said...

@Naveen, it sounds like the GetJavaClass approach is the correct one. The "More than one overload matches" error tells you that the method you are calling has multiple definitions with different parameters and PeopleCode can't decide which one to use based on parameter count and parameter type. You have three alternatives, and all are demonstrated on this blog:

#1 Use reflection. This is the ugliest and hardest approach.

#2 Write your own Java wrapper/proxy that invokes the overloaded methods, but does so using method names that are not overloaded. This is the easiest approach, but requires you to maintain custom Java and restart the app server if you have to redeploy your Java.

#3 Use JavaScript on the server. This involves writing a JavaScript fragment that uses iText and then running that JavaScript from PeopleCode. I have at least one example on this blog and other examples in my last 2 years of OpenWorld/Collaborate/Alliance presentations. This is the easiest to maintain, but is a little harder to comprehend than #2. I think it is definitely easier than #1.

Unknown said...

Hi Jim,

Thanks for all the information which you are providing through your blogs.
I was trying to encrypt data using Asymmetric encryption.The SSL being not implemented with Peoplesoft we are not able to generate public and private key using OPENSSL utility.
Please let me know if there is any way to generate Public and Private keys for Asymmetric encryption if we dont have SSL implemented.Thanks.

Chandra Selagamsetty said...

I was more keen in doing this using SQLSERVER for converting String into Base64

%NoUppercase SELECT CAST(N'' AS XML).value('xs:base64Binary(xs:hexBinary(sql:column(""bin"")))', 'VARCHAR(MAX)') Base64Encoding FROM (SELECT CAST( AS VARBINARY(MAX)) AS bin) AS bin_sql_server_temp

Vikas Bhartiya said...

Hi Jim,
I have just posted a question on OTN, but thought to put this to you as well..

https://community.oracle.com/thread/4009757

The requirement is to do AES/CBC/NoPadding encryption - and I have written a java class for it which throws "NoSuchAlgorithm" found exception (details of the code and the error in the link above).

My Tools version is rather old - 8.50.18 and the java version seems to be java 6, update 15.

I am wondering if it is my code or the java version and what are my options :(

Vikas

Vikas Bhartiya said...

I was able to resolve- was a java issue - cipher code needed to be within a try-catch..works like a charm now!!

Thanks Jim as always...

Vikas

Unknown said...

Hi Jim,

I tried UTL_ENCODE.BASE64_ENCODE solution above but the said result has different output when values has carriage return compare to available Base64 encoders online. I am not sure now if the encoded values is even correct.

SELECT UTL_RAW.CAST_TO_VARCHAR2(UTL_ENCODE.BASE64_ENCODE(UTL_RAW.CAST_TO_RAW(
'A
B'
))) FROM dual;
Result: QQpC

Online Encoders Result: QQ0KQg==

I noticed the result is already different from running UTL_RAW.CAST_TO_RAW. Maybe the cast to raw has different encoding on carriage return or line feeds?

I tried implementing the %textin and still has a different result.

The Peoplesoft encryption technology has the same result: QQcP
Algorithm Chain:
PSUnicodeToAscii
base64_encode
PSAsciiToUnicode

The encoding base64 result we are expecting is what the online encoders are generating.

PLease advise. thanks

Jim Marion said...

@Ryan, that is really interesting. Just for fun, I tried an online base64 decoder. Both of them show AB with a new line in between. What I didn't check is the new line character. As you know, a new line may be represented by a carriage return or a line feed or both. I'm suspicious that the difference you are seeing is caused by differences between the new line characters.

Unknown said...

Hello Jim,

I have a requirement where user from other system are navigated to PS and login. The URL has been given 2 extra parameter when PS page load based on the parameter value i need to calculaion in PS but I am not able to fetcj the URL parameter on component peoplecode.

I have tried %request.getparameter but this does not work

Jim Marion said...

@Kavita, that is unusual. Usually all parameters flow through to the component. Can you see the parameters in the URL in your browser when the component loads? If you look at the components iframe URL using the browser's inspector tool, can you see the parameters? Are the parameters lost as the user moves through the login page?

Unknown said...

Hey Jim,

Thank you for the response.
I can see the parameter in the URL but when I cant be fetched from %request. I have tried % request on Rowinit, postbuild and page activate as well but nothing seems to work.

Example of my URL is like below,

https://hostname/psp/pscrmacc/EMPLOYEE/CRM/c/component.GBL?FolderPath=PORTAL_ROOT_OBJECT.serachpage&IsFolder=false&IgnoreParamTempl=&emplid=&job_code=&name=&cust=&id=1234&phone=0000

and i need to fetch phone value on my page. I am not sure if the phone should be mentione in uppercase(if it something to do with the case).

What i am trying to fetch the phone number is

event : component post build
global string ☎
&phone=%request.getparameter("phone");
and when I print phone number it has blank values.
Apart from the above code do we do something else too?

when I check PeopleTools > Portal > General Settings , the default template name is 'Default template'.


and under Portal Objects > Templates the default template has storage type as'Remote by URL'

Appreciate your help.

Thank you

Jim Marion said...

I don't see any reason it wouldn't work. Other people say it should work: http://www.greyheller.com/blog/passing-additional-parameters-to-peoplesoft-pages/. Here is someone that had the same problem as you: http://peoplesoft.ittoolbox.com/groups/technical-functional/peopletools-l/requestgetparameterparm-returns-blank-5235694.

Allen Kuruvilla said...

Hi Jim,

I saw in one of the comments that IB automaticaly converts long data field into base64. Is it application if my entire xml (created through string) is large.

I am using REST consumer based services. We are sending an XML response to third party. XML But the entire data gets encoded for some reason. Its happening for only one scenario, lets say an invoice.

I noticed in the IB logs that the data is being encoded.

Y

I have set the HEADER property sendUncompressed as Y but its still getting compressed for some reason.

The service works fine for other invoices. The data being sent for this invoice is large as compared to others. I am not sure if thats the issue.

Regards,
Allen

Jim Marion said...

@Allen, by encoded, do you mean gzip compressed? good question and thought on the size. It has been a while since I've dug around in there, so nothing is coming to mind, but that could be true. I'm not sure if PS can be configured to treat this correctly. If it can't, my thought is to use a ServletFilter or some other proxy service to inflate. Not ideal, but possible.

Unknown said...

Jim ,
We have a requirement where we have attachments in the database and should be sent to a third party system using integration broker rest services.
I am looking for ideas on how to convert an attachment in a data base into Binary format and then insert into a message and publish.
Any help is appreciated.

Jim Marion said...

@Govi, Generally speaking, integrations use plain text. If that is the case, then you will be converting your binary attachment to base64 for submission.

Sandra said...

For the base64 encoding/decoding. You can also refer to that link as well
url-decode.com/tool/base64-decode

Prasannababu D said...

Hi Jim,

Hope you are doing good.

I am facing an issue by passing '&' or '%26' or char(38) in viewcontenturl() as it converting %26 as %2526 in URL.

My requirement is to view the content of the below url as example.
https://google.com/Browse.aspx?repo=DEMO#?search=({[]:[Business Unit] = "USA"} & {[]:[Voucher ID] = "123456"})

Please help.

Ketan Kothari said...

There is a sample peoplecode delivered in App engine program used by Search engine indexing. It is PTSF_GENFEED -> Setup -> Step04 – PeopleCode


Local JavaObject &header = CreateJavaObject("java.lang.String", &esuser | ":" | Decrypt("", &espass));
Local JavaObject &oEncoder = CreateJavaObject("com.peoplesoft.tools.util.Base64");
&auth = &oEncoder.encode(&header.getBytes());
&auth = "Authorization: Basic " | &auth;

You can also find references of delivered peoplecode using base64 using below SQL

select * from pspcmtxt where upper(PCTEXT) like '%BASE64%';

Jim Marion said...

@Ketan, Great find!

Top10+ said...

@Jim Hi Jim Is there are any possible way to get the http URL of a stored file (database or SFTP), like when we hit view attachment function by giving file location and file name it generates a http URL and open it into new window. How can I achieve this because I want to open a PDF file into a page using HTML Area and HTML Iframe that's why I need src of http type for passing in IFrame .

or is there any other way to do this "I want to open a PDF file into a page using HTMLArea and HTML Iframe"

Thank you.