/usr/share/pyshared/scolasync/ownedUsbDisk.py is in scolasync 2.3-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | # -*- coding: utf-8 -*-
# $Id: ownedUsbDisk.py 47 2011-06-13 10:20:14Z georgesk $
licence={}
licence['en']="""
file ownedUsbDisk.py
this file is part of the project scolasync
Copyright (C) 2010 Georges Khaznadar <georgesk@ofset.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import usbDisk, db
import os.path, dbus, subprocess, time
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from globaldef import markFileName
"""
liste statique pour éviter de demander chaque seconde le nom d'un
propriétaire de clé si on n'a pas souhaité le donner.
"""
def editRecord(owd, student=""):
"""
édition de la base de données
@param owd une instance de ownedUsbDisk
@param student nom de propriétaire pour la clé. Chaîne vide par défaut.
"""
newStudent, ok = QInputDialog.getText(None,
u"Choix du propriétaire",
u"Nouveau nom du propriétaire de la clé",
text=student
)
if ok:
newStudent=u"%s" %newStudent
db.writeStudent(owd.stickid, owd.getFatUuid(), owd.tattoo(), newStudent)
class uDisk(usbDisk.uDisk,QObject):
"""
une classe qui ajoute un nom de propriétaire aux disque USB,
et qui en même temps ajoute des particularités selon le nom du
vendeur et le modèle.
"""
def __init__(self, path, bus, checkable=False):
"""
@param path un chemin dans le système dbus
@param bus un objet dbus.BusSystem
@param checkable vrai si on fera usage de self.selected
"""
usbDisk.uDisk.__init__(self,path, bus, checkable)
QObject.__init__(self)
self.owner="" # le propriétaire est déterminé plus tard
self.vendor=self.getProp("drive-vendor")
self.model=self.getProp("drive-model")
self.visibleDirs=self.readQuirks()
def uniqueId(self):
"""
@return un identifiant unique, composé du nom du propriétaire
suivi du tatouage
"""
return "%s~%s" %(self.owner, self.tattoo())
def tattoo(self):
"""
Renvoie un tatouage présent sur la clé, quitte à le créer.
@result un tatouage, supposément unique.
"""
ff=self.getFirstFat()
if ff:
fatPath=ff.ensureMounted()
tattooFileName=os.path.join(fatPath,".scolasync-tattoo")
if os.path.exists(tattooFileName):
tattoo_=open(tattooFileName,"r").read()
# on vérifie par acquis de conscience, qu'il n'existe pas
# un tatouage identique dans la base de données
# s'il est déjà présent : on le change. Il faudrait
# probablement aussi prévenir le prof !!!
if tattoo_ in db.tattooList():
tattoo_="%12.2f" %time.time()
time.sleep(0.05)
else:
tattoo_="%12.2f" %time.time()
time.sleep(0.05)
outfile=open(tattooFileName,"w")
outfile.write(tattoo_)
outfile.close()
return tattoo_
else:
return ""
def readQuirks (self):
"""
Lit un dictionnaire indexé par le noms de vendeurs et les noms de modèle
pour associer à ces modèles particuliers un répertoire visible.
voir la fonction visibleDir. Ce dictionnaire est dans le fichier
/usr/share/scolasync/marques.py ou dans ${HOME}/.scolasync/marques.py,
(sous Linux) cette dernière place étant prépondérante.
"""
f1="/usr/share/scolasync/marques.py"
f2=os.path.expanduser(markFileName)
if os.path.exists(f2):
f=f2
else:
f=f1
result=eval(open(f,"r").read())
return result
def visibleDir(self):
"""
Renvoie le répertoire particulier de la partition qui sera visible
quand le baladeur est utilisé par son interface utilisateur. Ce
répertoire peut varier selon les vendeurs et les modèles.
"""
k=self.vendor+":"+self.model
if k in self.visibleDirs.keys():
return self.visibleDirs[k]
else:
return "."
def headers(checkable=False,locale="C"):
"""
Méthode statique
renvoie des titres pour les items obtenus par __getitem__
la deuxième colonne sera toujours le propriétaire
@param checkable vrai si le premier en-tête correspond à une colonne de cases à cocher
@param locale la locale, pour traduire les titres
@return une liste de titres de colonnes
"""
result=usbDisk.uDisk.headers(checkable, locale)
ownerProp=QApplication.translate("uDisk","owner",None, QApplication.UnicodeUTF8)
result.insert(1,ownerProp)
return result
def ownerByDb(self):
"""
renvoie un nom de propriétaire dans tous les cas.
"""
if self.owner != "":
return self.owner
else:
s=db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
if s != None:
self.owner=s
return s
else:
return QApplication.translate("Dialog","inconnu",None, QApplication.UnicodeUTF8)
def __getitem__(self,n):
"""
renvoie un élément de listage de données internes au disque
Fait en sorte que la deuxième colonne soit toujours le propriétaire
@param n un nombre
@param checkable vrai si on doit renvoyer une propriété supplémentaire pour n==0
@return si n==-1, renvoie self ; si checkable est vrai, renvoie un élément si n>0, et le drapeau self.selected si n==0 ; sinon un élément de façon ordinaire. Les noms des éléments sont dans la liste self.itemNames
"""
propListe=usbDisk.uDisk.headers()
if n == -1:
return self # pour accéder à toutes les données d'une partition
if self.checkable:
if n==0:
return self.selected
elif n==1:
return self.ownerByDb()
elif n==2:
return self.unNumberProp(0)
else:
return self.unNumberProp(n-1)
else:
if n==0:
return self.unNumberProp(0)
elif n==1:
return self.ownerByDb()
else:
return self.unNumberProp(n)
headers = staticmethod(headers)
def ensureOwner(self):
"""
Demande un nom de propriétaire si celui-ci n'est pas encore défini
pour cette clé USB
@return un nom de propriétaire si c'est un disque, sinon None
"""
if self.getProp("device-is-drive") and self.isUsbDisk():
if not db.knowsId(self.stickid, self.getFatUuid(), self.tattoo()) :
prompt=QApplication.translate("Dialog","La cle %1<br>n'est pas identifiee, donnez le nom du proprietaire",None, QApplication.UnicodeUTF8).arg(self.stickid)
text,ok = QInputDialog.getText(None,
QApplication.translate("Dialog","Entrer un nom",None, QApplication.UnicodeUTF8),
prompt)
if ok and len(text)>0:
db.writeStudent(self.stickid, self.getFatUuid(), self.tattoo(), u"%s" %text.toUtf8())
return db.readStudent(self.stickid, self.getFatUuid(), self.tattoo())
class Available(usbDisk.Available):
"""
Une classe qui fournit une collection de disques USB connectés,
avec leurs propriétaires. On a répliqué le code de la classe parente,
ne sachant pas si le contructeur prendrait les uDisks dans le module
courant ou dans le module parent. Pour éviter les confusion il faudrait
peut-être faire une classe abstraite Available
"""
def __init__(self, checkable=False, access="disk"):
"""
@param checkable : vrai si on veut pouvoir cocher les disques de la
collection. Faux par défaut.
@param access définit le type d'accès souhaité. Par défaut, c'est "disk"
c'est à dire qu'on veut la liste des disques USB. Autres valeurs
possibles : "firstFat" pour les premières partitions vfat.
"""
self.checkable=checkable
self.access=access
self.bus = dbus.SystemBus()
proxy = self.bus.get_object("org.freedesktop.UDisks",
"/org/freedesktop/UDisks")
iface = dbus.Interface(proxy, "org.freedesktop.UDisks")
self.disks={}
self.enumDev=iface.EnumerateDevices()
### récupération des disques usb dans le dictionnaire self.disks
for path in self.enumDev:
ud=uDisk(path, self.bus, checkable)
if ud.isUsbDisk():
self.disks[ud]=[]
# cas des disques sans partitions
if bool(ud.getProp("device-is-partition-table")) == False:
# la propriété "device-is-partition-table" est fausse,
# probablement qu'il y a un système de fichiers
self.disks[ud].append(ud)
### une deuxième passe pour récupérer et associer les partitions
for path in self.enumDev:
ud=uDisk(path, self.bus, checkable)
for d in self.disks.keys():
if ud.master() == d.path:
self.disks[d].append(ud)
### on s'assure que chaque disque a bien un propriétaire
### sinon on le demande
self.getFirstFats() # premier passage, pour repérer chaque partition FAT
for d in self.disks.keys():
d.owner=d.ensureOwner()
### on fabrique la liste des premières partitions FAT,
### en positionnant les attributs de propriétaire
self.firstFats = self.getFirstFats(setOwners=True)
### on monte les partitions si nécessaire
if self.access=="firstFat":
for p in self.firstFats:
p.ensureMounted()
|