Philip Maloney Stream Fetcher

Seit einigen Wochen können auf srf.ch die Philip Maloney Streams nicht mehr als mp3-Datei heruntergeladen werden. Die einzigen Dateien, die ich finden konnte, sind unzählige, 10 Sekunden langen aac-Dateien. Diese werden wärend dem Streaming offenbar Stück für Stück übertragen.

Die aac-Dateien scheinen nicht ganz wie gewünscht zu funktionieren. So beinhalten sie zwar jeweils Daten für 10 Sekunden, jeder von mir getestete Musikplayer zeigt die Zeitdauer aber als 0 Sekunden an. Dies lässt sich zum Glück mit ffmpeg korrigieren. Auch lassen sich die Dateien damit wieder zusammensetzen und in eine mp3-Datei umwandeln.

Um das Ganze zu automatisieren, habe ich ein neues Script geschrieben. Dieses lädt die aac-Dateien herunter und wandelt sie in eine einzelne mp3-Datei um. Dieses wird zudem mit den korrekten ID3-Tags versehen. Das Script ist nachfolgend aufgeführt. Die Verwendung des Scripts ist auf eigene Gefahr! Das Herunterladen der Streams und danach online Bereitstellen ist nicht legal! Deshalb wird es von dieser Seite aus keine Links auf die mp3-Dateien geben.

Script

Das Script wurde unter Linux (Ubuntu) sowie auf der Synology Diskstation getestet. Es werden die Tools ffmpeg und mp3info benötigt.

<?php

/*****************************************************************
 * This script finds the streaming data for a Philip Maloney
 * stream and downloads it. The stream is splitted in multiple
 * aac files which get merged and converted to a mp3 file
 * Copyright (c) 2015 by George Ruinelli <george [at] ruinelli.ch>
 * Updates & Infos: www.ruinelli.ch/maloney
 * Use this script at your own risc!
 * The Philip Maloney streams are copyright by Roger Graf (www.rogergraf.ch)
 * The streams are prvided by www.srf.ch (www.srf.ch/sendungen/maloney)
 * It is forbiden to provide the generated mp3 files on the internet!
 *
 * This script has to be run on a command line under linux or
 * another equal system. It depends on PHP, ffmpeg and mp3info (optional)!
 * Run it without a parameter and it downloads the latest episode.
 * To download a specific stream, provide its ID as a parameter
 * I.e. a6056b76-a537-43f3-a9a2-9d72ba63f430
 *
 * Changelog:
 *   03.01.2015 - Initial Release
 *   02.02.2015 - ID grabber updated
 *****************************************************************/

$PATH_TO_FFMPEG = "ffmpeg";
$PATH_TO_ID_TAGGER = "../bin/mp3info";

/* Nothing to change bejond this line */

// Report simple running errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);

/*****************************************************************
 * Helper function
 * It gets the data from a URL using curl
 *****************************************************************/
function get_data($url)
{
  echo "Fetching $url...\n";
  $ch = curl_init();
  $timeout = 5;
  curl_setopt($ch,CURLOPT_URL,$url);
  curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
  curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);

  curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" );
  curl_setopt( $ch, CURLOPT_URL, $url );
  curl_setopt( $ch, CURLOPT_COOKIEJAR, $cookie );
  curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
  curl_setopt( $ch, CURLOPT_ENCODING, "" );
  curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
  curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
  curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
  curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
  curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 );

  $data = curl_exec($ch);
  curl_close($ch);
  return $data;
}

echo "*****************************************************************\n";
echo "* Downloading a Philip Maloney stream\n";
echo "* Copyright (c) 2015 by George Ruinelli <george [at] ruinelli.ch>\n";
echo "* Updates & Infos: www.ruinelli.ch/maloney\n";
echo "*****************************************************************\n";

/*****************************************************************
 * Get the ID of the stream
 *****************************************************************/
// $ID = $_GET["ID"];
$ID = $argv[1];
if($ID == ""){
  echo "No ID given, downloading the latest stream\n";

  for($i=0; $i < 10; $i++){ //it seems that this failes sometimes under cron, so try it multiple times
    echo "Try $i\n";
    $overview = get_data("www.srf.ch/sendungen/maloney");
//     echo "$overview\n";
    $overview_arr = explode("\n", $overview);
//     $overview_audioembed_urls = array_values(preg_grep('/audioembed/', $overview_arr)); //get list of all linked streams and their IDs
  // [0] => href="http://www.srf.ch/player/radio/audioembed?id=a6056b76-a537-43f3-a9a2-9d72ba63f430&amp;mode=inline&amp;autoplay=true&amp;html5playersize=small"
    $overview_audioembed_urls = array_values(preg_grep('/popupaudioplayer/', $overview_arr)); //get list of all linked streams and their IDs
// href="http://www.srf.ch/play/radio/popupaudioplayer?id=22095695-98a9-4837-bbe0-18e7a94cfe6f"
    print_r($overview_audioembed_urls);

    $p1 = strpos($overview_audioembed_urls[0], "?id="); //select most top (latest) stream
//     $p2 = strpos($overview_audioembed_urls[0], "&amp;mode");
    $p2 = $p1 + strlen("?id=") + strlen("22095695-98a9-4837-bbe0-18e7a94cfe6f");
    $ID = substr($overview_audioembed_urls[0], $p1 + strlen("?id="), $p2 - $p1 - strlen("?id="));

//   echo "ID: $ID\n";
//   exit;

  if($ID != "")break;
  }
}

if($ID == ""){
  echo "No ID given, quitting\n";
  exit;
}
echo "Found ID: \"$ID\"\n";

/*****************************************************************
 * Get XML data of stream
 *****************************************************************/
echo "Fetching Philipp Maloney Episode with ID $ID\n";

$xml_url="http://www.srf.ch/webservice/ais/report/audio/withLiveStreams/$ID.xml";
// I.e. http://www.srf.ch/webservice/ais/report/audio/withLiveStreams/a6056b76-a537-43f3-a9a2-9d72ba63f430.xml
$xml_data = get_data($xml_url);

$p = xml_parser_create();
xml_parse_into_struct($p, $xml_data, $vals, $index);
xml_parser_free($p);

// print_r($index);
// print_r($vals);

$title_id = $index['TITLE'][0];
$title = $vals[$title_id]['value'];

$lead_id = $index['LEAD'][0];
$lead = $vals[$lead_id]['value'];

$setTitle_id = $index['ASSETSETTITLE'][0];
$setTitle = $vals[$setTitle_id]['value'];

$publishedDate_id = $index['PUBLISHEDDATE'][0];
$publishedDate = $vals[$publishedDate_id]['value'];

$hlsPlaylistUrl_id = $index['HLSPLAYLISTURL'][0];
$hlsPlaylistUrl = $vals[$hlsPlaylistUrl_id]['value'];

echo "Title:       \"$title\"\n";
echo "Description: \"$lead\"\n";
echo "Broadcasted: \"$setTitle\"\n";
// echo "hlsPlaylistUrl: $hlsPlaylistUrl\n";

// $mp3 = date('Y-m-d') . " - $title.mp3";
$mp3 = substr($publishedDate, 0, 10) . " - $title.mp3";
echo "Final mp3 file: $mp3\n";

/*****************************************************************
 * Fetch playlist
 *****************************************************************/
$hlsPlaylist = get_data($hlsPlaylistUrl);
/* i.e.
 * hlsPlaylist: #EXTM3U
 * #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=30000,CODECS="mp4a.40.2"
 * http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q10,q20,.mp4.csmil/index_0_a.m3u8?null=
 * #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=62000,CODECS="mp4a.40.2"
 * http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q10,q20,.mp4.csmil/index_1_a.m3u8?null=
 */
$hlsPlaylist_arr = explode("\n",$hlsPlaylist);
$hlsPlaylist_urls = preg_grep('/http/', $hlsPlaylist_arr);
$hlsPlaylist_fetch_url = current($hlsPlaylist_urls); //select first entry
// i.e. http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q10,q20,.mp4.csmil/index_0_a.m3u8?null=

$aac_urls_data = get_data($hlsPlaylist_fetch_url);
// echo "aac_urls: $aac_urls_data\n";
/* i.e.
 * #EXTINF:10,
 * http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q10,q20,.mp4.csmil/segment1_0_a.aac?null=
 * [..]
 * #EXTINF:10,
 * http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q10,q20,.mp4.csmil/segment120_0_a.aac?null=
 */

$aac_urls_arr = explode("\n",$aac_urls_data);
$aac_urls = array_values(preg_grep('/http/', $aac_urls_arr)); //generate url list of all parts

/*****************************************************************
 * Download all parts
 *****************************************************************/
echo "Downloading parts (" . count($aac_urls) . ")";
$i = 0;
exec("rm -f filelist.txt");
foreach($aac_urls as $aac_url){
  exec("wget -q $aac_url -O $i.aac"); //download  
  /* The aac files seem to be corrupted. Their length is 0 seconds instead of 10.
   * This will fix them (optional as it also happens during the later merging) */
  exec("$PATH_TO_FFMPEG -loglevel panic -i $i.aac -c copy $i-fixed.aac");
  exec("rm -f $i.aac");
  exec("echo \"file $i-fixed.aac\" >> filelist.txt"); //generate file list for ffmpeg
  $i++;
  echo ".";  
//   if($i == 5)break;  //testing
}

echo "\nDownloaded $i parts\n";

/*****************************************************************
 * Merging
 *****************************************************************/
echo "Merging parts with ffmpeg and save as mp3 (stream duration approx. " . round($i*10/60, 1) . " minutes = " . round($i*10*128/8, 1) . "kB @ 128 kbits/s)...\n";
exec("rm -f \"$mp3\"");
exec("$PATH_TO_FFMPEG -loglevel panic -stats -f concat -i filelist.txt > copy \"$mp3\"");

echo "\nMerging completed\n";

/*****************************************************************
 * Cleanup
 *****************************************************************/
echo "Deleting temporary files...\n";
exec("rm -f *.aac");
exec("rm -f filelist.txt");
exec("rm -f copy");

/*****************************************************************
 * Add ID3 Tags
 * Note: There are other tools which would support ID3v2 or newer
 * However due to my lazyness, I did not compile them for my
 * Synology Diskstation
 *****************************************************************/
echo "Adding ID3 Tags...\n";
exec("$PATH_TO_ID_TAGGER -t \"$title\" \"$mp3\"");
exec("$PATH_TO_ID_TAGGER -l \"Philip Maloney\" \"$mp3\"");
exec("$PATH_TO_ID_TAGGER -a \"Roger Graf\" \"$mp3\"");
exec("$PATH_TO_ID_TAGGER -c \"$lead\" \"$mp3\""); //max 30 characters on ID3v1.0!

exec("echo \"$ID\" > \"$mp3.txt\"");
exec("echo \"$title\" >> \"$mp3.txt\"");
exec("echo \"$lead\" >> \"$mp3.txt\"");
exec("echo \"$xml_url\" >> \"$mp3.txt\"");

echo "Completed\n";

echo "*****************************************************************\n";
exec("$PATH_TO_ID_TAGGER \"$mp3\"");
echo "*****************************************************************\n";
?>

Updates

03.01.2015:

Anstatt dem umständlichen Herunterladen der einzelnen aac-Dateien kann mittels avconv direkt auf die m3u8 Playlist verwiesen werden und daraus eine mp3-Datei generiert werden:

avconv -i http://srfaodorigin-vh.akamaihd.net/i/world/maloney/a6056b76-a537-43f3-a9a2-9d72ba63f430.,q20,.mp4.csmil/master.m3u8 foo.mp3

Besten Dank an Philippe K. für den Tipp.

02.02.2015:

ID grabber aktualisiert.

How to use a free Web SMS from Sunrise within a shell script

Many mobile phone providers allow you a free amount of SMS if you use the web interface. Maybe you don’t want to log in every time to use them or you want to send the SMS from your own web site or even from within a shell script.

The following script can be uses to send free SMS with using the web SMS system of the Swiss Mobile provider Sunrise. It is adapted by the great Android tool from play.google.com/store/apps/details?id=de.ub0r.android.websms and especially the Sunrise plugin by Koni (play.google.com/store/apps/details?id=com.rothconsulting.android.websms.connector.sunrise). The source code for it is available under github.com/konir/websms-connector-sunrise.

I use it i.e. to check any incoming email and send me an SMS when ever a special subject is found.

Since I have two account at Sunrise, the commands are a bit more tricky as after the login the correct account has to be selected first. The good thing is that I can check the number of free SMS and switch to the other account once all SMS are used.

Updates

  • 21.09.2014: Updated script with more options and corrected URLs
  • 19.12.2014: Addapted URL changes for new Sunrise Webinterface, Extended script

Script

Send SMS

#!/bin/bash
##################################################################
# Script to send a SMS over the Sunrise free SMS webinterface
# Call it with no parameters to get usage help
# Copyright 2013-2014 by George Ruinelli <george@ruinelli.ch>
# Adapted from https://github.com/konir/websms-connector-sunrise
# Changelog
# 19.12.2014:
# - Fixed URL (http:// => https://)
#   See changes on https://github.com/konir/websms-connector-sunrise/commit/bcbdba308b75c5c6b852bce147968a93a9668faa
# - Extended script to show numbe rof really used SMS after sending
##################################################################

#Example call:
# bash /home/ruinelli/sms/sms_send.sh -r +4176******* -m "This is an test message" -v -a

account1=076*******
account2=076*******
password="*******"

script_path=`dirname "$0"`
logfile="$script_path/send.log"
html_logfile="$script_path/sms_log.htm"
dryrun=0
verbose=0
showhelp=0
force_account1=0
extended=0

date >>  $logfile

##########################
while getopts r:m:d?vax option #see http://linux.about.com/od/Bash_Scripting_Solutions/a/How-To-Pass-Arguments-To-A-Bash-Script.htm
do
        case "${option}"
        in
                r) recipient=${OPTARG};;
                m) message=${OPTARG};;
                d) dryrun=1;;
                v) verbose=1;;
                a) force_account1=1;;
                x) extended=1;;
                ?) showhelp=1;;
        esac
done

if [ "$recipient" == "" ]; then
    echo "ERROR: No recipient given"
    showhelp=1
fi

if [ "$message" == "" ]; then
    echo "ERROR: No message given"
    showhelp=1
fi

if [ $showhelp -ge 1 ]; then
    echo "---------------------------------------------------------------------------------"
    echo "SMS sender sends a SMS over Sunrises Web2SMS interface"
    echo "Since I have 2 accounts, it first uses the free SMS of the"
    echo "2nd one, then switches to the 1st one."
    echo "Copyright 2013 by George Ruinelli"
    echo "Parameter:"
    echo " -m MESSAGE (max 160 characters, more will be truncated)"
    echo " -r RECIPIENT NUMBER (leading country code is optional)"
    echo " -d (optional, dry run, does not actually send the message)"
    echo " -v (optional, appends the number of available free SMS to the message)"
    echo " -a (optional, force usage of account 2, even when no free SMS left)"
    echo " -x (optional, split into multiple SMS if text is too long, max 480 characters)"
    echo ""
    echo "The message will be sent from account 2 ($account2) if there are free SMS left,"
    echo "else account 1 ($account1) is used (unless -a is applied where always account 1 is used)"
    echo "Example: bash /home/ruinelli/sms/sms_send.sh -v -r 076******* -m \"This is a test message\""
    echo "---------------------------------------------------------------------------------"
    exit
fi

if [ $verbose -ge 1 ]; then #make space for 9 characters additional: " (xx, xx)"
    echo "Will append number of free SMS"
    valid_message_lenght=151 #160-9
else
    valid_message_lenght=160
fi

#check message length
length=`echo ${#message}`

if [ $extended -ge 1 ]; then
#   nothing to do
  if [ $length -gt $valid_message_lenght ]; then
      echo "NOTE, message is too long ($length characters total), it might consume multiple SMS"
  fi
else
  if [ $length -gt $valid_message_lenght ]; then
      let valid_message_lenght=valid_message_lenght-4
      message=`echo ${message:0:$valid_message_lenght}`
      message="$message..."
      echo "WARNING, message is too long ($length characters total), will truncate it to: $message"
  fi
fi

##########################

#logging in
echo "Logging in..." | tee -a $logfile
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d LoginForm_Login="$account1" -d LoginForm_Password="$password" -d LoginRedirectSecret="89cff646d5a3f65ce8a8ea59a3d7cad3" -d LoginRedirectURL="https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewStandardCatalog-Browse?CatalogCategoryID=zv7AqFI.Z.gAAAEkbGdQzDCf&LoginOrigin=Mein%20Konto&LoginDestination=Mein%20Konto" -d ajaxhref="http://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewPersonalCodeRetrieval-New?SpcRetrievalMode=ECare" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewApplication-Login > $html_logfile

echo "Selecting accounts and fetching left free SMS..." | tee -a $logfile

#getting amount of left free SMS for account 1
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account1" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt > $html_logfile

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

left1=`grep "Gratis" $html_logfile`
left1=`echo $left1 | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

echo "Free SMS left on account 1: $left1" | tee -a $logfile

#getting amount of left free SMS for account 2
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account2" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt  > /dev/null

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

cat $html_logfile > "left_sms_account2.htm"

left2=`grep "Gratis" $html_logfile`
left2=`echo $left2 | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

# left2=0 #simulating no SMS left on account 2

echo "Free SMS left on account 2: $left2" | tee -a $logfile

### selecting account for sending
used_account1=""
used_account2=""
if [ $force_account1 -ge 1 ]; then #force account1
  echo "Forcing to use account 1" | tee -a $logfile #if no free SMS left, we pay for them
  account=$account1
#   let left1=left1-1 #update verbose text for situation after sending
    used_account1="*" #mark account
else
  if [ $left2 -ge 1 ]; then #use account 2 first
    echo "Using account 2" | tee -a $logfile
    account=$account2
#     let left2=left2-1 #update verbose text for situation after sending
    used_account2="*" #mark account
  else
    echo "Using account 1" | tee -a $logfile #and if no free SMS left, we pay for them
    account=$account1
#     let left1=left1-1 #update verbose text for situation after sending
    used_account1="*" #mark account
  fi
fi

#now select right account
echo "Selecting sender: $account..." | tee -a $logfile
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt  > /dev/null

#add verbose text
if [ $verbose -ge 1 ]; then #make string showing free SMS: " (xx, xx)"
    message="$message ($used_account1$left1, $used_account2$left2)"
fi

#sending
echo "" > $html_logfile #make sure no old status is used
echo "Sending message:" | tee -a $logfile
echo "<b>$message</b>" | tee -a $logfile
echo "to $recipient..." | tee -a $logfile
if [ $dryrun -ge 1 ]; then
  echo "Dry-run, not sending it!"
else
  echo "Sending..."
  /usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d type="sms", -d recipient="$recipient" -d message="$message" -d send="send" -d task="send" -d currentMsisdn="$account" https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile
fi

#status message
reply_line=`sed -n '/id="errorBlock"/='  $html_logfile`
let reply_line=reply_line+5
status=`head -$reply_line $html_logfile | tail -1`
status=`echo $status | sed 's/<br\/>//g'`

echo "---------------------------------------------------------"
echo "Status:     $status" | tee -a $logfile
echo "---------------------------------------------------------" | tee -a $logfile

# echo "Selecting accounts and fetching left free SMS..." | tee -a $logfile

#getting amount of left free SMS for account 1
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account1" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt > $html_logfile

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

left1b=`grep "Gratis" $html_logfile`
left1b=`echo $left1b | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

# echo "Free SMS left on account 1: $left1b" | tee -a $logfile

#getting amount of left free SMS for account 2
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account2" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt  > /dev/null

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

cat $html_logfile > "left_sms_account2.htm"

left2b=`grep "Gratis" $html_logfile`
left2b=`echo $left2b | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

# echo "Free SMS left on account 2: $left2b" | tee -a $logfile

let "used1=left1-left1b"
let "used2=left2-left2b"

# echo "$left1, $left1b, $used1"
# echo "$left2, $left2b, $used2"

# echo "---------------------------------------------------------"
echo "Used SMS on account 1: $used1" | tee -a $logfile
echo "Used SMS on account 2: $used2" | tee -a $logfile
echo "---------------------------------------------------------"

Check left SMS

#!/bin/bash

account1=076******
account2=076******
password="********"

script_path=`dirname "$0"`
logfile="$script_path/send.log"
html_logfile="$script_path/sms_log.htm"

#logging in
# echo "Logging in..." | tee -a $logfile
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d LoginForm_Login="$account1" -d LoginForm_Password="$password" -d LoginRedirectSecret="89cff646d5a3f65ce8a8ea59a3d7cad3" -d LoginRedirectURL="https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewStandardCatalog-Browse?CatalogCategoryID=zv7AqFI.Z.gAAAEkbGdQzDCf&LoginOrigin=Mein%20Konto&LoginDestination=Mein%20Konto" -d ajaxhref="http://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewPersonalCodeRetrieval-New?SpcRetrievalMode=ECare" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewApplication-Login > $html_logfile

# echo "Selecting accounts and fetching left free SMS..." | tee -a $logfile

#getting amount of left free SMS for account 1
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account1" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt > $html_logfile

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

left1=`grep "Gratis" $html_logfile`
left1=`echo $left1 | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

echo $left1

#getting amount of left free SMS for account 2
echo "" > $html_logfile #make sure no old status is used
/usr/local/bin/curl -s  --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0 -d charsLeft="0" -d PhoneNumber="$account2" https://www1.sunrise.ch/is-bin/INTERSHOP.enfinity/WFS/Sunrise-Residential-Site/de_CH/-/CHF/ViewECareMessaging-Encrypt  > /dev/null

/usr/local/bin/curl -s --cookie /tmp/cookies.txt --cookie-jar /tmp/cookies.txt --user-agent Mozilla/4.0  https://mip.sunrise.ch/mip/dyn/login/smsMeinKonto?lang=de > $html_logfile

cat $html_logfile > "left_sms_account2.htm"

left2=`grep "Gratis" $html_logfile`
left2=`echo $left2 | sed 's/Gratis//g'| tr -d '\n' | tr -d '\r' | tr -d ' '` 

# left2=0 #simulating no SMS left on account 2

echo $left2

c:geo on BlackBerry BB10

I am hacgeoppy to announce that c:geo is now also available for BlackBerry BB10. Get it for free at appworld.blackberry.com/webstore/content/28277410. If you are still stuck on BB10.0, you download it from here.

c:geo is a simple to use but powerful geocaching client with a lot of additional features. In contrast with other similar applications, c:geo doesn’t require web browser nor exports. You can just go geocaching with your phone and without any home preparation or worries. Of course, you can go without paying – it’s free.

Main features:
– View caches on a Live Map
– Search for caches by various criteria
– Log your finds online or offline
– Store cache information on your device
– Create and manage waypoints
– Navigate using compass, map, or other apps
– Import/Export GPX files
– Full support for trackables
– Offline caching functions including offline maps

The BlackBerry version brings some (minor) limitations:
– No Google maps/satellite maps
– No additional tools like GCC or the calendar plugin available

c:geo is developed by the c:geo team.
I only maintain only the BlackBerry version!
For help, you can ask me or directly the c:geo team at www.cgeo.org if it is not a BlackBerry specific problem.

Geocaching with the Blackberry Z10

Update 2

I removed c:geo from the Blackberry World as I am unable to update it (lost the signing key and Blackberry gives no way to restore it).

Also there is no need for it anymore since the Android version works very good and with no issues. Get it from http://www.cgeo.org/cgeo.apk and sideload it or use any Android Store tool like http://redlightoflove.com/snap/

Update

The official version is now available in the BlackBerry Store: appworld.blackberry.com/webstore/content/28277410.

Continue reading

Android applications under Blackberry 10

With their new Operating System BB10 Blackberry made it very easy to convert existing Android applications into Blackberry 10 apps. My test revealed that around 50% of the applications work very well on my Blackberry Z10. The other ones will crash at their start, most likely due the incomplete API. With the soon coming update this might get even better.

I want to show you how easy it is to download, convert and install Android apps on your Blackberry device. The easiest way is to use the Chrome browser as it has 2 extensions which make our work much easier.

If you already have a BAR file (i.e. cgeo from here), you can start with step 10. :)

  1. Install Chrome Web browser
  2. Install the extension APK-Downloader
  3. Install the extension PlayBook App Manager
  4. Configure the APK-Downloader
  5. Configure the PlayBook App Manager and the Blackberry device
  6. With the Chrome browser go to the Google Play Store page of the desired application, i.e. c:geo.
  7. Download the APK file with the green icon behind the address bar
  8. Go to the page http://apk2bar.unker.net/ and upload the apk file
  9. Wait and download the generated BAR file.
  10. Open the PlayBook App Manager and install the BAR file

Done

Synchronize the contacts and calendar of your Blackberry 10 with OwnCloud

The new Blackberry 10 devices support CalDAV as well as CardDAV. With a bit of modifications of your Owncloud installation, it is possible to synchronize your calendar with CalDAV and your contacts with CardDAV.

Based on Nicolas Vivien’s modifications, I implemented my own patched Ownloud server. Nicolas helped me a lot tracing down the various problems and stumbling blocks.

First of all some important Blackberry limitations

On the current Blackberry 10 OS (10.9.10.35), CardDAV only works with a server which supports HTTPS. On the other side, CalDAV also accepts an insecure HTTP server (but first tries HTTPS).
Hopefully Blackberry will fix this in the near future.

My Workaround

Since my hoster only provides HTTPS at an extra cost, I had to look for another solution.
Luckily, my Synology DiskStation als has a webserver and even provides HTTPS.
So I moved my OwnCloud installation to my local DiskStation which is accessible through HTTP over the internet.

Required OwnCloud modifications

To keep the server addresses of the Server short, I added some htaccess RewriteRules to the root directory of my webserver:

RewriteEngine on
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

RewriteCond %{HTTP_HOST} ^carddav
RewriteCond %{REQUEST_URI} !^/apps
RewriteRule .* /owncloud/apps/contacts/carddav.php/$1 [L]

RewriteCond %{HTTP_HOST} ^caldav
RewriteCond %{REQUEST_URI} !^/apps
RewriteRule .* /owncloud/apps/calendar/caldav.php/$1 [L]

This will redirect any call from https://carddav.DOMAIN.ch/ to https://DOMAIN.ch/owncloud/apps/contacts/carddav.php and https://caldav.DOMAIN.ch to https://DOMAIN.ch//owncloud/apps/calendar/caldav.php.

You then should see pages similar to this:

principals Collection 2013-03-17T13:43:01+00:00
calendars Collection 2013-03-17T13:43:01+00:00

and

principals Collection 2013-03-17T13:44:48+00:00
addressbooks Collection 2013-03-17T13:44:48+00:00

Note:
Due my modifications, A direct call to the redirected URLs will lead to a Sabre_DAV_Exception_NotFound exception! How ever this doesn’t matter in normal operation since you can always use the much shorter and nicer sub domain call.

Blackberry configuration

CalDAV account

Description: [What ever you want]
User name: Your Owncloud user name
Email address: [Blackberry requires a valid emailadress. How ever Owncloud will ignore it]
Password: Your Owncloud password
Server address: carddav.DOMAIN.ch/calendars/USERNAME/defaultcalendar [add the /calendars/USERNAME/defaultcalendar, where USERNAME has to be replaced by your real user name, else Blackberry will not list the account. If you only have HTTP, you will heve to append a http://, else it uses implies https://]

CardDAV account

Description: [What ever you want]
User name: Your Owncloud user name
Email address: [Blackberry requires a valid emailadress. How ever Owncloud will ignore it]
Password: Your Owncloud password
Server address: carddav.DOMAIN.ch [omit the HTTPS://]

Required OwnCloud modifications

Jet to be documented…

For now, have a look at Nicolas’s patches: http://www.progweb.com/2012/05/playbook-pret-pour-le-cloud/

Local OpenStreetMap server

When you are one of those users who have a huge usage of OpenSTreetMap tiles (i.e. to generate offline maps for your phone), the you might know that most tile providers limit the access due the huge workload.

A solution to avoid this is to set up your own server. http://switch2osm.org/ documents very well, how this can be done. Since I am working on Linux (Kubuntu) anyway, I followed this guide: http://switch2osm.org/serving-tiles/building-a-tile-server-from-packages/.

You well need quite some RAM to generate the database, but afterwards, it works quite well and you can fetch as many tiles as you want :)