Skip to content

Instantly share code, notes, and snippets.

@RainerRoss
Created September 15, 2018 10:21
Show Gist options
  • Save RainerRoss/999febf1644f6aa9ef175d07cfd72829 to your computer and use it in GitHub Desktop.
Save RainerRoss/999febf1644f6aa9ef175d07cfd72829 to your computer and use it in GitHub Desktop.
ctl-opt dftactgrp(*no) alloc(*teraspace) option(*nodebugio)
main(main) actgrp('UPLOAD') bnddir('WEBSRVUTL':'YAJL');
//------------------------------------------------------------------//
// //
// File Upload with Webix //
// //
//----------------- //
// R.Ross 09.2018 * //
//------------------------------------------------------------------//
// Prototypes //
//------------------------------------------------------------------//
/include websrvutl/qcpysrc,websrvutl
/include websrvutl/qcpysrc,iconv
/include websrvutl/qcpysrc,ifs
/include websrvutl/qcpysrc,memcpy
/include websrvutl/qcpysrc,dspgms
/include websrvutl/qcpysrc,apierr
/include yajl/qrpglesrc,yajl_h
//------------------------------------------------------------------//
// Table Data //
//------------------------------------------------------------------//
dcl-ds TbData qualified; // DataTable
Status char(20) inz('server'); // Status
Errmsg char(256); // Error-Message
FileName like(GblFilnam); // FileName
TempFile varchar(50); // TempFile
end-ds;
//------------------------------------------------------------------//
// Global Variables //
//------------------------------------------------------------------//
dcl-s GblAvail int(10); // Bytes Available
dcl-s GblFilnam varchar(1024); // File-Name
dcl-s GblFiltyp varchar(256); // File-Type
dcl-s GblFilhead varchar(1024); // File-Header
//------------------------------------------------------------------//
// Main //
//------------------------------------------------------------------//
dcl-proc main;
dcl-c LocStatusOk Const(200);
dcl-s LocErrmsg varchar(500);
dcl-s LocStmp timestamp inz(*sys); // TimeStamp
dcl-s LocContlen uns(10); // ContentLength
dcl-s LocBuffer_p pointer inz(*null); // Buffer-Pointer
dcl-s LocAvail int(10); // Bytes Available
reset TbData; // JSON-Table
LocContlen = %dec(%str(getenv('CONTENT_LENGTH':DsApierr)):10:0);
if LocContlen > *zero and LocContlen < 6000000000;// max 6GB
LocBuffer_p = %alloc(LocContlen);
readStdin(LocBuffer_p:LocContlen:LocAvail:DsApierr);
if LocAvail > *zero; // Bytes available
readdata(LocBuffer_p:LocAvail); // Read Data
else;
TbData.Status = 'error';
endif;
endif;
yajl_genopen(*on);
crtjson(LocStmp);
yajl_writeStdout(LocStatusOk:LocErrMsg);
yajl_genclose();
end-proc;
//------------------------------------------------------------------//
// Read Data //
//------------------------------------------------------------------//
dcl-proc readData;
dcl-pi *n;
PiBuffer_p pointer const; // Buffer-Pointer
PiAvail like(GblAvail) const; // Available-Length
end-pi;
dcl-s LocHeader like(GblFilhead); // File-Header
dcl-s LocFilnam like(GblFilnam); // File-Name
dcl-s LocFiltyp like(GblFiltyp); // File-Type
dcl-s LocFillen uns(10); // File-Length
dcl-s LocStrpos uns(10); // Start-Position
dcl-s LocSeplen uns(10); // Separator-Length
dcl-s LocData_p pointer inz(*null); // Data-Pointer
LocHeader = getAscii(PiBuffer_p:PiAvail); // Get ASCII-Data
if LocHeader <> *blanks; // Header
LocFilnam = getfilnam(LocHeader); // File-Name
LocFiltyp = getfiltyp(LocHeader:LocStrpos);// File-Type & Start
LocSeplen = %scan(crlf:LocHeader); // FileSeperatorLen
LocFillen = PiAvail - LocStrpos - LocSeplen - 4; // File-Length
LocData_p = PiBuffer_p + LocStrpos - 1; // Data-Pointer
wrtifs(LocData_p:LocFillen:LocFilnam); // Write to IFS
endif;
end-proc;
//------------------------------------------------------------------//
// Get ASCII-Data //
//------------------------------------------------------------------//
dcl-proc getascii;
dcl-pi *n like(GblFilhead) rtnparm;
PiBuffer_p pointer const;
PiAvail like(GblAvail) const;
end-pi;
dcl-s LocString char(1024);
dcl-s LocHeader like(GblFilhead);
dcl-s LocLength uns(10);
if PiBuffer_p = *null or PiAvail = *zero;
return *blanks;
endif;
if PiAvail > %size(LocString);
LocLength = %size(LocString);
else;
LocLength = PiAvail;
endif;
memcpy(%addr(LocString):Pibuffer_p:LocLength);
LocHeader = cvtData(%addr(LocString):LocLength:1141:1208);
return LocHeader;
end-proc;
//------------------------------------------------------------------//
// Get FileName //
// Example: 'filename="home\dir1\dir2\dir3\test.txt"' + CRLF //
//------------------------------------------------------------------//
dcl-proc getfilnam;
dcl-pi *n like(LocFilnam) rtnparm;// FileName
PiData like(GblFilhead) const; // Data
end-pi;
dcl-s LocFilnam like(GblFilnam); // FileName
dcl-s LocTag varchar(50); // Tag
dcl-s LocPos1 uns(10); // Pos 1
dcl-s LocPos2 uns(10); // Pos 2
dcl-s LocSlash uns(10); // Slash
LocTag = 'filename="'; // Tag
LocPos1 = %scan(LocTag:PiData); // Scan FileName
if LocPos1 > *zero; // Found
LocPos2 = %scan(crlf:PiData:LocPos1 + %len(LocTag));
LocFilnam = %subst(PiData:LocPos1 + %len(LocTag):
LocPos2 - (LocPos1 + %len(LocTag)) - 1);
else;
return *blanks;
endif;
// Backslash Handling
LocPos1 = *zero; // Position
if %scan('\':LocFilnam) > *zero; // Scan Backslash
dou LocPos1 = *zero;
LocPos1 = %scan('\':LocFilnam:LocPos1 + 1);
select;
when LocPos1 > *zero;
LocSlash = LocPos1;
when LocPos1 = *zero and LocSlash > *zero;
LocFilnam = %subst(LocFilnam:LocSlash + 1:
%len(LocFilnam) - LocSlash);
endsl;
enddo;
endif;
LocFilnam = %trim(LocFilnam);
TbData.FileName = LocFilnam;
TbData.TempFile = %trim(%str(crttmpstmf(*omit))); // CrtTempFile
return %trim(LocFilnam);
end-proc;
//------------------------------------------------------------------//
// Get FileType //
// Example: 'Content-Type: text/plain' + CRLF //
//------------------------------------------------------------------//
dcl-proc getfiltyp;
dcl-pi *n like(LocFiltyp) rtnparm;
PiData like(GblFilhead) const; // Data
PiStrpos like(LocStrpos); // StartPosition
end-pi;
dcl-s LocFiltyp like(GblFiltyp); // FileType
dcl-s LocTag varchar(50); // Tag
dcl-s LocPos1 uns(10); // Pos 1
dcl-s LocPos2 uns(10); // Pos 2
dcl-s LocStrpos uns(10); // StartPosition
LocTag = 'Content-Type:'; // Tag
LocPos1 = %scan(LocTag:PiData); // Scan Tag
if LocPos1 > *zero; // Found
LocPos2 = %scan(crlf:PiData:LocPos1 + %len(LocTag));
LocFiltyp = %subst(PiData:LocPos1 + %len(LocTag) + 1:
LocPos2 - (LocPos1 + %len(LocTag)) - 1);
PiStrpos = LocPos2 + 4; // FileStartPosition
endif;
return %trim(LocFiltyp);
end-proc;
//------------------------------------------------------------------//
// Write Data to IFS //
//------------------------------------------------------------------//
dcl-proc wrtifs;
dcl-pi *n;
PiData_p pointer const; // Data-Pointer
PiFillen uns(10) const; // File-Length
PiFilnam like(d#file) const; // File-Name
end-pi;
dcl-s LocFlags int(10); // Flags
dcl-s LocAuth int(10); // Authority
dcl-s LocFd int(10); // FileDescriptor
dcl-s LocDir varchar(256); // Directory
dcl-s LocStmf varchar(256); // StreamFile
if PiData_p = *null or PiFillen = *zero or PiFilnam = *blanks;
return;
endif;
LocFlags = o#rdwr + o#creat + o#ccsid + // Flags
o#textdata + o#textcreat;
Locauth = s#irwxu + s#irgrp + s#iroth; // Authority
LocDir = '/tmp/upload/'; // Upload-Directory
LocStmf = LocDir + PiFilnam; // Streamfile
if PiData_p <> *null and PiFillen > *zero; // File
unlink(LocStmf); // Delete File
LocFd = open(LocStmf:LocFlags:LocAuth:1208:1208);
if LocFd >= *zero; // FileDescriptor
callp write(LocFd:PiData_p:PiFillen);
callp close(LocFd); // CloseFile
endif;
endif;
end-proc;
//------------------------------------------------------------------//
// Convert Data between CCSID's //
//------------------------------------------------------------------//
dcl-proc cvtData export;
dcl-pi *n varchar(100000) rtnparm; // Result
PiSrc_p pointer const; // Source-Pointer
PiSrcLen uns(10) const; // Source-Length
PiTrgCcsid uns(10) const; // Target-CCSID
PiSrcCcsid uns(10) const; // Source-CCSID
end-pi;
dcl-s LocTarget char(100000); // Target 100 K
dcl-s LocTrg_p pointer inz(%addr(LocTarget));
dcl-s LocTrglen uns(10) inz(%size(LocTarget));
DsSrcCcsid.tq_ccsid = PiSrcCcsid; // Source-CCSID
DsTrgCcsid.tq_ccsid = PiTrgCcsid; // Target-CCSID
DsConv = *allx'00';
DsConv = iconv_open(DsTrgCcsid:DsSrcCcsid); // Open
iconv(DsConv:PiSrc_p:PiSrcLen:LocTrg_p:LocTrglen); // Convert
iconv_close(DsConv); // Close
return %subst(LocTarget:1:%size(LocTarget) - LocTrglen);
end-proc;
//------------------------------------------------------------------//
// Create JSON-Data //
// Webix verlangt beim upload als Returnwert einen Status //
// {status: server oder error} //
//------------------------------------------------------------------//
dcl-proc crtjson;
dcl-pi *n;
PiStmp timestamp const; // TimeStamp
end-pi;
yajl_beginobj();
yajl_addchar('status' :%trim(TbData.Status));
yajl_addchar('errmsg' :%trim(TbData.Errmsg));
yajl_addchar('filename' :%trim(TbData.FileName));
yajl_addchar('tempfile' :%trim(TbData.TempFile));
yajl_endobj();
end-proc;
//------------------------------------------------------------------//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment