iTMSTransporter metadata.xml md5 utility ios - ios

So I have 100 achievements to upload, rather than using the website I thought it may be faster to create a metadata.xml file and use iTMSTransporter to upload the data. Unfortunately one snag is a MD5 checksum must be computed for each image file, or Apple rejects the entire itmsp package. Requiring this almost invalidates the whole "ease" of using iTMSTransporter.
Is there a utility to parse the metadata file and update it with the checksums? Or perhaps something which generates a metadata file and does it?

There is a command line program that will generate the metadata.xml file and compute the files' checksums. It requires you to put your metadata in a YAML file which it turns into a metadata.xml: https://github.com/colinhumber/itunes_transporter_generator
You can use this script to update a directory containing a metadata.xml file (or files) and assets:
require "rexml/document"
require "digest"
def set_checksum(path)
xml = File.read(path)
doc = Document.new(xml)
doc.get_elements("//achievement//file_name").each do |e|
next unless e.text =~ /\S/
file = File.join($source, e.text.strip)
puts "Computing checksum for #{file}"
$md5.file(file)
checksum = $md5.hexdigest!
node = e.parent.elements["checksum"]
node = Element.new("checksum", e.parent) unless node
node.text = checksum
node.add_attribute("type", "md5")
end
puts "Saving update file"
File.write(path, doc.to_s)
end
include REXML
$source = ARGV.shift || Dir.pwd
$md5 = Digest::MD5.new
Dir["#$source/*.xml"].each do |path|
puts "Processing #{path}"
set_checksum(path)
end
Use it as follows:
> ruby script.rb
or
> ruby script.rb /path/to/metadata/directory

Related

Rails FTP OPEN CSV

I have the following code to connect my rails app to my FTP. This works great. However, I want to use open-uri to open the csv file so I can parse it. Any ideas how to do this? I think it's an easy thing to do but I'm missing something.
require 'net/ftp'
ftp = Net::FTP.new
ftp.connect("xxx.xxx.xx.xxx",21)
ftp.login("xxxxx","xxxx")
ftp.chdir("/")
ftp.passive = true
puts ftp.list("TEST.csv")
You'll need to use #gettextfile.
A) Get the file to a local temporary file and read its content
# Creating a tmp file can be done differently as well.
# It may also be omitted, in which case `gettextfile`
# will create a file in the current directory.
Dir::Tmpname.create(['TEST', ['.csv']) do |file_name|
ftp.gettextfile('TEST.csv', file_name)
content = File.read(file_name)
end
B) Pass a block to gettextfile and get the content one line at a time
content = ''
ftp.gettextfile('TEST.csv') do |line|
content << line
end

Using Tempfile to create a zip file in rails

I want to create a temporary .zip in rails. For creating zip file I am using rubyzip gem.
Currently I am doing this:
zfname = Tempfile.new(['somename','.zip'], Rails.root.to_s + '/tmp/')
Zip::ZipFile.open(zfname.path, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
This generates following error:
Zip::ZipError: Zip end of central directory signature not found
Is it possible to use Tempfile for zip? If yes, what is wrong here?
In my rails app when I needed to send zip files to user, I just stored them in a buffer and used 'send data' method in controller.
I was trying to use 'Tempfile' initially but it had an added task of removing zip files after sending it to user which is a pain.
Is this something you are looking for?
Zip::OutputStream.write_buffer do |stream|
file_paths.each_with_index do |file_path, index|
# rename the pdf
stream.put_next_entry("#{name}-#{index + 1}.pdf")
# add pdf to zip
stream.write IO.read(file_path)
end
end
So it doesn't actually look like you need or want a Tempfile. You really want a random path in the Rails.root/tmp directory. Try something like this:
zfpath = Rails.root.join('tmp', "somename-#{SecureRandom.hex(8)}.zip"
Zip::ZipFile.open(zfpath, Zip::ZipFile::CREATE) do |zipfile|
zipfile.add(file, basepath + file)
end
Update:
While it's far more complex, you can find a discussion of how to do this with a Tempfile here - http://thinkingeek.com/2013/11/15/create-temporary-zip-file-send-response-rails/ .

Carrierwave & Zipfiles: Using an extracted file as a version

Something I'm not getting about the version process...
I have a zip file with a file inside, and I want to upload the file as a "version" of the zip:
Uploader:
version :specificFile do
process :extract_file
end
def extract_file
file = nil
Zip::ZipFile.open(current_path) do |zip_file|
file = zip_file.select{|f| f.name.match(/specificFile/)}.first
zip_file.extract(file, "tmp/" + file.name.gsub("/", "-")){ true }
end
File.open("tmp/" + file.name.gsub("/", "-"))
end
Usage:
=link_to "Specific File", instance.uploader.specificFile.url
Only this just nets me two copies of the zip. Clearly, there's something I'm missing about how version / process works, and I haven't been able to find documentation that actually explains the magic.
So how do I do this, and what am I missing?
This provided the "why", although it took a bit to understand:
How do you create a new file in a CarrierWave process?
To rephrase, when you go to create a version, carrierwave makes a copy of the file and then passes the process the file path. When the process exits, carrierwave will upload the contents of that path - not the file the process returns, which is what I thought was going on.
Working code:
version :specificFile do
process :extract_file
def full_filename (for_file = model.logo.file)
"SpecificFile.ext"
end
end
def extract_plist
file = nil
Zip::ZipFile.open(current_path) do |zip_file|
file = zip_file.select{|f| f.name.match(/specificFile/)}.first
zip_file.extract(file, "tmp/" + file.name.gsub("/", "-")){ true }
end
File.delete(current_path)
FileUtils.cp("tmp/" + file.name.gsub("/", "-"), current_path)
end
So, to make what I want to happen, happen, I:
Tell carrierwave to use a particular filename. I'm using a hardcoded value but you should be able to use whatever you want.
Overwrite the contents of current_path with the contents you want under the version name. In my case, I can't just overwrite the zip while I'm "in it" (I think), so I make a copy of the file I care about and overwrite the zip via File and FileUtils.
PS - It would be nice to avoid the duplication of the zip, but it doesn't look like you can tell carrierwave to skip the duplication.

Ruby Net::FTP, extract filename from ftp.list()

I'm using the following code to try and get all files from ftp using Ruby.
files = ftp.list()
files.each do |file|
ftp.gettextfile(file)
end
The problem is ftp.list returns a whole line of information, not just the filename e.g.
-rw-r--r-- 1 ftp ftp 0 May 31 11:18 brett.txt
How do I extract the filname from this string?
Many thanks
You can use the nlst public method like this
files = ftp.nlst("*.zip")|ftp.nlst("*.txt")|ftp.nlst("*.xml")
#optionally exclude falsely matched files
exclude = /\.old|temp/
#exclude files with 'old' or 'temp' in the name
files = files.reject{ |e| exclude.match e } #remove files matching the exclude regex
files.each do |file|
#do something with each file here
end
If you want to process the output of ftp.list you may find net-ftp-list useful.
However, list appears to be useful, as you can pass in a matching pattern, which it doesn't appear that nlst supports. I just did a quick-and-dirty hack to make list output work:
ftp.list("*.zip") do |zipfile|
zipfile = zipfile.split(/\s+/).last
# ... do something with the file
end

How to close a ZipFile

I'm passing a dynamic zip file location to a def from a database. I want to unzip the file to a temp location, extract the xml report file inside, apply an xslt stylesheet, copy it as an rhtml to a view directory for rendering, and delete the temp extracted xml file. The functionality is working fine (the rhtml file is overwritten each time and renders) except it is extracting from the same parent zip for each execution and the extracted xml can not be deleted which leads me to believe that the first execution is not closing the parent zip (releasing its handle). Therefore, subsequent executions are extracting the xml from the first zip executed. I've tried "Zip::ZipFile.close", "zipFile = Zip::ZipFile.open(fileLocation); zipFile.close","File.close(fileLocation)", and other permutations.
Any help would be appreciated.
Can you pass a block to Zip::ZipFile.open? This will close it when the block exits:
Zip::ZipFile.open(file_name) do |zip_file|
zip_file.extract('report.xml', '/tmp')
end
# zip file is closed at this point
# apply_xslt
# copy rhtml to app/views/...
# etc
== EDIT ==
Based on your comments, here's a working example:
require 'rubygems'
require 'zip/zip'
require 'fileutils'
zip_file_name = 'test.zip'
out_dir = 'tmp_for_zip'
FileUtils.mkdir_p out_dir
Zip::ZipFile.open(zip_file_name) do |zip_file|
report_name = File.basename(zip_file.name).gsub('zip', 'xml')
out = File.join(out_dir, report_name)
zip_file.extract(report_name, out) unless File.exists?(out)
puts "extracted #{report_name} to #{out}"
end
Also, I don't know if you are running a unix, but you can use lsof (list open files) to find out if the file is actually open:
lsof | grep your_file_name

Resources