Created
September 15, 2018 10:21
-
-
Save RainerRoss/999febf1644f6aa9ef175d07cfd72829 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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