From 15c057620760be20c6335bfdafede088dc4a7faf Mon Sep 17 00:00:00 2001 From: allan Date: Sat, 17 May 2025 15:06:47 +0100 Subject: [PATCH 01/12] feat: new mf_mimetype macro (and associated test) --- base/mf_mimetype.sas | 440 ++++++++++++++++++++++++++++++++ tests/base/mf_mimetype.test.sas | 16 ++ 2 files changed, 456 insertions(+) create mode 100644 base/mf_mimetype.sas create mode 100644 tests/base/mf_mimetype.test.sas diff --git a/base/mf_mimetype.sas b/base/mf_mimetype.sas new file mode 100644 index 0000000..18055e9 --- /dev/null +++ b/base/mf_mimetype.sas @@ -0,0 +1,440 @@ +/** + @file + @brief Returns a mime type from a file extension + @details Provide a file extension and get a mime type. + The mappings were derived from this source: + https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + + + + @param [in] ext The file extension (unquoted) + @return output The mime type + + @version 9.2 + @author Allan Bowe +**/ + +%macro mf_mimetype( + ext +)/*/STORE SOURCE*/ /minoperator mindelimiter=' '; + +%let ext=%lowcase(&ext); + +%if &ext in (sas txt text conf def list log) +%then %do;%str(text/plain)%end; +%else %if &ext=xlsx %then %do; +%str(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)%end; +%else %if &ext in (xls xlm xla xlc xlt xlw) +%then %do;%str(application/vnd.ms-excel)%end; +%else %if &ext=xlsm +%then %do;%str(application/vnd.ms-excel.sheet.macroenabled.12)%end; +%else %if &ext=xlsb +%then %do;%str(application/vnd.ms-excel.sheet.binary.macroenabled.12)%end; +%else %if &ext in (css csv html n3 sgml vcard) +%then %do;%str(text/&ext)%end; +%else %if &ext in (avif bmp cgm gif ief jxl ktx png sgi tiff webp) +%then %do;%str(image/&ext)%end; +%else %if &ext in (exi gxf ipfix json mbox mp21 mxf oda oxps pdf rtf sdp wasm + xml yang zip) +%then %do;%str(application/&ext)%end; +%else %if &ext in (jpeg jpg jpe) %then %do;%str(image/jpeg)%end; +%else %if &ext in (mp4 mp4v mpg4) %then %do;%str(video/mp4)%end; +%else %if &ext in (otf ttf woff woff2) %then %do;%str(font/&ext)%end; +%else %if &ext in (mpeg mpg mpe m1v m2v) +%then %do;%str(video/mpeg)%end; +%else %if &ext in (h261 h263 h264 jpm mj2 webm) +%then %do;%str(video/&ext)%end; +%else %if &ext in (f4v fli flv m4v mng smv) +%then %do;%str(video/x-&ext)%end; +%else %if &ext in (3ds cmx pcx rgb tga) +%then %do;%str(image/x-&ext)%end; +%else %if &ext in (asm nfo opml sfv) +%then %do;%str(text/x-&ext)%end; +%else %if &ext in (aac caf flac wav) +%then %do;%str(audio/x-&ext)%end; +%else %if &ext in (ts m2t m2ts mts) +%then %do;%str(video/mp2t)%end; +%else %if &ext in (pfa pfb pfm afm) +%then %do;%str(application/x-font-type1)%end; +%else %if &ext in (oga ogg spx opus) +%then %do;%str(audio/ogg)%end; +%else %if &ext in (mid midi kar rmi) +%then %do;%str(audio/midi)%end; +%else %if &ext in (onetoc onetoc2 onetmp onepkg) +%then %do;%str(application/onenote)%end; +%else %if &ext in (mxml xhvml xvml xvm) +%then %do;%str(application/xv+xml)%end; +%else %if &ext in (f for f77 f90) +%then %do;%str(text/x-fortran)%end; +%else %if &ext in (wmf wmz emf emz) +%then %do;%str(application/x-msmetafile)%end; +%else %if &ext in (exe dll com bat msi) +%then %do;%str(application/x-msdownload)%end; +%else %if &ext in (bin dms lrf mar so dist distz pkg bpk dump elc deploy) +%then %do;%str(application/octet-stream)%end; +%else %if &ext in (atom atomcat atomsvc ccxml davmount emma gml gpx inkml mads + mathml metalink mets mods omdoc pls rdf rsd rss sbml shf smil sru ssdl ssml + tei wsdl wspolicy xaml xenc xhtml xop xslt xspf yin) +%then %do;%str(application/&ext+xml)%end; +%else %if &ext in (dir dcr dxr cst cct cxt w3d fgd swa) +%then %do;%str(application/x-director)%end; +%else %if &ext in (z1 z2 z3 z4 z5 z6 z7 z8) +%then %do;%str(application/x-zmachine)%end; +%else %if &ext in (c cc cxx cpp h hh dic) +%then %do;%str(text/x-c)%end; +%else %if &ext in (mpga mp2 mp2a mp3 m2a m3a) +%then %do;%str(audio/mpeg)%end; +%else %if &ext in (t tr roff man me ms) +%then %do;%str(text/troff)%end; +%else %if &ext in (cbr cba cbt cbz cb7) +%then %do;%str(application/x-cbr)%end; +%else %if &ext in (fh fhc fh4 fh5 fh7) +%then %do;%str(image/x-freehand)%end; +%else %if &ext in (aab x32 u32 vox) +%then %do;%str(application/x-authorware-bin)%end; +%else %if &ext in (uvi uvvi uvg uvvg) +%then %do;%str(image/vnd.dece.graphic)%end; +%else %if &ext in (cdx cif cmdf cml csml xyz) +%then %do;%str(chemical/x-&ext)%end; +%else %if &ext in (aif aiff aifc) %then %do;%str(audio/x-aiff)%end; +%else %if &ext in (ma nb mb) %then %do;%str(application/mathematica)%end; +%else %if &ext in (mvb m13 m14) %then %do;%str(application/x-msmediaview)%end; +%else %if &ext in (msh mesh silo) %then %do;%str(model/mesh)%end; +%else %if &ext in (uri uris urls) %then %do;%str(text/uri-list)%end; +%else %if &ext in (mkv mk3d mks) %then %do;%str(video/x-matroska)%end; +%else %if &ext=ez %then %do;%str(application/andrew-inset)%end; +%else %if &ext=aw %then %do;%str(application/applixware)%end; +%else %if &ext=cdmia %then %do;%str(application/cdmi-capability)%end; +%else %if &ext=cdmic %then %do;%str(application/cdmi-container)%end; +%else %if &ext=cdmid %then %do;%str(application/cdmi-domain)%end; +%else %if &ext=cdmio %then %do;%str(application/cdmi-object)%end; +%else %if &ext=cdmiq %then %do;%str(application/cdmi-queue)%end; +%else %if &ext=cu %then %do;%str(application/cu-seeme)%end; +%else %if &ext=dssc %then %do;%str(application/dssc+der)%end; +%else %if &ext=xdssc %then %do;%str(application/dssc+xml)%end; +%else %if &ext=ecma %then %do;%str(application/ecmascript)%end; +%else %if &ext=epub %then %do;%str(application/epub+zip)%end; +%else %if &ext=pfr %then %do;%str(application/font-tdpfr)%end; +%else %if &ext=stk %then %do;%str(application/hyperstudio)%end; +%else %if &ext=ink %then %do;%str(application/inkml+xml)%end; +%else %if &ext=jar %then %do;%str(application/java-archive)%end; +%else %if &ext=ser %then %do;%str(application/java-serialized-object)%end; +%else %if &ext=class %then %do;%str(application/java-vm)%end; +%else %if &ext=jsonml %then %do;%str(application/jsonml+json)%end; +%else %if &ext=lostxml %then %do;%str(application/lost+xml)%end; +%else %if &ext=hqx %then %do;%str(application/mac-binhex40)%end; +%else %if &ext=cpt %then %do;%str(application/mac-compactpro)%end; +%else %if &ext=mrc %then %do;%str(application/marc)%end; +%else %if &ext=mrcx %then %do;%str(application/marcxml+xml)%end; +%else %if &ext=mscml %then %do;%str(application/mediaservercontrol+xml)%end; +%else %if &ext=meta4 %then %do;%str(application/metalink4+xml)%end; +%else %if &ext=m21 %then %do;%str(application/mp21)%end; +%else %if &ext=mp4s %then %do;%str(application/mp4)%end; +%else %if &ext=doc %then %do;%str(application/msword)%end; +%else %if &ext=dot %then %do;%str(application/msword)%end; +%else %if &ext=opf %then %do;%str(application/oebps-package+xml)%end; +%else %if &ext=ogx %then %do;%str(application/ogg)%end; +%else %if &ext=xer %then %do;%str(application/patch-ops-error+xml)%end; +%else %if &ext=pgp %then %do;%str(application/pgp-encrypted)%end; +%else %if &ext=asc %then %do;%str(application/pgp-signature)%end; +%else %if &ext=sig %then %do;%str(application/pgp-signature)%end; +%else %if &ext=prf %then %do;%str(application/pics-rules)%end; +%else %if &ext=p10 %then %do;%str(application/pkcs10)%end; +%else %if &ext=p7m %then %do;%str(application/pkcs7-mime)%end; +%else %if &ext=p7c %then %do;%str(application/pkcs7-mime)%end; +%else %if &ext=p7s %then %do;%str(application/pkcs7-signature)%end; +%else %if &ext=p8 %then %do;%str(application/pkcs8)%end; +%else %if &ext=ac %then %do;%str(application/pkix-attr-cert)%end; +%else %if &ext=cer %then %do;%str(application/pkix-cert)%end; +%else %if &ext=crl %then %do;%str(application/pkix-crl)%end; +%else %if &ext=pkipath %then %do;%str(application/pkix-pkipath)%end; +%else %if &ext=pki %then %do;%str(application/pkixcmp)%end; +%else %if &ext=cww %then %do;%str(application/prs.cww)%end; +%else %if &ext=pskcxml %then %do;%str(application/pskc+xml)%end; +%else %if &ext=rif %then %do;%str(application/reginfo+xml)%end; +%else %if &ext=rnc %then %do;%str(application/relax-ng-compact-syntax)%end; +%else %if &ext=rld %then %do;%str(application/resource-lists-diff+xml)%end; +%else %if &ext=rl %then %do;%str(application/resource-lists+xml)%end; +%else %if &ext=gbr %then %do;%str(application/rpki-ghostbusters)%end; +%else %if &ext=mft %then %do;%str(application/rpki-manifest)%end; +%else %if &ext=roa %then %do;%str(application/rpki-roa)%end; +%else %if &ext=scq %then %do;%str(application/scvp-cv-request)%end; +%else %if &ext=scs %then %do;%str(application/scvp-cv-response)%end; +%else %if &ext=spq %then %do;%str(application/scvp-vp-request)%end; +%else %if &ext=spp %then %do;%str(application/scvp-vp-response)%end; +%else %if &ext=setpay %then %do;%str(application/set-payment-initiation)%end; +%else %if &ext=setreg %then %do;%str(application/set-registration-initiation)%end; +%else %if &ext=smi %then %do;%str(application/smil+xml)%end; +%else %if &ext=rq %then %do;%str(application/sparql-query)%end; +%else %if &ext=srx %then %do;%str(application/sparql-results+xml)%end; +%else %if &ext=gram %then %do;%str(application/srgs)%end; +%else %if &ext=grxml %then %do;%str(application/srgs+xml)%end; +%else %if &ext=teicorpus %then %do;%str(application/tei+xml)%end; +%else %if &ext=tfi %then %do;%str(application/thraud+xml)%end; +%else %if &ext=tsd %then %do;%str(application/timestamped-data)%end; +%else %if &ext=vxml %then %do;%str(application/voicexml+xml)%end; +%else %if &ext=wgt %then %do;%str(application/widget)%end; +%else %if &ext=hlp %then %do;%str(application/winhlp)%end; +%else %if &ext=7z %then %do;%str(application/x-7z-compressed)%end; +%else %if &ext=abw %then %do;%str(application/x-abiword)%end; +%else %if &ext=ace %then %do;%str(application/x-ace-compressed)%end; +%else %if &ext=dmg %then %do;%str(application/x-apple-diskimage)%end; +%else %if &ext=aam %then %do;%str(application/x-authorware-map)%end; +%else %if &ext=aas %then %do;%str(application/x-authorware-seg)%end; +%else %if &ext=bcpio %then %do;%str(application/x-bcpio)%end; +%else %if &ext=torrent %then %do;%str(application/x-bittorrent)%end; +%else %if &ext=blb %then %do;%str(application/x-blorb)%end; +%else %if &ext=blorb %then %do;%str(application/x-blorb)%end; +%else %if &ext=bz %then %do;%str(application/x-bzip)%end; +%else %if &ext=bz2 %then %do;%str(application/x-bzip2)%end; +%else %if &ext=boz %then %do;%str(application/x-bzip2)%end; +%else %if &ext=vcd %then %do;%str(application/x-cdlink)%end; +%else %if &ext=cfs %then %do;%str(application/x-cfs-compressed)%end; +%else %if &ext=chat %then %do;%str(application/x-chat)%end; +%else %if &ext=pgn %then %do;%str(application/x-chess-pgn)%end; +%else %if &ext=nsc %then %do;%str(application/x-conference)%end; +%else %if &ext=cpio %then %do;%str(application/x-cpio)%end; +%else %if &ext=csh %then %do;%str(application/x-csh)%end; +%else %if &ext=deb %then %do;%str(application/x-debian-package)%end; +%else %if &ext=udeb %then %do;%str(application/x-debian-package)%end; +%else %if &ext=dgc %then %do;%str(application/x-dgc-compressed)%end; +%else %if &ext=wad %then %do;%str(application/x-doom)%end; +%else %if &ext=ncx %then %do;%str(application/x-dtbncx+xml)%end; +%else %if &ext=dtb %then %do;%str(application/x-dtbook+xml)%end; +%else %if &ext=res %then %do;%str(application/x-dtbresource+xml)%end; +%else %if &ext=dvi %then %do;%str(application/x-dvi)%end; +%else %if &ext=evy %then %do;%str(application/x-envoy)%end; +%else %if &ext=eva %then %do;%str(application/x-eva)%end; +%else %if &ext=bdf %then %do;%str(application/x-font-bdf)%end; +%else %if &ext=gsf %then %do;%str(application/x-font-ghostscript)%end; +%else %if &ext=psf %then %do;%str(application/x-font-linux-psf)%end; +%else %if &ext=pcf %then %do;%str(application/x-font-pcf)%end; +%else %if &ext=snf %then %do;%str(application/x-font-snf)%end; +%else %if &ext=arc %then %do;%str(application/x-freearc)%end; +%else %if &ext=spl %then %do;%str(application/x-futuresplash)%end; +%else %if &ext=gca %then %do;%str(application/x-gca-compressed)%end; +%else %if &ext=ulx %then %do;%str(application/x-glulx)%end; +%else %if &ext=gnumeric %then %do;%str(application/x-gnumeric)%end; +%else %if &ext=gramps %then %do;%str(application/x-gramps-xml)%end; +%else %if &ext=gtar %then %do;%str(application/x-gtar)%end; +%else %if &ext=hdf %then %do;%str(application/x-hdf)%end; +%else %if &ext=install %then %do;%str(application/x-install-instructions)%end; +%else %if &ext=iso %then %do;%str(application/x-iso9660-image)%end; +%else %if &ext=jnlp %then %do;%str(application/x-java-jnlp-file)%end; +%else %if &ext=latex %then %do;%str(application/x-latex)%end; +%else %if &ext=lzh %then %do;%str(application/x-lzh-compressed)%end; +%else %if &ext=lha %then %do;%str(application/x-lzh-compressed)%end; +%else %if &ext=mie %then %do;%str(application/x-mie)%end; +%else %if &ext=prc %then %do;%str(application/x-mobipocket-ebook)%end; +%else %if &ext=mobi %then %do;%str(application/x-mobipocket-ebook)%end; +%else %if &ext=application %then %do;%str(application/x-ms-application)%end; +%else %if &ext=lnk %then %do;%str(application/x-ms-shortcut)%end; +%else %if &ext=wmd %then %do;%str(application/x-ms-wmd)%end; +%else %if &ext=wmz %then %do;%str(application/x-ms-wmz)%end; +%else %if &ext=xbap %then %do;%str(application/x-ms-xbap)%end; +%else %if &ext=mdb %then %do;%str(application/x-msaccess)%end; +%else %if &ext=obd %then %do;%str(application/x-msbinder)%end; +%else %if &ext=crd %then %do;%str(application/x-mscardfile)%end; +%else %if &ext=clp %then %do;%str(application/x-msclip)%end; +%else %if &ext=mny %then %do;%str(application/x-msmoney)%end; +%else %if &ext=pub %then %do;%str(application/x-mspublisher)%end; +%else %if &ext=scd %then %do;%str(application/x-msschedule)%end; +%else %if &ext=trm %then %do;%str(application/x-msterminal)%end; +%else %if &ext=wri %then %do;%str(application/x-mswrite)%end; +%else %if &ext=nc %then %do;%str(application/x-netcdf)%end; +%else %if &ext=cdf %then %do;%str(application/x-netcdf)%end; +%else %if &ext=nzb %then %do;%str(application/x-nzb)%end; +%else %if &ext=p12 %then %do;%str(application/x-pkcs12)%end; +%else %if &ext=pfx %then %do;%str(application/x-pkcs12)%end; +%else %if &ext=p7b %then %do;%str(application/x-pkcs7-certificates)%end; +%else %if &ext=spc %then %do;%str(application/x-pkcs7-certificates)%end; +%else %if &ext=p7r %then %do;%str(application/x-pkcs7-certreqresp)%end; +%else %if &ext=rar %then %do;%str(application/x-rar-compressed)%end; +%else %if &ext=ris %then %do;%str(application/x-research-info-systems)%end; +%else %if &ext=sh %then %do;%str(application/x-sh)%end; +%else %if &ext=shar %then %do;%str(application/x-shar)%end; +%else %if &ext=swf %then %do;%str(application/x-shockwave-flash)%end; +%else %if &ext=xap %then %do;%str(application/x-silverlight-app)%end; +%else %if &ext=sql %then %do;%str(application/x-sql)%end; +%else %if &ext=sit %then %do;%str(application/x-stuffit)%end; +%else %if &ext=sitx %then %do;%str(application/x-stuffitx)%end; +%else %if &ext=srt %then %do;%str(application/x-subrip)%end; +%else %if &ext=sv4cpio %then %do;%str(application/x-sv4cpio)%end; +%else %if &ext=sv4crc %then %do;%str(application/x-sv4crc)%end; +%else %if &ext=t3 %then %do;%str(application/x-t3vm-image)%end; +%else %if &ext=gam %then %do;%str(application/x-tads)%end; +%else %if &ext=tar %then %do;%str(application/x-tar)%end; +%else %if &ext=tcl %then %do;%str(application/x-tcl)%end; +%else %if &ext=tex %then %do;%str(application/x-tex)%end; +%else %if &ext=tfm %then %do;%str(application/x-tex-tfm)%end; +%else %if &ext=texinfo %then %do;%str(application/x-texinfo)%end; +%else %if &ext=texi %then %do;%str(application/x-texinfo)%end; +%else %if &ext=obj %then %do;%str(application/x-tgif)%end; +%else %if &ext=ustar %then %do;%str(application/x-ustar)%end; +%else %if &ext=src %then %do;%str(application/x-wais-source)%end; +%else %if &ext=der %then %do;%str(application/x-x509-ca-cert)%end; +%else %if &ext=crt %then %do;%str(application/x-x509-ca-cert)%end; +%else %if &ext=fig %then %do;%str(application/x-xfig)%end; +%else %if &ext=xlf %then %do;%str(application/x-xliff+xml)%end; +%else %if &ext=xpi %then %do;%str(application/x-xpinstall)%end; +%else %if &ext=xz %then %do;%str(application/x-xz)%end; +%else %if &ext=xdf %then %do;%str(application/xcap-diff+xml)%end; +%else %if &ext=xht %then %do;%str(application/xhtml+xml)%end; +%else %if &ext=xsl %then %do;%str(application/xml)%end; +%else %if &ext=dtd %then %do;%str(application/xml-dtd)%end; +%else %if &ext=xpl %then %do;%str(application/xproc+xml)%end; +%else %if &ext=adp %then %do;%str(audio/adpcm)%end; +%else %if &ext=au %then %do;%str(audio/basic)%end; +%else %if &ext=snd %then %do;%str(audio/basic)%end; +%else %if &ext=m4a %then %do;%str(audio/mp4)%end; +%else %if &ext=mp4a %then %do;%str(audio/mp4)%end; +%else %if &ext=s3m %then %do;%str(audio/s3m)%end; +%else %if &ext=sil %then %do;%str(audio/silk)%end; +%else %if &ext=uva %then %do;%str(audio/vnd.dece.audio)%end; +%else %if &ext=uvva %then %do;%str(audio/vnd.dece.audio)%end; +%else %if &ext=eol %then %do;%str(audio/vnd.digital-winds)%end; +%else %if &ext=dra %then %do;%str(audio/vnd.dra)%end; +%else %if &ext=dts %then %do;%str(audio/vnd.dts)%end; +%else %if &ext=dtshd %then %do;%str(audio/vnd.dts.hd)%end; +%else %if &ext=lvp %then %do;%str(audio/vnd.lucent.voice)%end; +%else %if &ext=pya %then %do;%str(audio/vnd.ms-playready.media.pya)%end; +%else %if &ext=ecelp4800 %then %do;%str(audio/vnd.nuera.ecelp4800)%end; +%else %if &ext=ecelp7470 %then %do;%str(audio/vnd.nuera.ecelp7470)%end; +%else %if &ext=ecelp9600 %then %do;%str(audio/vnd.nuera.ecelp9600)%end; +%else %if &ext=rip %then %do;%str(audio/vnd.rip)%end; +%else %if &ext=weba %then %do;%str(audio/webm)%end; +%else %if &ext=mka %then %do;%str(audio/x-matroska)%end; +%else %if &ext=m3u %then %do;%str(audio/x-mpegurl)%end; +%else %if &ext=wax %then %do;%str(audio/x-ms-wax)%end; +%else %if &ext=wma %then %do;%str(audio/x-ms-wma)%end; +%else %if &ext=ra %then %do;%str(audio/x-pn-realaudio)%end; +%else %if &ext=ram %then %do;%str(audio/x-pn-realaudio)%end; +%else %if &ext=rmp %then %do;%str(audio/x-pn-realaudio-plugin)%end; +%else %if &ext=xm %then %do;%str(audio/xm)%end; +%else %if &ext=ttc %then %do;%str(font/collection)%end; +%else %if &ext=g3 %then %do;%str(image/g3fax)%end; +%else %if &ext=btif %then %do;%str(image/prs.btif)%end; +%else %if &ext=svg %then %do;%str(image/svg+xml)%end; +%else %if &ext=svgz %then %do;%str(image/svg+xml)%end; +%else %if &ext=tif %then %do;%str(image/tiff)%end; +%else %if &ext=psd %then %do;%str(image/vnd.adobe.photoshop)%end; +%else %if &ext=djv %then %do;%str(image/vnd.djvu)%end; +%else %if &ext=djvu %then %do;%str(image/vnd.djvu)%end; +%else %if &ext=sub %then %do;%str(image/vnd.dvb.subtitle)%end; +%else %if &ext=dwg %then %do;%str(image/vnd.dwg)%end; +%else %if &ext=dxf %then %do;%str(image/vnd.dxf)%end; +%else %if &ext=fbs %then %do;%str(image/vnd.fastbidsheet)%end; +%else %if &ext=fpx %then %do;%str(image/vnd.fpx)%end; +%else %if &ext=fst %then %do;%str(image/vnd.fst)%end; +%else %if &ext=mmr %then %do;%str(image/vnd.fujixerox.edmics-mmr)%end; +%else %if &ext=rlc %then %do;%str(image/vnd.fujixerox.edmics-rlc)%end; +%else %if &ext=mdi %then %do;%str(image/vnd.ms-modi)%end; +%else %if &ext=wdp %then %do;%str(image/vnd.ms-photo)%end; +%else %if &ext=npx %then %do;%str(image/vnd.net-fpx)%end; +%else %if &ext=wbmp %then %do;%str(image/vnd.wap.wbmp)%end; +%else %if &ext=xif %then %do;%str(image/vnd.xiff)%end; +%else %if &ext=ras %then %do;%str(image/x-cmu-raster)%end; +%else %if &ext=ico %then %do;%str(image/x-icon)%end; +%else %if &ext=sid %then %do;%str(image/x-mrsid-image)%end; +%else %if &ext=pct %then %do;%str(image/x-pict)%end; +%else %if &ext=pic %then %do;%str(image/x-pict)%end; +%else %if &ext=pnm %then %do;%str(image/x-portable-anymap)%end; +%else %if &ext=pbm %then %do;%str(image/x-portable-bitmap)%end; +%else %if &ext=pgm %then %do;%str(image/x-portable-graymap)%end; +%else %if &ext=ppm %then %do;%str(image/x-portable-pixmap)%end; +%else %if &ext=xbm %then %do;%str(image/x-xbitmap)%end; +%else %if &ext=xpm %then %do;%str(image/x-xpixmap)%end; +%else %if &ext=xwd %then %do;%str(image/x-xwindowdump)%end; +%else %if &ext=eml %then %do;%str(message/rfc822)%end; +%else %if &ext=mime %then %do;%str(message/rfc822)%end; +%else %if &ext=iges %then %do;%str(model/iges)%end; +%else %if &ext=igs %then %do;%str(model/iges)%end; +%else %if &ext=dae %then %do;%str(model/vnd.collada+xml)%end; +%else %if &ext=dwf %then %do;%str(model/vnd.dwf)%end; +%else %if &ext=gdl %then %do;%str(model/vnd.gdl)%end; +%else %if &ext=gtw %then %do;%str(model/vnd.gtw)%end; +%else %if &ext=vtu %then %do;%str(model/vnd.vtu)%end; +%else %if &ext=vrml %then %do;%str(model/vrml)%end; +%else %if &ext=wrl %then %do;%str(model/vrml)%end; +%else %if &ext=x3db %then %do;%str(model/x3d+binary)%end; +%else %if &ext=x3dbz %then %do;%str(model/x3d+binary)%end; +%else %if &ext=x3dv %then %do;%str(model/x3d+vrml)%end; +%else %if &ext=x3dvz %then %do;%str(model/x3d+vrml)%end; +%else %if &ext=x3d %then %do;%str(model/x3d+xml)%end; +%else %if &ext=x3dz %then %do;%str(model/x3d+xml)%end; +%else %if &ext=appcache %then %do;%str(text/cache-manifest)%end; +%else %if &ext=ics %then %do;%str(text/calendar)%end; +%else %if &ext=ifb %then %do;%str(text/calendar)%end; +%else %if &ext=htm %then %do;%str(text/html)%end; +%else %if &ext=js %then %do;%str(text/javascript)%end; +%else %if &ext=mjs %then %do;%str(text/javascript)%end; +%else %if &ext=dsc %then %do;%str(text/prs.lines.tag)%end; +%else %if &ext=rtx %then %do;%str(text/richtext)%end; +%else %if &ext=sgm %then %do;%str(text/sgml)%end; +%else %if &ext=tsv %then %do;%str(text/tab-separated-values)%end; +%else %if &ext=ttl %then %do;%str(text/turtle)%end; +%else %if &ext=curl %then %do;%str(text/vnd.curl)%end; +%else %if &ext=dcurl %then %do;%str(text/vnd.curl.dcurl)%end; +%else %if &ext=mcurl %then %do;%str(text/vnd.curl.mcurl)%end; +%else %if &ext=scurl %then %do;%str(text/vnd.curl.scurl)%end; +%else %if &ext=sub %then %do;%str(text/vnd.dvb.subtitle)%end; +%else %if &ext=fly %then %do;%str(text/vnd.fly)%end; +%else %if &ext=flx %then %do;%str(text/vnd.fmi.flexstor)%end; +%else %if &ext=gv %then %do;%str(text/vnd.graphviz)%end; +%else %if &ext=3dml %then %do;%str(text/vnd.in3d.3dml)%end; +%else %if &ext=spot %then %do;%str(text/vnd.in3d.spot)%end; +%else %if &ext=jad %then %do;%str(text/vnd.sun.j2me.app-descriptor)%end; +%else %if &ext=wml %then %do;%str(text/vnd.wap.wml)%end; +%else %if &ext=wmls %then %do;%str(text/vnd.wap.wmlscript)%end; +%else %if &ext=s %then %do;%str(text/x-asm)%end; +%else %if &ext=java %then %do;%str(text/x-java-source)%end; +%else %if &ext=p %then %do;%str(text/x-pascal)%end; +%else %if &ext=pas %then %do;%str(text/x-pascal)%end; +%else %if &ext=etx %then %do;%str(text/x-setext)%end; +%else %if &ext=uu %then %do;%str(text/x-uuencode)%end; +%else %if &ext=vcs %then %do;%str(text/x-vcalendar)%end; +%else %if &ext=vcf %then %do;%str(text/x-vcard)%end; +%else %if &ext=3gp %then %do;%str(video/3gpp)%end; +%else %if &ext=3g2 %then %do;%str(video/3gpp2)%end; +%else %if &ext=jpgv %then %do;%str(video/jpeg)%end; +%else %if &ext=jpgm %then %do;%str(video/jpm)%end; +%else %if &ext=mjp2 %then %do;%str(video/mj2)%end; +%else %if &ext=ogv %then %do;%str(video/ogg)%end; +%else %if &ext=mov %then %do;%str(video/quicktime)%end; +%else %if &ext=qt %then %do;%str(video/quicktime)%end; +%else %if &ext=uvh %then %do;%str(video/vnd.dece.hd)%end; +%else %if &ext=uvvh %then %do;%str(video/vnd.dece.hd)%end; +%else %if &ext=uvm %then %do;%str(video/vnd.dece.mobile)%end; +%else %if &ext=uvvm %then %do;%str(video/vnd.dece.mobile)%end; +%else %if &ext=uvp %then %do;%str(video/vnd.dece.pd)%end; +%else %if &ext=uvvp %then %do;%str(video/vnd.dece.pd)%end; +%else %if &ext=uvs %then %do;%str(video/vnd.dece.sd)%end; +%else %if &ext=uvvs %then %do;%str(video/vnd.dece.sd)%end; +%else %if &ext=uvv %then %do;%str(video/vnd.dece.video)%end; +%else %if &ext=uvvv %then %do;%str(video/vnd.dece.video)%end; +%else %if &ext=dvb %then %do;%str(video/vnd.dvb.file)%end; +%else %if &ext=fvt %then %do;%str(video/vnd.fvt)%end; +%else %if &ext=m4u %then %do;%str(video/vnd.mpegurl)%end; +%else %if &ext=mxu %then %do;%str(video/vnd.mpegurl)%end; +%else %if &ext=pyv %then %do;%str(video/vnd.ms-playready.media.pyv)%end; +%else %if &ext=uvu %then %do;%str(video/vnd.uvvu.mp4)%end; +%else %if &ext=uvvu %then %do;%str(video/vnd.uvvu.mp4)%end; +%else %if &ext=viv %then %do;%str(video/vnd.vivo)%end; +%else %if &ext=asf %then %do;%str(video/x-ms-asf)%end; +%else %if &ext=asx %then %do;%str(video/x-ms-asf)%end; +%else %if &ext=vob %then %do;%str(video/x-ms-vob)%end; +%else %if &ext=wm %then %do;%str(video/x-ms-wm)%end; +%else %if &ext=wmv %then %do;%str(video/x-ms-wmv)%end; +%else %if &ext=wmx %then %do;%str(video/x-ms-wmx)%end; +%else %if &ext=wvx %then %do;%str(video/x-ms-wvx)%end; +%else %if &ext=avi %then %do;%str(video/x-msvideo)%end; +%else %if &ext=movie %then %do;%str(video/x-sgi-movie)%end; +%else %if &ext=ice %then %do;%str(x-conference/x-cooltalk)%end; +%else %if "&ext"="in" %then %do;%str(text/plain)%end; +%else %do; + %put %str(WARN)ING: extension &ext not found!; + %put %str(WARN)ING- Returning text/plain.; + %str(text/plain) +%end; + +%mend mf_mimetype; \ No newline at end of file diff --git a/tests/base/mf_mimetype.test.sas b/tests/base/mf_mimetype.test.sas new file mode 100644 index 0000000..fc5ded3 --- /dev/null +++ b/tests/base/mf_mimetype.test.sas @@ -0,0 +1,16 @@ +/** + @file + @brief Testing mf_mimetype macro + +

SAS Macros

+ @li mf_mimetype.sas + @li mp_assert.sas + +**/ + + +%mp_assert( + iftrue=("%mf_mimetype(XLS)"="application/vnd.ms-excel", + desc=Checking correct value +) + From 51042cbd47e0a3c943a97b6fbacee3111fdd193e Mon Sep 17 00:00:00 2001 From: github-actions Date: Sat, 17 May 2025 14:07:20 +0000 Subject: [PATCH 02/12] chore: updating all.sas --- all.sas | 439 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) diff --git a/all.sas b/all.sas index a77f33a..10aeaf5 100644 --- a/all.sas +++ b/all.sas @@ -1844,6 +1844,445 @@ Usage: %mend mf_loc; /** + @file + @brief Returns a mime type from a file extension + @details Provide a file extension and get a mime type. + The mappings were derived from this source: + https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + + + + @param [in] ext The file extension (unquoted) + @return output The mime type + + @version 9.2 + @author Allan Bowe +**/ + +%macro mf_mimetype( + ext +)/*/STORE SOURCE*/ /minoperator mindelimiter=' '; + +%let ext=%lowcase(&ext); + +%if &ext in (sas txt text conf def list log) +%then %do;%str(text/plain)%end; +%else %if &ext=xlsx %then %do; +%str(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)%end; +%else %if &ext in (xls xlm xla xlc xlt xlw) +%then %do;%str(application/vnd.ms-excel)%end; +%else %if &ext=xlsm +%then %do;%str(application/vnd.ms-excel.sheet.macroenabled.12)%end; +%else %if &ext=xlsb +%then %do;%str(application/vnd.ms-excel.sheet.binary.macroenabled.12)%end; +%else %if &ext in (css csv html n3 sgml vcard) +%then %do;%str(text/&ext)%end; +%else %if &ext in (avif bmp cgm gif ief jxl ktx png sgi tiff webp) +%then %do;%str(image/&ext)%end; +%else %if &ext in (exi gxf ipfix json mbox mp21 mxf oda oxps pdf rtf sdp wasm + xml yang zip) +%then %do;%str(application/&ext)%end; +%else %if &ext in (jpeg jpg jpe) %then %do;%str(image/jpeg)%end; +%else %if &ext in (mp4 mp4v mpg4) %then %do;%str(video/mp4)%end; +%else %if &ext in (otf ttf woff woff2) %then %do;%str(font/&ext)%end; +%else %if &ext in (mpeg mpg mpe m1v m2v) +%then %do;%str(video/mpeg)%end; +%else %if &ext in (h261 h263 h264 jpm mj2 webm) +%then %do;%str(video/&ext)%end; +%else %if &ext in (f4v fli flv m4v mng smv) +%then %do;%str(video/x-&ext)%end; +%else %if &ext in (3ds cmx pcx rgb tga) +%then %do;%str(image/x-&ext)%end; +%else %if &ext in (asm nfo opml sfv) +%then %do;%str(text/x-&ext)%end; +%else %if &ext in (aac caf flac wav) +%then %do;%str(audio/x-&ext)%end; +%else %if &ext in (ts m2t m2ts mts) +%then %do;%str(video/mp2t)%end; +%else %if &ext in (pfa pfb pfm afm) +%then %do;%str(application/x-font-type1)%end; +%else %if &ext in (oga ogg spx opus) +%then %do;%str(audio/ogg)%end; +%else %if &ext in (mid midi kar rmi) +%then %do;%str(audio/midi)%end; +%else %if &ext in (onetoc onetoc2 onetmp onepkg) +%then %do;%str(application/onenote)%end; +%else %if &ext in (mxml xhvml xvml xvm) +%then %do;%str(application/xv+xml)%end; +%else %if &ext in (f for f77 f90) +%then %do;%str(text/x-fortran)%end; +%else %if &ext in (wmf wmz emf emz) +%then %do;%str(application/x-msmetafile)%end; +%else %if &ext in (exe dll com bat msi) +%then %do;%str(application/x-msdownload)%end; +%else %if &ext in (bin dms lrf mar so dist distz pkg bpk dump elc deploy) +%then %do;%str(application/octet-stream)%end; +%else %if &ext in (atom atomcat atomsvc ccxml davmount emma gml gpx inkml mads + mathml metalink mets mods omdoc pls rdf rsd rss sbml shf smil sru ssdl ssml + tei wsdl wspolicy xaml xenc xhtml xop xslt xspf yin) +%then %do;%str(application/&ext+xml)%end; +%else %if &ext in (dir dcr dxr cst cct cxt w3d fgd swa) +%then %do;%str(application/x-director)%end; +%else %if &ext in (z1 z2 z3 z4 z5 z6 z7 z8) +%then %do;%str(application/x-zmachine)%end; +%else %if &ext in (c cc cxx cpp h hh dic) +%then %do;%str(text/x-c)%end; +%else %if &ext in (mpga mp2 mp2a mp3 m2a m3a) +%then %do;%str(audio/mpeg)%end; +%else %if &ext in (t tr roff man me ms) +%then %do;%str(text/troff)%end; +%else %if &ext in (cbr cba cbt cbz cb7) +%then %do;%str(application/x-cbr)%end; +%else %if &ext in (fh fhc fh4 fh5 fh7) +%then %do;%str(image/x-freehand)%end; +%else %if &ext in (aab x32 u32 vox) +%then %do;%str(application/x-authorware-bin)%end; +%else %if &ext in (uvi uvvi uvg uvvg) +%then %do;%str(image/vnd.dece.graphic)%end; +%else %if &ext in (cdx cif cmdf cml csml xyz) +%then %do;%str(chemical/x-&ext)%end; +%else %if &ext in (aif aiff aifc) %then %do;%str(audio/x-aiff)%end; +%else %if &ext in (ma nb mb) %then %do;%str(application/mathematica)%end; +%else %if &ext in (mvb m13 m14) %then %do;%str(application/x-msmediaview)%end; +%else %if &ext in (msh mesh silo) %then %do;%str(model/mesh)%end; +%else %if &ext in (uri uris urls) %then %do;%str(text/uri-list)%end; +%else %if &ext in (mkv mk3d mks) %then %do;%str(video/x-matroska)%end; +%else %if &ext=ez %then %do;%str(application/andrew-inset)%end; +%else %if &ext=aw %then %do;%str(application/applixware)%end; +%else %if &ext=cdmia %then %do;%str(application/cdmi-capability)%end; +%else %if &ext=cdmic %then %do;%str(application/cdmi-container)%end; +%else %if &ext=cdmid %then %do;%str(application/cdmi-domain)%end; +%else %if &ext=cdmio %then %do;%str(application/cdmi-object)%end; +%else %if &ext=cdmiq %then %do;%str(application/cdmi-queue)%end; +%else %if &ext=cu %then %do;%str(application/cu-seeme)%end; +%else %if &ext=dssc %then %do;%str(application/dssc+der)%end; +%else %if &ext=xdssc %then %do;%str(application/dssc+xml)%end; +%else %if &ext=ecma %then %do;%str(application/ecmascript)%end; +%else %if &ext=epub %then %do;%str(application/epub+zip)%end; +%else %if &ext=pfr %then %do;%str(application/font-tdpfr)%end; +%else %if &ext=stk %then %do;%str(application/hyperstudio)%end; +%else %if &ext=ink %then %do;%str(application/inkml+xml)%end; +%else %if &ext=jar %then %do;%str(application/java-archive)%end; +%else %if &ext=ser %then %do;%str(application/java-serialized-object)%end; +%else %if &ext=class %then %do;%str(application/java-vm)%end; +%else %if &ext=jsonml %then %do;%str(application/jsonml+json)%end; +%else %if &ext=lostxml %then %do;%str(application/lost+xml)%end; +%else %if &ext=hqx %then %do;%str(application/mac-binhex40)%end; +%else %if &ext=cpt %then %do;%str(application/mac-compactpro)%end; +%else %if &ext=mrc %then %do;%str(application/marc)%end; +%else %if &ext=mrcx %then %do;%str(application/marcxml+xml)%end; +%else %if &ext=mscml %then %do;%str(application/mediaservercontrol+xml)%end; +%else %if &ext=meta4 %then %do;%str(application/metalink4+xml)%end; +%else %if &ext=m21 %then %do;%str(application/mp21)%end; +%else %if &ext=mp4s %then %do;%str(application/mp4)%end; +%else %if &ext=doc %then %do;%str(application/msword)%end; +%else %if &ext=dot %then %do;%str(application/msword)%end; +%else %if &ext=opf %then %do;%str(application/oebps-package+xml)%end; +%else %if &ext=ogx %then %do;%str(application/ogg)%end; +%else %if &ext=xer %then %do;%str(application/patch-ops-error+xml)%end; +%else %if &ext=pgp %then %do;%str(application/pgp-encrypted)%end; +%else %if &ext=asc %then %do;%str(application/pgp-signature)%end; +%else %if &ext=sig %then %do;%str(application/pgp-signature)%end; +%else %if &ext=prf %then %do;%str(application/pics-rules)%end; +%else %if &ext=p10 %then %do;%str(application/pkcs10)%end; +%else %if &ext=p7m %then %do;%str(application/pkcs7-mime)%end; +%else %if &ext=p7c %then %do;%str(application/pkcs7-mime)%end; +%else %if &ext=p7s %then %do;%str(application/pkcs7-signature)%end; +%else %if &ext=p8 %then %do;%str(application/pkcs8)%end; +%else %if &ext=ac %then %do;%str(application/pkix-attr-cert)%end; +%else %if &ext=cer %then %do;%str(application/pkix-cert)%end; +%else %if &ext=crl %then %do;%str(application/pkix-crl)%end; +%else %if &ext=pkipath %then %do;%str(application/pkix-pkipath)%end; +%else %if &ext=pki %then %do;%str(application/pkixcmp)%end; +%else %if &ext=cww %then %do;%str(application/prs.cww)%end; +%else %if &ext=pskcxml %then %do;%str(application/pskc+xml)%end; +%else %if &ext=rif %then %do;%str(application/reginfo+xml)%end; +%else %if &ext=rnc %then %do;%str(application/relax-ng-compact-syntax)%end; +%else %if &ext=rld %then %do;%str(application/resource-lists-diff+xml)%end; +%else %if &ext=rl %then %do;%str(application/resource-lists+xml)%end; +%else %if &ext=gbr %then %do;%str(application/rpki-ghostbusters)%end; +%else %if &ext=mft %then %do;%str(application/rpki-manifest)%end; +%else %if &ext=roa %then %do;%str(application/rpki-roa)%end; +%else %if &ext=scq %then %do;%str(application/scvp-cv-request)%end; +%else %if &ext=scs %then %do;%str(application/scvp-cv-response)%end; +%else %if &ext=spq %then %do;%str(application/scvp-vp-request)%end; +%else %if &ext=spp %then %do;%str(application/scvp-vp-response)%end; +%else %if &ext=setpay %then %do;%str(application/set-payment-initiation)%end; +%else %if &ext=setreg %then %do;%str(application/set-registration-initiation)%end; +%else %if &ext=smi %then %do;%str(application/smil+xml)%end; +%else %if &ext=rq %then %do;%str(application/sparql-query)%end; +%else %if &ext=srx %then %do;%str(application/sparql-results+xml)%end; +%else %if &ext=gram %then %do;%str(application/srgs)%end; +%else %if &ext=grxml %then %do;%str(application/srgs+xml)%end; +%else %if &ext=teicorpus %then %do;%str(application/tei+xml)%end; +%else %if &ext=tfi %then %do;%str(application/thraud+xml)%end; +%else %if &ext=tsd %then %do;%str(application/timestamped-data)%end; +%else %if &ext=vxml %then %do;%str(application/voicexml+xml)%end; +%else %if &ext=wgt %then %do;%str(application/widget)%end; +%else %if &ext=hlp %then %do;%str(application/winhlp)%end; +%else %if &ext=7z %then %do;%str(application/x-7z-compressed)%end; +%else %if &ext=abw %then %do;%str(application/x-abiword)%end; +%else %if &ext=ace %then %do;%str(application/x-ace-compressed)%end; +%else %if &ext=dmg %then %do;%str(application/x-apple-diskimage)%end; +%else %if &ext=aam %then %do;%str(application/x-authorware-map)%end; +%else %if &ext=aas %then %do;%str(application/x-authorware-seg)%end; +%else %if &ext=bcpio %then %do;%str(application/x-bcpio)%end; +%else %if &ext=torrent %then %do;%str(application/x-bittorrent)%end; +%else %if &ext=blb %then %do;%str(application/x-blorb)%end; +%else %if &ext=blorb %then %do;%str(application/x-blorb)%end; +%else %if &ext=bz %then %do;%str(application/x-bzip)%end; +%else %if &ext=bz2 %then %do;%str(application/x-bzip2)%end; +%else %if &ext=boz %then %do;%str(application/x-bzip2)%end; +%else %if &ext=vcd %then %do;%str(application/x-cdlink)%end; +%else %if &ext=cfs %then %do;%str(application/x-cfs-compressed)%end; +%else %if &ext=chat %then %do;%str(application/x-chat)%end; +%else %if &ext=pgn %then %do;%str(application/x-chess-pgn)%end; +%else %if &ext=nsc %then %do;%str(application/x-conference)%end; +%else %if &ext=cpio %then %do;%str(application/x-cpio)%end; +%else %if &ext=csh %then %do;%str(application/x-csh)%end; +%else %if &ext=deb %then %do;%str(application/x-debian-package)%end; +%else %if &ext=udeb %then %do;%str(application/x-debian-package)%end; +%else %if &ext=dgc %then %do;%str(application/x-dgc-compressed)%end; +%else %if &ext=wad %then %do;%str(application/x-doom)%end; +%else %if &ext=ncx %then %do;%str(application/x-dtbncx+xml)%end; +%else %if &ext=dtb %then %do;%str(application/x-dtbook+xml)%end; +%else %if &ext=res %then %do;%str(application/x-dtbresource+xml)%end; +%else %if &ext=dvi %then %do;%str(application/x-dvi)%end; +%else %if &ext=evy %then %do;%str(application/x-envoy)%end; +%else %if &ext=eva %then %do;%str(application/x-eva)%end; +%else %if &ext=bdf %then %do;%str(application/x-font-bdf)%end; +%else %if &ext=gsf %then %do;%str(application/x-font-ghostscript)%end; +%else %if &ext=psf %then %do;%str(application/x-font-linux-psf)%end; +%else %if &ext=pcf %then %do;%str(application/x-font-pcf)%end; +%else %if &ext=snf %then %do;%str(application/x-font-snf)%end; +%else %if &ext=arc %then %do;%str(application/x-freearc)%end; +%else %if &ext=spl %then %do;%str(application/x-futuresplash)%end; +%else %if &ext=gca %then %do;%str(application/x-gca-compressed)%end; +%else %if &ext=ulx %then %do;%str(application/x-glulx)%end; +%else %if &ext=gnumeric %then %do;%str(application/x-gnumeric)%end; +%else %if &ext=gramps %then %do;%str(application/x-gramps-xml)%end; +%else %if &ext=gtar %then %do;%str(application/x-gtar)%end; +%else %if &ext=hdf %then %do;%str(application/x-hdf)%end; +%else %if &ext=install %then %do;%str(application/x-install-instructions)%end; +%else %if &ext=iso %then %do;%str(application/x-iso9660-image)%end; +%else %if &ext=jnlp %then %do;%str(application/x-java-jnlp-file)%end; +%else %if &ext=latex %then %do;%str(application/x-latex)%end; +%else %if &ext=lzh %then %do;%str(application/x-lzh-compressed)%end; +%else %if &ext=lha %then %do;%str(application/x-lzh-compressed)%end; +%else %if &ext=mie %then %do;%str(application/x-mie)%end; +%else %if &ext=prc %then %do;%str(application/x-mobipocket-ebook)%end; +%else %if &ext=mobi %then %do;%str(application/x-mobipocket-ebook)%end; +%else %if &ext=application %then %do;%str(application/x-ms-application)%end; +%else %if &ext=lnk %then %do;%str(application/x-ms-shortcut)%end; +%else %if &ext=wmd %then %do;%str(application/x-ms-wmd)%end; +%else %if &ext=wmz %then %do;%str(application/x-ms-wmz)%end; +%else %if &ext=xbap %then %do;%str(application/x-ms-xbap)%end; +%else %if &ext=mdb %then %do;%str(application/x-msaccess)%end; +%else %if &ext=obd %then %do;%str(application/x-msbinder)%end; +%else %if &ext=crd %then %do;%str(application/x-mscardfile)%end; +%else %if &ext=clp %then %do;%str(application/x-msclip)%end; +%else %if &ext=mny %then %do;%str(application/x-msmoney)%end; +%else %if &ext=pub %then %do;%str(application/x-mspublisher)%end; +%else %if &ext=scd %then %do;%str(application/x-msschedule)%end; +%else %if &ext=trm %then %do;%str(application/x-msterminal)%end; +%else %if &ext=wri %then %do;%str(application/x-mswrite)%end; +%else %if &ext=nc %then %do;%str(application/x-netcdf)%end; +%else %if &ext=cdf %then %do;%str(application/x-netcdf)%end; +%else %if &ext=nzb %then %do;%str(application/x-nzb)%end; +%else %if &ext=p12 %then %do;%str(application/x-pkcs12)%end; +%else %if &ext=pfx %then %do;%str(application/x-pkcs12)%end; +%else %if &ext=p7b %then %do;%str(application/x-pkcs7-certificates)%end; +%else %if &ext=spc %then %do;%str(application/x-pkcs7-certificates)%end; +%else %if &ext=p7r %then %do;%str(application/x-pkcs7-certreqresp)%end; +%else %if &ext=rar %then %do;%str(application/x-rar-compressed)%end; +%else %if &ext=ris %then %do;%str(application/x-research-info-systems)%end; +%else %if &ext=sh %then %do;%str(application/x-sh)%end; +%else %if &ext=shar %then %do;%str(application/x-shar)%end; +%else %if &ext=swf %then %do;%str(application/x-shockwave-flash)%end; +%else %if &ext=xap %then %do;%str(application/x-silverlight-app)%end; +%else %if &ext=sql %then %do;%str(application/x-sql)%end; +%else %if &ext=sit %then %do;%str(application/x-stuffit)%end; +%else %if &ext=sitx %then %do;%str(application/x-stuffitx)%end; +%else %if &ext=srt %then %do;%str(application/x-subrip)%end; +%else %if &ext=sv4cpio %then %do;%str(application/x-sv4cpio)%end; +%else %if &ext=sv4crc %then %do;%str(application/x-sv4crc)%end; +%else %if &ext=t3 %then %do;%str(application/x-t3vm-image)%end; +%else %if &ext=gam %then %do;%str(application/x-tads)%end; +%else %if &ext=tar %then %do;%str(application/x-tar)%end; +%else %if &ext=tcl %then %do;%str(application/x-tcl)%end; +%else %if &ext=tex %then %do;%str(application/x-tex)%end; +%else %if &ext=tfm %then %do;%str(application/x-tex-tfm)%end; +%else %if &ext=texinfo %then %do;%str(application/x-texinfo)%end; +%else %if &ext=texi %then %do;%str(application/x-texinfo)%end; +%else %if &ext=obj %then %do;%str(application/x-tgif)%end; +%else %if &ext=ustar %then %do;%str(application/x-ustar)%end; +%else %if &ext=src %then %do;%str(application/x-wais-source)%end; +%else %if &ext=der %then %do;%str(application/x-x509-ca-cert)%end; +%else %if &ext=crt %then %do;%str(application/x-x509-ca-cert)%end; +%else %if &ext=fig %then %do;%str(application/x-xfig)%end; +%else %if &ext=xlf %then %do;%str(application/x-xliff+xml)%end; +%else %if &ext=xpi %then %do;%str(application/x-xpinstall)%end; +%else %if &ext=xz %then %do;%str(application/x-xz)%end; +%else %if &ext=xdf %then %do;%str(application/xcap-diff+xml)%end; +%else %if &ext=xht %then %do;%str(application/xhtml+xml)%end; +%else %if &ext=xsl %then %do;%str(application/xml)%end; +%else %if &ext=dtd %then %do;%str(application/xml-dtd)%end; +%else %if &ext=xpl %then %do;%str(application/xproc+xml)%end; +%else %if &ext=adp %then %do;%str(audio/adpcm)%end; +%else %if &ext=au %then %do;%str(audio/basic)%end; +%else %if &ext=snd %then %do;%str(audio/basic)%end; +%else %if &ext=m4a %then %do;%str(audio/mp4)%end; +%else %if &ext=mp4a %then %do;%str(audio/mp4)%end; +%else %if &ext=s3m %then %do;%str(audio/s3m)%end; +%else %if &ext=sil %then %do;%str(audio/silk)%end; +%else %if &ext=uva %then %do;%str(audio/vnd.dece.audio)%end; +%else %if &ext=uvva %then %do;%str(audio/vnd.dece.audio)%end; +%else %if &ext=eol %then %do;%str(audio/vnd.digital-winds)%end; +%else %if &ext=dra %then %do;%str(audio/vnd.dra)%end; +%else %if &ext=dts %then %do;%str(audio/vnd.dts)%end; +%else %if &ext=dtshd %then %do;%str(audio/vnd.dts.hd)%end; +%else %if &ext=lvp %then %do;%str(audio/vnd.lucent.voice)%end; +%else %if &ext=pya %then %do;%str(audio/vnd.ms-playready.media.pya)%end; +%else %if &ext=ecelp4800 %then %do;%str(audio/vnd.nuera.ecelp4800)%end; +%else %if &ext=ecelp7470 %then %do;%str(audio/vnd.nuera.ecelp7470)%end; +%else %if &ext=ecelp9600 %then %do;%str(audio/vnd.nuera.ecelp9600)%end; +%else %if &ext=rip %then %do;%str(audio/vnd.rip)%end; +%else %if &ext=weba %then %do;%str(audio/webm)%end; +%else %if &ext=mka %then %do;%str(audio/x-matroska)%end; +%else %if &ext=m3u %then %do;%str(audio/x-mpegurl)%end; +%else %if &ext=wax %then %do;%str(audio/x-ms-wax)%end; +%else %if &ext=wma %then %do;%str(audio/x-ms-wma)%end; +%else %if &ext=ra %then %do;%str(audio/x-pn-realaudio)%end; +%else %if &ext=ram %then %do;%str(audio/x-pn-realaudio)%end; +%else %if &ext=rmp %then %do;%str(audio/x-pn-realaudio-plugin)%end; +%else %if &ext=xm %then %do;%str(audio/xm)%end; +%else %if &ext=ttc %then %do;%str(font/collection)%end; +%else %if &ext=g3 %then %do;%str(image/g3fax)%end; +%else %if &ext=btif %then %do;%str(image/prs.btif)%end; +%else %if &ext=svg %then %do;%str(image/svg+xml)%end; +%else %if &ext=svgz %then %do;%str(image/svg+xml)%end; +%else %if &ext=tif %then %do;%str(image/tiff)%end; +%else %if &ext=psd %then %do;%str(image/vnd.adobe.photoshop)%end; +%else %if &ext=djv %then %do;%str(image/vnd.djvu)%end; +%else %if &ext=djvu %then %do;%str(image/vnd.djvu)%end; +%else %if &ext=sub %then %do;%str(image/vnd.dvb.subtitle)%end; +%else %if &ext=dwg %then %do;%str(image/vnd.dwg)%end; +%else %if &ext=dxf %then %do;%str(image/vnd.dxf)%end; +%else %if &ext=fbs %then %do;%str(image/vnd.fastbidsheet)%end; +%else %if &ext=fpx %then %do;%str(image/vnd.fpx)%end; +%else %if &ext=fst %then %do;%str(image/vnd.fst)%end; +%else %if &ext=mmr %then %do;%str(image/vnd.fujixerox.edmics-mmr)%end; +%else %if &ext=rlc %then %do;%str(image/vnd.fujixerox.edmics-rlc)%end; +%else %if &ext=mdi %then %do;%str(image/vnd.ms-modi)%end; +%else %if &ext=wdp %then %do;%str(image/vnd.ms-photo)%end; +%else %if &ext=npx %then %do;%str(image/vnd.net-fpx)%end; +%else %if &ext=wbmp %then %do;%str(image/vnd.wap.wbmp)%end; +%else %if &ext=xif %then %do;%str(image/vnd.xiff)%end; +%else %if &ext=ras %then %do;%str(image/x-cmu-raster)%end; +%else %if &ext=ico %then %do;%str(image/x-icon)%end; +%else %if &ext=sid %then %do;%str(image/x-mrsid-image)%end; +%else %if &ext=pct %then %do;%str(image/x-pict)%end; +%else %if &ext=pic %then %do;%str(image/x-pict)%end; +%else %if &ext=pnm %then %do;%str(image/x-portable-anymap)%end; +%else %if &ext=pbm %then %do;%str(image/x-portable-bitmap)%end; +%else %if &ext=pgm %then %do;%str(image/x-portable-graymap)%end; +%else %if &ext=ppm %then %do;%str(image/x-portable-pixmap)%end; +%else %if &ext=xbm %then %do;%str(image/x-xbitmap)%end; +%else %if &ext=xpm %then %do;%str(image/x-xpixmap)%end; +%else %if &ext=xwd %then %do;%str(image/x-xwindowdump)%end; +%else %if &ext=eml %then %do;%str(message/rfc822)%end; +%else %if &ext=mime %then %do;%str(message/rfc822)%end; +%else %if &ext=iges %then %do;%str(model/iges)%end; +%else %if &ext=igs %then %do;%str(model/iges)%end; +%else %if &ext=dae %then %do;%str(model/vnd.collada+xml)%end; +%else %if &ext=dwf %then %do;%str(model/vnd.dwf)%end; +%else %if &ext=gdl %then %do;%str(model/vnd.gdl)%end; +%else %if &ext=gtw %then %do;%str(model/vnd.gtw)%end; +%else %if &ext=vtu %then %do;%str(model/vnd.vtu)%end; +%else %if &ext=vrml %then %do;%str(model/vrml)%end; +%else %if &ext=wrl %then %do;%str(model/vrml)%end; +%else %if &ext=x3db %then %do;%str(model/x3d+binary)%end; +%else %if &ext=x3dbz %then %do;%str(model/x3d+binary)%end; +%else %if &ext=x3dv %then %do;%str(model/x3d+vrml)%end; +%else %if &ext=x3dvz %then %do;%str(model/x3d+vrml)%end; +%else %if &ext=x3d %then %do;%str(model/x3d+xml)%end; +%else %if &ext=x3dz %then %do;%str(model/x3d+xml)%end; +%else %if &ext=appcache %then %do;%str(text/cache-manifest)%end; +%else %if &ext=ics %then %do;%str(text/calendar)%end; +%else %if &ext=ifb %then %do;%str(text/calendar)%end; +%else %if &ext=htm %then %do;%str(text/html)%end; +%else %if &ext=js %then %do;%str(text/javascript)%end; +%else %if &ext=mjs %then %do;%str(text/javascript)%end; +%else %if &ext=dsc %then %do;%str(text/prs.lines.tag)%end; +%else %if &ext=rtx %then %do;%str(text/richtext)%end; +%else %if &ext=sgm %then %do;%str(text/sgml)%end; +%else %if &ext=tsv %then %do;%str(text/tab-separated-values)%end; +%else %if &ext=ttl %then %do;%str(text/turtle)%end; +%else %if &ext=curl %then %do;%str(text/vnd.curl)%end; +%else %if &ext=dcurl %then %do;%str(text/vnd.curl.dcurl)%end; +%else %if &ext=mcurl %then %do;%str(text/vnd.curl.mcurl)%end; +%else %if &ext=scurl %then %do;%str(text/vnd.curl.scurl)%end; +%else %if &ext=sub %then %do;%str(text/vnd.dvb.subtitle)%end; +%else %if &ext=fly %then %do;%str(text/vnd.fly)%end; +%else %if &ext=flx %then %do;%str(text/vnd.fmi.flexstor)%end; +%else %if &ext=gv %then %do;%str(text/vnd.graphviz)%end; +%else %if &ext=3dml %then %do;%str(text/vnd.in3d.3dml)%end; +%else %if &ext=spot %then %do;%str(text/vnd.in3d.spot)%end; +%else %if &ext=jad %then %do;%str(text/vnd.sun.j2me.app-descriptor)%end; +%else %if &ext=wml %then %do;%str(text/vnd.wap.wml)%end; +%else %if &ext=wmls %then %do;%str(text/vnd.wap.wmlscript)%end; +%else %if &ext=s %then %do;%str(text/x-asm)%end; +%else %if &ext=java %then %do;%str(text/x-java-source)%end; +%else %if &ext=p %then %do;%str(text/x-pascal)%end; +%else %if &ext=pas %then %do;%str(text/x-pascal)%end; +%else %if &ext=etx %then %do;%str(text/x-setext)%end; +%else %if &ext=uu %then %do;%str(text/x-uuencode)%end; +%else %if &ext=vcs %then %do;%str(text/x-vcalendar)%end; +%else %if &ext=vcf %then %do;%str(text/x-vcard)%end; +%else %if &ext=3gp %then %do;%str(video/3gpp)%end; +%else %if &ext=3g2 %then %do;%str(video/3gpp2)%end; +%else %if &ext=jpgv %then %do;%str(video/jpeg)%end; +%else %if &ext=jpgm %then %do;%str(video/jpm)%end; +%else %if &ext=mjp2 %then %do;%str(video/mj2)%end; +%else %if &ext=ogv %then %do;%str(video/ogg)%end; +%else %if &ext=mov %then %do;%str(video/quicktime)%end; +%else %if &ext=qt %then %do;%str(video/quicktime)%end; +%else %if &ext=uvh %then %do;%str(video/vnd.dece.hd)%end; +%else %if &ext=uvvh %then %do;%str(video/vnd.dece.hd)%end; +%else %if &ext=uvm %then %do;%str(video/vnd.dece.mobile)%end; +%else %if &ext=uvvm %then %do;%str(video/vnd.dece.mobile)%end; +%else %if &ext=uvp %then %do;%str(video/vnd.dece.pd)%end; +%else %if &ext=uvvp %then %do;%str(video/vnd.dece.pd)%end; +%else %if &ext=uvs %then %do;%str(video/vnd.dece.sd)%end; +%else %if &ext=uvvs %then %do;%str(video/vnd.dece.sd)%end; +%else %if &ext=uvv %then %do;%str(video/vnd.dece.video)%end; +%else %if &ext=uvvv %then %do;%str(video/vnd.dece.video)%end; +%else %if &ext=dvb %then %do;%str(video/vnd.dvb.file)%end; +%else %if &ext=fvt %then %do;%str(video/vnd.fvt)%end; +%else %if &ext=m4u %then %do;%str(video/vnd.mpegurl)%end; +%else %if &ext=mxu %then %do;%str(video/vnd.mpegurl)%end; +%else %if &ext=pyv %then %do;%str(video/vnd.ms-playready.media.pyv)%end; +%else %if &ext=uvu %then %do;%str(video/vnd.uvvu.mp4)%end; +%else %if &ext=uvvu %then %do;%str(video/vnd.uvvu.mp4)%end; +%else %if &ext=viv %then %do;%str(video/vnd.vivo)%end; +%else %if &ext=asf %then %do;%str(video/x-ms-asf)%end; +%else %if &ext=asx %then %do;%str(video/x-ms-asf)%end; +%else %if &ext=vob %then %do;%str(video/x-ms-vob)%end; +%else %if &ext=wm %then %do;%str(video/x-ms-wm)%end; +%else %if &ext=wmv %then %do;%str(video/x-ms-wmv)%end; +%else %if &ext=wmx %then %do;%str(video/x-ms-wmx)%end; +%else %if &ext=wvx %then %do;%str(video/x-ms-wvx)%end; +%else %if &ext=avi %then %do;%str(video/x-msvideo)%end; +%else %if &ext=movie %then %do;%str(video/x-sgi-movie)%end; +%else %if &ext=ice %then %do;%str(x-conference/x-cooltalk)%end; +%else %if "&ext"="in" %then %do;%str(text/plain)%end; +%else %do; + %put %str(WARN)ING: extension &ext not found!; + %put %str(WARN)ING- Returning text/plain.; + %str(text/plain) +%end; + +%mend mf_mimetype;/** @file @brief Creates a directory, including any intermediate directories @details Works on windows and unix environments via dcreate function. From 667198e5c0f3f44d03d7252956c007a5990d8e10 Mon Sep 17 00:00:00 2001 From: allan Date: Sun, 18 May 2025 18:48:18 +0100 Subject: [PATCH 03/12] feat: mfv_getpathuri macro to get the uri of a file or folder Also refactoring mv_createfolder.sas --- base/mf_mimetype.sas | 6 +- sasjs/sasjsconfig.json | 6 +- tests/testinit.sas | 2 +- tests/viyaonly/mfv_getpathuri.test.sas | 35 +++++++ tests/viyaonly/mv_createfile.test.sas | 17 +++- tests/viyaonly/mv_createfolder.test.sas | 16 ++++ viya/mfv_getpathuri.sas | 48 ++++++++++ viya/mv_createfile.sas | 120 ++++++++++++++++++------ viya/mv_createfolder.sas | 26 +++-- 9 files changed, 229 insertions(+), 47 deletions(-) create mode 100644 tests/viyaonly/mfv_getpathuri.test.sas create mode 100644 viya/mfv_getpathuri.sas diff --git a/base/mf_mimetype.sas b/base/mf_mimetype.sas index 18055e9..c134428 100644 --- a/base/mf_mimetype.sas +++ b/base/mf_mimetype.sas @@ -431,10 +431,6 @@ %else %if &ext=movie %then %do;%str(video/x-sgi-movie)%end; %else %if &ext=ice %then %do;%str(x-conference/x-cooltalk)%end; %else %if "&ext"="in" %then %do;%str(text/plain)%end; -%else %do; - %put %str(WARN)ING: extension &ext not found!; - %put %str(WARN)ING- Returning text/plain.; - %str(text/plain) -%end; +%else %do;%str(application/octet-stream)%end; %mend mf_mimetype; \ No newline at end of file diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index ab77752..7a8b058 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -31,12 +31,16 @@ "targets": [ { "name": "viya", - "serverUrl": "", + "serverUrl": "https://viya-f0g8ht62vq.engage.sas.com", "serverType": "SASVIYA", "httpsAgentOptions": { "allowInsecureRequests": false }, "appLoc": "/Public/app/macrocore", + "deployConfig": { + "deployServicePack": true, + "deployScripts": [] + }, "macroFolders": [ "viya", "tests/viyaonly" diff --git a/tests/testinit.sas b/tests/testinit.sas index d9344ee..854b048 100644 --- a/tests/testinit.sas +++ b/tests/testinit.sas @@ -10,7 +10,7 @@ **/ /* location in metadata or SAS Drive for temporary files */ -%let mcTestAppLoc=/tmp/tests/sasjs/core/%mf_uid(); +%let mcTestAppLoc=/Public/testresults/sasjs_core/%mf_uid(); /* set defaults */ %mp_init() diff --git a/tests/viyaonly/mfv_getpathuri.test.sas b/tests/viyaonly/mfv_getpathuri.test.sas new file mode 100644 index 0000000..ef3a866 --- /dev/null +++ b/tests/viyaonly/mfv_getpathuri.test.sas @@ -0,0 +1,35 @@ +/** + @file + @brief Testing mfv_getpathuri macro function + +

SAS Macros

+ @li mf_uid.sas + @li mfv_getpathuri.sas + @li mp_assert.sas + @li mv_createfile.sas + +**/ + +options mprint sgen; + +%let file=%mf_uid(); + +/* create a folder */ +filename somefile temp; +data _null_; + file somefile; + put 'hello testings'; +run; +%let path=&mcTestAppLoc/temp; +%mv_createfile(path=&path, name=&file..txt,inref=somefile) + + +%mp_assert( + iftrue=(%mfv_existfile(&path/&file..txt)=1), + desc=Check if created file exists +) + +%mp_assert( + iftrue=(%length(%mfv_getpathuri(&path/&file..txt))>0), + desc=Check that a URI was returned +) \ No newline at end of file diff --git a/tests/viyaonly/mv_createfile.test.sas b/tests/viyaonly/mv_createfile.test.sas index 52ea2fc..708bb64 100644 --- a/tests/viyaonly/mv_createfile.test.sas +++ b/tests/viyaonly/mv_createfile.test.sas @@ -21,20 +21,33 @@ data _null_; file somefile; put 'hello testings'; run; -%mv_createfile(path=&mcTestAppLoc/temp, name=&file..txt,inref=somefile) +%mv_createfile(path=&mcTestAppLoc/temp, name=&file..txt,inref=somefile,mdebug=1) %mp_assert( iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..txt)=1), desc=Check if created file exists ) +%put TEST 2 - html file; +filename f2 temp; +data _null_; + file f2; + put '

Hello world

'; +run; +%mv_createfile(path=&mcTestAppLoc/temp, name=test.html,inref=f2,mdebug=1) + +%mp_assert( + iftrue=(%mfv_existfile(&mcTestAppLoc/temp/test.html)=1), + desc=Check if created file exists +) + %put TEST 2 - dataset upload ; data temp; x=1; run; filename ds "%sysfunc(pathname(work))/temp.sas7bdat"; -%mv_createfile(path=&mcTestAppLoc/temp, name=&file..sas7bdat,inref=ds) +%mv_createfile(path=&mcTestAppLoc/temp, name=&file..sas7bdat,inref=ds,mdebug=1) %mp_assert( iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..sas7bdat)=1), diff --git a/tests/viyaonly/mv_createfolder.test.sas b/tests/viyaonly/mv_createfolder.test.sas index ce10507..605d818 100644 --- a/tests/viyaonly/mv_createfolder.test.sas +++ b/tests/viyaonly/mv_createfolder.test.sas @@ -29,4 +29,20 @@ run; %mp_assert( iftrue=(&test=1), desc=Check if temp folder can be successfully created +) + +/* create a folder without output dataset as part of the original macro */ +%mv_createfolder(path=&mcTestAppLoc/temp/&folder/folder2,outds=folders2) + +%let test=0; +data _null_; + set work.folders2; + putlog (_all_)(=); + if not missing(self_uri) and not missing(parent_uri) + then call symputx('test2',1); +run; + +%mp_assert( + iftrue=(&test2=1), + desc=Check if outds param works ) \ No newline at end of file diff --git a/viya/mfv_getpathuri.sas b/viya/mfv_getpathuri.sas new file mode 100644 index 0000000..285ff66 --- /dev/null +++ b/viya/mfv_getpathuri.sas @@ -0,0 +1,48 @@ +/** + @file + @brief Returns the uri of a file or folder + @details The automatic variable _FILESRVC_[fref]_URI is used after assigning + a fileref using the filesrvc engine. + + Usage: + + %put %mfv_existfile(/Public/folder/file.txt); + %put %mfv_existfile(/Public/folder); + + @param [in] filepath The full path to the file on SAS drive + (eg /Public/myfile.txt) + +

SAS Macros

+ @li mf_abort.sas + @li mf_getuniquefileref.sas + +

Related Macros

+ @li mfv_existfile.sas + @li mfv_existfolder.sas + + @version 3.5 + @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/) +**/ + +%macro mfv_getpathuri(filepath +)/*/STORE SOURCE*/; + + %mf_abort( + iftrue=(&syscc ne 0), + msg=Cannot enter &sysmacroname with syscc=&syscc + ) + + %local fref rc path name; + %let fref=%mf_getuniquefileref(); + %let name=%scan(&filepath,-1,/); + %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1); + + %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0 + %then %do;&&_FILESRVC_&fref._URI%let rc=%sysfunc(filename(fref)); + %end; + %else %do; + %put &sysmacroname: did not find &filepath; + %let syscc=0; + %end; + +%mend mfv_getpathuri; \ No newline at end of file diff --git a/viya/mv_createfile.sas b/viya/mv_createfile.sas index 20196c8..bcf98c1 100644 --- a/viya/mv_createfile.sas +++ b/viya/mv_createfile.sas @@ -1,8 +1,12 @@ /** @file - @brief Creates a file in SAS Drive - @details Creates a file in SAS Drive and adds the appropriate content type. + @brief Creates a file in SAS Drive using the API method + @details Creates a file in SAS Drive using the API interface. If the parent folder does not exist, it is created. + The API approach is more flexible than using the filesrvc engine of the + filename statement, as it provides more options. + + SAS docs: https://developer.sas.com/rest-apis/files/createNewFile Usage: @@ -14,49 +18,54 @@ %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile) - @param [in] path= The parent folder in which to create the file + @param [in] path= The parent (SAS Drive) folder in which to create the file @param [in] name= The name of the file to be created @param [in] inref= The fileref pointing to the file to be uploaded @param [in] intype= (BINARY) The type of the input data. Valid values: @li BINARY File is copied byte for byte using the mp_binarycopy.sas macro. @li BASE64 File will be first decoded using the mp_base64.sas macro, then loaded byte by byte to SAS Drive. - @param [in] contentdisp= (inline) Content Disposition. Example values: + @param [in] contentdisp= Content Disposition. Example values: @li inline @li attachment - @param [in] ctype= (0) Set a default HTTP Content-Type header to be returned - with the file when the content is retrieved from the Files service. + @param [in] ctype= (0) The actual MIME type of the file (if blank will be + determined based on file extension)) @param [in] access_token_var= The global macro variable to contain the access token, if using authorization_code grant type. @param [in] grant_type= (sas_services) Valid values are: @li password @li authorization_code @li sas_services + @param [out] outds= (_null_) Output dataset with the uri of the new file @param [in] mdebug= (0) Set to 1 to enable DEBUG messages - @version VIYA V.03.05 - @author Allan Bowe, source: https://github.com/sasjs/core -

SAS Macros

+ @li mf_getplatform.sas @li mf_getuniquefileref.sas + @li mf_getuniquename.sas @li mf_isblank.sas + @li mf_mimetype.sas @li mp_abort.sas @li mp_base64copy.sas @li mp_binarycopy.sas @li mv_createfolder.sas +

Related Macros

+ @li mv_createfile.sas + **/ %macro mv_createfile(path= ,name= ,inref= ,intype=BINARY - ,contentdisp=inline + ,contentdisp= ,ctype=0 ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services ,mdebug=0 + ,outds=_null_ ); %local dbg; %if &mdebug=1 %then %do; @@ -91,38 +100,87 @@ ,msg=%str(name value with length >1 must be provided) ) +/* prep the source file */ +%local fref; +%let fref=%mf_getuniquefileref(); + +%if %upcase(&intype)=BINARY %then %do; + %mp_binarycopy(inref=&inref, outref=&fref) +%end; +%else %if %upcase(&intype)=BASE64 %then %do; + %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) +%end; +%else %put %str(ERR)OR: invalid value for intype: &intype; + + +%if &mdebug=1 %then %do; + data _null_; + infile &fref lrecl=32767; + input; + put _infile_; + run; +%end; + + /* create folder if it does not already exist */ +%local folderds parenturi; +%let folderds=%mf_getuniquename(prefix=folderds); %mv_createfolder(path=&path ,access_token_var=&access_token_var ,grant_type=&grant_type ,mdebug=&mdebug + ,outds=&folderds ) +data _null_; + set &folderds; + call symputx('self_uri',self_uri,'l'); +run; -/* create file with relevant options */ -%local fref; -%let fref=%mf_getuniquefileref(); -filename &fref filesrvc - folderPath="&path" - filename="&name" - cdisp="&contentdisp" -%if "&ctype" ne "0" %then %do; - ctype="&ctype" -%end; - lrecl=1048544; -%if &intype=BINARY %then %do; - %mp_binarycopy(inref=&inref, outref=&fref) -%end; -%else %if &intype=BASE64 %then %do; - %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) -%end; - -filename &fref clear; +options noquotelenmax; %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); -%put &sysmacroname: File &name successfully created in &path; -%put &sysmacroname:;%put; + +/* fetch job info */ +%local fname1; +%let fname1=%mf_getuniquefileref(); +proc http method='POST' out=&fname1 &oauth_bearer in=&fref + %if "&ctype" = "0" %then %do; + ct="%mf_mimetype(%scan(&name,-1,.))" + %end; + %else %do; + ct="&ctype" + %end; + url="&base_uri/files/files?parentFolderUri=&self_uri"; + + headers "Accept"="application/json" + %if &grant_type=authorization_code %then %do; + "Authorization"="Bearer &&&access_token_var" + %end; + "Content-Disposition"= "&contentdisp filename=""&name""; name=""&name"";"; +run; +%put &=SYS_PROCHTTP_STATUS_CODE; +%put &=SYS_PROCHTTP_STATUS_PHRASE; +%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) + ,mac=&sysmacroname + ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) +) +%local libref2; +%let libref2=%mf_getuniquelibref(); +libname &libref2 JSON fileref=&fname1; +%put Grabbing the follow on link ; +data &outds; + set &libref2..links end=last; + if rel='createChild' then do; + call symputx('href',quote(cats("&base_uri",href)),'l'); + &dbg put (_all_)(=); + end; +run; + + + +%put &sysmacroname: File &name successfully created:;%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; diff --git a/viya/mv_createfolder.sas b/viya/mv_createfolder.sas index 3ff7279..1fca4d3 100644 --- a/viya/mv_createfolder.sas +++ b/viya/mv_createfolder.sas @@ -17,15 +17,16 @@ @li sas_services @param [in] mdebug=(0) set to 1 to enable DEBUG messages + @param [out] outds=(_null_) Optionally create an output dataset which will + contain the uri (self_uri) of the created (and parent) folder. - @version VIYA V.03.04 - @author Allan Bowe, source: https://github.com/sasjs/core

SAS Macros

@li mp_abort.sas @li mf_getuniquefileref.sas @li mf_getuniquelibref.sas @li mf_isblank.sas + @li mfv_getpathuri.sas @li mf_getplatform.sas @li mfv_existfolder.sas @@ -36,6 +37,7 @@ ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services ,mdebug=0 + ,outds=_null_ ); %local dbg; %if &mdebug=1 %then %do; @@ -46,6 +48,11 @@ %if %mfv_existfolder(&path)=1 %then %do; %put &sysmacroname: &path already exists; + data &outds; + self_uri="%mfv_getpathuri(&path)"; + output; + stop; + run; %return; %end; @@ -80,12 +87,12 @@ options noquotelenmax; %local subfolder_cnt; /* determine the number of subfolders */ %let subfolder_cnt=%sysfunc(countw(&path,/)); -%local href; /* resource address (none for root) */ -%let href="/folders/folders?parentFolderUri=/folders/folders/none"; - %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); +%local href; /* resource address (none for root) */ +%let href="&base_uri/folders/folders?parentFolderUri=/folders/folders/none"; + %local x newpath subfolder; %do x=1 %to &subfolder_cnt; %let subfolder=%scan(&path,&x,%str(/)); @@ -115,7 +122,7 @@ options noquotelenmax; %put &sysmacroname following check to see if &newpath exists:; %put _local_; data _null_; - set &fname1; + infile &fname1; input; putlog _infile_; run; @@ -167,12 +174,17 @@ options noquotelenmax; %let libref2=%mf_getuniquelibref(); libname &libref2 JSON fileref=&fname2; %put &sysmacroname &newpath now created. Grabbing the follow on link ; - data _null_; + data &outds; set &libref2..links; if rel='createChild' then do; call symputx('href',quote(cats("&base_uri",href)),'l'); &dbg put (_all_)(=); end; + if method='GET' and rel='self' then do; + self_uri=uri; + output; + end; + keep self_uri ; run; libname &libref2 clear; From 285ca791d8c3cebfcef4bbb3f30fc68365b27f18 Mon Sep 17 00:00:00 2001 From: github-actions Date: Sun, 18 May 2025 17:49:16 +0000 Subject: [PATCH 04/12] chore: updating all.sas --- all.sas | 199 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 156 insertions(+), 43 deletions(-) diff --git a/all.sas b/all.sas index 10aeaf5..c179ce8 100644 --- a/all.sas +++ b/all.sas @@ -2276,11 +2276,7 @@ Usage: %else %if &ext=movie %then %do;%str(video/x-sgi-movie)%end; %else %if &ext=ice %then %do;%str(x-conference/x-cooltalk)%end; %else %if "&ext"="in" %then %do;%str(text/plain)%end; -%else %do; - %put %str(WARN)ING: extension &ext not found!; - %put %str(WARN)ING- Returning text/plain.; - %str(text/plain) -%end; +%else %do;%str(application/octet-stream)%end; %mend mf_mimetype;/** @file @@ -24175,9 +24171,60 @@ run; %mend mfv_existsashdat; /** @file - @brief Creates a file in SAS Drive - @details Creates a file in SAS Drive and adds the appropriate content type. + @brief Returns the uri of a file or folder + @details The automatic variable _FILESRVC_[fref]_URI is used after assigning + a fileref using the filesrvc engine. + + Usage: + + %put %mfv_existfile(/Public/folder/file.txt); + %put %mfv_existfile(/Public/folder); + + @param [in] filepath The full path to the file on SAS drive + (eg /Public/myfile.txt) + +

SAS Macros

+ @li mf_abort.sas + @li mf_getuniquefileref.sas + +

Related Macros

+ @li mfv_existfile.sas + @li mfv_existfolder.sas + + @version 3.5 + @author [Allan Bowe](https://www.linkedin.com/in/allanbowe/) +**/ + +%macro mfv_getpathuri(filepath +)/*/STORE SOURCE*/; + + %mf_abort( + iftrue=(&syscc ne 0), + msg=Cannot enter &sysmacroname with syscc=&syscc + ) + + %local fref rc path name; + %let fref=%mf_getuniquefileref(); + %let name=%scan(&filepath,-1,/); + %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1); + + %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0 + %then %do;&&_FILESRVC_&fref._URI%let rc=%sysfunc(filename(fref)); + %end; + %else %do; + %put &sysmacroname: did not find &filepath; + %let syscc=0; + %end; + +%mend mfv_getpathuri;/** + @file + @brief Creates a file in SAS Drive using the API method + @details Creates a file in SAS Drive using the API interface. If the parent folder does not exist, it is created. + The API approach is more flexible than using the filesrvc engine of the + filename statement, as it provides more options. + + SAS docs: https://developer.sas.com/rest-apis/files/createNewFile Usage: @@ -24189,49 +24236,54 @@ run; %mv_createfile(path=/Public/temp,name=newfile.txt,inref=myfile) - @param [in] path= The parent folder in which to create the file + @param [in] path= The parent (SAS Drive) folder in which to create the file @param [in] name= The name of the file to be created @param [in] inref= The fileref pointing to the file to be uploaded @param [in] intype= (BINARY) The type of the input data. Valid values: @li BINARY File is copied byte for byte using the mp_binarycopy.sas macro. @li BASE64 File will be first decoded using the mp_base64.sas macro, then loaded byte by byte to SAS Drive. - @param [in] contentdisp= (inline) Content Disposition. Example values: + @param [in] contentdisp= Content Disposition. Example values: @li inline @li attachment - @param [in] ctype= (0) Set a default HTTP Content-Type header to be returned - with the file when the content is retrieved from the Files service. + @param [in] ctype= (0) The actual MIME type of the file (if blank will be + determined based on file extension)) @param [in] access_token_var= The global macro variable to contain the access token, if using authorization_code grant type. @param [in] grant_type= (sas_services) Valid values are: @li password @li authorization_code @li sas_services + @param [out] outds= (_null_) Output dataset with the uri of the new file @param [in] mdebug= (0) Set to 1 to enable DEBUG messages - @version VIYA V.03.05 - @author Allan Bowe, source: https://github.com/sasjs/core -

SAS Macros

+ @li mf_getplatform.sas @li mf_getuniquefileref.sas + @li mf_getuniquename.sas @li mf_isblank.sas + @li mf_mimetype.sas @li mp_abort.sas @li mp_base64copy.sas @li mp_binarycopy.sas @li mv_createfolder.sas +

Related Macros

+ @li mv_createfile.sas + **/ %macro mv_createfile(path= ,name= ,inref= ,intype=BINARY - ,contentdisp=inline + ,contentdisp= ,ctype=0 ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services ,mdebug=0 + ,outds=_null_ ); %local dbg; %if &mdebug=1 %then %do; @@ -24266,38 +24318,87 @@ run; ,msg=%str(name value with length >1 must be provided) ) +/* prep the source file */ +%local fref; +%let fref=%mf_getuniquefileref(); + +%if %upcase(&intype)=BINARY %then %do; + %mp_binarycopy(inref=&inref, outref=&fref) +%end; +%else %if %upcase(&intype)=BASE64 %then %do; + %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) +%end; +%else %put %str(ERR)OR: invalid value for intype: &intype; + + +%if &mdebug=1 %then %do; + data _null_; + infile &fref lrecl=32767; + input; + put _infile_; + run; +%end; + + /* create folder if it does not already exist */ +%local folderds parenturi; +%let folderds=%mf_getuniquename(prefix=folderds); %mv_createfolder(path=&path ,access_token_var=&access_token_var ,grant_type=&grant_type ,mdebug=&mdebug + ,outds=&folderds ) +data _null_; + set &folderds; + call symputx('self_uri',self_uri,'l'); +run; -/* create file with relevant options */ -%local fref; -%let fref=%mf_getuniquefileref(); -filename &fref filesrvc - folderPath="&path" - filename="&name" - cdisp="&contentdisp" -%if "&ctype" ne "0" %then %do; - ctype="&ctype" -%end; - lrecl=1048544; -%if &intype=BINARY %then %do; - %mp_binarycopy(inref=&inref, outref=&fref) -%end; -%else %if &intype=BASE64 %then %do; - %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) -%end; - -filename &fref clear; +options noquotelenmax; %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); -%put &sysmacroname: File &name successfully created in &path; -%put &sysmacroname:;%put; + +/* fetch job info */ +%local fname1; +%let fname1=%mf_getuniquefileref(); +proc http method='POST' out=&fname1 &oauth_bearer in=&fref + %if "&ctype" = "0" %then %do; + ct="%mf_mimetype(%scan(&name,-1,.))" + %end; + %else %do; + ct="&ctype" + %end; + url="&base_uri/files/files?parentFolderUri=&self_uri"; + + headers "Accept"="application/json" + %if &grant_type=authorization_code %then %do; + "Authorization"="Bearer &&&access_token_var" + %end; + "Content-Disposition"= "&contentdisp filename=""&name""; name=""&name"";"; +run; +%put &=SYS_PROCHTTP_STATUS_CODE; +%put &=SYS_PROCHTTP_STATUS_PHRASE; +%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201) + ,mac=&sysmacroname + ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) +) +%local libref2; +%let libref2=%mf_getuniquelibref(); +libname &libref2 JSON fileref=&fname1; +%put Grabbing the follow on link ; +data &outds; + set &libref2..links end=last; + if rel='createChild' then do; + call symputx('href',quote(cats("&base_uri",href)),'l'); + &dbg put (_all_)(=); + end; +run; + + + +%put &sysmacroname: File &name successfully created:;%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; @@ -24320,15 +24421,16 @@ filename &fref clear; @li sas_services @param [in] mdebug=(0) set to 1 to enable DEBUG messages + @param [out] outds=(_null_) Optionally create an output dataset which will + contain the uri (self_uri) of the created (and parent) folder. - @version VIYA V.03.04 - @author Allan Bowe, source: https://github.com/sasjs/core

SAS Macros

@li mp_abort.sas @li mf_getuniquefileref.sas @li mf_getuniquelibref.sas @li mf_isblank.sas + @li mfv_getpathuri.sas @li mf_getplatform.sas @li mfv_existfolder.sas @@ -24339,6 +24441,7 @@ filename &fref clear; ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services ,mdebug=0 + ,outds=_null_ ); %local dbg; %if &mdebug=1 %then %do; @@ -24349,6 +24452,11 @@ filename &fref clear; %if %mfv_existfolder(&path)=1 %then %do; %put &sysmacroname: &path already exists; + data &outds; + self_uri="%mfv_getpathuri(&path)"; + output; + stop; + run; %return; %end; @@ -24383,12 +24491,12 @@ options noquotelenmax; %local subfolder_cnt; /* determine the number of subfolders */ %let subfolder_cnt=%sysfunc(countw(&path,/)); -%local href; /* resource address (none for root) */ -%let href="/folders/folders?parentFolderUri=/folders/folders/none"; - %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); +%local href; /* resource address (none for root) */ +%let href="&base_uri/folders/folders?parentFolderUri=/folders/folders/none"; + %local x newpath subfolder; %do x=1 %to &subfolder_cnt; %let subfolder=%scan(&path,&x,%str(/)); @@ -24418,7 +24526,7 @@ options noquotelenmax; %put &sysmacroname following check to see if &newpath exists:; %put _local_; data _null_; - set &fname1; + infile &fname1; input; putlog _infile_; run; @@ -24470,12 +24578,17 @@ options noquotelenmax; %let libref2=%mf_getuniquelibref(); libname &libref2 JSON fileref=&fname2; %put &sysmacroname &newpath now created. Grabbing the follow on link ; - data _null_; + data &outds; set &libref2..links; if rel='createChild' then do; call symputx('href',quote(cats("&base_uri",href)),'l'); &dbg put (_all_)(=); end; + if method='GET' and rel='self' then do; + self_uri=uri; + output; + end; + keep self_uri ; run; libname &libref2 clear; From de32d12b511591d9a1f465bc193a657077540438 Mon Sep 17 00:00:00 2001 From: allan Date: Mon, 19 May 2025 09:04:50 +0100 Subject: [PATCH 05/12] fix: applying correct typedefname --- viya/mv_createfile.sas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viya/mv_createfile.sas b/viya/mv_createfile.sas index bcf98c1..2cf69dd 100644 --- a/viya/mv_createfile.sas +++ b/viya/mv_createfile.sas @@ -152,7 +152,7 @@ proc http method='POST' out=&fname1 &oauth_bearer in=&fref %else %do; ct="&ctype" %end; - url="&base_uri/files/files?parentFolderUri=&self_uri"; + url="&base_uri/files/files?parentFolderUri=&self_uri%str(&)typeDefName=file"; headers "Accept"="application/json" %if &grant_type=authorization_code %then %do; @@ -179,8 +179,8 @@ data &outds; run; - %put &sysmacroname: File &name successfully created:;%put; +%put &base_uri%mfv_getpathuri(&path/&name);%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From 376800d4642b1842591f40d899b9ce2057ced398 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 May 2025 08:05:57 +0000 Subject: [PATCH 06/12] chore: updating all.sas --- all.sas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/all.sas b/all.sas index c179ce8..5e428ec 100644 --- a/all.sas +++ b/all.sas @@ -24370,7 +24370,7 @@ proc http method='POST' out=&fname1 &oauth_bearer in=&fref %else %do; ct="&ctype" %end; - url="&base_uri/files/files?parentFolderUri=&self_uri"; + url="&base_uri/files/files?parentFolderUri=&self_uri%str(&)typeDefName=file"; headers "Accept"="application/json" %if &grant_type=authorization_code %then %do; @@ -24397,8 +24397,8 @@ data &outds; run; - %put &sysmacroname: File &name successfully created:;%put; +%put &base_uri%mfv_getpathuri(&path/&name);%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From 7117e2e8e9a73f0e874e0d0d892f4ade5e317ad5 Mon Sep 17 00:00:00 2001 From: allan Date: Mon, 19 May 2025 10:19:10 +0100 Subject: [PATCH 07/12] fix: enabling reading from / writing to SAS Drive. Closes #334 --- tests/viyaonly/mv_createfile.test.sas | 27 +++++++++++++++++++++++++-- viya/mv_createfile.sas | 25 +++++++++++++++---------- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/tests/viyaonly/mv_createfile.test.sas b/tests/viyaonly/mv_createfile.test.sas index 708bb64..db3b65e 100644 --- a/tests/viyaonly/mv_createfile.test.sas +++ b/tests/viyaonly/mv_createfile.test.sas @@ -41,7 +41,7 @@ run; desc=Check if created file exists ) -%put TEST 2 - dataset upload ; +%put TEST 3 - dataset upload ; data temp; x=1; run; @@ -52,4 +52,27 @@ filename ds "%sysfunc(pathname(work))/temp.sas7bdat"; %mp_assert( iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..sas7bdat)=1), desc=Check if created dataset exists -) \ No newline at end of file +) + +%put TEST 4 - create a .sas file; +filename f4 temp; +data _null_; + file f4; + put '%put hello FromSASStudioBailey; '; +run; +%mv_createfile(path=&mcTestAppLoc/temp, name=test4.sas,inref=f4,mdebug=1) + +%mp_assert( + iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..sas)=1), + desc=Check if created sas program exists +) + + + +%put TEST 5 - reading from files service and writing back; +filename sendfrom filesrvc folderpath="&mcTestAppLoc/temp" filename='test4.sas'; + +OPTIONS MERROR SYMBOLGEN MLOGIC MPRINT; + +%mv_createfile(path=&mcTestAppLoc/temp,name=test5.sas,inref=sendfrom,mdebug=1) ; + diff --git a/viya/mv_createfile.sas b/viya/mv_createfile.sas index 2cf69dd..f715fc4 100644 --- a/viya/mv_createfile.sas +++ b/viya/mv_createfile.sas @@ -25,7 +25,7 @@ @li BINARY File is copied byte for byte using the mp_binarycopy.sas macro. @li BASE64 File will be first decoded using the mp_base64.sas macro, then loaded byte by byte to SAS Drive. - @param [in] contentdisp= Content Disposition. Example values: + @param [in] contentdisp= (attchment) Content Disposition. Example values: @li inline @li attachment @param [in] ctype= (0) The actual MIME type of the file (if blank will be @@ -48,7 +48,6 @@ @li mf_mimetype.sas @li mp_abort.sas @li mp_base64copy.sas - @li mp_binarycopy.sas @li mv_createfolder.sas

Related Macros

@@ -60,7 +59,7 @@ ,name= ,inref= ,intype=BINARY - ,contentdisp= + ,contentdisp=attachment ,ctype=0 ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services @@ -104,9 +103,7 @@ %local fref; %let fref=%mf_getuniquefileref(); -%if %upcase(&intype)=BINARY %then %do; - %mp_binarycopy(inref=&inref, outref=&fref) -%end; +%if %upcase(&intype)=BINARY %then %let fref=&inref; %else %if %upcase(&intype)=BASE64 %then %do; %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) %end; @@ -141,18 +138,26 @@ options noquotelenmax; %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); +%local url mimetype; +%let url=&base_uri/files/files?parentFolderUri=&self_uri; /* fetch job info */ %local fname1; %let fname1=%mf_getuniquefileref(); proc http method='POST' out=&fname1 &oauth_bearer in=&fref %if "&ctype" = "0" %then %do; - ct="%mf_mimetype(%scan(&name,-1,.))" + %let mimetype=%mf_mimetype(%scan(&name,-1,.)); + ct="&mimetype" %end; %else %do; ct="&ctype" %end; - url="&base_uri/files/files?parentFolderUri=&self_uri%str(&)typeDefName=file"; + %if "&mimetype"="text/html" %then %do; + url="&url%str(&)typeDefName=file"; + %end; + %else %do; + url="&url"; + %end; headers "Accept"="application/json" %if &grant_type=authorization_code %then %do; @@ -178,9 +183,9 @@ data &outds; end; run; - +%local mfv_getpathurivar=%mfv_getpathuri(&path/&name); %put &sysmacroname: File &name successfully created:;%put; -%put &base_uri%mfv_getpathuri(&path/&name);%put; +%put &base_uri&mfv_getpathurivar;%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From 2de6fba5bbfa437686e166b38fff8eaa1cd13dfe Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 May 2025 09:19:44 +0000 Subject: [PATCH 08/12] chore: updating all.sas --- all.sas | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/all.sas b/all.sas index 5e428ec..d87ad14 100644 --- a/all.sas +++ b/all.sas @@ -24243,7 +24243,7 @@ run; @li BINARY File is copied byte for byte using the mp_binarycopy.sas macro. @li BASE64 File will be first decoded using the mp_base64.sas macro, then loaded byte by byte to SAS Drive. - @param [in] contentdisp= Content Disposition. Example values: + @param [in] contentdisp= (attchment) Content Disposition. Example values: @li inline @li attachment @param [in] ctype= (0) The actual MIME type of the file (if blank will be @@ -24266,7 +24266,6 @@ run; @li mf_mimetype.sas @li mp_abort.sas @li mp_base64copy.sas - @li mp_binarycopy.sas @li mv_createfolder.sas

Related Macros

@@ -24278,7 +24277,7 @@ run; ,name= ,inref= ,intype=BINARY - ,contentdisp= + ,contentdisp=attachment ,ctype=0 ,access_token_var=ACCESS_TOKEN ,grant_type=sas_services @@ -24322,9 +24321,7 @@ run; %local fref; %let fref=%mf_getuniquefileref(); -%if %upcase(&intype)=BINARY %then %do; - %mp_binarycopy(inref=&inref, outref=&fref) -%end; +%if %upcase(&intype)=BINARY %then %let fref=&inref; %else %if %upcase(&intype)=BASE64 %then %do; %mp_base64copy(inref=&inref, outref=&fref, action=DECODE) %end; @@ -24359,18 +24356,26 @@ options noquotelenmax; %local base_uri; /* location of rest apis */ %let base_uri=%mf_getplatform(VIYARESTAPI); +%local url mimetype; +%let url=&base_uri/files/files?parentFolderUri=&self_uri; /* fetch job info */ %local fname1; %let fname1=%mf_getuniquefileref(); proc http method='POST' out=&fname1 &oauth_bearer in=&fref %if "&ctype" = "0" %then %do; - ct="%mf_mimetype(%scan(&name,-1,.))" + %let mimetype=%mf_mimetype(%scan(&name,-1,.)); + ct="&mimetype" %end; %else %do; ct="&ctype" %end; - url="&base_uri/files/files?parentFolderUri=&self_uri%str(&)typeDefName=file"; + %if "&mimetype"="text/html" %then %do; + url="&url%str(&)typeDefName=file"; + %end; + %else %do; + url="&url"; + %end; headers "Accept"="application/json" %if &grant_type=authorization_code %then %do; @@ -24396,9 +24401,9 @@ data &outds; end; run; - +%local mfv_getpathurivar=%mfv_getpathuri(&path/&name); %put &sysmacroname: File &name successfully created:;%put; -%put &base_uri%mfv_getpathuri(&path/&name);%put; +%put &base_uri&mfv_getpathurivar;%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From 2ddded960086e920ac4f65ea749c1488917ab8cd Mon Sep 17 00:00:00 2001 From: allan Date: Mon, 19 May 2025 12:20:54 +0100 Subject: [PATCH 09/12] chore: test fixes --- tests/viyaonly/mv_createfile.test.sas | 10 +++++++++- viya/mfv_getpathuri.sas | 8 ++++++-- viya/mv_createfile.sas | 3 +-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/viyaonly/mv_createfile.test.sas b/tests/viyaonly/mv_createfile.test.sas index db3b65e..00bd499 100644 --- a/tests/viyaonly/mv_createfile.test.sas +++ b/tests/viyaonly/mv_createfile.test.sas @@ -6,6 +6,7 @@ @li mf_uid.sas @li mfv_existfile.sas @li mp_assert.sas + @li mp_assertscope.sas @li mv_createfile.sas @@ -21,7 +22,14 @@ data _null_; file somefile; put 'hello testings'; run; +%mp_assertscope(SNAPSHOT) %mv_createfile(path=&mcTestAppLoc/temp, name=&file..txt,inref=somefile,mdebug=1) +%mp_assertscope(COMPARE + ,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADPNUM + MCLIB0_JADVLEN MCLIB2_JADP1LEN + SASJSPROCESSMODE SASJS_STPSRV_HEADER_LOC + MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN +) %mp_assert( iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..txt)=1), @@ -63,7 +71,7 @@ run; %mv_createfile(path=&mcTestAppLoc/temp, name=test4.sas,inref=f4,mdebug=1) %mp_assert( - iftrue=(%mfv_existfile(&mcTestAppLoc/temp/&file..sas)=1), + iftrue=(%mfv_existfile(&mcTestAppLoc/temp/test4.sas)=1), desc=Check if created sas program exists ) diff --git a/viya/mfv_getpathuri.sas b/viya/mfv_getpathuri.sas index 285ff66..a6309f6 100644 --- a/viya/mfv_getpathuri.sas +++ b/viya/mfv_getpathuri.sas @@ -32,13 +32,17 @@ msg=Cannot enter &sysmacroname with syscc=&syscc ) - %local fref rc path name; + %local fref rc path name var /* var is used to avoid delete timing issue */; %let fref=%mf_getuniquefileref(); %let name=%scan(&filepath,-1,/); %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1); %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0 - %then %do;&&_FILESRVC_&fref._URI%let rc=%sysfunc(filename(fref)); + %then %do; + %let var=_FILESRVC_&fref._URI; + %str(&&&var) + %let rc=%sysfunc(filename(fref)); + %symdel &var; %end; %else %do; %put &sysmacroname: did not find &filepath; diff --git a/viya/mv_createfile.sas b/viya/mv_createfile.sas index f715fc4..c109b39 100644 --- a/viya/mv_createfile.sas +++ b/viya/mv_createfile.sas @@ -183,9 +183,8 @@ data &outds; end; run; -%local mfv_getpathurivar=%mfv_getpathuri(&path/&name); %put &sysmacroname: File &name successfully created:;%put; -%put &base_uri&mfv_getpathurivar;%put; +%put &base_uri%mfv_getpathuri(&path/&name);%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From d4f1df5bc000166675d77a34e764f0e753c00e12 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 May 2025 11:21:25 +0000 Subject: [PATCH 10/12] chore: updating all.sas --- all.sas | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/all.sas b/all.sas index d87ad14..7489f52 100644 --- a/all.sas +++ b/all.sas @@ -24203,13 +24203,17 @@ run; msg=Cannot enter &sysmacroname with syscc=&syscc ) - %local fref rc path name; + %local fref rc path name var /* var is used to avoid delete timing issue */; %let fref=%mf_getuniquefileref(); %let name=%scan(&filepath,-1,/); %let path=%substr(&filepath,1,%length(&filepath)-%length(&name)-1); %if %sysfunc(filename(fref,,filesrvc,folderPath="&path" filename="&name"))=0 - %then %do;&&_FILESRVC_&fref._URI%let rc=%sysfunc(filename(fref)); + %then %do; + %let var=_FILESRVC_&fref._URI; + %str(&&&var) + %let rc=%sysfunc(filename(fref)); + %symdel &var; %end; %else %do; %put &sysmacroname: did not find &filepath; @@ -24401,9 +24405,8 @@ data &outds; end; run; -%local mfv_getpathurivar=%mfv_getpathuri(&path/&name); %put &sysmacroname: File &name successfully created:;%put; -%put &base_uri&mfv_getpathurivar;%put; +%put &base_uri%mfv_getpathuri(&path/&name);%put; %put &base_uri/SASJobExecution?_file=&path/&name;%put; %put &sysmacroname:; From a1c24b2e4adc544c04e3dc97c6b30f2fcf75783e Mon Sep 17 00:00:00 2001 From: allan Date: Mon, 19 May 2025 12:23:03 +0100 Subject: [PATCH 11/12] chore: remove server url --- sasjs/sasjsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sasjs/sasjsconfig.json b/sasjs/sasjsconfig.json index 7a8b058..bbdb6e7 100644 --- a/sasjs/sasjsconfig.json +++ b/sasjs/sasjsconfig.json @@ -31,7 +31,7 @@ "targets": [ { "name": "viya", - "serverUrl": "https://viya-f0g8ht62vq.engage.sas.com", + "serverUrl": "", "serverType": "SASVIYA", "httpsAgentOptions": { "allowInsecureRequests": false From 6c6561debabe0cfb3b6bdf8d5d4c7f4bac123278 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 May 2025 11:23:29 +0000 Subject: [PATCH 12/12] chore: updating all.sas