Export VCF image to JPEG - export

I have created a .vcf contact with an iPhone and sent the file to myself in email. In that .vcf, I took a photo which is directly saved in the vCard, not in the phone's memory.
In the source of the .vcf, there is a code part starting like this:
PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/4QBYRXhpZgAATU0AKgAA
And it continues on... Now, I would like to get this photo and save it as a .JPEG. Any ideas how to do that?
Thanks.

In macOS, it easy to to from the line command with "vi" and "base64.
For example,
Export the "Apple Inc." contact that comes with every user account.
Use vi to manually remove the other lines.
Remove the heading and the meta-data for that line
PHOTO;ENCODING=b;TYPE=JPEG:
base64 decode the remaining file
# base64 -D -i Apple\ Inc..vcf -o Apple_Logo.jpeg

The encoding is Base64. You can find a tool for decoding online.
I can recommend Freeformatter.com's decoder, which lets you save as a binary file. You will then need to rename that file to photo.jpg.

You should use a vCard parser (like vpim) that provides the ability to pull photo data from the vCard.

Another vCard parser is ez-vcard, which is written in Java (disclaimer: I am the author).
File file = new File("vcard.vcf");
VCard vcard = Ezvcard.parse(file).first();
for (PhotoType photo : vcard.getPhotos()){
byte data[] = photo.getData();
//save byte array to file
}

Because this isn't https://apple.stackexchange.com/ I'll suggest a quick bash script that I've used to extracted images from .vcf files on the command line:
#!/bin/bash
#vcf_photo_extractor ver 20180207094631 Copyright 2018 alexx, MIT Licence
if [ ! -f "$1" ]; then
echo "Usage: $(basename $0) [path/]any/contact.vcf"
exit 1
fi
DATA=$(cat "$1" |tr -d "\r\n"|sed -e 's/.*TYPE=//' -e 's/END:VCARD.*//')
NAME=$(grep -a '^N;' $1|sed -e 's/.*://')
#if [ $(wc -c <<< $DATA) -lt 5 ];then #bashism
if [ $(echo $DATA|wc -c) -lt 5 ];then
echo "No images found in $1"
exit 2
fi
EXT=${DATA%%:*}
if [ "$EXT" == 'BEGIN' ]; then echo "FAILED to extract $EXT"; exit 3; fi
IMG=${DATA#*:}
FILE=${1%.*}
Fn=${FILE##*/}
if [ -f "${FILE}.${EXT}" ]; then
echo "Overwrite ${FILE}.${EXT} ? "
read -r YN
if [ "$YN" != 'y' ]; then exit; fi
fi
echo $IMG | base64 -id > ${FILE}.${EXT} || \
echo "Failed to output $NAME to ${FILE}.${EXT}"
This script tries to extract the base64 data, decode it using base64 and create an image file. I found on linux that base64 -id worked but base64 -d threw errors.
If you are a fan of single-line code or code-golf then this might work:
cat 1.vcf|tr -d "\n"|sed -e 's/.*TYPE=[^:]*://' -e 's/END:V.*//'|base64 -id >1.jpg
If you want something cleaner then Matt Brock's
vCard_photo_extractor.sh might be what you are looking for.

Used http://www.sobolsoft.com/convertvcfjpg/ with vCards from OSX, with success.

Related

Why my bash script does not work properly?

I wrote the following bash script for resizing an image (icon.png) using file config.xml, which contains necessary image sizes and links for saving resized files.
#!/usr/bin/env bash
function help {
echo "For running the program, please write"
echo "1) config.xml file's location containing image sizes and links for saving resized images;"
echo "2) a name of an image to be resized."
}
function resize {
array=()
while read -r line
do
case $line in *icon*) array+=("$line");; esac
done < $1
for ((a=0; a < ${#array[*]}; a++))
do
echo "$a: ${array[$a]}"
imagesize=$(echo "$a: ${array[$a]}" | grep "<icon"| grep -E -o "height=\"(\d+)" | grep -E -o "\d+")
imagelink=$(echo "$a: ${array[$a]}" | grep "<icon"| grep -E -o "[^\"\'=[:space:]]+\.(jpe?g|png|gif)")
echo $2 -resize $imagesizex$imagesize! ../../$imagelink
done
echo "Resizement has been executed"
}
if [ ! -f "$1" ] || [ ! -f "$2" ]
then
help
else
resize
fi
I get the following error: "line 9: $1: ambiguous redirect"
If I check the array, I get the following output:
<icon height="36" width="36" density="ldpi" src="res/icon/android/ldpi.png"/>.
I get only one line instead of a list of lines.
Could you please help me to make the code work correctly? Also, I would like to know why the script isn't correct.

Using loop to convert multiple files into separate files

I used this command to convert multiple pcap log files to text using tcpdump :
$ cat /home/dalya/snort-2.9.9.0/snort_logs/snort.log.* | tcpdump -n -r - > /home/dalya/snort-2.9.9.0/snort_logs2/bigfile.txt
and it worked well.
Now I want to separate the output, each converted file in a separate output file using loop like this :
for f in /home/dalya/snort-2.9.9.0/snort_logs/snort.log.* ; do
tcpdump -n -r "$f" > /home/dalya/snort-2.9.9.0/snort_logs2/"$f.txt" ;
done
But it gave me :
bash: /home/dalya/snort-2.9.9.0/snort_logs2//home/dalya/snort-2.9.9.0/snort_logs/snort.log.1485894664.txt: No such file or directory
bash: /home/dalya/snort-2.9.9.0/snort_logs2//home/dalya/snort-2.9.9.0/snort_logs/snort.log.1485894770.txt: No such file or directory
bash: /home/dalya/snort-2.9.9.0/snort_logs2//home/dalya/snort-2.9.9.0/snort_logs/snort.log.1487346947.txt: No such file or directory
I think the problem in $f, Where did I go wrong?
If you run
for f in /home/dalya/snort-2.9.9.0/snort_logs/snort.log.* ; do
echo $f
done
You'll find that you're getting
/home/dalya/snort-2.9.9.0/snort_logs/snort.log.1485894664
/home/dalya/snort-2.9.9.0/snort_logs/snort.log.1485894770
/home/dalya/snort-2.9.9.0/snort_logs/snort.log.1487346947
You can use basename
To get only the filename, something like this:
for f in /home/dalya/snort-2.9.9.0/snort_logs/snort.log.* ; do
base="$(basename $f)"
echo $base
done
Once you're satisfied that this is working, remove the echo statement and use
tcpdump -n -r "$f" > /home/dalya/snort-2.9.9.0/snort_logs2/"$base.txt"
instead.
Edit: tcpdump -n -r "$base" > ... should have been tcpdump -n -r "$f" > ...; you only want to use $base in the context of creating the new filename, not in the context of reading the existing data.

How I can retrieve and play audio file in cakephp

I am uploading audio files using cakephp app. I can move file successfully to folder and can update its path in database too. But I can not retrive that file successfully. server reply with 206 Partial Content AND some times with 304 Not Modified status. can anyone help me to figure out why server respondig with such status?
You are using chromium. Mp3 is not supported in both chromium and firefox for ubuntu. You can convert mp3 to ogg to play them in chromium and firefox. Or you can install chrome if you don't want to convert mp3 to ogg. If you want to convert them, you can do it with this shell script
#!/bin/bash
echo "The script convert mp3->ogg or ogg->mp3.";
echo "The script takes one parameter: ";
echo "[mp3ogg] - converting mp3->ogg";
echo "[oggmp3] - converting ogg->mp3";
if [ "$1" = "" ]; then
echo "";
echo "Argument does not exist!!!";
exit 102;
fi
if [ "$1" = "mp3ogg" ]; then
for file in *.mp3; do
avconv -i "$file" "`echo '../ogg/'${file%.mp3}.ogg`";
done
exit 0;
fi
if [ "$1" = "oggmp3" ]; then
for file in *.ogg; do
avconv -i "$file" -acodec libmp3lame "`echo ${file%.ogg}.mp3`";
done
exit 0;
fi
exit 104;
But you only problem is that chromium and firefox will not support mp3, they will support only ogg in ubuntu.

Bash scripting testing for existing file with arbitrary extension in a while or for loop

I've been trying to figure this one out for a while. I've read through multiple threads, and feel like I'm close, but the script just isn't coming together.
Scenario:
I have a media server and thousands of movie files. Each movie file has various accessory files such as the Cover artwork, Database info, Fanart, and trailer. While everything in the directory has it's coverart and database info, some files may or may not have their respective fanart or trailer. For these files I'm trying to get this script working which will create an empty "dummy" file in place of the file that should be there. Then when I actually have the time I can go back and search out just the dummy files and work to fill in the gaps where I can.
Here is what I have so far.
#!/bin/bash
find . -type f -print0 | while read -d $'\0' movie ;
do
echo $movie
moviename=${movie%\.*} #remove the extension from the string
moviename1=`echo $moviename | sed 's/\ /\\ /'` #add escaped spaces to the string
echo $moviename1 #echo the string (for debugging)
if [ ! -f $moviename-fanart* ]; #because the fanart could be .jpg, or .png, etc
then
echo "Creating $moviename-fanart.dummy"
touch "$moviename-fanart.dummy"
fi
if [ ! -f $moviename-trailer* ]; #because tralers could be .mp4, .mov, .mkv, .avi, etc
then
echo "Creating $moviename-trailer.dummy"
touch "$moviename-trailer.dummy"
fi
done
This should be pretty simple, but I think that I'm not getting the proper formating for the input string going into the test operators.
Any help would be greatly appreciated.
Thanks
Line-by-line analysis:
find . -type f -print0 | while read -d $'\0' movie; do
OK, but with bash4 you can just use shopt -s globstar to operate recursively on a directory.
moviename=${movie%\.*} #remove the extension from the string
You don't need the backslash.
moviename1=`echo $moviename | sed 's/\ /\\ /'` #add escaped spaces to the string
This line is suspect because if you quote the name, escaped spaces become doubly-escaped. You're confusing the value of the string with the representation you see of it.
if [ ! -f $moviename-fanart* ]; then #because the fanart could be .jpg, or .png, etc
Quote the string or use bash's [[ test keyword. It's a little dangerous to expand a glob inside the test expression because if it matches multiple results you'll get an error. That said, if you're sure there can be only one you can quote up to the glob. "$moviename-fanart"*.
touch "$moviename-fanart.dummy"
Here, you quote it. So essentially you're dealing with a different name now.
fi
if [ ! -f $moviename-trailer* ]; then #because tralers could be .mp4, .mov, .mkv, .avi, etc
echo "Creating $moviename-trailer.dummy"
touch "$moviename-trailer.dummy"
fi
Same thing.
done

Calculate checksum of audio files without considering the header

I want to programmatically create a SHA1 checksum of audio files (MP3, Ogg Vorbis, Flac).
The requirement is that the checksum should be stable even if the header (eg. ID3) changes.
Note: The audio files don't have CRCs
This is what I tried by now:
1) Reading + Hashing all MPEG frames using Perl and MPEG::Audio::Frame
my $sha1 = Digest::SHA1->new;
while (my $frame = MPEG::Audio::Frame->read(\*FH)) {
$sha1->add($frame->content());
}
2) Decoding + Hashing all MPEG frames using Python and libmad (pymad)
mf = mad.MadFile(path)
sha1 = hashlib.sha1()
while 1:
buf = mf.read()
if (buf is None):
break
sha1.update(buf)
3) Using mp3cat
> mp3cat - - < file.mp3 | sha1sum
However, none of those methods provided a stable checksum. Namely, in some cases the checksum changed after retagging the file with picard.
Are there any libraries that already provide what I want?
I don't care about the programming language…
Update:
I debugged the case a bit further.
The libmad checksum inconsitency seems to happen in cases where libmad gets some decoding errors, like "Huffman data overrun (0x0238)".
As this really happens on many of the mp3 files I'm not sure if it really indicates a broken file…
If you are looking for stable hashes for the actual music you might want to look at libOFA. Your current methods will give you different results because the formats can have embedded tags. Also if you want two different files with the same song to return the same hash you need to regard things like bitrate and sample frequencies.
libOFA on the other hand can give you a stable hash that can be used between formats and different encodings. Might be what you want?
I needed tools to quickly check if my MP3/OGG library is still valid.
For MP3 I found mp3md5.py (http://snipplr.com/view/4025/mp3-checksum-in-id3-tag/) which does the job, but no simple tool for OGG Vorbis, but I coded a little bash script to do this for me.
Both tools should tolerate modifications of the comment/ID3Tag.
#!/bin/bash
# This bash script appends an MD5SUM to the vorbiscomment and/or verifies it if it exists
# Later modification of the vorbis comment does not alter the MD5SUM
# Julian M.K.
FILE="$1"
if [[ ! -f "$FILE" || ! -r "$FILE" || ! -w "$FILE" ]] ; then
echo "File $FILE" does not exist or is not readable or writable
exit 1
fi
OLDCRC=`vorbiscomment "$FILE" | grep ^CRC=|cut -d "=" -f 2`
NEWCRC=`ogginfo "$FILE" |grep "Total data length:" |cut -d ":" -f 2 | md5sum |cut -d " " -f 1`
if [[ "$OLDCRC" == "" ]] ; then
echo "ADDED $FILE $NEWCRC"
vorbiscomment -a -t "CRC=$NEWCRC" "$FILE"
# rewrite CRC to get proper data length, I dont know why this is necessary
NEWCRC=`ogginfo "$FILE" |grep "Total data length:" |cut -d ":" -f 2 | md5sum |cut -d " " -f 1`
vorbiscomment -w -t "CRC=$NEWCRC" "$FILE"
elif [[ "$OLDCRC" == "$NEWCRC" ]] ; then
echo "VERIFIED $FILE"
else
echo "FAILURE $FILE -- $OLDCRC - $NEWCRC"
fi
There is an easy stable way to do it. Just make a copy of the file and remove all the tags from it (e.g. using mutagen.id3) and take the hashsum of the resulting file.
The only disadvantage of this method is its performance.
Bene, If I were you, (And I am in the process of working on something very similar to what you want to do), I would hash the mp3 data block. (Extract it to raw data first, and write it out to disk, so you know what you are dealing with). Then, modify the ID3 tag. Hash your data again. Now, if it changes, compare your two sets of raw data and find out WHERE it changed. Chances are, you might be over-stepping a boundary somewhere. If I recall, MP3 files start with something like FF F8. Well, at least the frame does.
I'm interested in your findings, as I'm still writing all my code to deal with the finger prints, etc, and haven't gotten to the actual hashing yet.
Update many years later:
See my answer here to a very similar question. It turns out that ffmpeg actually supports doing checksums of the individual streams. To get the md5 hash of only the audio stream:
ffmpeg -i "$filename" -map 0:a -codec copy -f md5 "$filename.md5"
There is also support for other hash formats with the generic -f hash format, or for doing it per frame with -f framemd5.
I'm trying to do the same thing. I used MD5 instead of SHA1. I started to export audio checksums using mp3tag (www.mp3tag.de/en/); then made a Perl script similar to yours to do the same thing. Then I removed all tags from my test file, and the audio checksum remained the same.
This is the script:
use MPEG::Audio::Frame;
use Digest::MD5 qw(md5_hex);
use strict;
my $file = 'E:\Music\MP3\Russensoul\01 - 5nizza , Soldat (Russensoul - Russensoul).mp3';
my $mp3tag_audio_md5 = lc '2EDFBD62995A46A45CEEC08C1F303486';
my $md5 = Digest::MD5->new;
open(FILE, $file) or die "Cannot open $file : $!\n";
binmode FILE;
while(my $frame = MPEG::Audio::Frame->read(\*FILE)){
$md5->add($frame->asbin);
}
print '$md5->hexdigest : ', $md5->hexdigest, "\n",
'mp3tag_audio_md5 : ', $mp3tag_audio_md5, "\n",
;
Is it possible that whatever you use to modify your tags sometimes also modifies mp3 headers?

Resources