Django

Code

Ticket #6071: utils.py

File utils.py, 33.8 kB (added by hans.rauch@gmx.net, 1 year ago)
Line 
1 #-*-coding: utf-8 -*-
2 """
3 /dms/utils.py
4
5 .. enthaelt Hilfefunktionen fuer
6          Django content Management System
7
8 Hans Rauch
9
10 hans.rauch@gmx.net
11
12 Die Programme des dms-Systems koennen frei genutzt und den spezifischen
13 Beduerfnissen entsprechend angepasst werden.
14
15 0.01  13.01.2007  Beginn der Dokumentation
16 0.02  16.01.2007  check_name
17 0.03  20.1.2007   base_site_url
18 0.04  04.02.2007  bei Vortraegen wird der Titel in der breadcrum angezeigt
19 0.05  01.03.2007  send_control_email
20 0.06  17.05.2007  show_link - info=''
21 0.07  01.06.2007  get_folderish_actions ueberarbeitet
22 0.08  10.09.2007  add_if_app_available
23 0.09  02.10.2007  manage_site_mode, manage_domain_mode
24 0.10  03.10.2007  get_site_actions
25 0.11  17.10.2007  get_link_by_item_container fuer Redirects in Lernarchiven angepasst
26 0.12  23.10.2007  get_item_container_data_object_by_id
27 0.13  31.10.2007  PROJECT_FOLDER
28 0.14  10.11.2007  is_protected
29 """
30
31 import string
32 import datetime
33
34 from django.utils.translation import ugettext as _
35
36 from math               import floor
37 from datetime           import date
38
39 from django.utils.translation import ugettext as _
40
41 from django.utils.encoding  import smart_unicode
42 from django             import newforms as forms
43
44 from django.utils.translation import ugettext as _
45
46 from dms.settings       import DOWNLOAD_URL
47 from dms.settings       import MY_DOMAINS
48
49 from dms.queries        import get_top_item
50 from dms.queries        import get_parent_item_container
51 from dms.queries        import get_menuitems_navmenu_top
52 from dms.queries        import get_menuitems_navmenu_left
53 from dms.queries        import is_file_by_item_container
54 from dms.queries        import get_prev_parent_item_containers
55 from dms.queries        import get_next_parent_item_containers
56 from dms.queries        import get_licenses
57 from dms.queries        import get_site_url
58 from dms.queries        import get_base_site_url
59 from dms.queries        import get_faecher
60 from dms.queries        import get_schularten
61 from dms.queries        import is_app_available
62 from dms.queries        import get_item_container_data_object_by_id
63 from dms.queries        import is_protected
64
65 from dms.encode_decode  import decode_html
66 from dms.encode_decode  import encode_html
67
68 from dms.text_icons     import FOLDER_ICON, PROJECT_ICON
69 from dms.text_icons     import EXTERN_ICON, NEW_WINDOW_ICON, FILE_DETAIL, REDIRECT_ICON
70
71 # -----------------------------------------------------
72 # E-Mail-Adressen verschluesseln
73
74 # Created by jmeile
75 # Anpassung an zecom: Hans Rauch, 3.12.2002, 04.01-2006
76
77 def encode_email(emailvalue, namevalue=None,rClass=None,info=None):
78   #Taken from http://www.happysnax.com.au/testemail.php
79   #Original comments:
80   '''this function creates the hexadecimal equivalent to
81      "document.write('<a href="mailto:emailaddress">name</a>')"
82      ie it effectively encrpts this as far as spam-bots are concerned
83      the Javascript to unencrypt it simply changes the hex back into ascii
84      then executes the code using the 'eval' statement
85      /... and ta da ... you've got a normal mailto address displayed in the browser.
86      //Written by Jeff Robson of Cynergic Net Solutions www.cynergic.net jeff.robson@cynergic.net'''
87   if emailvalue == '' :
88     return namevalue
89   if namevalue == None :
90     namevalue = emailvalue
91   if rClass != None :
92     cClass = ' class="' + rClass + '"'
93   else :
94     cClass = ''
95   if info != None :
96     cInfo = ' title="' + info + '"'
97   else :
98     cInfo = ''
99   new_text = hex_string ( 'document.write(\'<a' + cClass + ' href=\"mailto:'+emailvalue+'\"' + \
100                           cInfo + '>'+namevalue+'</a>\')' )
101   return '<script type=\"text/javascript\">eval(unescape(\''+new_text+'\'))</script>'
102
103 def hex_string(mystring):
104   #Taken from http://www.happysnax.com.au/testemail.php
105   '''Written by Jeff Robson of Cynergic Net Solutions www.cynergic.net jeff.robson@cynergic.net'''
106   newstring=''
107   length=len(mystring)
108   for i in range(length):
109     newstring=newstring+'%'+tohex(ord(mystring[i]))
110   return newstring
111
112 def tohex(n):
113   #Taken from http://www.happysnax.com.au/testemail.php
114   '''Written by Jeff Robson of Cynergic Net Solutions www.cynergic.net jeff.robson@cynergic.net'''
115   hs='0123456789ABCDEF'
116   return hs[int(floor(n/16))]+hs[n%16]
117
118 # -----------------------------------------------------
119 def get_footer_email(object, use_string_1=False):
120   """ liefert Namen und Adresse des Autors """
121   if smart_unicode(str(type(object))) == "<class 'dms.models.DmsItem'>":
122     item = object
123   else:
124     item = object.item
125   try:
126     my_ext_item = get_ext_item(item)
127     return encode_email(my_ext_item.owner_email, my_ext_item.owner, 'navLink')
128   except:
129     if use_string_1:
130       return encode_email(item.string_2, item.string_1, 'navLink')
131     else:
132       return encode_email(item.owner.email, item.owner.get_full_name(), 'navLink')
133
134 def get_author_email(author, email):
135   """ liefert Namen und Adresse des Autors """
136   return encode_email(email, author, 'nav')
137
138 # -----------------------------------------------------
139 def get_tabbed_form(rFormItems, rFormHelp, rHelpName, rFormData,
140                     do_tab=True, tab_cluster={}, valign=True, max_cols=1,
141                     show_errors=True):
142   """ baut Tabbed-Formulare zusammen: Quelle ??? """
143   from dms.form_system        import form_system
144   from django.template.loader import get_template
145   from django.template        import Context
146
147   t = get_template('utils/yui_tab_base.html')
148   content = ''
149   headers = []
150   tabs = []
151   tab_id = 'tab_'
152   tab_no = 0
153   for item in rFormItems:
154     this_tab_id = tab_id + str(tab_no)
155     tab_no += 1
156     headers.append ( {'tab_id': this_tab_id,
157                       'text': rFormHelp[item[0]]['title'],
158                       'selected': tab_no == 1
159                       } )
160     tabs.append ( {'tab_id': this_tab_id,
161                     'info': rFormHelp[item[0]]['info'],
162                     'content': form_system().get_form(item[1], rFormHelp,
163                                     rHelpName, rFormData,
164                                     tab_cluster, valign, max_cols, show_errors)
165                   } )
166     c = Context ( {'headers': headers, 'tabs': tabs } )
167   return t.render(c)
168
169 # -----------------------------------------------------
170 def info_slot_to_header(text) :
171   """ wandelt rechten Infoslot in HTML fuer WYSIWYG-Editor um """
172   HEADER_START = '<!-- header start -->'
173   HEADER_END   = '<!-- header end -->'
174   INFO_START   = '<!-- info start -->'
175   INFO_END     = '<!-- info end -->'
176   ret = ''
177   nStart = 0
178   nHStart = string.find(text, HEADER_START, nStart)
179   while nHStart >= 0 :
180     nHEnd = string.find ( text, HEADER_END, nHStart )
181     header  = text[nHStart+len(HEADER_START):nHEnd]
182     nIStart = string.find ( text, INFO_START, nHEnd )
183     nIEnd   = string.find ( text, INFO_END, nIStart )
184     info    = text[nIStart+len(INFO_START):nIEnd]
185     ret += '<h4>'+header+'</h4>\n'
186     ret += info + '\n'
187     nHStart = string.find(text, HEADER_START, nIEnd)
188   return ret
189
190 # -----------------------------------------------------
191 def get_section_choices(sections):
192   """ wandelt Textzeilen in Liste um """
193   ret = []
194   sections = string.splitfields(decode_html(sections), '\n')
195   for s in sections :
196     s = string.strip(s)
197     ret.append((encode_html(s), s))
198   return ret
199   #  if s != '':
200   #    yield(encode_html(s), s)
201
202 # -----------------------------------------------------
203 def get_parent_section_choices(my_item_container):
204   item_container = get_parent_item_container(my_item_container)
205   return get_section_choices(item_container.container.sections)
206
207 # -----------------------------------------------------
208 def get_license_choices(my_item_container):
209   #return get_section_choices(get_licenses())
210   ret = []
211   licenses = get_licenses()
212   for lic in licenses:
213     if lic.url != '':
214       l = show_link(lic.url, lic.name)
215     else:
216       l = lic.name
217     ret.append((lic.id, l))
218   return ret
219
220 # -----------------------------------------------------
221 def get_fach_choices():
222   # --- Liste aller Faecher
223   ret = []
224   ret.append((-1, '---'))
225   faecher = get_faecher()
226   for fach in faecher:
227     ret.append((fach.id, decode_html(fach.name)))
228   return ret
229
230 # -----------------------------------------------------
231 def get_schulart_choices():
232   # --- Liste aller Faecher
233   ret = []
234   ret.append((-1, '---'))
235   schularten = get_schularten()
236   for schulart in schularten:
237     ret.append((schulart.id, decode_html(schulart.name)))
238   return ret
239
240 # -----------------------------------------------------
241 def check_name( name, is_name_ok):
242   """ entfernt Umlaute etc. aus Dateinamen """
243   try:
244     name = unicode(name, 'utf-8')
245   except:
246     pass
247   name = name[max(string.rfind(name,'/'),
248                   string.rfind(name,'\\'),
249                   string.rfind(name,':')
250                   )+1:]
251   name = string.replace(name, u"'", u'_')
252   name = string.replace(name, u'ä', u'ae')
253   name = string.replace(name, u'ö', u'oe')
254   name = string.replace(name, u'ü', u'ue')
255   name = string.replace(name, u'Ä', u'Ae')
256   name = string.replace(name, u'Ö', u'Oe')
257   name = string.replace(name, u'Ü', u'Ue')
258   name = string.replace(name, u'ß', u'ss')
259   bad_chars  = ' ,;()[]{}*"#%+~!'
260   good_chars = '________________'
261   TRANSMAP = string.maketrans(bad_chars, good_chars)
262   name = name.encode('iso-8859-1')
263   name = string.translate(name, TRANSMAP)
264   if is_name_ok:
265     return name
266   html = '.html'
267   if name[-5:] != html :
268     name += html
269   return name
270
271 # -----------------------------------------------------
272 def show_link(url, info='', url_extern=False, url_class='', title=''):
273   """ zeigt Verweise an - externe Verweise werden optisch gekennzeichnet """
274   if info == '':
275     if url.startswith('http://'):
276       info += url[7:]
277     else:
278       info = url
279   from dms.settings import MY_DOMAINS
280   from django.template.loader import get_template
281   from django.template import Context
282   t = get_template('utils/show_link.html')
283   target = ''
284   start  = ''
285   is_my_domain = False
286   # --- Parameter in URL ausschliessen
287   n_pos = url.find('?')
288   if n_pos > -1:
289     u = url[:n_pos]
290   else:
291     u = url
292   if u.startswith('http://'):
293     for domain in MY_DOMAINS:
294       if u.find(domain) >= 0 :
295         is_my_domain = True
296         break
297     if is_my_domain :
298       if url_extern :
299         target = '_extern'
300         start  = NEW_WINDOW_ICON
301     else :
302       target = '_extern'
303       start  = EXTERN_ICON
304   else :
305     # Javascript - das Oeffnen in einem eigenen Fenster erfolgt ueber Javascript
306     #target = '_extern'
307     start  = NEW_WINDOW_ICON
308   if url_class != '' and not url_class.startswith('class='):
309     url_class = u' class="%s"' % url_class
310   if title != '' and not title.startswith('title='):
311     title = u' title="%s"' % title
312   c = Context ( {'start': start, 'url' : url, 'class': url_class,
313                  'target': target, 'info': info, 'title': title } )
314   return t.render(c)
315
316 # -----------------------------------------------------
317 def get_link_by_item_container(item_container, is_folder=False):
318   """ liefert die entsprechende URL """
319   d_extern = ''
320   d_info = ''
321   d_title = item_container.item.title
322   if item_container.item.app.is_folderish or is_folder:
323     #d_class = 'class="folderLink" '
324     postfix = FOLDER_ICON
325   else :
326     #d_class = ''
327     postfix = ''
328   # --- handelt es sich um ein Datei- oder Ordner-Objekt?
329   is_file = is_file_by_item_container(item_container)
330   is_text = item_container.item.app.name == 'dmsText'
331   if string.find(item_container.item.name, '.html') > 0 or is_file or is_text:
332     if item_container.item.app.name == 'dmsRedirect':
333       d_url = item_container.item.url_more
334       if string.find(item_container.item.url_more, 'http://') >= 0:
335         is_my_domain = False
336         for domain in MY_DOMAINS:
337           if string.find(item_container.item.url_more, domain) >= 0:
338             is_my_domain = True
339             break
340         if is_my_domain:
341           if item_container.item.url_more_extern:
342             d_extern = '_extern'
343             d_extern_icon = NEW_WINDOW_ICON
344         else :
345           d_extern = '_extern'
346           d_extern_icon = EXTERN_ICON
347     elif is_file:
348       d_extern = '_extern'
349       d_extern_icon = NEW_WINDOW_ICON
350       d_info = FILE_DETAIL % get_site_url(item_container, item_container.item.name + '/show/')
351       d_url = DOWNLOAD_URL + item_container.container.path + item_container.item.name
352     else:
353       d_url = get_site_url(item_container, item_container.item.name)
354   else :
355     if item_container.is_data_object:
356       d_url = get_site_url(item_container, 'index.html')
357     else:
358       real_item_container = get_item_container_data_object_by_id(item_container.item.id)
359       if real_item_container == None:
360         d_url = get_site_url(item_container, 'index.html')
361       else:
362         d_url = get_site_url(real_item_container[0], 'index.html')
363   if d_extern:
364     help = _('Wird in einem eigenen Fenster ge&ouml;ffnet ...')
365     this_link = d_extern_icon + u'<a href="%s" target="d_extern" title="%s">%s</a>' % \
366                         (d_url, help, d_title)
367   elif item_container.item.app.name == 'dmsRedirect' or not item_container.is_data_object:
368     s_info = REDIRECT_ICON + '&nbsp;'
369     help = _('Springt zu einer anderen Stelle ...')
370     this_link = s_info + u'<a href="%s" title="%s">%s</a>' % (d_url, help, d_title)
371   else:
372     this_link = u'<a href="%s">%s</a>' % (d_url, d_title)
373   if is_protected(item_container):
374     return '<i>' + this_link + d_info + '</i>' + PROJECT_ICON
375   return this_link + d_info + postfix
376
377 # -----------------------------------------------------
378 def show_more ( url, url_extern, info='Mehr ...' ) :
379   """ erzeugt einen Verweis fuer "mehr ..." """
380   return show_link ( url, info, url_extern )
381
382 # -----------------------------------------------------
383 def get_breadcrumb(item_container, text_only=False, ignore_own_breadcrumb=False):
384   """ Navigationszeile zusammenbauen """
385   if text_only:
386     ret = ''
387     length = len(item_container.container.site.base_folder)
388     n = 0  # --- Begrenzung der Schachtelungstiefe
389     if not item_container.item.app.is_folderish:
390       item_container = get_parent_item_container(item_container)
391     while     item_container != None \
392           and (ignore_own_breadcrumb or \
393                not item_container.item.app.has_own_breadcrumb) \
394           and not item_container.container.is_top_folder \
395           and item_container.parent_item_id != -1 \
396           and n < 20:
397       ret = item_container.container.nav_title + ' | ' + ret
398       n += 1
399       if n >= 20:
400         assert False
401       item_container = get_parent_item_container(item_container)
402     return ret
403   else:
404     from django.template.loader import get_template
405     from django.template import Context
406     t = get_template('utils/nav_item.html')
407     ret = ''
408     length = len(item_container.container.site.base_folder)
409     n = 0  # --- Begrenzung der Schachtelungstiefe
410     if not item_container.item.app.is_folderish:
411       item_container = get_parent_item_container(item_container)
412     while         item_container != None \
413           and (ignore_own_breadcrumb or \
414                not item_container.item.app.has_own_breadcrumb) \
415           and not item_container.container.is_top_folder \
416           and item_container.parent_item_id != -1 \
417           and n < 20:
418       c = Context( {'url'  : item_container.container.site.url+\
419                              item_container.container.path[length:]+'index.html',
420                     'title': item_container.item.title,
421                     'info' : item_container.container.nav_title,})
422       ret = t.render(c) + ret
423       n += 1
424       if n >= 20:
425         assert False
426       item_container = get_parent_item_container(item_container)
427     if item_container != None:
428       if item_container.item.app.has_own_breadcrumb :
429         c=Context({'url'  : get_site_url(item_container, 'index.html'),
430                   'title': item_container.item.title,
431                   'info' : item_container.container.nav_title,})
432         ret = t.render(c) + ret
433         parent_item_container = get_parent_item_container(item_container)
434         c=Context({'url'  : parent_item_container.get_absolute_url(),
435                   'title': _('Zur&uuml;ck zu den normalen Web-Seiten'),
436                   'info' : _('Ausgang'),})
437       elif item_container.container.is_top_folder:
438         c=Context({'url'  : get_site_url(item_container, 'index.html'),
439                   'title': item_container.item.title,
440                   'info' : item_container.container.nav_title,})
441         ret = t.render(c) + ret
442         item_container = get_top_item()
443         c=Context({'url'  : get_site_url(item_container, 'index.html'),
444                   'title': item_container.item.title,
445                   'info' : item_container.container.nav_title,})
446       else:
447         c=Context({'url'  : get_site_url(item_container, 'index.html'),
448                   'title': item_container.item.title,
449                   'info' : item_container.container.nav_title,})
450       ret = t.render(c) + ret
451       return ret
452     else:
453       return 'item_container == None!!!'
454
455 # -----------------------------------------------------
456 def get_prev_next(item_container):
457   """ Geschwisterseiten """
458
459   def get_string(line, max_char=30):
460     if len(line) < max_char:
461       return line
462     return line[:max_char] + ' ...'
463
464   items = get_prev_parent_item_containers(item_container)
465   p_len = len(items)
466   if p_len == 0:
467     prev_url  = ''
468     prev_info = ''
469   else:
470     p_item = items[p_len-1].item
471     prev_url  = p_item.name
472     prev_info = get_string(p_item.title)
473   items = get_next_parent_item_containers(item_container)
474   if len(items) >0:
475     next_url  = items[0].item.name
476     next_info = get_string(items[0].item.title)
477   else:
478     next_url  = ''
479     next_info = ''
480   return prev_url, prev_info, next_url, next_info
481
482 # -----------------------------------------------------
483 def get_prev_next_line(item_container):
484   """ Geschwisterseiten anzeigen """
485   from django.template.loader import get_template
486   from django.template import Context
487   t = get_template('utils/prev_next.html')
488   prev_url, prev_info, next_url, next_info = get_prev_next(item_container)
489   c = Context({'prev_url'    : prev_url,
490                'prev_info'   : prev_info,
491                'complete_url': './index.html/show_complete/',
492                'next_url'    : next_url,
493                'next_info'   : next_info, })
494   return t.render(c)
495
496 # -----------------------------------------------------
497 def get_folderish_actions(request, user_perms, item_container, app_name,
498                           has_user_folder, dont={}):
499   from django.template.loader import get_template
500   from django.template import Context
501   if not request.user.is_authenticated():
502     return ''
503   t = get_template('app/manage_options_folderish.html')
504   nPos = max ( string.rfind ( request.path, '/add/' ),
505                string.rfind ( request.path, '/edit/' ),
506                string.rfind ( request.path, '/navigation/' ),
507                string.rfind ( request.path, '/navigation_left/' ),
508                string.rfind ( request.path, '/navigation_top/' ),
509                string.rfind ( request.path, '/manage/' ),
510                string.rfind ( request.path, '/manage_browseable/' ),
511                string.rfind ( request.path, '/manage_comments/' ),
512                string.rfind ( request.path, '/import/' ),
513                string.rfind ( request.path, '/export/' ),
514                string.rfind ( request.path, '/manage_site/' ),
515                string.rfind ( request.path, '/manage_user/' ),
516                string.rfind ( request.path, '/sort/' ),
517                string.rfind ( request.path, '/empty_folders/' ),
518                string.rfind ( request.path, '/find_items/' ),
519              )
520   if nPos >