Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Read the contents of a P6 .xer file and convert it into a Python object.
Disclaimers:
It's helpfull if you are already familiar with the mapping and schemas used by P6 during the export process.
Refer to the Oracle Documentation for more information regarding how data is mapped to the XER format.
Tested on .xer files exported as versions 15.2 through 19.12.
Windows:
pip install xerparser
Linux/Mac:
pip3 install xerparser
Import the Xer
class from xerparser
and pass the contents of a .xer file as an argument. Use the Xer
class variable CODEC
to set the proper encoding to decode the file.
from xerparser import Xer
file = r"/path/to/file.xer"
with open(file, encoding=Xer.CODEC, errors="ignore") as f:
file_contents = f.read()
xer = Xer(file_contents)
Do not pass the the .xer file directly as an argument to the Xer
class. The file must be decoded and read into a string, which can then be passed as an argument. Or, pass the .xer file into the Xer.reader
classmethod, which accepts:
from xerparser import Xer
file = r"/path/to/file.xer"
xer = Xer.reader(file)
The tables stored in the .xer file are accessable as either Global, Project specific, Task specific, or Resource specific:
xer.export_info # export data
xer.activity_code_types # dict of ACTVTYPE objects
xer.activity_code_values # dict of ACTVCODE objects
xer.calendars # dict of all CALENDAR objects
xer.financial_periods # dict of FINDATES objects
xer.notebook_topics # dict of MEMOTYPE objects
xer.projects # dict of PROJECT objects
xer.project_code_types # dict of PCATTYPE objects
xer.project_code_values # dict of PCATVAL objects
xer.tasks # dict of all TASK objects
xer.relationships # dict of all TASKPRED objects
xer.resources # dict of RSRC objects
xer.resource_rates # dict of RSRCRATE objects
xer.udf_types # dict of UDFTYPE objects
xer.wbs_nodes # dict of all PROJWBS objects
# Get first project
project = list(xer.projects.values())[0]
project.activity_codes # list of project specific ACTVTYPE objects
project.calendars # list of project specific CALENDAR objects
project.project_codes # dict of PCATTYPE: PCATVAL objects
project.tasks # list of project specific TASK objects
project.relationships # list of project specific TASKPRED objects
project.resources # lest of project specific TASKRSRC objects
project.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
project.wbs_nodes # list of project specific PROJWBS objects
# Get projects root wbs node
wbs_node = project.wbs_root
wbs_node.children # list of child PROJWBS objects
wbs_node.project # PROJECT the WBS node belongs to
wbs_node.tasks # list of TASK objects assigned directly to WBS node
wbs_node.all_tasks # list of TASK objects under the WBS node
wbs_node.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
# Get first task
task = project.tasks[0]
task.activity_codes # dict of ACTVTYPE: ACTVCODE objects
task.memos # list of TASKMEMO objects
task.periods # list of TASKFIN objects
task.resources # dict of TASKRSRC objects
task.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
# Get first task resource
resource = list(task.resources.values())[0]
resource.periods # list of TRSRCFIN objects
resource.user_defined_fields # dict of `UDFTYPE`: `UDF Value` pairs
Sometimes the xer file is corrupted during the export process. If this is the case, a CorruptXerFile
Exception will be raised during initialization. A list of the errors can be accessed from the CorruptXerFile
Exception, or by using the find_xer_errors
function.
errors
attribute of CorruptXerFile
exception (preferred)from xerparser import Xer, CorruptXerFile
file = r"/path/to/file.xer"
try:
xer = Xer.reader(file)
except CorruptXerFile as e:
for error in e.errors:
print(error)
find_xer_errors
functionfrom xerparser import parser, file_reader, find_xer_errors
file = r"/path/to/file.xer"
xer_data = parser(file_reader(file))
file_errors = find_xer_errors(xer_data)
for error in file_errors:
print(error)
Minimum required tables - an error is recorded if one of the following tables is missing:
Required table pairs - an error is recorded if Table 1 is included but not Table 2:
Table 1 | Table 2 | Notes |
---|---|---|
TASKFIN | FINDATES | Financial Period Data for Task |
TRSRCFIN | FINDATES | Financial Period Data for Task Resource |
TASKRSRC | RSRC | Resource Data |
TASKMEMO | MEMOTYPE | Notebook Data |
ACTVCODE | ACTVTYPE | Activity Code Data |
TASKACTV | ACTVCODE | Activity Code Data |
PCATVAL | PCATTYPE | Project Code Data |
PROJPCAT | PCATVAL | Project Code Data |
UDFVALUE | UDFTYPE | User Defined Field Data |
Non-existent calendars assigned to tasks.
Non-existent resources assigned to task resources.
FAQs
Parse a P6 .xer file to a Python object.
We found that xerparser demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.