|
1 # |
|
2 # Copyright (c) 2015-2020 Thierry Florac <tflorac AT ulthar.net> |
|
3 # All Rights Reserved. |
|
4 # |
|
5 # This software is subject to the provisions of the Zope Public License, |
|
6 # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
10 # FOR A PARTICULAR PURPOSE. |
|
11 # |
|
12 |
|
13 """PyAMS_*** module |
|
14 |
|
15 """ |
|
16 |
|
17 __docformat__ = 'restructuredtext' |
|
18 |
|
19 import re |
|
20 |
|
21 from pyquery import PyQuery |
|
22 from pyramid.threadlocal import get_current_registry |
|
23 from zope.lifecycleevent import ObjectCreatedEvent |
|
24 |
|
25 from pyams_content.component.association import IAssociationContainer |
|
26 from pyams_content.component.extfile import IBaseExtFile |
|
27 from pyams_content.component.links import ExternalLink, IExternalLink, IInternalLink, IMailtoLink, \ |
|
28 InternalLink, MailtoLink |
|
29 from pyams_i18n.interfaces import II18n |
|
30 from pyams_sequence.interfaces import ISequentialIntIds |
|
31 from pyams_utils.registry import get_utility |
|
32 from pyams_utils.request import check_request |
|
33 from pyams_utils.url import absolute_url |
|
34 |
|
35 |
|
36 FULL_EMAIL = re.compile('(.*) \<(.*)\>') |
|
37 |
|
38 |
|
39 def check_associations(context, body, lang, notify=True): |
|
40 """Check for link associations from HTML content""" |
|
41 associations = IAssociationContainer(context, None) |
|
42 if associations is None: |
|
43 return |
|
44 registry = get_current_registry() |
|
45 html = PyQuery('<html>{0}</html>'.format(body)) |
|
46 for link in html('a[href]'): |
|
47 link_info = None |
|
48 has_link = False |
|
49 href = link.attrib['href'] |
|
50 if href.startswith('oid://'): |
|
51 sequence = get_utility(ISequentialIntIds) |
|
52 oid = sequence.get_full_oid(href.split('//', 1)[1]) |
|
53 for association in associations.values(): |
|
54 internal_info = IInternalLink(association, None) |
|
55 if (internal_info is not None) and (internal_info.reference == oid): |
|
56 has_link = True |
|
57 break |
|
58 if not has_link: |
|
59 link_info = InternalLink() |
|
60 link_info.visible = False |
|
61 link_info.reference = oid |
|
62 link_info.title = {lang: link.attrib.get('title') or link.text} |
|
63 elif href.startswith('mailto:'): |
|
64 name = None |
|
65 email = href[7:] |
|
66 if '<' in email: |
|
67 groups = FULL_EMAIL.findall(email) |
|
68 if groups: |
|
69 name, email = groups[0] |
|
70 for association in associations.values(): |
|
71 mailto_info = IMailtoLink(association, None) |
|
72 if (mailto_info is not None) and (mailto_info.address == email): |
|
73 has_link = True |
|
74 break |
|
75 if not has_link: |
|
76 link_info = MailtoLink() |
|
77 link_info.visible = False |
|
78 link_info.address = email |
|
79 link_info.address_name = name or email |
|
80 link_info.title = {lang: link.attrib.get('title') or link.text} |
|
81 elif href.startswith('http://') or href.startswith('https://'): |
|
82 for association in associations.values(): |
|
83 external_info = IExternalLink(association, None) |
|
84 if (external_info is not None) and (external_info.url == href): |
|
85 has_link = True |
|
86 break |
|
87 else: |
|
88 extfile_info = IBaseExtFile(association, None) |
|
89 if extfile_info is not None: |
|
90 request = check_request() |
|
91 extfile_url = absolute_url( |
|
92 II18n(extfile_info).query_attribute('data', request=request), |
|
93 request=request) |
|
94 if extfile_url.endswith(href): |
|
95 has_link = True |
|
96 break |
|
97 if not has_link: |
|
98 link_info = ExternalLink() |
|
99 link_info.visible = False |
|
100 link_info.url = href |
|
101 link_info.title = {lang: link.attrib.get('title') or link.text} |
|
102 if link_info is not None: |
|
103 registry.notify(ObjectCreatedEvent(link_info)) |
|
104 associations.append(link_info, notify=notify) |