Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

772 lines (605 sloc) 27.999 kb
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import os
import sys
import ftplib
import pickle
import subprocess
import urllib2
from time import ctime
import dropbox
import dbus
from dbus.mainloop.glib import DBusGMainLoop
import PIL
from PIL import Image
import paramiko
import pexpect
import mnotification as notify
from QtMobility.SystemInfo import QSystemNetworkInfo
from PySide import QtCore
from PySide.QtCore import QTimer
class NewFotoCheck:
def __init__(self):
print
print "-== FOTOSHARE N9 DAEMON ==-"
print
# Standard init-------------------------------------------------------
# Stop daemon if there is no settings file
if os.path.isfile('/home/user/.config/fotoshare.cfg'):
print "Found config file. Load settings now..."
self.load_settings()
else:
print "No config file: Daemon stops."
sys.exit(0)
# Without connection details: stop daemon!
if not self.connection and self.db_sync_status == 'False':
print "No connection details: stopping."
sys.exit(0)
# If true user starts daemon from UIs switch - allowed! ;)
print "Check Daemon startup type:"
if self.check_startup_from_UI():
print "Daemon started from UI."
pass
# If not and if not allowed to boot on start - stop it!
else:
print "Daemon starts on boot/via terminal!"
if self.daemon_status == '':
print 'Daemon not allowed to start: stop!'
sys.exit(0)
# Timer loads up pics later if N9 is offline when they are shot
self.offline_timer = QTimer()
self.offline_timer.timeout.connect(self.try_offline_pic_upload)
# Timer loads up pics later if user selected interval upload
self.interval_timer = QTimer()
# Try to upload if N9 was offline and a picture could not
# uploaded and N9/Daemon switched off and the pics waiting
if os.path.isfile('/home/user/.config/fotoshare_offline.sav'):
print "Maybe some pics not uploaded so far - checking it!"
self.try_offline_pic_upload()
# DBUS Init---------------------------------------------------
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
self.bus = dbus.SessionBus()
try:
# Get the remote object
self.remote_object = self.bus.get_object(
'com.nokia.maemo.CameraService',
'/',
follow_name_owner_changes=True)
# Get the remote interface for the remote object
self.iface = dbus.Interface(self.remote_object,
'com.nokia.maemo.meegotouch.CameraInterface')
except dbus.DBusException:
print_exc()
sys.exit(1)
self.iface.connect_to_signal('captureCompleted',
self.init_upload_steps)
# Main functions -------------------------------------------------
def check_startup_from_UI(self):
"""
Checks for daemon is started from autostart or GUI.
If daemon starts via boot, it will be checked if he is allowed
to start on boot (self.daemon_status) if not daemon stops
itself. If daemon starts from UI (means UI is running) it will
not stop, because in this case, it has to run!
"""
cmd = 'ps aux| grep python'
pid = os.popen(cmd)
data = pid.readlines()
for i in data:
print i
print type(i)
if 'fotoshareGUI' in str(i):
print "Found running GUI"
return True
break
def load_settings(self):
"""
Loads all relevant data for the daemon from fotoshare.cfg
"""
f = open('/home/user/.config/fotoshare.cfg')
l = pickle.load(f)
print
print "These are the settings"
print
print l
print
# holds picture names, that are not uploaded yet
# (interval upload selected)
self.interval_waiting_list = []
# holds pictures names, that are not uploaded yet
# (offline when shot)
self.offline_picture_list = []
# normal settings
self.server_adress = l['server']
self.server_port = l['port']
self.server_folder = l['path']
self.server_user = l['username']
self.server_pass = l['pass']
self.connection = l['connection']
self.access_token = l['db_access_token']
self.access_secret = l['db_access_secret']
self.upload_type = l['upload_type']
self.db_sync_status = l['db_sync']
self.data_connection = l['data_connection']
self.daemon_status = l['daemon_startup']
self.interval_time = l['interval_time']
self.log = l['log']
self.notification_type = l['notification_type']
self.resize = l['resize']
self.video_allowed = l['video_upload']
print "hostkey (setting)"
self.hostkey = None
print self.hostkey
print "hostkeytype (setting)"
self.hostkeytype = None
print self.hostkeytype
# Dropbox API stuff
self.APP_KEY = 'uvxyouqhkdljbdn'
self.APP_SECRET = '09sd2chtvifn5aj'
self.ACCESS_TYPE = 'app_folder'
f.close()
print "Settings loaded successful!"
def get_hostkey(self, hostname):
"""
Reads server hostkeys from ~/.ssh/known_hosts and sets self.hostkey
"""
hostkeytype = None
hostkey = None
try:
host_keys = paramiko.util.load_host_keys(
os.path.expanduser('~/.ssh/known_hosts'))
except IOError:
print '*** Unable to open host keys file'
host_keys = {}
print host_keys
if host_keys.has_key(hostname):
hostkeytype = host_keys[hostname].keys()[0]
self.hostkey = host_keys[hostname][hostkeytype]
print 'Using host key of type %s' % hostkeytype
print hostkeytype
print self.hostkey
def check_is_wlan(self):
"""
Checks that Wifi/WLAN connection is active or not.
"""
networkInfo = QSystemNetworkInfo()
name = 'wlan'
mode = getattr(QSystemNetworkInfo, name.capitalize() + 'Mode')
status = networkInfo.networkStatus(mode)
status = str(status)
status = status.split('.')
return status[-1] == 'Connected'
def write_log_data(self, name, status, connection, error=''):
"""
Writes given informations in the log file at MyDocs.
"""
if status == 'success':
string = str(ctime())+':'+name+' was successfuly uploaded via '+connection+'\n'
else:
string = str(ctime())+': while uploading '+name+' with '+connection+'an error occured!\n'
if error != '':
string = str(ctime())+':'+error+'\n'
with open('/home/user/MyDocs/fotoshare.log', 'a') as log:
log.write(string)
# Main upload functions ----------------------------------------------
def connect_ftp(self):
"""
Connects to the ftp server with known settings.
"""
self.ftp = ftplib.FTP()
self.ftp.connect(self.server_adress, self.server_port)
self.ftp.login(self.server_user, self.server_pass)
self.ftp.cwd(self.server_folder)
def connect_sftp(self):
"""
Connects to the FTP Server via sFTP from paramiko module
"""
print "connect sftp runs"
self.get_hostkey(self.server_adress)
self.sftp_transport = paramiko.Transport((self.server_adress,
int(self.server_port)))
print "sftp_transport steht"
self.sftp_transport.connect(username=self.server_user,
password=self.server_pass,
hostkey=self.hostkey)
print "sftp_transport.connect steht"
self.sftp = paramiko.SFTPClient.from_transport(self.sftp_transport)
print "sftp Client steht"
self.sftp.chdir(self.server_folder)
print "Verzeichnis gewechselt"
def init_upload_steps(self, arg1, data):
"""
Init the upload process and starts relevant upload functions
How it works:
first of all it's getting DBUS signal strings, so arg1 is
useless, but data is the name and path of the picture and will
be used.
Maybe the user want a resized picture - so do that, save it
and make the path to the smaller sized version the new "data"
string, which holds the whole path to the file and is used in
all further steps.
Next step is to checks if the user selected interval upload,
if yes, it collects the pic names/paths in a waiting list and
starts the QTimer instance. On timeout it starts a function,
which will run a for-loop to upload all pics that are waiting.
If no interval upload is selected, it just start normal upload
process.
"""
print "Init upload and prepare data."
# load latest settings - maybe some options changed since start,
# or also between two pictures
self.load_settings()
filename = os.path.split(data)
filename = filename[-1]
video_check = filename.split('.')
if self.resize > 0:
print "Resize is wanted!"
small_pic_path="/home/user/MyDocs/DCIM/FotoShareN9_small/"
if not os.path.isdir(small_pic_path):
os.makedirs(small_pic_path)
data_old = data
data = small_pic_path+filename
print data
#create a useable value from percent
percent = self.resize
percent = percent * 0.01
print str(percent)+" %"
# open original picture from DBUS signal string
img = Image.open(data_old)
# claculate new height and width
new_width = float((img.size[0])) * percent
new_height = float((img.size[1])) * percent
# resize the picture
img = img.resize((int(new_width), int(new_height)), PIL.Image.ANTIALIAS)
# save smaller version of the picture
img.save(small_pic_path+filename)
# Is the file a picture OR a video, and is video allowed
if video_check[1] == 'jpg' or (video_check[1] == 'mp4' and self.video_allowed == 'allowed'):
# sets pics on an waiting list, due to the interval upload feature
if self.upload_type == 'interval':
self.interval_waiting_list.append(data)
print "The waiting list:"
print self.interval_waiting_list
if self.interval_timer.isActive():
print "interval_timer is running, so we do nothing"
else:
print "setting interval_timer to:"+str(self.interval_time)
self.interval_timer.timeout.connect(self.start_interval_upload)
# multiply with 60.000 to convert minutes to milliseconds
self.interval_timer.start(self.interval_time*60000)
else:
self.start_upload(data)
else:
print "Video Upload is forbidden!"
self.show_notification(error = 'Video upload is disabled!')
pass
def start_interval_upload(self):
"""
Uploads all pictures in the waiting list via a for-iteration.
"""
# To be sure the timer is stoped, it's done here.
if self.interval_timer.isActive():
print "Stopping timer"
self.interval_timer.stop()
galerie_list = os.listdir("/home/user/MyDocs/DCIM")
waiting_pics_tmp = []
# create a temp list with pathless data names
for pics in self.interval_waiting_list:
var = os.path.split(pics)
var = var[-1]
waiting_pics_tmp.append(var)
print waiting_pics_tmp
# checks that pics from (temporary) waiting list still in
# gallery, if not - no upload will happen.
for pic in waiting_pics_tmp:
if not pic in galerie_list:
print "Entferne: /home/user/MyDocs/DCIM/"+pic
self.interval_waiting_list.remove("/home/user/MyDocs/DCIM/"+pic)
print "Uploading pics in interval_waiting_list"
for data in self.interval_waiting_list:
self.start_upload(data)
def start_upload(self, data):
"""
Start normal upload function. Check for WLAN only upload before.
"""
# check if the user want wifi only upload
if self.data_connection == 'Wlan':
if self.check_is_wlan():
print "FotoShareN9 is uploading via Wifi!"
self.upload_picture(data)
else:
print "No Wifi - uploading later!"
self.offline_except_handler(str(data))
else:
print "FotoShareN9 is uploading with 3G or Wifi!"
self.upload_picture(data)
def upload_picture(self, data):
"""
Uploads pictures to ftp/sftp/scp server or your Dropbox.
"""
f = open(data, 'r')
name = os.path.split(data)
name = name[-1]
print "Upload via: "+self.connection
if self.connection == 'ftp':
try:
self.connect_ftp()
self.ftp.storbinary('STOR '+name, f)
print "ftp upload finished."
self.show_notification(name, 'ftp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'ftp')
except:
if self.log == 'yes':
self.write_log_data(name, 'fail', 'ftp')
self.offline_except_handler(str(data))
print self.offline_picture_list
if self.connection == 'sftp':
try:
self.connect_sftp()
print "1"
self.sftp.put(data, name)
print "2"
self.sftp_transport.close()
print "sftp upload finished."
self.show_notification(name, 'sftp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'sftp')
except:
if self.log == 'yes':
self.write_log_data(name, 'fail', 'sftp')
self.offline_except_handler(str(data))
print self.offline_picture_list
if self.connection == 'scp':
try:
print "Starting with scp"
dest = self.server_user+'@'+self.server_adress+':/'+self.server_folder
print "the destination is: "+dest
self.get_hostkey(self.server_adress)
# get files at .ssh - "fotoshare" would be the public key
try:
files_at_ssh = os.listdir('/home/user/.ssh')
except:
files_at_ssh = []
if not os.path.isdir('/home/user/.ssh'):
print "scp: no ~/.shh found"
try:
scp = pexpect.spawn('scp %r %r' %(str(data), dest))
scp.expect("Are you sure you want to continue connecting (yes/no)?")
scp.sendline("yes")
scp.expect(self.server_user+'@'+self.server_adress+"'s password:")
scp.sendline(self.server_pass)
scp.wait()
self.show_notification(name, 'scp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'scp')
except:
print "SCP: except @ no .ssh dir"
self.offline_except_handler(str(data))
print self.offline_picture_list
if self.hostkey:
print "scp: no publickey found"
try:
scp = pexpect.spawn('scp %r %r' %(str(data), dest))
scp.expect(self.server_user+'@'+self.server_adress+"'s password:")
scp.sendline(self.server_pass)
scp.wait()
self.show_notification(name, 'scp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'scp')
except:
print "SCP: except @ known_hosts only"
self.offline_except_handler(str(data))
print self.offline_picture_list
# public key is commented out due to bugs -> will be re enabled in later version
# if self.hostkey and 'fotoshare' in files_at_ssh:
# print "scp: publickey found"
# try:
# scp = pexpect.spawn('scp %r %r' %(str(data), dest))
# # FotoShareN9 accept only a public key with the name "fotoshare"
# scp.expect("Enter passphrase for key '/home/user/.ssh/fotoshare: ")
# scp.sendline(self.server_pass)
# scp.wait()
# self.show_notification(name, 'scp')
# if self.log == 'yes':
# self.write_log_data(name, 'success', 'scp')
# except:
# print "SCP: except @ public key auth"
# self.offline_except_handler(str(data))
# print self.offline_picture_list
except:
if self.log == 'yes':
self.write_log_data(name, 'fail', 'scp',
'All kinds three of SCP uploading failed. Maybe it helps to reset FotoShareN9.')
if self.db_sync_status == 'True':
try:
print "Start Dropbox upload"
session = dropbox.session.DropboxSession(self.APP_KEY,
self.APP_SECRET,
self.ACCESS_TYPE)
session.set_token(self.access_token,
self.access_secret)
client = dropbox.client.DropboxClient(session)
print "Dropbox uploading..."+name
f = open(data)
client.put_file('/'+name, f)
print "Dropbox upload finished!"
self.show_notification(name, 'Dropbox')
if self.log == 'yes':
self.write_log_data(name, 'success', 'Dropbox')
except:
if self.log == 'yes':
self.write_log_data(name, 'fail', 'Dropbox')
self.offline_except_handler(str(data))
f.close()
print "--- FOTOUPLOAD ENDE ---"
# Offline exception handling -----------------------------------------
def offline_except_handler(self, data):
"""
Safes the names of pictures, which were not uploaded yet.
"""
if self.notification_type != 'off':
self.show_notification('','','Warning: N9 is offline!\nFotoShareN9 try to upload in 20 min. again.')
print "Offline handler is called"
self.offline_picture_list.append(data)
print self.offline_picture_list
print type(self.offline_picture_list)
if os.path.isfile('/home/user/.config/fotoshare_offline.sav'):
f = open('/home/user/.config/fotoshare_offline.sav', 'w')
pickle.dump(self.offline_picture_list, f)
f.close()
else:
f = open('/home/user/.config/fotoshare_offline.sav', 'w')
pickle.dump(self.offline_picture_list,f)
f.close()
if self.offline_timer.isActive():
print "offline_timer is running, nothing is done."
else:
print "offline_timer is set to 20 min."
# 1.2 mio. sec = 20 mins. (time is hard coded)
self.offline_timer.start(1200000)
def try_offline_pic_upload(self):
"""
Try to load up pictures that could not be uploaded before, due
to N9 was offline or maybe an upload error happend.
It's nearly the same, like normal picture upload but without
the except handler stuff.
"""
if os.path.isfile('/home/user/.config/fotoshare_offline.sav'):
f = open('/home/user/.config/fotoshare_offline.sav')
l = pickle.load(f)
if not len(l):
print "today no pics to upload"
else:
print "Upload pictures from last time/offline."
for data in l:
f = open(data, 'r')
name = os.path.split(data)
name = name[-1]
if self.connection == 'ftp':
try:
self.connect_ftp()
print "Start ftp upload of: "+name
self.ftp.storbinary('STOR '+name, f)
print "Finished ftp upload"
self.show_notification(name, 'ftp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'ftp')
except:
pass
if self.connection == 'sftp':
try:
self.connect_sftp()
print "Start sftp upload of: "+name
self.sftp.put(data, name)
print "Finished sftp upload"
self.sftp_transport.close()
self.show_notification(name, 'sftp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'sftp')
except:
pass
if self.connection == 'scp':
try:
print "Start with scp"
dest = self.server_user+'@'+self.server_adress+':/'+self.server_folder
print "the destination is: "+dest
self.get_hostkey(self.server_adress)
# get number of files at .ssh for checking "fotoshare" key is in it
files_at_ssh = os.listdir('/home/user/.ssh')
if not os.path.isdir('/home/user/.ssh'):
print "scp: no ~/.shh found"
try:
scp = pexpect.spawn('scp %r %r' %(str(data), dest))
scp.expect("Are you sure you want to continue connecting (yes/no)?")
scp.sendline("yes")
scp.expect(self.server_user+'@'+self.server_adress+"'s password:")
scp.sendline(self.server_pass)
scp.wait()
self.show_notification(name, 'scp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'scp')
except:
print "SCP: except @ no .ssh dir"
if self.hostkey:
print "scp: no publickey found"
try:
scp = pexpect.spawn('scp %r %r' %(str(data), dest))
scp.expect(self.server_user+'@'+self.server_adress+"'s password:")
scp.sendline(self.server_pass)
scp.wait()
self.show_notification(name, 'scp')
if self.log == 'yes':
self.write_log_data(name, 'success', 'scp')
except:
print "SCP: except @ known_hosts only"
# commented out due to a bug, re enabled in later version
# if self.hostkey and 'fotoshare' in files_at_ssh:
# print "scp: publickey found"
# try:
# scp = pexpect.spawn('scp %r %r' %(str(data), dest))
# # FotoShareN9 accept only a public key with the name "fotoshare"
# scp.expect("Enter passphrase for key '/home/user/.ssh/fotoshare: ")
# scp.sendline(self.server_pass)
# scp.wait()
# self.show_notification(name, 'scp')
# if self.log == 'yes':
# self.write_log_data(name, 'success', 'scp')
# except:
# print "SCP: except @ public key auth"
except:
pass
if self.db_sync_status == 'True':
try:
print "Start dropbox upload"
session = dropbox.session.DropboxSession(self.APP_KEY,
self.APP_SECRET,
self.ACCESS_TYPE)
session.set_token(self.access_token, self.access_secret)
client = dropbox.client.DropboxClient(session)
print "Uploading "+name+" to Dropbox."
f = open(data)
client.put_file('/'+name, f)
print "Finished!"
self.show_notification(name, 'Dropbox')
if self.log == 'yes':
self.write_log_data(name, 'success', 'Dropbox')
except:
pass
# set list back and save this, because now all pics uploaded
self.offline_picture_list = []
f = open('/home/user/.config/fotoshare_offline.sav', 'w')
pickle.dump(self.offline_picture_list, f)
f.close()
# stoping timer for delayed pic upload (offline)
self.offline_timer.stop()
print "offline_timer is stoped"
print self.offline_timer.isActive()
# Notifications ------------------------------------------------------
def show_notification(self, name='', connection='', error=''):
"""
Shows different types of Notifications on the GUI
"""
if error == '':
if self.notification_type == 'off':
pass
elif self.notification_type == 'banner':
message = notify.MNotification(notify.MNotification.DeviceEvent, '', '')
message.setImage('/usr/share/icons/hicolor/80x80/apps/fotoshare.png')
message.setBody(str('FotoShareN9 uploaded '+name+' via '+connection))
message.publish()
elif self.notification_type == 'EventFeed':
message = notify.MNotification(notify.MNotification.TransferEvent, '', '')
message.setImage('/usr/share/icons/hicolor/80x80/apps/fotoshare.png')
message.setSummary(str('Uploaded '+name+' via '+connection))
message.setBody('FotoShareN9')
message.publish()
else:
message = notify.MNotification(notify.MNotification.DeviceEvent, '', '')
message.setBody(str(error))
message.publish()
# Daemon start -------------------------------------------------------
if __name__ == '__main__':
app = QtCore.QCoreApplication(sys.argv)
start = NewFotoCheck()
sys.exit(app.exec_())
Jump to Line
Something went wrong with that request. Please try again.