Blog
Winnie | 05.10.2008
Wie schon erwähnt, bin ich auf der Suche nach der perfekten Lösung, meine Googlemail-E-Mails zu sichern. Und ich denke ich habe sie gefunden: ein Ruby-Script, das die Synchronisation zwischen meinem Googlemail-Account und einem zweiten IMAP-Account übernimmt. Synchronisation ist dabei vielleicht das falsche Wort, es ist eher ein Backup, was den zweiten IMAP-Account auf dem gleichen Stand wie den Googlemail-Account hält.
Die Basis für das Script kommt von Ryan Grove. Ich habe das Löschen von Nachrichten und die Ordner-Auflistung hinzugefügt.
Mehr »
Wie schon erwähnt, bin ich auf der Suche nach der perfekten Lösung, meine Googlemail-E-Mails zu sichern. Und ich denke ich habe sie gefunden: ein Ruby-Script, das die Synchronisation zwischen meinem Googlemail-Account und einem zweiten IMAP-Account übernimmt. Synchronisation ist dabei vielleicht das falsche Wort, es ist eher ein Backup, was den zweiten IMAP-Account auf dem gleichen Stand wie den Googlemail-Account hält.
Die Basis für das Script kommt von Ryan Grove. Ich habe das Löschen von Nachrichten und die Ordner-Auflistung hinzugefügt.
#!/usr/bin/env ruby
require 'net/imap'
# Source server connection info.
SOURCE_HOST = 'imap.googlemail.com'
SOURCE_PORT = 993
SOURCE_SSL = true
SOURCE_USER = 'EMAIL@googlemail.com'
SOURCE_PASS = 'PASSWORT'
# Destination server connection info.
DEST_HOST = 'imap.SERVER.com'
DEST_PORT = 143
DEST_SSL = false
DEST_USER = 'USER'
DEST_PASS = 'PASSWORT'
# List of all Folder that should not be synced
FOLDERS_EXCLUDE = [
'[Google Mail]',
'[Google Mail]/Sent Mail',
'[Google Mail]/Spam',
'[Google Mail]/Trash'
]
# Utility methods.
def dd(message)
puts "[#{DEST_HOST}] #{message}"
end
def ds(message)
puts "[#{SOURCE_HOST}] #{message}"
end
# Connect and log into both servers.
ds 'connecting...'
source = Net::IMAP.new(SOURCE_HOST, SOURCE_PORT, SOURCE_SSL)
ds 'logging in...'
source.login(SOURCE_USER, SOURCE_PASS)
dd 'connecting...'
dest = Net::IMAP.new(DEST_HOST, DEST_PORT, DEST_SSL)
dd 'logging in...'
dest.login(DEST_USER, DEST_PASS)
# Getting the folders to sync
folders = Array.new
source.list("", "%").each do |mailbox|
if FOLDERS_EXCLUDE.include?(mailbox.name) == false
folders e
begin
dd "folder not found; creating..."
dest.create(foldername)
dest.select(foldername)
rescue => ee
dd "error: could not create folder: #{e}"
next
end
end
# Build a lookup hash of all message ids present in the destination folder.
dest_info = {}
dd 'analyzing existing messages...'
uids = dest.uid_search(['ALL'])
if uids.length > 0
dest.uid_fetch(uids, ['ENVELOPE']).each do |data|
dest_info[data.attr['ENVELOPE'].message_id] = true
end
end
# Loop through all messages in the source folder.
uids = source.uid_search(['ALL'])
if uids.length > 0
source.uid_fetch(uids, ['ENVELOPE']).each do |data|
mid = data.attr['ENVELOPE'].message_id
# If this message is already in the destination folder, skip it.
next if dest_info[mid]
# Download the full message body from the source folder.
ds "downloading message #{mid}..."
msg = source.uid_fetch(data.attr['UID'], ['RFC822', 'FLAGS',
'INTERNALDATE']).first
# Append the message to the destination folder, preserving flags and
# internal timestamp.
dd "storing message #{mid}..."
dest.append(foldername, msg.attr['RFC822'], msg.attr['FLAGS'],
msg.attr['INTERNALDATE'])
end
end
# Build a lookup hash of all message ids present in the source folder.
source_info = {}
dd 'analyzing source messages...'
uids = source.uid_search(['ALL'])
if uids.length > 0
source.uid_fetch(uids, ['ENVELOPE']).each do |data|
source_info[data.attr['ENVELOPE'].message_id] = true
end
end
# Loop through all messages in the source folder.
uids = dest.uid_search(['ALL'])
if uids.length > 0
dest.uid_fetch(uids, ['ENVELOPE']).each do |data|
mid = data.attr['ENVELOPE'].message_id
# If this message is already in the destination folder, skip it.
next if source_info[mid]
# Setting flag for deletion
ds "deleting message #{mid}..."
dest.store(data.seqno, "+FLAGS", [:Deleted])
end
end
dest.expunge
source.close
dest.close
end
puts 'done'
Kategorien: Blog | 12 Kommentare
Winnie | 28.09.2008
Das Bedürfnis, meine E-Mail vom Googlemail-Server zu sichern ist in den letzten Wochen extrem gestiegen. Grund dafür sind immer wieder Schauermärchen von gesperrten Mail-Accounts. Deswegen habe ich mich auf die Suche nach einer Backup-Möglichkeit für meine E-Mails gemacht und bin bei fetchmail fündig geworden. Fetchmail ist auf dem Mac unter Leopard vorinstalliert.
Mehr »
Das Bedürfnis, meine E-Mail vom Googlemail-Server zu sichern ist in den letzten Wochen extrem gestiegen. Grund dafür sind immer wieder Schauermärchen von gesperrten Mail-Accounts. Deswegen habe ich mich auf die Suche nach einer Backup-Möglichkeit für meine E-Mails gemacht und bin bei fetchmail fündig geworden. Fetchmail ist auf dem Mac unter Leopard vorinstalliert.
Um Mails mit fetchmail empfangen zu können, muss man als erstes ein Zertifikatsverzeichnis einrichten und die nötigen SSL-Zertifikate von Googlemail herunterladen. Dazu gibt man im Terminal folgende Zeilen ein:
mkdir ~/.certs
cd ~/.certs
openssl s_client -connect pop.googlemail.com:995 -showcerts
Kategorien: Blog | 3 Kommentare
Winnie | 13.07.2008
Das alte Studio steht nicht mehr, Kathrin Bauerfeind ist schon lange zur Old-Media-Konkurrenz gewechselt. Und mein alter Feed läuft nach dem Relaunch der Website auch nicht mehr – die Dateien gibt es jetzt nur noch gezippt.
Deswegen gibt es hier ein Update, das zumindest den Mac-Usern etwas weiterhilft. Zumindest unter Leopard. Alle anderen können das Skript mit mehr oder weniger Aufwand ans eigene System anpassen.
Mehr »
Das alte Studio steht nicht mehr, Kathrin Bauerfeind ist schon lange zur Old-Media-Konkurrenz gewechselt. Und mein alter Feed läuft nach dem Relaunch der Website auch nicht mehr - die Dateien gibt es jetzt nur noch gezippt.
Deswegen gibt es hier ein Update, das zumindest den Mac-Usern etwas weiterhilft. Zumindest unter Leopard. Alle anderen können das Skript mit mehr oder weniger Aufwand ans eigene System anpassen.
Lokalen Webserver mit PHP aktivieren
Terminal öffnen
sudo pico /etc/apache2/httpd.conf um die Config-Datei des lokalen Webservers zu bearbeiten. Dafür wird noch ein Admin-Passwort abgefragt.
mit Ctrl + W nach 'php' suchen
das Kommentarzeichen ’#' am Anfang der Zeile entfernen
mit Ctrl + X, und dann mit Y und dann Enter speichern
in den Systemeinstellungen unter 'Sharing' den Punkt 'Web-Sharing' aktivieren
die lokale Adresse (z.B. http://192.168.1.1/~username/) merken
Das Podcastskript (feed.php herunterladen und in ~/Sites/podcastfeed/feed.php speichern. Der Ordner braucht Schreibrechte für den Webserver-User. In den ersten paar Zeilen müssen noch die richtigen Servernamen und so für deine Lieblings-Internet-Fernsehsendung eingetragen werden.
Zusätzliche Klassen installieren
SimplePie laden und unter ~/Sites/podcastfeed/class/simplepie.class.php speichern
rss_writer.class.php laden und unter ~/Sites/podcastfeed/class/rss_writer.class.php speichern - die Klasse basiert auf der FeedCreator.class.php von Kai Blankenhorn
In dem podcastfeed-Ordner müssen außerdem noch zwei Unterordner cache und files, jeweils mit vollen Schreib- und Leserechten angelegt werden.
Podcast in iTunes abonnieren
Unter 'Erweitert | Podcast abonnieren' die Feed-Adresse vom eigenen Rechner eintragen, z.B. http://192.168.1.1/~username/podcastfeed/feed.php
iTunes wird jetzt beim ersten Aufruf noch keine Folgen finden, sie werden aber im Hintergrund heruntergeladen und auf dem eigenen Rechner ausgepackt.
Beim nächsten Update von iTunes werden die ersten Folgen erscheinen, die schon heruntergeladen sind.
Das Skript behält immer die letzten 10 Folgen auf dem System.
Obacht: Das Aktivieren des lokalen Webservers ist evtl. nicht jedermanns Sache, andererseits - wer bis hierher durchgehalten hat, weiß hoffentlich, was er tut.
Wenns nicht läuft - Das Apache-Log könnt ihr mit der Konsole in /var/log/apache2/ einsehen.
Ich bin Winnie. Das war mein Podcastskript. Tschüß.
out();
header("Content-type: $contentType");
echo $xml;
}
function header()
{
$out = '' . "\n";
$out .= '' . "\n";
return $out;
}
function footer()
{
return '';
}
}
class RSSItem
{
var $title;
var $link;
var $description;
var $pubDate;
var $guid;
var $tags;
var $attachment;
var $length;
var $mimetype;
function RSSItem()
{
$this->tags = array();
}
function setPubDate($when)
{
if(strtotime($when) == false)
$this->pubDate = date("D, d M Y H:i:s ", $when) . "GMT";
else
$this->pubDate = date("D, d M Y H:i:s ", strtotime($when)) . "GMT";
}
function getPubDate()
{
if(empty($this->pubDate))
return date("D, d M Y H:i:s ") . "GMT";
else
return $this->pubDate;
}
function addTag($tag, $value)
{
$this->tags[$tag] = $value;
}
function out()
{
$out .= "\n";
$out .= "" . $this->title . "\n";
$out .= "" . $this->link . "\n";
$out .= "" . $this->description . "\n";
$out .= "" . $this->getPubDate() . "\n";
if($this->attachment != "")
$out .= "";
if(empty($this->guid)) $this->guid = $this->link;
$out .= "" . $this->guid . "\n";
foreach($this->tags as $key => $val) $out .= "$val";
$out .= "\n";
return $out;
}
function enclosure($url, $mimetype, $length)
{
$this->attachment = $url;
$this->mimetype = $mimetype;
$this->length = $length;
}
}
?>
encoding = ($uFeed->get_encoding()?$uFeed->get_encoding():'UTF-8');
$rss->title = $uFeed->get_title();
$rss->link = $uFeed->get_permalink();
$rss->description = $uFeed->get_description();
$rss->language = $uFeed->get_language();
if ($uFeed->data) {
$items = $uFeed->get_items();
foreach($items as $thisItem) {
$rssItem = new RSSItem();
$locEnclosureLink = getEnclosureLink($thisItem->get_categories());
// Datei aus Feed in System vorhanden, dann in Feed aufnehmen
if (in_array($locEnclosureLink.VIDEO_EXTENSION, $locFiles))
{
$rssItem->title = $thisItem->get_title();
$rssItem->link = $thisItem->get_link();
$rssItem->setPubDate($thisItem->get_date());
$rssItem->description = "";
if (!is_null($locEnclosureLink)) {
$rssItem->enclosure(WEB_PATH.$uFolder.$locEnclosureLink.VIDEO_EXTENSION, BLOG_VIDEO_TYPE, 12);
}
$rss->addItem($rssItem);
}
}
}
echo $rss->serve();
}
// liefert den Original-RSS-Feed mit Enclosures
function showRssFromOrginalFeed(&$uFeed)
{
header('Content-type: text/xml');
$rss = new RSS();
$rss->encoding = ($uFeed->get_encoding()?$uFeed->get_encoding():'UTF-8');
$rss->title = $uFeed->get_title();
$rss->link = $uFeed->get_permalink();
$rss->description = $uFeed->get_description();
$rss->language = $uFeed->get_language();
if ($uFeed->data) {
$items = $uFeed->get_items();
foreach($items as $thisItem) {
$rssItem = new RSSItem();
$rssItem->title = $thisItem->get_title();
$rssItem->link = $thisItem->get_link();
$rssItem->setPubDate($thisItem->get_date());
$rssItem->description = "";
if (!is_null($locEnclosureLink = getEnclosureLink($thisItem->get_categories()))) {
$rssItem->enclosure(BLOG_VIDEO_URL.$locEnclosureLink.BLOG_VIDEO_DOWNLOAD_EXTENSION, BLOG_VIDEO_TYPE, 12);
}
$rss->addItem($rssItem);
}
}
echo $rss->serve();
}
// liefert den Enclosure-Link zurück
function getEnclosureLink(&$uEnclosure) {
$locEnclosureLink = null;
$locEnclosure = $uEnclosure;
if (isset($locEnclosure[0])) {
if (is_array($locEnclosure)) {
for ($i=0; $i < count($locEnclosure); $i++) {
//echo $i;
$locItem = $locEnclosure[$i];
if (is_object($locItem)) {
if (isset($locItem->term)) {
if (strpos($locItem->term, date("Y")) !== false) {
$locEnclosureLink = $locItem->term;
}
}
}
}
}
}
return $locEnclosureLink;
}
// läd die Dateien aus dem Feed, die noch nicht im System liegen
// bzw. wenn Datei nicht im Feed aber im System dann löschen
function getFilesFromFeed(&$uFeed) {
$locFilesInSystem = getFileListFromSystem(VIDEO_URL, true, VIDEO_EXTENSION);
$locFilesInFeed = getFileListFromFeed($uFeed, BLOG_VIDEO_DOWNLOAD_EXTENSION, true);
// welche Dateien sind im System aber nicht im Feed
$locDiffSystemToFeed = array_diff($locFilesInSystem, $locFilesInFeed);
// welche Dateien sind im Feed aber nicht im System
$locDiffFeedToSystem = array_diff($locFilesInFeed, $locFilesInSystem);
// Datei, die nicht im Feed sind vom System löschen
foreach ($locDiffSystemToFeed as $item) {
@unlink(VIDEO_URL.$item.VIDEO_EXTENSION);
}
$locExec = "#!/bin/bash\n";
// Datei, die nicht im System sind aus Feed holen
foreach ($locDiffFeedToSystem as $item) {
$submit_url = BLOG_VIDEO_URL.$item.BLOG_VIDEO_DOWNLOAD_EXTENSION;
$save_path = VIDEO_URL.$item.BLOG_VIDEO_DOWNLOAD_EXTENSION;
$locExec .= "/usr/bin/curl ".$submit_url." -o ".$save_path." -L\n"; // Datei laden
$locExec .= "/usr/bin/unzip ".$save_path." *".VIDEO_EXTENSION." -d ".VIDEO_URL."\n"; // Datei entzippen
$locExec .= "rm ".$save_path."\n\n"; // Zip löschen
}
// in eine Datei schreiben und Datei als Script ausführen
if (count($locDiffFeedToSystem) > 0) {
$handle = fopen (ABSOLUTE_PATH."loadFeedFiles.sh", "w");
fputs($handle, $locExec);
fclose($handle);
@chmod (ABSOLUTE_PATH."loadFeedFiles.sh", 0777);
// Script ausführen
exec("./loadFeedFiles.sh > /dev/null &");
}
}
// gibt alle Dateien aus dem Feed als Array zurück
function getFileListFromFeed(&$uFeed, $uExtension="", $uBasename=false) {
$files = array();
if ($uFeed->data) {
$items = $uFeed->get_items();
foreach($items as $thisItem) {
if (!is_null($locEnclosureLink = getEnclosureLink($thisItem->get_categories()))) {
$files[] = $locEnclosureLink.(($uBasename)?"":$uExtension);
}
}
}
return $files;
}
// gibt alle Dateien aus dem Ordner als Array zurück
function getFileListFromSystem($uFolder, $uBasename=false, $uExtension="") {
$files = array();
if($dir = opendir($uFolder))
{
while($file = readdir($dir))
{
if (!is_dir($file) && $file != "." && $file != ".." && $file != ".DS_Store" & $file != "__MACOSX")
{
$files[] = (($uBasename)?basename($file, $uExtension):$file);
}
}
closedir($dir);
}
return $files;
}
?>
Kategorien: Blog | 4 Kommentare
Winnie | 24.03.2008
Kennst du diese praktische Funktion in iPhoto? Fotos markieren, neues Album aus Auswahl erstellen? Großartig. Leider hat Apple die Funktion in iTunes vergessen.
Dieses AppleScript nimmt die markierten Songs, macht einen meist sinnvollen Namensvorschlag, den du auch noch ändern kannst, und packt sie in eine Wiedergabeliste.
Um das Skript zu installieren, legst du es einfach entpackt in ~/Library/iTunes/Scripts ab. Wenn dieser Ordner noch nicht existiert, leg ihn an. Wenn alles geklappt hat, erscheint neben dem “Fenster”-Menü in iTunes ein neues Skript-Menü mit dem Link “iTunes – selection 2 playlist”.
Download
Kennst du diese praktische Funktion in iPhoto? Fotos markieren, neues Album aus Auswahl erstellen? Großartig. Leider hat Apple die Funktion in iTunes vergessen.
Dieses AppleScript nimmt die markierten Songs, macht einen meist sinnvollen Namensvorschlag, den du auch noch ändern kannst, und packt sie in eine Wiedergabeliste.
Um das Skript zu installieren, legst du es einfach entpackt in ~/Library/iTunes/Scripts ab. Wenn dieser Ordner noch nicht existiert, leg ihn an. Wenn alles geklappt hat, erscheint neben dem "Fenster"-Menü in iTunes ein neues Skript-Menü mit dem Link "iTunes - selection 2 playlist".
Download
Kategorien: Blog | 6 Kommentare
Winnie | 10.09.2007
Auch wenn Kathrin Bauerfeind diesen nicht näher genannten Podcast nicht mehr moderiert, so ist er trotzdem einer meiner Lieblingspodcasts. Nur nervt es, sich das Video immer auf der Webseite anschauen zu müssen, weil es keinen Podcastfeed gibt. Aber da kann geholfen werden: ich hab mir einen eigenen Feed mit PHP programmiert und kann nun den Podcast bequem in iTunes laden und anschauen.
Mehr »
Auch wenn Kathrin Bauerfeind diesen nicht näher genannten Podcast nicht mehr moderiert, so ist er trotzdem einer meiner Lieblingspodcasts. Nur nervt es, sich das Video immer auf der Webseite anschauen zu müssen, weil es keinen Podcastfeed gibt. Aber da kann geholfen werden: ich hab mir einen eigenen Feed mit PHP programmiert und kann nun den Podcast bequem in iTunes laden und anschauen.
So geht's:
Zum einen brauchst du die PHP-Klasse Snoopy. Die kopierst du auf deinen Webspace in den Ordner "class". Eine weitere Klasse kommt noch hinzu: xml2obj. Markiere den Quelltext, kopiere sie in einen Texteditor, speichere sie unter dem Dateinamen "xml2obj.class.php" und spiele sie ebenfalls in den Ordner "class" auf deinem Webspace.
Das eigentliche Erstellen des Feeds mit Enclosures für die Videodateien findest du hier:
feed.php. Kopiere dir wieder den Quelltext und spiele ihn in ein neues Dokument in deinen Texteditor. Nun mußt du die URLs "BLOG_RSS_URL" (Zeile 7) und "BLOG_VIDEO_URL" (Zeile 8) von der Podcastwebseite heraussuchen und eintragen. Der Internetauftritt des Podcasts bietet einen normalen Feed an - seine Adresse mußt du bei "BLOG_RSS_URL" eintragen. Die "BLOG_VIDEO_URL" ist die URL zu einem Video sein, aber ohnen den Dateinamen des Films. Damit die Videos auch auf den iPod gesynct werden können, solltest du die Adresse zum Quicktime-Video nehmen. Dann mußt du die Datei unter dem Dateinamen "feed.php" speichern und in den Root-Ordner deines Webspaces spielen. Dann nur noch die "feed.php" im iTunes abonnieren (Advanced -> Subscribe to Podcast) und that's it.
path = "\$this->result";
$this->path = "\$this";
$this->index = 0;
$xml_parser = xml_parser_create($encoding);
xml_set_object($xml_parser, $this);
xml_set_element_handler($xml_parser, 'startElement', 'endElement');
xml_set_character_data_handler($xml_parser, 'characterData');
xml_parse($xml_parser, $data, true);
xml_parser_free($xml_parser);
$this->path = null;
$this->_rawXML = $data;
}
function startElement($parser, $tag, $attributeList) {
eval("\$vars = get_object_vars(".$this->path.");");
$this->path .= "->".$tag;
if ($vars and array_key_exists($tag, $vars))
{
eval("\$data = ".$this->path.";");
if (is_array($data))
{
$index = sizeof($data);
$this->path .= "[".$index."]";
}
else if (is_object($data))
{
eval($this->path." = array(".$this->path.");");
$this->path .= "[1]";
}
}
eval($this->path." = null;");
foreach($attributeList as $name => $value)
{
eval($this->path."->".$name." = \$value;");
}
}
function endElement($parser, $tag) {
$this->path = substr($this->path, 0, strrpos($this->path, "->"));
}
function characterData($parser, $data) {
eval($this->path." .= '".trim($data)."';");
}
}
?>
fetch($submit_url);
// Blog-RSS in Objekt umwandeln
$xmlObj = new xml2obj($snoopy->results, "UTF-8");
// Podcast-Feed erstellen
show_podcastfeed_xml($xmlObj);
// Podcast-Feed erstellen
function show_podcastfeed_xml($uXmlObj)
{
$locDateArray = array();
echo ''."\n";
?>
VERSION))?' version="'.$uXmlObj->RSS->VERSION.'"':'')?>>
RSS->CHANNEL->TITLE))?$uXmlObj->RSS->CHANNEL->TITLE:'')?>
RSS->CHANNEL->LINK))?$uXmlObj->RSS->CHANNEL->LINK:'')?>
RSS->CHANNEL->DESCRIPTION))?$uXmlObj->RSS->CHANNEL->DESCRIPTION:'')?>
RSS->CHANNEL->LANGUAGE))?$uXmlObj->RSS->CHANNEL->LANGUAGE:'')?>
RSS->CHANNEL->ITEM))
{
foreach ($uXmlObj->RSS->CHANNEL->ITEM as $podcast)
{
$locText = $podcast->DESCRIPTION;
$locLink = $podcast->LINK;
$locLinkArray = explode("/", $locLink);
// Datum des Postings für das Videodatum ermitteln
$locDate = $locLinkArray[3]."-".$locLinkArray[4]."-".$locLinkArray[5];
?>
]]>
Kategorien: Blog | 2 Kommentare
« Zurück