/*************************************************************************************************************
This ado-file unzips files.

Required:
File path: file paths of folder to be unzipped.

Options:
Replace: replace existing files.
Outfolder: specify folder to unzip files into.
zipexecutable: location of 7za executable file
stata: use stata unzipfile command in place of gunzipfile. Extension of file to unzip must be .zip.
use: after unzipping use infilename
erase: erase unzipped file at end of program
mac: For use on OSX. Requires installation of p7za in Terminal. Tested on OSX 10.9. Step-by-step instructions:
You need to run the command in the terminal app.
(Original from this website: http://superuser.com/questions/548349/how-can-i-install-7zip-so-i-can-run-it-from-terminal-on-os-x)
To install p7zip using Homebrew, first update your brew formulae to be sure you are getting the latest p7zip.
$ brew update
Use Homebrew to install p7zip:
$ brew install p7zip
Add all files in the sputnik directory to the compressed file heed.7z:
$ 7z a heed.7z sputnik
Unzip heed.7z:
$ 7z x heed.7z
*: any other options that go along with Stata's unzipfile command if Stata is specified

Written by Gabriel Chodorow-Reich and provided without any warranty
This version: August 2024
*************************************************************************************************************/

capture program drop gunzipfile
program define gunzipfile, rclass
syntax anything(name=infilename id="File path"), [outfolder(string) ZIPEXEcutable(string) dtaname(string) stata replace use erase nounzip filelist mac *]

/*Define paths*/
local dir "`c(pwd)'"
if `"`zipexecutable'"' != `""' local ZipExe `"`zipexecutable'"'
else local ZipExe `"`=regexr(`"`=c(pwd)'"',`"[Dd]ropbox.*$"',`"Dropbox"')'/7-Zip"'

/*Define outfolder*/
local s out
if `"``s'folder'"'==`""' local `s'file `"`dir'"'
else if regexm(`"``s'folder'"',`"^([aA-zZ]:)|^(/)"') local `s'file `"``s'folder'"'
else local `s'file `"`dir'/``s'folder'"'


cap di `infilename'
if _rc==0 {
	local infilename = `infilename'
}
local infile "`infilename'"
if regexm(`"`infile'"',`"^\.\."') {
	local filename = regexr(`"`infile'"',`"^.*[/\\]"',`""')
	cd `"`=regexr(`"`infile'"',`"[/\\]`filename'.*$"',`""')'"'
	local infile `"`c(pwd)'/`filename'"'
	cd `"`dir'"'
}
else if !regexm(`"`infile'"',`"^(([aA-zZ]:)|(/)|(\\\\))"') {
	local infile `"`dir'/`infile'"'
}
if !regexm(`"`infile'"',`"^.*\."') {
	foreach z in 7z zip gz {
		cap confirm file `"`infile'.`z'"'
		if _rc==0 {
			local infile = `"`infile'"' + `".`z'"'
			continue
		}
	}
}

if `"`replace'"'==`"replace"' {
	local overwrite `"-y"'
}
di `"Unzipping `infile'"'

if inlist(`"`c(os)'"',`"Windows"',`"Unix"') & regexm(`"`:dir `"`ZipExe'"' files *'"',`"7za"') & `"`stata'"'!=`"stata"' & "`unzip'"!=`"nounzip"' {
	di `"!cd "`ZipExe'" & 7za x `overwrite' "`infile'" -o"`outfile'""'
	!cd "`ZipExe'" & 7za x `overwrite' "`infile'" -o"`outfile'"
}
else if (inlist(`"`c(os)'"',`"MacOSX"') | `"`mac'"'==`"mac"') & regexm(`"`:dir `"`ZipExe'"' files *'"',`"7za"') & `"`stata'"'!=`"stata"' & "`unzip'"!=`"nounzip"' {
	di `"shell /usr/local/bin/7za 7za x  `overwrite' "`infile'" -o"`outfile'""'
	shell /usr/local/bin/7za x `overwrite' "`infile'" -o"`outfile'"
}
else if "`unzip'"!=`"nounzip"' {
	cap assert regexm(`"`infile'"',`"\.zip"')
	 if _rc!=0 {
		di as error `"File to be unzipped must be .zip if option stata is specified or if 7za not found"'
		exit as error
	}
	unzipfile `"`infile'"', `replace' `options'
}

if `"`use'"'==`"use"' {
	if `"`dtaname'"'==`""' local dtaname = regexr(regexr(`"`infilename'"',`".*[/\\]"',`""'),`"\..*"',`""')
	cap use `"`dtaname'"', clear
	if _rc!=0 {
		zipcontents "`infile'", zipexe( `"`ZipExe'"')
		local dtaname: word 1 of `r(filelist)'
		use `"`dtaname'"', clear
	}
	if !regexm(`"`dtaname'"',`"\.dta$"') local dtaname `dtaname'.dta
	if `"`erase'"'==`"erase"' erase `"`dtaname'"'
}

if `"`filelist'"'==`"filelist"' {
	zipcontents "`infile'", zipexe( `"`ZipExe'"')
	return local filelist `r(filelist)'
}

end

/*************************************************************************************************************
Program to return contents of zip file
*************************************************************************************************************/
cap program drop zipcontents
program define zipcontents, rclass
syntax anything(name=infilename id="File path"), ZIPEXEcutable(string) [mac]
local ZipExe `zipexecutable'

* List the contents of the ZIP file and store them in a temporary file
local dir "`c(pwd)'"
tempname contents
if inlist(`"`c(os)'"',`"Windows"',`"Unix"') {
	!cd "`ZipExe'" & 7za l -ba `infilename' > `dir'/`contents'.txt
}

* Read the contents of the temporary file into a local macro
file open myfile using `dir'/`contents'.txt, read text
file read myfile line
* Loop through the file and extract filenames
while r(eof) == 0 {
	di `"`line'"'
	local filelist `"`filelist' `"`:word 6 of `line''"'"'
    file read myfile line
}
file close myfile
return local filelist = `"`filelist'"'
erase `dir'/`contents'.txt
end