##// END OF EJS Templates
Do not try to add an attachment ref for external attachment if there is an internal and external attachment in the same post
neko259 -
r1839:4c8bff54 default
parent child Browse files
Show More
@@ -1,379 +1,379 b''
1 import xml.etree.ElementTree as et
1 import xml.etree.ElementTree as et
2 import logging
2 import logging
3 from xml.etree import ElementTree
3 from xml.etree import ElementTree
4
4
5 from boards.abstracts.exceptions import SyncException
5 from boards.abstracts.exceptions import SyncException
6 from boards.abstracts.sync_filters import ThreadFilter
6 from boards.abstracts.sync_filters import ThreadFilter
7 from boards.models import KeyPair, GlobalId, Signature, Post, Tag
7 from boards.models import KeyPair, GlobalId, Signature, Post, Tag
8 from boards.models.attachment.downloaders import download
8 from boards.models.attachment.downloaders import download
9 from boards.models.signature import TAG_REQUEST, ATTR_TYPE, TYPE_GET, \
9 from boards.models.signature import TAG_REQUEST, ATTR_TYPE, TYPE_GET, \
10 ATTR_VERSION, TAG_MODEL, ATTR_NAME, TAG_ID, TYPE_LIST
10 ATTR_VERSION, TAG_MODEL, ATTR_NAME, TAG_ID, TYPE_LIST
11 from boards.utils import get_file_mimetype, get_file_hash
11 from boards.utils import get_file_mimetype, get_file_hash
12 from django.db import transaction
12 from django.db import transaction
13
13
14 EXCEPTION_NODE = 'Sync node returned an error: {}.'
14 EXCEPTION_NODE = 'Sync node returned an error: {}.'
15 EXCEPTION_DOWNLOAD = 'File was not downloaded.'
15 EXCEPTION_DOWNLOAD = 'File was not downloaded.'
16 EXCEPTION_HASH = 'File hash does not match attachment hash.'
16 EXCEPTION_HASH = 'File hash does not match attachment hash.'
17 EXCEPTION_SIGNATURE = 'Invalid model signature for {}.'
17 EXCEPTION_SIGNATURE = 'Invalid model signature for {}.'
18 EXCEPTION_AUTHOR_SIGNATURE = 'Model {} has no author signature.'
18 EXCEPTION_AUTHOR_SIGNATURE = 'Model {} has no author signature.'
19 EXCEPTION_THREAD = 'No thread exists for post {}'
19 EXCEPTION_THREAD = 'No thread exists for post {}'
20 ENCODING_UNICODE = 'unicode'
20 ENCODING_UNICODE = 'unicode'
21
21
22 TAG_MODEL = 'model'
22 TAG_MODEL = 'model'
23 TAG_REQUEST = 'request'
23 TAG_REQUEST = 'request'
24 TAG_RESPONSE = 'response'
24 TAG_RESPONSE = 'response'
25 TAG_ID = 'id'
25 TAG_ID = 'id'
26 TAG_STATUS = 'status'
26 TAG_STATUS = 'status'
27 TAG_MODELS = 'models'
27 TAG_MODELS = 'models'
28 TAG_TITLE = 'title'
28 TAG_TITLE = 'title'
29 TAG_TEXT = 'text'
29 TAG_TEXT = 'text'
30 TAG_THREAD = 'thread'
30 TAG_THREAD = 'thread'
31 TAG_PUB_TIME = 'pub-time'
31 TAG_PUB_TIME = 'pub-time'
32 TAG_SIGNATURES = 'signatures'
32 TAG_SIGNATURES = 'signatures'
33 TAG_SIGNATURE = 'signature'
33 TAG_SIGNATURE = 'signature'
34 TAG_CONTENT = 'content'
34 TAG_CONTENT = 'content'
35 TAG_ATTACHMENTS = 'attachments'
35 TAG_ATTACHMENTS = 'attachments'
36 TAG_ATTACHMENT = 'attachment'
36 TAG_ATTACHMENT = 'attachment'
37 TAG_TAGS = 'tags'
37 TAG_TAGS = 'tags'
38 TAG_TAG = 'tag'
38 TAG_TAG = 'tag'
39 TAG_ATTACHMENT_REFS = 'attachment-refs'
39 TAG_ATTACHMENT_REFS = 'attachment-refs'
40 TAG_ATTACHMENT_REF = 'attachment-ref'
40 TAG_ATTACHMENT_REF = 'attachment-ref'
41 TAG_TRIPCODE = 'tripcode'
41 TAG_TRIPCODE = 'tripcode'
42 TAG_VERSION = 'version'
42 TAG_VERSION = 'version'
43
43
44 TYPE_GET = 'get'
44 TYPE_GET = 'get'
45
45
46 ATTR_VERSION = 'version'
46 ATTR_VERSION = 'version'
47 ATTR_TYPE = 'type'
47 ATTR_TYPE = 'type'
48 ATTR_NAME = 'name'
48 ATTR_NAME = 'name'
49 ATTR_VALUE = 'value'
49 ATTR_VALUE = 'value'
50 ATTR_MIMETYPE = 'mimetype'
50 ATTR_MIMETYPE = 'mimetype'
51 ATTR_KEY = 'key'
51 ATTR_KEY = 'key'
52 ATTR_REF = 'ref'
52 ATTR_REF = 'ref'
53 ATTR_URL = 'url'
53 ATTR_URL = 'url'
54 ATTR_ID_TYPE = 'id-type'
54 ATTR_ID_TYPE = 'id-type'
55
55
56 ID_TYPE_MD5 = 'md5'
56 ID_TYPE_MD5 = 'md5'
57 ID_TYPE_URL = 'url'
57 ID_TYPE_URL = 'url'
58
58
59 STATUS_SUCCESS = 'success'
59 STATUS_SUCCESS = 'success'
60
60
61
61
62 logger = logging.getLogger('boards.sync')
62 logger = logging.getLogger('boards.sync')
63
63
64
64
65 class SyncManager:
65 class SyncManager:
66 @staticmethod
66 @staticmethod
67 def generate_response_get(model_list: list):
67 def generate_response_get(model_list: list):
68 response = et.Element(TAG_RESPONSE)
68 response = et.Element(TAG_RESPONSE)
69
69
70 status = et.SubElement(response, TAG_STATUS)
70 status = et.SubElement(response, TAG_STATUS)
71 status.text = STATUS_SUCCESS
71 status.text = STATUS_SUCCESS
72
72
73 models = et.SubElement(response, TAG_MODELS)
73 models = et.SubElement(response, TAG_MODELS)
74
74
75 for post in model_list:
75 for post in model_list:
76 model = et.SubElement(models, TAG_MODEL)
76 model = et.SubElement(models, TAG_MODEL)
77 model.set(ATTR_NAME, 'post')
77 model.set(ATTR_NAME, 'post')
78
78
79 global_id = post.global_id
79 global_id = post.global_id
80
80
81 attachments = post.attachments.all()
81 attachments = post.attachments.all()
82 if global_id.content:
82 if global_id.content:
83 model.append(et.fromstring(global_id.content))
83 model.append(et.fromstring(global_id.content))
84 if len(attachments) > 0:
84 if len(attachments) > 0:
85 internal_attachments = False
85 internal_attachments = False
86 for attachment in attachments:
86 for attachment in attachments:
87 if attachment.is_internal():
87 if attachment.is_internal():
88 internal_attachments = True
88 internal_attachments = True
89 break
89 break
90
90
91 if internal_attachments:
91 if internal_attachments:
92 attachment_refs = et.SubElement(model, TAG_ATTACHMENT_REFS)
92 attachment_refs = et.SubElement(model, TAG_ATTACHMENT_REFS)
93 for file in attachments:
93 for file in attachments:
94 SyncManager._attachment_to_xml(
94 SyncManager._attachment_to_xml(
95 None, attachment_refs, file)
95 None, attachment_refs, file)
96 else:
96 else:
97 content_tag = et.SubElement(model, TAG_CONTENT)
97 content_tag = et.SubElement(model, TAG_CONTENT)
98
98
99 tag_id = et.SubElement(content_tag, TAG_ID)
99 tag_id = et.SubElement(content_tag, TAG_ID)
100 global_id.to_xml_element(tag_id)
100 global_id.to_xml_element(tag_id)
101
101
102 title = et.SubElement(content_tag, TAG_TITLE)
102 title = et.SubElement(content_tag, TAG_TITLE)
103 title.text = post.title
103 title.text = post.title
104
104
105 text = et.SubElement(content_tag, TAG_TEXT)
105 text = et.SubElement(content_tag, TAG_TEXT)
106 text.text = post.get_sync_text()
106 text.text = post.get_sync_text()
107
107
108 thread = post.get_thread()
108 thread = post.get_thread()
109 if post.is_opening():
109 if post.is_opening():
110 tag_tags = et.SubElement(content_tag, TAG_TAGS)
110 tag_tags = et.SubElement(content_tag, TAG_TAGS)
111 for tag in thread.get_tags():
111 for tag in thread.get_tags():
112 tag_tag = et.SubElement(tag_tags, TAG_TAG)
112 tag_tag = et.SubElement(tag_tags, TAG_TAG)
113 tag_tag.text = tag.name
113 tag_tag.text = tag.name
114 else:
114 else:
115 tag_thread = et.SubElement(content_tag, TAG_THREAD)
115 tag_thread = et.SubElement(content_tag, TAG_THREAD)
116 thread_id = et.SubElement(tag_thread, TAG_ID)
116 thread_id = et.SubElement(tag_thread, TAG_ID)
117 thread.get_opening_post().global_id.to_xml_element(thread_id)
117 thread.get_opening_post().global_id.to_xml_element(thread_id)
118
118
119 pub_time = et.SubElement(content_tag, TAG_PUB_TIME)
119 pub_time = et.SubElement(content_tag, TAG_PUB_TIME)
120 pub_time.text = str(post.get_pub_time_str())
120 pub_time.text = str(post.get_pub_time_str())
121
121
122 if post.tripcode:
122 if post.tripcode:
123 tripcode = et.SubElement(content_tag, TAG_TRIPCODE)
123 tripcode = et.SubElement(content_tag, TAG_TRIPCODE)
124 tripcode.text = post.tripcode
124 tripcode.text = post.tripcode
125
125
126 if len(attachments) > 0:
126 if len(attachments) > 0:
127 attachments_tag = et.SubElement(content_tag, TAG_ATTACHMENTS)
127 attachments_tag = et.SubElement(content_tag, TAG_ATTACHMENTS)
128
128
129 internal_attachments = False
129 internal_attachments = False
130 for attachment in attachments:
130 for attachment in attachments:
131 if attachment.is_internal():
131 if attachment.is_internal():
132 internal_attachments = True
132 internal_attachments = True
133 break
133 break
134
134
135 if internal_attachments:
135 if internal_attachments:
136 attachment_refs = et.SubElement(model, TAG_ATTACHMENT_REFS)
136 attachment_refs = et.SubElement(model, TAG_ATTACHMENT_REFS)
137 else:
137 else:
138 attachment_refs = None
138 attachment_refs = None
139
139
140 for file in attachments:
140 for file in attachments:
141 SyncManager._attachment_to_xml(
141 SyncManager._attachment_to_xml(
142 attachments_tag, attachment_refs, file)
142 attachments_tag, attachment_refs, file)
143 version_tag = et.SubElement(content_tag, TAG_VERSION)
143 version_tag = et.SubElement(content_tag, TAG_VERSION)
144 version_tag.text = str(post.version)
144 version_tag.text = str(post.version)
145
145
146 global_id.content = et.tostring(content_tag, ENCODING_UNICODE)
146 global_id.content = et.tostring(content_tag, ENCODING_UNICODE)
147 global_id.save()
147 global_id.save()
148
148
149 signatures_tag = et.SubElement(model, TAG_SIGNATURES)
149 signatures_tag = et.SubElement(model, TAG_SIGNATURES)
150 post_signatures = global_id.signature_set.all()
150 post_signatures = global_id.signature_set.all()
151 if post_signatures:
151 if post_signatures:
152 signatures = post_signatures
152 signatures = post_signatures
153 else:
153 else:
154 key = KeyPair.objects.get(public_key=global_id.key)
154 key = KeyPair.objects.get(public_key=global_id.key)
155 signature = Signature(
155 signature = Signature(
156 key_type=key.key_type,
156 key_type=key.key_type,
157 key=key.public_key,
157 key=key.public_key,
158 signature=key.sign(global_id.content),
158 signature=key.sign(global_id.content),
159 global_id=global_id,
159 global_id=global_id,
160 )
160 )
161 signature.save()
161 signature.save()
162 signatures = [signature]
162 signatures = [signature]
163 for signature in signatures:
163 for signature in signatures:
164 signature_tag = et.SubElement(signatures_tag, TAG_SIGNATURE)
164 signature_tag = et.SubElement(signatures_tag, TAG_SIGNATURE)
165 signature_tag.set(ATTR_TYPE, signature.key_type)
165 signature_tag.set(ATTR_TYPE, signature.key_type)
166 signature_tag.set(ATTR_VALUE, signature.signature)
166 signature_tag.set(ATTR_VALUE, signature.signature)
167 signature_tag.set(ATTR_KEY, signature.key)
167 signature_tag.set(ATTR_KEY, signature.key)
168
168
169 return et.tostring(response, ENCODING_UNICODE)
169 return et.tostring(response, ENCODING_UNICODE)
170
170
171 @staticmethod
171 @staticmethod
172 def parse_response_get(response_xml, hostname):
172 def parse_response_get(response_xml, hostname):
173 tag_root = et.fromstring(response_xml)
173 tag_root = et.fromstring(response_xml)
174 tag_status = tag_root.find(TAG_STATUS)
174 tag_status = tag_root.find(TAG_STATUS)
175 if STATUS_SUCCESS == tag_status.text:
175 if STATUS_SUCCESS == tag_status.text:
176 tag_models = tag_root.find(TAG_MODELS)
176 tag_models = tag_root.find(TAG_MODELS)
177 for tag_model in tag_models:
177 for tag_model in tag_models:
178 SyncManager.parse_post(tag_model, hostname)
178 SyncManager.parse_post(tag_model, hostname)
179 else:
179 else:
180 raise SyncException(EXCEPTION_NODE.format(tag_status.text))
180 raise SyncException(EXCEPTION_NODE.format(tag_status.text))
181
181
182 @staticmethod
182 @staticmethod
183 @transaction.atomic
183 @transaction.atomic
184 def parse_post(tag_model, hostname):
184 def parse_post(tag_model, hostname):
185 tag_content = tag_model.find(TAG_CONTENT)
185 tag_content = tag_model.find(TAG_CONTENT)
186
186
187 content_str = et.tostring(tag_content, ENCODING_UNICODE)
187 content_str = et.tostring(tag_content, ENCODING_UNICODE)
188
188
189 tag_id = tag_content.find(TAG_ID)
189 tag_id = tag_content.find(TAG_ID)
190 global_id, exists = GlobalId.from_xml_element(tag_id)
190 global_id, exists = GlobalId.from_xml_element(tag_id)
191 signatures = SyncManager._verify_model(global_id, content_str, tag_model)
191 signatures = SyncManager._verify_model(global_id, content_str, tag_model)
192
192
193 version = int(tag_content.find(TAG_VERSION).text)
193 version = int(tag_content.find(TAG_VERSION).text)
194 is_old = exists and global_id.post.version < version
194 is_old = exists and global_id.post.version < version
195 if exists and not is_old:
195 if exists and not is_old:
196 print('Post with same ID exists and is up to date.')
196 print('Post with same ID exists and is up to date.')
197 else:
197 else:
198 global_id.content = content_str
198 global_id.content = content_str
199 global_id.save()
199 global_id.save()
200 for signature in signatures:
200 for signature in signatures:
201 signature.global_id = global_id
201 signature.global_id = global_id
202 signature.save()
202 signature.save()
203
203
204 title = tag_content.find(TAG_TITLE).text or ''
204 title = tag_content.find(TAG_TITLE).text or ''
205 text = tag_content.find(TAG_TEXT).text or ''
205 text = tag_content.find(TAG_TEXT).text or ''
206 pub_time = tag_content.find(TAG_PUB_TIME).text
206 pub_time = tag_content.find(TAG_PUB_TIME).text
207 tripcode_tag = tag_content.find(TAG_TRIPCODE)
207 tripcode_tag = tag_content.find(TAG_TRIPCODE)
208 if tripcode_tag is not None:
208 if tripcode_tag is not None:
209 tripcode = tripcode_tag.text or ''
209 tripcode = tripcode_tag.text or ''
210 else:
210 else:
211 tripcode = ''
211 tripcode = ''
212
212
213 thread = tag_content.find(TAG_THREAD)
213 thread = tag_content.find(TAG_THREAD)
214 tags = []
214 tags = []
215 if thread:
215 if thread:
216 thread_id = thread.find(TAG_ID)
216 thread_id = thread.find(TAG_ID)
217 op_global_id, exists = GlobalId.from_xml_element(thread_id)
217 op_global_id, exists = GlobalId.from_xml_element(thread_id)
218 if exists:
218 if exists:
219 opening_post = Post.objects.get(global_id=op_global_id)
219 opening_post = Post.objects.get(global_id=op_global_id)
220 else:
220 else:
221 raise Exception(EXCEPTION_THREAD.format(global_id))
221 raise Exception(EXCEPTION_THREAD.format(global_id))
222 else:
222 else:
223 opening_post = None
223 opening_post = None
224 tag_tags = tag_content.find(TAG_TAGS)
224 tag_tags = tag_content.find(TAG_TAGS)
225 for tag_tag in tag_tags:
225 for tag_tag in tag_tags:
226 tag, created = Tag.objects.get_or_create(
226 tag, created = Tag.objects.get_or_create(
227 name=tag_tag.text)
227 name=tag_tag.text)
228 tags.append(tag)
228 tags.append(tag)
229
229
230 # TODO Check that the replied posts are already present
230 # TODO Check that the replied posts are already present
231 # before adding new ones
231 # before adding new ones
232
232
233 files = []
233 files = []
234 urls = []
234 urls = []
235 tag_attachments = tag_content.find(TAG_ATTACHMENTS) or list()
235 tag_attachments = tag_content.find(TAG_ATTACHMENTS) or list()
236 tag_refs = tag_model.find(TAG_ATTACHMENT_REFS)
236 tag_refs = tag_model.find(TAG_ATTACHMENT_REFS)
237 for attachment in tag_attachments:
237 for attachment in tag_attachments:
238 if attachment.get(ATTR_ID_TYPE) == ID_TYPE_URL:
238 if attachment.get(ATTR_ID_TYPE) == ID_TYPE_URL:
239 urls.append(attachment.text)
239 urls.append(attachment.text)
240 else:
240 else:
241 tag_ref = tag_refs.find("{}[@ref='{}']".format(
241 tag_ref = tag_refs.find("{}[@ref='{}']".format(
242 TAG_ATTACHMENT_REF, attachment.text))
242 TAG_ATTACHMENT_REF, attachment.text))
243 url = tag_ref.get(ATTR_URL)
243 url = tag_ref.get(ATTR_URL)
244 attached_file = download(hostname + url, validate=False)
244 attached_file = download(hostname + url, validate=False)
245 if attached_file is None:
245 if attached_file is None:
246 raise SyncException(EXCEPTION_DOWNLOAD)
246 raise SyncException(EXCEPTION_DOWNLOAD)
247
247
248 hash = get_file_hash(attached_file)
248 hash = get_file_hash(attached_file)
249 if hash != attachment.text:
249 if hash != attachment.text:
250 raise SyncException(EXCEPTION_HASH)
250 raise SyncException(EXCEPTION_HASH)
251
251
252 files.append(attached_file)
252 files.append(attached_file)
253
253
254 if is_old:
254 if is_old:
255 post = global_id.post
255 post = global_id.post
256 Post.objects.update_post(
256 Post.objects.update_post(
257 post, title=title, text=text, pub_time=pub_time,
257 post, title=title, text=text, pub_time=pub_time,
258 tags=tags, files=files, file_urls=urls,
258 tags=tags, files=files, file_urls=urls,
259 tripcode=tripcode, version=version)
259 tripcode=tripcode, version=version)
260 logger.debug('Parsed updated post {}'.format(global_id))
260 logger.debug('Parsed updated post {}'.format(global_id))
261 else:
261 else:
262 Post.objects.import_post(
262 Post.objects.import_post(
263 title=title, text=text, pub_time=pub_time,
263 title=title, text=text, pub_time=pub_time,
264 opening_post=opening_post, tags=tags,
264 opening_post=opening_post, tags=tags,
265 global_id=global_id, files=files,
265 global_id=global_id, files=files,
266 file_urls=urls, tripcode=tripcode,
266 file_urls=urls, tripcode=tripcode,
267 version=version)
267 version=version)
268 logger.debug('Parsed new post {}'.format(global_id))
268 logger.debug('Parsed new post {}'.format(global_id))
269
269
270 @staticmethod
270 @staticmethod
271 def generate_response_list(filters):
271 def generate_response_list(filters):
272 response = et.Element(TAG_RESPONSE)
272 response = et.Element(TAG_RESPONSE)
273
273
274 status = et.SubElement(response, TAG_STATUS)
274 status = et.SubElement(response, TAG_STATUS)
275 status.text = STATUS_SUCCESS
275 status.text = STATUS_SUCCESS
276
276
277 models = et.SubElement(response, TAG_MODELS)
277 models = et.SubElement(response, TAG_MODELS)
278
278
279 posts = Post.objects.prefetch_related('global_id')
279 posts = Post.objects.prefetch_related('global_id')
280 for post_filter in filters:
280 for post_filter in filters:
281 posts = post_filter.filter(posts)
281 posts = post_filter.filter(posts)
282
282
283 for post in posts:
283 for post in posts:
284 tag_model = et.SubElement(models, TAG_MODEL)
284 tag_model = et.SubElement(models, TAG_MODEL)
285 tag_id = et.SubElement(tag_model, TAG_ID)
285 tag_id = et.SubElement(tag_model, TAG_ID)
286 post.global_id.to_xml_element(tag_id)
286 post.global_id.to_xml_element(tag_id)
287 tag_version = et.SubElement(tag_model, TAG_VERSION)
287 tag_version = et.SubElement(tag_model, TAG_VERSION)
288 tag_version.text = str(post.version)
288 tag_version.text = str(post.version)
289
289
290 return et.tostring(response, ENCODING_UNICODE)
290 return et.tostring(response, ENCODING_UNICODE)
291
291
292 @staticmethod
292 @staticmethod
293 def _verify_model(global_id, content_str, tag_model):
293 def _verify_model(global_id, content_str, tag_model):
294 """
294 """
295 Verifies all signatures for a single model.
295 Verifies all signatures for a single model.
296 """
296 """
297
297
298 signatures = []
298 signatures = []
299
299
300 tag_signatures = tag_model.find(TAG_SIGNATURES)
300 tag_signatures = tag_model.find(TAG_SIGNATURES)
301 has_author_signature = False
301 has_author_signature = False
302 for tag_signature in tag_signatures:
302 for tag_signature in tag_signatures:
303 signature_type = tag_signature.get(ATTR_TYPE)
303 signature_type = tag_signature.get(ATTR_TYPE)
304 signature_value = tag_signature.get(ATTR_VALUE)
304 signature_value = tag_signature.get(ATTR_VALUE)
305 signature_key = tag_signature.get(ATTR_KEY)
305 signature_key = tag_signature.get(ATTR_KEY)
306
306
307 if global_id.key_type == signature_type and\
307 if global_id.key_type == signature_type and\
308 global_id.key == signature_key:
308 global_id.key == signature_key:
309 has_author_signature = True
309 has_author_signature = True
310
310
311 signature = Signature(key_type=signature_type,
311 signature = Signature(key_type=signature_type,
312 key=signature_key,
312 key=signature_key,
313 signature=signature_value)
313 signature=signature_value)
314
314
315 if not KeyPair.objects.verify(signature, content_str):
315 if not KeyPair.objects.verify(signature, content_str):
316 raise SyncException(EXCEPTION_SIGNATURE.format(content_str))
316 raise SyncException(EXCEPTION_SIGNATURE.format(content_str))
317
317
318 signatures.append(signature)
318 signatures.append(signature)
319 if not has_author_signature:
319 if not has_author_signature:
320 raise SyncException(EXCEPTION_AUTHOR_SIGNATURE.format(content_str))
320 raise SyncException(EXCEPTION_AUTHOR_SIGNATURE.format(content_str))
321
321
322 return signatures
322 return signatures
323
323
324 @staticmethod
324 @staticmethod
325 def _attachment_to_xml(tag_attachments, tag_refs, attachment):
325 def _attachment_to_xml(tag_attachments, tag_refs, attachment):
326 if tag_attachments is not None:
326 if tag_attachments is not None:
327 attachment_tag = et.SubElement(tag_attachments, TAG_ATTACHMENT)
327 attachment_tag = et.SubElement(tag_attachments, TAG_ATTACHMENT)
328 if attachment.is_internal():
328 if attachment.is_internal():
329 mimetype = get_file_mimetype(attachment.file.file)
329 mimetype = get_file_mimetype(attachment.file.file)
330 attachment_tag.set(ATTR_MIMETYPE, mimetype)
330 attachment_tag.set(ATTR_MIMETYPE, mimetype)
331 attachment_tag.set(ATTR_ID_TYPE, ID_TYPE_MD5)
331 attachment_tag.set(ATTR_ID_TYPE, ID_TYPE_MD5)
332 attachment_tag.text = attachment.hash
332 attachment_tag.text = attachment.hash
333 else:
333 else:
334 attachment_tag.set(ATTR_ID_TYPE, ID_TYPE_URL)
334 attachment_tag.set(ATTR_ID_TYPE, ID_TYPE_URL)
335 attachment_tag.text = attachment.url
335 attachment_tag.text = attachment.url
336
336
337 if tag_refs is not None:
337 if tag_refs is not None and attachment.is_internal():
338 attachment_ref = et.SubElement(tag_refs, TAG_ATTACHMENT_REF)
338 attachment_ref = et.SubElement(tag_refs, TAG_ATTACHMENT_REF)
339 attachment_ref.set(ATTR_REF, attachment.hash)
339 attachment_ref.set(ATTR_REF, attachment.hash)
340 attachment_ref.set(ATTR_URL, attachment.file.url)
340 attachment_ref.set(ATTR_URL, attachment.file.url)
341
341
342 @staticmethod
342 @staticmethod
343 def generate_request_get(global_id_list: list):
343 def generate_request_get(global_id_list: list):
344 """
344 """
345 Form a get request from a list of ModelId objects.
345 Form a get request from a list of ModelId objects.
346 """
346 """
347
347
348 request = et.Element(TAG_REQUEST)
348 request = et.Element(TAG_REQUEST)
349 request.set(ATTR_TYPE, TYPE_GET)
349 request.set(ATTR_TYPE, TYPE_GET)
350 request.set(ATTR_VERSION, '1.0')
350 request.set(ATTR_VERSION, '1.0')
351
351
352 model = et.SubElement(request, TAG_MODEL)
352 model = et.SubElement(request, TAG_MODEL)
353 model.set(ATTR_VERSION, '1.0')
353 model.set(ATTR_VERSION, '1.0')
354 model.set(ATTR_NAME, 'post')
354 model.set(ATTR_NAME, 'post')
355
355
356 for global_id in global_id_list:
356 for global_id in global_id_list:
357 tag_id = et.SubElement(model, TAG_ID)
357 tag_id = et.SubElement(model, TAG_ID)
358 global_id.to_xml_element(tag_id)
358 global_id.to_xml_element(tag_id)
359
359
360 return et.tostring(request, 'unicode')
360 return et.tostring(request, 'unicode')
361
361
362 @staticmethod
362 @staticmethod
363 def generate_request_list(opening_post=None):
363 def generate_request_list(opening_post=None):
364 """
364 """
365 Form a pull request from a list of ModelId objects.
365 Form a pull request from a list of ModelId objects.
366 """
366 """
367
367
368 request = et.Element(TAG_REQUEST)
368 request = et.Element(TAG_REQUEST)
369 request.set(ATTR_TYPE, TYPE_LIST)
369 request.set(ATTR_TYPE, TYPE_LIST)
370 request.set(ATTR_VERSION, '1.0')
370 request.set(ATTR_VERSION, '1.0')
371
371
372 model = et.SubElement(request, TAG_MODEL)
372 model = et.SubElement(request, TAG_MODEL)
373 model.set(ATTR_VERSION, '1.0')
373 model.set(ATTR_VERSION, '1.0')
374 model.set(ATTR_NAME, 'post')
374 model.set(ATTR_NAME, 'post')
375
375
376 if opening_post:
376 if opening_post:
377 ThreadFilter().add_filter(model, opening_post)
377 ThreadFilter().add_filter(model, opening_post)
378
378
379 return et.tostring(request, 'unicode')
379 return et.tostring(request, 'unicode')
General Comments 0
You need to be logged in to leave comments. Login now