Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
D
dcpman
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
dcp
dcpman
Commits
b31f724e
Commit
b31f724e
authored
10 years ago
by
nimrod
Browse files
Options
Downloads
Patches
Plain Diff
Work on future feature (full ingest of DCP from removable media).
parent
234ffe5b
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
source/dcp.py
+118
-52
118 additions, 52 deletions
source/dcp.py
source/manager.py
+17
-0
17 additions, 0 deletions
source/manager.py
with
135 additions
and
52 deletions
source/dcp.py
+
118
−
52
View file @
b31f724e
#!/usr/bin/env python3
from
hashlib
import
sha1
from
base64
import
b64encode
from
os
import
stat
,
listdir
from
os
import
stat
,
listdir
,
mkdir
,
statvfs
from
os.path
import
isdir
,
basename
from
shutil
import
copyfile
from
xml.dom.minidom
import
parse
import
sys
import
vlc
class
Asset
(
object
):
class
Asset
(
object
):
'''
A simple asset that
'
s part of whole DCP package.
'''
def
verifySize
(
self
):
def
verifySize
(
self
):
'''
verify that the size of the file is correct, if present.
'''
try
:
return
stat
(
self
.
fullpath
).
st_size
==
self
.
size
return
stat
(
self
.
fullpath
).
st_size
==
self
.
size
except
AttributeError
:
return
True
def
verifyHash
(
self
):
def
verifyHash
(
self
):
'''
verify that the hash is correct, if present.
'''
if
hasattr
(
self
,
'
hash
'
)
==
False
:
if
hasattr
(
self
,
'
hash
'
)
==
False
:
return
True
#from os import stat
#try:
...
...
@@ -25,13 +27,38 @@ class Asset(object):
#except:
#buffersize = 2**16
buffersize
=
2
**
16
fh
=
open
(
self
.
fullpath
,
'
rb
'
)
buffer
=
fh
.
read
(
buffersize
)
hash
=
sha1
()
fh
=
open
(
self
.
fullpath
,
'
rb
'
)
buffer
=
fh
.
read
(
buffersize
)
hash
=
sha1
()
while
buffer
:
hash
.
update
(
buffer
)
buffer
=
fh
.
read
(
buffersize
)
return
(
self
.
hash
==
b64encode
(
hash
.
digest
()).
decode
())
hash
.
update
(
buffer
)
buffer
=
fh
.
read
(
buffersize
)
fh
.
close
()
return
(
self
.
hash
==
b64encode
(
hash
.
digest
()).
decode
())
def
copyAndVerify
(
self
,
destination
):
'''
Copies the file to the destination directory and verifies the hash
during.
'''
newfilepath
=
destination
+
'
/
'
+
self
.
filename
if
hasattr
(
self
,
'
hash
'
)
==
False
:
copyfile
(
self
.
fullpath
,
newfilepath
)
self
.
fullpath
=
newfilepath
self
.
rootpath
=
destination
return
True
buffersize
=
2
**
16
in_fh
=
open
(
self
.
fullpath
,
'
rb
'
)
out_fh
=
open
(
newfullpath
,
'
wb
'
)
buffer
=
in_fh
.
read
(
buffersize
)
hash
=
sha1
()
while
buffer
:
hash
.
update
(
buffer
)
out_fh
.
write
(
buffer
)
buffer
=
in_fh
.
read
(
buffersize
)
in_fh
.
close
()
out_fh
.
close
()
self
.
rootpath
=
destination
self
.
fullpath
=
newfullpath
return
(
self
.
hash
==
b64encode
(
hash
.
digest
()).
decode
())
def
add_duration
(
self
):
if
hasattr
(
self
,
'
type
'
)
and
self
.
type
.
find
(
'
mxf
'
)
>
-
1
:
...
...
@@ -40,7 +67,8 @@ class Asset(object):
media
.
parse
()
self
.
duration
=
media
.
get_duration
()
def
__init__
(
self
,
rootpath
,
filename
,
id
=
None
,
hash
=
None
,
size
=
None
,
packinglist
=
False
,
type
=
None
):
def
__init__
(
self
,
rootpath
,
filename
,
id
=
None
,
hash
=
None
,
size
=
None
,
\
packinglist
=
False
,
type
=
None
):
'''
Initialize an asset, has to have a filename and path.
'''
self
.
rootpath
=
rootpath
if
filename
[
0
:
8
]
==
'
file:///
'
:
...
...
@@ -60,15 +88,15 @@ class Asset(object):
class
DCP
:
'''
A complete DCP package.
'''
def
verify
(
self
):
def
verify
(
self
):
'''
Verifies that all assets are of the correct size and have
the correct hash.
'''
for
asset
in
self
.
assets
:
try
:
if
asset
.
verifySize
()
==
False
:
if
asset
.
verifySize
()
==
False
:
return
False
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed size comparisement for
'
+
raise
RuntimeError
(
'
Failed size comparisement for
'
+
\
asset
.
filename
)
from
e
#Sort the assets by size before calculating hashes, for performance.
def
sortkey
(
x
):
...
...
@@ -76,71 +104,75 @@ class DCP:
return
x
.
size
except
AttributeError
:
return
0
self
.
assets
.
sort
(
key
=
sortkey
)
self
.
assets
.
sort
(
key
=
sortkey
)
for
asset
in
self
.
assets
:
try
:
if
asset
.
verifyHash
()
==
False
:
if
asset
.
verifyHash
()
==
False
:
return
False
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed hash calculation for
'
+
raise
RuntimeError
(
'
Failed hash calculation for
'
+
\
asset
.
filename
)
from
e
return
True
def
_parse_assetmap
(
self
):
'''
Adds the asset map file to the list of assets and parses it.
'''
if
'
ASSETMAP.xml
'
in
listdir
(
self
.
directory
):
if
'
ASSETMAP.xml
'
in
listdir
(
self
.
directory
):
filename
=
'
ASSETMAP.xml
'
elif
'
ASSETMAP
'
in
listdir
(
self
.
directory
):
elif
'
ASSETMAP
'
in
listdir
(
self
.
directory
):
filename
=
'
ASSETMAP
'
else
:
raise
RuntimeError
(
'
Couldn
\'
t find assetmap file
'
)
self
.
assets
=
[
Asset
(
self
.
directory
,
filename
,
type
=
'
text/xml
'
)]
self
.
assets
=
[
Asset
(
self
.
directory
,
filename
,
type
=
'
text/xml
'
)]
assetmap
=
self
.
assets
[
0
].
fullpath
try
:
assetmap
=
parse
(
assetmap
).
getElementsByTagName
(
'
Asset
'
)
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
))
assetmap
=
parse
(
assetmap
).
getElementsByTagName
(
'
Asset
'
)
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
))
for
element
in
assetmap
:
id
=
element
.
getElementsByTagName
(
'
Id
'
)[
0
].
firstChild
.
data
id
=
id
.
split
(
'
:
'
)[
-
1
]
filename
=
element
.
getElementsByTagName
(
'
Path
'
)[
0
].
firstChild
.
data
packinglist
=
len
(
element
.
getElementsByTagName
(
'
PackingList
'
))
>
0
id
=
element
.
getElementsByTagName
(
'
Id
'
)[
0
].
firstChild
.
data
id
=
id
.
split
(
'
:
'
)[
-
1
]
filename
=
element
.
getElementsByTagName
(
'
Path
'
)[
0
].
firstChild
.
data
packinglist
=
len
(
element
.
getElementsByTagName
(
'
PackingList
'
))
>
0
if
packinglist
:
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
id
=
id
,
packinglist
=
packinglist
,
type
=
'
text/xml
'
))
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
\
id
=
id
,
packinglist
=
packinglist
,
type
=
'
text/xml
'
))
else
:
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
id
=
id
,
packinglist
=
packinglist
))
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
\
id
=
id
,
packinglist
=
packinglist
))
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed to parse assetmap file
'
)
from
e
def
_add_volindex
(
self
):
'''
Adds the volume index file to the list of assets.
'''
if
'
VOLINDEX.xml
'
in
listdir
(
self
.
directory
):
if
'
VOLINDEX.xml
'
in
listdir
(
self
.
directory
):
filename
=
'
VOLINDEX.xml
'
elif
'
VOLINDEX
'
in
listdir
(
self
.
directory
):
elif
'
VOLINDEX
'
in
listdir
(
self
.
directory
):
filename
=
'
VOLINDEX
'
else
:
#raise RuntimeError ('Couldn\'t find volindex file')
return
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
type
=
'
text/xml
'
))
self
.
assets
.
append
(
Asset
(
self
.
directory
,
filename
,
type
=
'
text/xml
'
))
def
_parse_packinglist
(
self
):
'''
Parses the packing list.
'''
try
:
pkls
=
(
parse
(
x
.
fullpath
)
for
x
in
self
.
assets
if
x
.
packinglist
)
pkls
=
(
parse
(
x
.
fullpath
)
for
x
in
self
.
assets
if
x
.
packinglist
)
for
pkl
in
pkls
:
if
hasattr
(
self
,
'
signed
'
)
==
False
:
self
.
signed
=
len
(
pkl
.
getElementsByTagName
(
'
Signer
'
))
>
0
if
hasattr
(
self
,
'
signed
'
)
==
False
:
self
.
signed
=
len
(
pkl
.
getElementsByTagName
(
'
Signer
'
))
>
0
try
:
if
hasattr
(
self
,
'
name
'
)
==
False
:
self
.
name
=
pkl
.
getElementsByTagName
(
'
AnnotationText
'
)[
0
].
firstChild
.
data
.
strip
()
if
hasattr
(
self
,
'
name
'
)
==
False
:
self
.
name
=
pkl
.
getElementsByTagName
\
(
'
AnnotationText
'
)[
0
].
firstChild
.
data
.
strip
()
except
:
pass
for
element
in
pkl
.
getElementsByTagName
(
'
Asset
'
):
id
=
element
.
getElementsByTagName
(
'
Id
'
)[
0
].
firstChild
.
data
id
=
id
.
split
(
'
:
'
)[
-
1
]
hash
=
element
.
getElementsByTagName
(
'
Hash
'
)[
0
].
firstChild
.
data
type
=
element
.
getElementsByTagName
(
'
Type
'
)[
0
].
firstChild
.
data
size
=
int
(
element
.
getElementsByTagName
(
'
Size
'
)[
0
].
firstChild
.
data
)
asset
=
[
x
for
x
in
self
.
assets
if
hasattr
(
x
,
'
id
'
)
and
x
.
id
==
id
][
0
]
for
element
in
pkl
.
getElementsByTagName
(
'
Asset
'
):
id
=
element
.
getElementsByTagName
(
'
Id
'
)[
0
].
firstChild
.
data
id
=
id
.
split
(
'
:
'
)[
-
1
]
hash
=
element
.
getElementsByTagName
(
'
Hash
'
)[
0
].
firstChild
.
data
type
=
element
.
getElementsByTagName
(
'
Type
'
)[
0
].
firstChild
.
data
size
=
int
(
element
.
getElementsByTagName
(
'
Size
'
)[
0
].
firstChild
.
data
)
asset
=
[
x
for
x
in
self
.
assets
if
hasattr
(
x
,
'
id
'
)
and
\
x
.
id
==
id
][
0
]
asset
.
hash
=
hash
asset
.
size
=
size
asset
.
type
=
type
...
...
@@ -148,23 +180,57 @@ class DCP:
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed to parse packinglist file
'
)
from
e
def
__init__
(
self
,
directory
):
def
__init__
(
self
,
directory
):
'''
Parses the DCP in the directory specified.
'''
self
.
directory
=
directory
self
.
_parse_assetmap
()
self
.
_add_volindex
()
self
.
_parse_packinglist
()
try
:
self
.
duration
=
max
([
x
.
duration
for
x
in
self
.
assets
if
hasattr
(
x
,
'
duration
'
)])
self
.
duration
=
max
([
x
.
duration
for
x
in
self
.
assets
if
hasattr
\
(
x
,
'
duration
'
)])
except
:
self
.
duration
=
'
Unknown
'
def
copyAndVerify
(
self
,
destination
):
'''
Copies the DCP to the destination directory and verifies during.
'''
for
asset
in
self
.
assets
:
totalsize
=
stat
(
asset
.
fullpath
).
st_size
try
:
if
asset
.
verifySize
()
==
False
:
return
False
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed size comparisement for
'
+
\
asset
.
filename
)
from
e
freespace
=
statvfs
(
destination
).
f_bavail
*
statvfs
\
(
destination
).
f_bsize
if
freespace
<
totalsize
:
return
False
#Sort the assets by size before calculating hashes, for performance.
def
sortkey
(
x
):
try
:
return
x
.
size
except
AttributeError
:
return
0
self
.
assets
.
sort
(
key
=
sortkey
)
newdirectory
=
destination
+
'
/
'
+
basename
(
self
.
directory
)
mkdir
(
newdirectory
)
for
asset
in
self
.
assets
:
try
:
if
asset
.
copyAndVerify
(
newdirectory
)
==
False
:
return
False
except
BaseException
as
e
:
raise
RuntimeError
(
'
Failed hash calculation for
'
+
\
asset
.
filename
)
from
e
self
.
directory
=
newdirectory
return
True
if
__name__
==
'
__main__
'
:
if
(
len
(
sys
.
argv
)
==
2
)
:
dcp
=
DCP
(
sys
.
argv
[
1
])
if
len
(
sys
.
argv
)
==
2
:
dcp
=
DCP
(
sys
.
argv
[
1
])
else
:
dcp
=
DCP
(
'
./
'
)
dcp
=
DCP
(
'
./
'
)
try
:
print
(
'
Name:
'
,
dcp
.
name
)
except
:
...
...
@@ -174,8 +240,8 @@ if __name__ == '__main__':
else
:
print
(
'
DCP is unsigned
'
)
print
(
'
Duration:
'
,
dcp
.
duration
)
if
(
dcp
.
verify
(
)
):
if
dcp
.
verify
():
print
(
'
Verification succeeded.
'
)
else
:
print
(
'
Verification failed.
'
)
exit
(
0
)
exit
(
0
)
This diff is collapsed.
Click to expand it.
source/manager.py
+
17
−
0
View file @
b31f724e
...
...
@@ -6,6 +6,8 @@ from PyQt4 import QtCore
from
dcp
import
DCP
import
ui
import
sys
import
syslog
import
time
class
verifyThread
(
QtCore
.
QThread
):
'''
A seperate thread to verify the DCP (IO intensive).
...
...
@@ -20,8 +22,12 @@ class verifyThread(QtCore.QThread):
result
=
dcp
.
verify
()
if
result
:
window
.
verifyLine
.
setText
(
'
OK
'
)
syslog
.
syslog
(
syslog
.
LOG_INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
verification succeeded.
'
)
else
:
window
.
verifyLine
.
setText
(
'
Corrupted!
'
)
syslog
.
syslog
(
syslog
.
LOG_INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
verification failed.
'
)
except
BaseException
as
exception
:
window
.
verifyLine
.
setText
(
str
(
exception
))
...
...
@@ -38,6 +44,7 @@ def verify_in_thread():
if
__name__
==
'
__main__
'
:
syslog
.
openlog
(
ident
=
'
dcpman
'
,
facility
=
syslog
.
LOG_USER
)
app
=
QtGui
.
QApplication
(
sys
.
argv
)
icon
=
QtGui
.
QIcon
(
'
/usr/share/icons/oxygen/16x16/apps/kmplayer.png
'
)
app
.
setWindowIcon
(
icon
)
...
...
@@ -51,8 +58,18 @@ if __name__ == '__main__':
dcp
=
DCP
(
directory
)
try
:
window
.
nameLine
.
setText
(
dcp
.
name
)
syslog
.
syslog
(
syslog
.
INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
parsed.
'
)
except
AttributeError
:
window
.
nameLine
.
setText
(
directory
.
split
(
'
/
'
)[
-
1
])
if
dcp
.
signed
:
syslog
.
syslog
(
syslog
.
INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
is signed.
'
)
else
:
syslog
.
syslog
(
syslog
.
INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
is not sigend.
'
)
syslog
.
syslog
(
syslog
.
INFO
,
time
.
ctime
()
+
dcp
.
name
+
\
'
duration is
'
+
dcp
.
duration
)
if
dcp
.
signed
and
dcp
.
duration
==
0
:
window
.
encryptedLine
.
setText
(
'
Most likely
'
)
elif
dcp
.
signed
or
dcp
.
duration
==
0
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment