Advertisement
rijarob

foxycart.py XML Transactions

May 16th, 2017
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.74 KB | None | 0 0
  1. """
  2. Utilities for decrypting and parsing a FoxyCart datafeed.
  3. """
  4. from xml.dom.minidom import parseString
  5. from datetime import datetime
  6.  
  7. # Thanks, Wikipedia: http://en.wikipedia.org/wiki/RC4#Implementation
  8. class ARC4:
  9. def __init__(self, key = None):
  10. self.state = range(256) # Initialize state array with values 0 .. 255
  11. self.x = self.y = 0 # Our indexes. x, y instead of i, j
  12.  
  13. if key is not None:
  14. self.init(key)
  15.  
  16. # KSA
  17. def init(self, key):
  18. for i in range(256):
  19. self.x = (ord(key[i % len(key)]) + self.state[i] + self.x) & 0xFF
  20. self.state[i], self.state[self.x] = self.state[self.x], self.state[i]
  21. self.x = 0
  22.  
  23. # PRGA
  24. def crypt(self, input):
  25. output = [None]*len(input)
  26. for i in xrange(len(input)):
  27. self.x = (self.x + 1) & 0xFF
  28. self.y = (self.state[self.x] + self.y) & 0xFF
  29. self.state[self.x], self.state[self.y] = self.state[self.y], self.state[self.x]
  30. r = self.state[(self.state[self.x] + self.state[self.y]) & 0xFF]
  31. output[i] = chr(ord(input[i]) ^ r)
  32. return ''.join(output)
  33.  
  34.  
  35. class FoxyData:
  36. DateFmt = '%Y-%m-%d'
  37. DateTimeFmt = '%Y-%m-%d %H:%M:%S'
  38.  
  39. class Transaction:
  40. def __init__(self, node):
  41. def extract_kv_node(node, key_name):
  42. el = node.getElementsByTagName(key_name)
  43. try:
  44. if el[0].firstChild is None:
  45. return len(el) and ''
  46. else:
  47. return len(el) > 0 and el[0].firstChild.data
  48. except:
  49. pass
  50.  
  51. self.id = extract_kv_node(node, 'id')
  52. self.date = datetime.strptime(
  53. extract_kv_node(node, 'transaction_date'), FoxyData.DateTimeFmt)
  54. self.customer_id = extract_kv_node(node, 'customer_id')
  55.  
  56. self.attributes = attrs = {}
  57. self.items = items = attrs['items'] = []
  58.  
  59. self.custom_fields = attrs['custom_fields'] = {}
  60. for custom_field in node.getElementsByTagName('custom_field'):
  61. self.custom_fields[extract_kv_node(custom_field, 'custom_field_name')] = \
  62. extract_kv_node(custom_field, 'custom_field_value')
  63.  
  64. self.transaction_details = attrs['detail'] = []
  65. for details in node.getElementsByTagName('transaction_detail'):
  66. item = {'product_code': extract_kv_node(details, 'product_code')}
  67.  
  68. for key in ['subscription_startdate', 'next_transaction_date']:
  69. date_str = extract_kv_node(details, key)
  70. try:
  71. if date_str is not None:
  72. item[key] = datetime.strptime(date_str, FoxyData.DateFmt)
  73. except ValueError:
  74. item[key] = date_str
  75.  
  76. detail = item['detail'] = {}
  77. for detail_opt in details.getElementsByTagName('transaction_detail_option'):
  78. detail[extract_kv_node(detail_opt, 'product_option_name')] = \
  79. extract_kv_node(detail_opt, 'product_option_value')
  80.  
  81. items.append(item)
  82.  
  83. def __init__(self, markup):
  84. self.markup = markup
  85. self.doc = parseString(self.markup)
  86. self.transactions = []
  87.  
  88. for transaction in self.doc.getElementsByTagName('transaction'):
  89. self.transactions.append(FoxyData.Transaction(transaction))
  90.  
  91. def __str__(self):
  92. return str(self.markup)
  93.  
  94.  
  95. @classmethod
  96. def from_str(self, data_str):
  97. return FoxyData(data_str)
  98.  
  99. """
  100. Given a string containing RC4-crypted FoxyCart datafeed XML and the
  101. cryptographic key, decrypt the contents and create a FoxyData object
  102. containing all of the Transactions in the data feed.
  103. """
  104. @classmethod
  105. def from_crypted_str(self, data_str, crypt_key):
  106. a = ARC4(crypt_key)
  107. return FoxyData.from_str(a.crypt(data_str))
  108.  
  109. def __len__(self):
  110. return len(self.transactions)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement