Welcome    Usage    Browse    Find CID    Search     Log in

cM API Documentation

module.py

Go to the documentation of this file.
00001 #
00002 # Collective Mind
00003 #
00004 # See cM LICENSE.txt for licensing details.
00005 # See cM Copyright.txt for copyright details.
00006 #
00007 # Developer(s): (C) Grigori Fursin, started on 2011.09
00008 #
00009 
00010 # Should always be here
00011 ini={}
00012 cm_kernel=None
00013 
00014 # Local settings
00015 import string
00016 import os
00017 import json
00018 import cgi
00019 import cgitb
00020 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
00021 from SocketServer import ThreadingMixIn
00022 import threading
00023 import urlparse
00024 import zipfile
00025 import Cookie
00026 import copy
00027 import base64
00028 import urllib
00029 
00030 cm_menu_login='login'
00031 cm_menu_logout='logout'
00032 
00033 cm_action_index='index'
00034 cm_action_show='show'
00035 cm_data_uoa_default='default'
00036 
00037 # View and sort by ...
00038 view_and_sort='cm_display_html' # 'cm_uoa'
00039 
00040 form6='#form6' # form for file upload - needed for server
00041 
00042 # ============================================================================
00043 def init(i):
00044     return {'cm_return':0}
00045 
00046 # ============================================================================
00047 def index(i):
00048 
00049     """
00050     Show cM main web page
00051 
00052     Input:  {
00053               (cm_web_preprocess)  - if 'yes', preprocess request (usually user authentication)
00054               (cm_menu)           - select user menu
00055             }
00056 
00057     Output: {
00058               cm_return  - return code >0 if error
00059             }
00060     """
00061 
00062     # Preprocessing ***************************************************************************
00063     if i.get('cm_web_preprocess','')=='yes':
00064        # Process login or logout attempt
00065        ii={'cm_return':0}
00066 
00067        if i.get('cm_web_login_attempt','')=='yes': ii=login(i)
00068        elif i.get('cm_menu','')==cm_menu_logout:   ii=logout(i)
00069 
00070        ii['cm_web_postprocess']='yes'
00071 
00072        return ii
00073 
00074     # Check if there is URL is of style ?view_cid=<CID>
00075     vcid=i.get('view_cid','')
00076     if vcid!='':
00077        if 'cm_subaction_view' not in i: i['cm_subaction_view']=''
00078        i['browse_cid']=vcid
00079        if 'cm_menu' not in i: i['cm_menu']='browse'
00080        
00081     # Postprocessing **************************************************************************
00082     menu=''
00083     if 'cm_menu' in i: menu=i['cm_menu']
00084 
00085     # Check if allow users to authenticate (just to differentiate users in public repositories)
00086     allow_web_user_auth=False
00087     if cm_kernel.ini['dcfg'].get('allow_web_user_auth','')=='yes' \
00088        or cm_kernel.ini['dcfg'].get('force_web_login','')=='yes':
00089        allow_web_user_auth=True
00090 
00091     # Check if authenticated
00092     authenticated=False
00093     if cm_kernel.ini['web_auth'].get('cm_user_status','')=='logged_in': authenticated=True
00094 
00095     # Check if need to force login (for private repositories)
00096     need_to_login=False
00097     if cm_kernel.ini['dcfg'].get('force_web_login','')=='yes' and \
00098        (not authenticated or menu==cm_menu_logout):
00099        need_to_login=True
00100 
00101     # Check if login failed
00102     login_failed=False
00103     if (i.get('cm_web_login_attempt','')=='yes' and \
00104        not authenticated):
00105        login_failed=True
00106 
00107     # Check user defaults and alias (either authenticated or auth not needed at all)
00108     if menu==cm_menu_logout:
00109        # Set default user if needed
00110        r=cm_kernel.auth_user_and_ini_cm({})
00111        # ignore output
00112 
00113     # Load default web configuration
00114     web=None
00115     cm_user_uoa=''
00116     cm_user_alias=''
00117     cm_user_uid=''
00118     if 'cm_user_status' in cm_kernel.ini['web_auth'] and \
00119        (cm_kernel.ini['web_auth']['cm_user_status']=='default' or \
00120         cm_kernel.ini['web_auth']['cm_user_status']=='logged_in'):
00121 
00122        cm_user_uoa=cm_kernel.get_var(cm_kernel.ini['web_auth'], 'cm_user_uoa')
00123        cm_user_alias=cm_kernel.get_var(cm_kernel.ini['web_auth'], 'cm_user_alias')
00124        cm_user_uid=cm_kernel.get_var(cm_kernel.ini['web_auth'], 'cm_user_uid')
00125 
00126     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
00127     else:
00128        return {'cm_return':1, 'cm_error':'web style is not defined'}
00129 
00130     # Set default menu
00131     if menu=='' and not need_to_login: 
00132        if 'cm_menu_default' in web and web['cm_menu_default']!='':
00133           menu=web['cm_menu_default']
00134        else:
00135           menu=web['cm_menu_top'][0]['menu']
00136 
00137     # Start visualizing
00138     cm_kernel.print_for_con(web.get('cm_html_start',''))
00139 
00140     cm_kernel.print_for_con('<style type="text/css">')
00141 
00142     if 'use_background' in web and web['use_background']=='yes':
00143        cm_kernel.print_for_con('#cm-background {position:fixed; top:0; left:0; width:100%; height:100%;}')
00144 
00145     if 'cm_web_styles' in web:
00146        for x in web['cm_web_styles']:
00147            if x['name']!='cm-background' or 'use_background' not in web or not web['use_background']:
00148               cm_kernel.print_for_web(x['style'])
00149 
00150     cm_kernel.print_for_con('</style>')
00151 
00152     if web.get('character_set','')!='':
00153        cm_kernel.print_for_web(web['character_set'])
00154 
00155     if 'use_background' in web and web['use_background']=='yes':
00156        cm_kernel.print_for_con('<!--[if IE 6]>')
00157        cm_kernel.print_for_con(' <style type="text/css">')
00158        cm_kernel.print_for_con('  html {overflow-y:hidden;}')
00159        cm_kernel.print_for_con('  body {overflow-y:auto;}')
00160        cm_kernel.print_for_con('  #page-background {position:absolute; z-index:-1}')
00161        cm_kernel.print_for_con('  #content {position:static;padding:0px}')
00162        cm_kernel.print_for_con(' </style>')
00163        cm_kernel.print_for_con('<![endif]-->')
00164 
00165     cm_kernel.print_for_con('</head>')
00166     cm_kernel.print_for_con('<body>')
00167 
00168     if 'use_background' in web and web['use_background']=='yes':
00169        cm_kernel.print_for_web('<div id="cm-background"><img src="'+web['http_prefix']+'cm_web_action=show&cm_module_uoa=web&cm_data_uoa=default&cm_web_filename=background.jpg" width="100%" height="100%"></div>')
00170 
00171     # Login page
00172     join=web['http_prefix']+'browse_module_uoa=user&cm_menu=browse&cm_subaction_add=yes'
00173     wlogin=web['http_prefix']+'cm_menu=login'
00174 
00175     hlog1 ='<center>\n'
00176     hlog1+=' <div class="cm-round-div" style="width:300px; position:absolute; top: 50%; left: 50%; margin-top: -130px; margin-left: -150px">\n'
00177     hlog1a ='<center>\n'
00178     hlog1a+=' <div class="cm-round-div" style="width:300px;">\n'
00179     hlog2 ='  <div class="cm-title">Log in to Collective Mind<br></div>\n'
00180     hlog2+='  <div class="cm-title"><img src="'+web['http_prefix']+'cm_web_action=show&cm_module_uoa=web&cm_data_uoa=default&cm_web_filename=cm-logo.png"></div>\n'
00181     hlog3 ='  <br>\n'
00182     hlog3+='   <input type="hidden" name="cm_web_login_attempt" value="yes">\n'
00183     hlog3+='   <table cellpadding="5">\n'
00184     hlog3+='   <tr><td align="right">Username</td>\n'
00185     hlog3+='       <td><input type="text" spellcheck="false" name="cm_user_uoa" value=""></td></tr>\n'
00186     hlog3+='   <tr><td align="right">Password</td>\n'
00187     hlog3+='       <td><input type="password" name="cm_user_password"></td></tr>\n'
00188     hlog3+='   <tr><td><input type="submit" class="cm-button" value="Log in"></td>\n'
00189     hlog3+='       <td><input type="checkbox" name="cm_web_set_cookies" value="yes" checked="checked"> Stay signed in</td></tr>\n'
00190     hlog3+='   </table>\n'
00191     hlog3+='  <br>\n'
00192     hlog3+='  <a href="'+join+'" target="_top">Register and join Collective Mind!</a><br>\n'
00193     hlog3+='  <a href="'+cm_kernel.get_var(web, 'cm_link_problem_with_account')+'" target="_top">Can\'t access your account?</a><br>\n'
00194     hlog4 =' </div>\n'
00195     hlog4+='</center>\n'
00196 
00197     if need_to_login or login_failed or menu==cm_menu_login or menu==cm_menu_logout:
00198        cm_kernel.print_for_con(hlog1)
00199        if menu==cm_menu_logout:
00200           cm_kernel.print_for_con('  <div class="cm-title">Thank you for using Collective Mind!<br></div>')
00201        elif need_to_login or menu==cm_menu_login or login_failed:
00202           cm_kernel.print_for_con(hlog2)
00203 
00204           if login_failed:
00205              cm_kernel.print_for_con('  <div class="cm-error">Login attempt failed!<br>')
00206 #             cm_kernel.print_for_web(cm_kernel.ini['web_auth'])
00207              if 'cm_error' in cm_kernel.ini['web_auth']:
00208                 cm_kernel.print_for_web('<br><i>'+cm_kernel.ini['web_auth']['cm_error']+'</i><BR>')
00209              cm_kernel.print_for_con('  </div>')
00210 
00211           action=''
00212           if 'cm_web_get' in i and (i['cm_web_get'].get('cm_menu','')==cm_menu_login or \
00213                                     i['cm_web_get'].get('cm_menu','')==cm_menu_logout):
00214              action=web['http_prefix']+'cm_menu='+web['cm_menu_top'][0]['menu']
00215           cm_kernel.print_for_web('  <form action="'+action+'" method="post" accept-charset="utf-8">')
00216           cm_kernel.print_for_web(hlog3)
00217        cm_kernel.print_for_web(hlog4)
00218 
00219     cm_kernel.print_for_con('<div id="cm-content">')
00220 
00221     # Create top bar
00222     xmenu={}
00223     cm_kernel.print_for_con('<div id="cm-top-bar">')
00224 
00225     cm_kernel.print_for_con('<table width="100%"><tr><td align="left">')
00226     if cm_kernel.ini['dcfg'].get('force_web_login','')=='yes' and \
00227        (not authenticated or menu==cm_menu_logout):
00228        # do not show top bar
00229        pass
00230     else:
00231        for x in web['cm_menu_top']:
00232            show=True
00233            if x.get('only_for_admin','')=='yes':
00234               show=False
00235               if cm_kernel.ini['web_auth'].get('cm_admin','')=='yes':
00236                  show=True
00237            elif x.get('only_for_registered','')=='yes':
00238               show=False
00239               if cm_kernel.ini['web_auth'].get('cm_user_status','')=='logged_in' or \
00240                  cm_kernel.ini['web_auth'].get('cm_admin','')=='yes':
00241                  show=True
00242 
00243            if menu==x['menu']: 
00244               sel="cm-top-bar-text-selected"
00245               xmenu=x
00246            else: sel="cm-top-bar-text"
00247            if show:
00248               cm_kernel.print_for_web('<span class="'+sel+'"><a href="'+web['http_prefix']+'cm_menu='+x['menu']+'">'+x['menu_text']+'</a></span>&nbsp;&nbsp;&nbsp;')
00249 
00250     cm_kernel.print_for_con('</span></td><td align="right"><span class="cm-top-bar-text">')
00251 
00252     # Print user if authenticated or no authentication at all
00253     if not (need_to_login and menu==cm_menu_logout):
00254 #       s=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&cm_subaction_view&browse_cid='+ini['cfg']['cm_modules']['cm-user']+':'+cm_user_uid
00255        s=web['http_prefix']+'view_cid='+ini['cfg']['cm_modules']['cm-user']+':'+cm_user_uid
00256        if cm_user_alias!='':
00257           cm_kernel.print_for_web('<i><a href="'+s+'">'+cm_user_alias+'</i></a>')
00258        elif cm_user_uid!='':
00259           cm_kernel.print_for_web('<i><a href="'+s+'">'+cm_user_uid+'</i></a>')
00260 
00261        # Check if default
00262        if cm_kernel.ini['web_auth'].get('cm_user_status','')=='default':
00263           cm_kernel.print_for_con('<i> (default) </i>')
00264 
00265     if allow_web_user_auth or need_to_login:
00266        if authenticated and menu!=cm_menu_logout:
00267           cm_kernel.print_for_web('&nbsp;<a href="'+web['http_prefix']+'cm_menu='+cm_menu_logout+'">Log out</a>')
00268        else:
00269           cm_kernel.print_for_web('&nbsp;<a href="'+web['http_prefix']+'cm_menu='+cm_menu_login+'">Log in</a>')
00270 
00271     cm_kernel.print_for_con('</span></td></tr></table>')
00272     cm_kernel.print_for_con('</div>')
00273 
00274     # If selected, call a module
00275     if not need_to_login and not login_failed and 'menu' in xmenu:
00276        ii={}; ii.update(i);
00277        ii['cm_run_module_uoa']=xmenu['menu_module']
00278        ii['cm_action']=xmenu['menu_action']
00279        ii['cm_console']='web'
00280 
00281        # Clear some sensitive variables
00282        if 'cm_password' in ii: del(ii['cm_password'])
00283 
00284        cm_kernel.print_for_con('<center><span id="cm-content-module">')
00285        r=cm_kernel.access(ii)
00286        if r['cm_return']>0:
00287           if r['cm_return']==32 or (not authenticated and r['cm_return']==16):
00288 #             x='<br><b>Sorry, you do not have sufficient privileges to perform this action!</b><br><br>'+\
00289 #               '<i>Try to <a href="'+wlogin+'">log in</a></i>!<br><br>'
00290 #             cm_kernel.print_for_web(x)
00291 
00292              cm_kernel.print_for_con(hlog1a)
00293              cm_kernel.print_for_con(hlog2)
00294 
00295              cm_kernel.print_for_con('  <div class="cm-error">Sorry, you do not have sufficient privileges to perform this action!<br>')
00296              cm_kernel.print_for_con('  ('+r['cm_error']+')<br>')
00297              cm_kernel.print_for_con('  </div>')
00298 
00299              if login_failed:
00300                 cm_kernel.print_for_con('  <div class="cm-error">Login attempt failed!<br>')
00301                 if 'cm_error' in cm_kernel.ini['web_auth']:
00302                    cm_kernel.print_for_web('<br><i>'+cm_kernel.ini['web_auth']['cm_error']+'</i><BR>')
00303                 cm_kernel.print_for_con('  </div>')
00304 
00305              action=''
00306              if 'cm_web_get' in i and (i['cm_web_get'].get('cm_menu','')==cm_menu_login or \
00307                                        i['cm_web_get'].get('cm_menu','')==cm_menu_logout):
00308                 action=web['http_prefix']+'cm_menu='+web['cm_menu_top'][0]['menu']
00309              cm_kernel.print_for_web('  <form action="'+action+'" method="post" accept-charset="utf-8">')
00310              cm_kernel.print_for_web(hlog3)
00311              cm_kernel.print_for_web(hlog4)
00312 
00313           else:
00314              cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00315 
00316        cm_kernel.print_for_con('</span></center>')
00317 
00318     if need_to_login or login_failed or menu==cm_menu_login \
00319       or menu==cm_menu_logout or xmenu.get('menu_footer_fix','')=='yes':
00320       cm_kernel.print_for_con('</div>')
00321       cm_kernel.print_for_con('<div id="cm-footer-bar">')
00322     else:
00323       cm_kernel.print_for_con('<div id="cm-footer-bar-relative">')
00324 
00325     r=cm_kernel.get_cm_version({})
00326     if r['cm_return']>0: return r
00327 
00328     x=cm_kernel.get_var(web, 'cm_html_bottom_line')
00329     x=x.replace(cm_kernel.convert_str_to_special('cm_version'), r['cm_string'])
00330     cm_kernel.print_for_web(x)
00331     cm_kernel.print_for_con('</div>')
00332 
00333     cm_kernel.print_for_web(cm_kernel.get_var(web, 'cm_html_end'))
00334 
00335     return {'cm_return':0}
00336 
00337 # ============================================================================ 
00338 def browse(i):
00339 
00340     """
00341     cM basic repository browsing
00342 
00343     Input:  {
00344               (browse_module_uoa)           - module UOA
00345               (browse_data_uoa)             - data UOA 
00346               (browse_repo_uoa)             - repo UOA
00347 
00348               (cm_subaction_delete)         - delete entry
00349               (cm_subaction_repo_delete)    - delete repository
00350 
00351               (cm_subaction_view)           - view entry
00352                 (show_add_info)             - additional view config (show additional info about entry)
00353                 (show_param_names)          - additional view config (show parameter names (for development))
00354               (cm_subaction_module_view)    - view module
00355               (cm_subaction_repo_view)      - view repository
00356  
00357               (cm_subaction_update)         - update entry
00358               (cm_subaction_repo_update)    - update repository
00359 
00360               (cm_subaction_add)            - add entry
00361               (cm_subaction_module_add)     - add module
00362               (cm_subaction_repo_add)       - add repository
00363 
00364               (cm_button_reset)             - reset current view
00365 
00366               (cm_back_json)                - previous web state to create 'back' button
00367             }
00368 
00369     Output: {
00370               cm_return - return code >0 if error
00371             }
00372     """
00373 
00374     # Check styles, etc
00375     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
00376     else:
00377        return {'cm_return':1, 'cm_error':'web style is not defined'}
00378 
00379     # Expand browse cid
00380     if 'browse_cid' in i and i['browse_cid']!='':
00381        rx=cm_kernel.cid2array({'cid':i['browse_cid'],
00382                                'prefix':'browse'})
00383        if rx['cm_return']>0: return rx
00384        i.update(rx['cm_array'])
00385        del(i['browse_cid'])
00386 
00387     # **********************************************************************************************************
00388     # Check submenus
00389     found=False
00390 
00391     #****************************************************************************************************
00392     if 'cm_subaction_rename' in i:
00393        found=True
00394        i['cm_run_module_uoa']=i.get('browse_module_uoa','')
00395        i['cm_action']='rename'
00396        r=cm_kernel.access(i)
00397        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00398 
00399     #****************************************************************************************************
00400     if 'cm_subaction_move' in i:
00401        found=True
00402        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-core']
00403        i['cm_action']='move'
00404        r=cm_kernel.access(i)
00405        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00406 
00407     #****************************************************************************************************
00408     if 'cm_subaction_copy' in i:
00409        found=True
00410        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-core']
00411        i['cm_action']='copy'
00412        r=cm_kernel.access(i)
00413        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00414 
00415     #****************************************************************************************************
00416     if 'cm_subaction_delete' in i:
00417        found=True
00418        i['cm_run_module_uoa']=i['browse_module_uoa']
00419        i['cm_action']='delete'
00420        r=cm_kernel.access(i)
00421        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00422 
00423     if 'cm_subaction_repo_delete' in i:
00424        found=True
00425        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-repo']
00426        i['cm_action']='delete'
00427        i['browse_module_uoa']=i['cm_run_module_uoa']
00428        i['browse_data_uoa']=i['browse_repo_uoa']
00429        i['cm_subaction_delete']='yes'
00430        del(i['browse_repo_uoa'])
00431        r=cm_kernel.access(i)
00432        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00433 
00434     #****************************************************************************************************
00435     elif 'cm_subaction_view' in i:
00436        found=True
00437        i['cm_run_module_uoa']=i['browse_module_uoa']
00438        i['cm_action']='view'
00439        r=cm_kernel.access(i)
00440 #       if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00441        if r['cm_return']>0: return r
00442 
00443     elif 'cm_subaction_module_view' in i:
00444        found=True
00445        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-module']
00446        i['cm_action']='view'
00447        i['browse_data_uoa']=i['browse_module_uoa']
00448        i['browse_module_uoa']=i['cm_run_module_uoa']
00449        r=cm_kernel.access(i)
00450 #       if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00451        if r['cm_return']>0: return r
00452 
00453     elif 'cm_subaction_repo_view' in i:
00454        found=True
00455        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-repo']
00456        i['cm_action']='view'
00457        i['browse_module_uoa']=i['cm_run_module_uoa']
00458        i['browse_data_uoa']=i['browse_repo_uoa']
00459        del(i['browse_repo_uoa'])
00460        r=cm_kernel.access(i)
00461 #       if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00462        if r['cm_return']>0: return r
00463 
00464     #****************************************************************************************************
00465     elif 'cm_subaction_update' in i:
00466        found=True
00467        i['cm_run_module_uoa']=i['browse_module_uoa']
00468        i['cm_action']='update'
00469        r=cm_kernel.access(i)
00470        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00471 
00472     elif 'cm_subaction_repo_update' in i:
00473        found=True
00474        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-repo']
00475        i['cm_action']='update'
00476        i['browse_module_uoa']=i['cm_run_module_uoa']
00477        i['browse_data_uoa']=i['browse_repo_uoa']
00478        if 'browse_repo_uoa' in i: del(i['browse_repo_uoa'])
00479        i['cm_subaction_update']='yes'
00480        r=cm_kernel.access(i)
00481        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00482 
00483     #****************************************************************************************************
00484     elif 'cm_subaction_add' in i:
00485        found=True
00486        i['cm_run_module_uoa']=i['browse_module_uoa']
00487        i['cm_action']='add'
00488        r=cm_kernel.access(i)
00489        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00490 
00491     elif 'cm_subaction_module_add' in i:
00492        found=True
00493        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-module']
00494        i['cm_action']='add'
00495        i['browse_module_uoa']=i['cm_run_module_uoa']
00496        r=cm_kernel.access(i)
00497        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00498 
00499     elif 'cm_subaction_repo_add' in i:
00500        found=True
00501        i['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-repo']
00502        i['cm_action']='add'
00503        i['browse_module_uoa']=i['cm_run_module_uoa']
00504        r=cm_kernel.access(i)
00505        if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
00506 
00507     # **********************************************************************************************************
00508     if found:
00509        if 'cm_back_json' in i:
00510           cm_kernel.print_for_con('<HR class="cm-hr">')
00511           r1=create_button_back({'cm_back_json':i['cm_back_json']})
00512           if r1['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r1['cm_error'])
00513     else:
00514        cm_kernel.print_for_con('<span class="cm-title">Browsing repositories</span>')
00515 
00516        # Check for empty variables for reset
00517        if 'browse_repo_uoa' in i and i['browse_repo_uoa']=='': 
00518           del(i['browse_repo_uoa'])
00519           if 'browse_module_uoa' in i: del(i['browse_module_uoa'])
00520           if 'browse_data_uoa' in i: del(i['browse_data_uoa'])
00521        if 'browse_module_uoa' in i and i['browse_module_uoa']=='': 
00522           del(i['browse_module_uoa'])
00523           if 'browse_data_uoa' in i: del(i['browse_data_uoa'])
00524        if 'browse_data_uoa' in i and i['browse_data_uoa']=='': del(i['browse_data_uoa'])
00525 
00526        if 'cm_button_reset' in i:
00527           if 'browse_repo_uoa' in i: del(i['browse_repo_uoa'])
00528           if 'browse_module_uoa' in i: del(i['browse_module_uoa'])
00529           if 'browse_data_uoa' in i: del(i['browse_data_uoa'])
00530 
00531        cm_kernel.print_for_web('<form action="'+web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'" method="post" name="web_browse" accept-charset="utf-8">')
00532 
00533        cm_kernel.print_for_con('<TABLE WIDTH="100%" CELLPADDING="10" border="0">')
00534        cm_kernel.print_for_con('<TR>')
00535 
00536        # Repositories *******************************************************************************
00537        cm_kernel.print_for_con('<TD valign="top" align="center">')
00538        cm_kernel.print_for_con('<div class="cm-round-div">')
00539        r=cm_kernel.access({'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-repo'],
00540                            'cm_action':'list'})
00541        cm_kernel.print_for_con('<b>Repositories:</b><br>')
00542        cm_kernel.print_for_web('<select class="cm-select" size="'+web['default_selector_size']+'" onchange="document.web_browse.submit();" name="browse_repo_uoa" style="width: 320px">')
00543        cm_kernel.print_for_con('<option value="">-</option>')
00544        if r['cm_return']>0: 
00545           cm_kernel.print_for_web('</select><B>cM error:</b> '+r['cm_error']+'<br>')
00546        else:
00547           found=False
00548           for xx in sorted(r['cm_mixed'], key=lambda k: tuple(s.lower() if isinstance(s,basestring) else s for s in k[view_and_sort])):
00549               x=xx['cm_uoa'];  xu=xx['cm_uid'];  xa=xx['cm_alias'];  xd=xx[view_and_sort]
00550               z=''
00551               if 'browse_repo_uoa' in i and (i['browse_repo_uoa']==x or i['browse_repo_uoa']==xu or i['browse_repo_uoa']==xa): 
00552                  z=' SELECTED '
00553                  found=True
00554               cm_kernel.print_for_web('<option value="'+xu+'"'+z+'>'+xd+'</option>')
00555           cm_kernel.print_for_con('</select><br>')
00556 
00557        # View
00558        z=' disabled="disabled" ';
00559        if 'browse_repo_uoa' in i and found: z=''
00560        cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_repo_view" value="View"'+z+'>')
00561        cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_repo_update" value="Update"'+z+'>')
00562        cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_repo_delete" value="Delete"'+z+'><br>')
00563        cm_kernel.print_for_con('<input type="submit" class="cm-button" name="cm_subaction_repo_add" value="Add">')
00564 
00565        cm_kernel.print_for_con('</div>')
00566        cm_kernel.print_for_con('</TD>')
00567        if 'browse_repo_uoa' in i and not found: del(i['browse_repo_uoa'])
00568 
00569        # Try to load repository to check if remote
00570        remote=False
00571        remote_url=''
00572        remote_repo_uoa=''
00573 
00574        if 'browse_repo_uoa' in i:
00575           jj={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-repo'],
00576               'cm_action':'load',
00577               'cm_data_uoa':i['browse_repo_uoa']}
00578           rx=cm_kernel.access(jj)
00579           if rx['cm_return']==0:
00580              dx=rx['cm_data_obj']['cfg']
00581 
00582              if dx.get('path_type','')=='remote_url':
00583                 remote=True
00584                 remote_url=dx.get('url','')
00585                 remote_repo_uoa=dx.get('remote_repo_uoa','')
00586 
00587        if not remote:
00588           # Modules ************************************************************************************
00589           cm_kernel.print_for_con('<TD valign="top" align="center">')
00590           cm_kernel.print_for_con('<div class="cm-round-div" style="width: 320px">')
00591           ii={}
00592           ii['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-module']
00593           ii['cm_action']='list'
00594           ii['cm_console']='no'
00595           r=cm_kernel.access(ii)
00596           cm_kernel.print_for_con('<b>Modules:</b><br>')
00597           cm_kernel.print_for_web('<select class="cm-select" size="'+web['default_selector_size']+'" onchange="document.web_browse.submit();" name="browse_module_uoa" style="width: 300px">')
00598           cm_kernel.print_for_con('<option value="">-</option>')
00599           if r['cm_return']>0: 
00600              cm_kernel.print_for_web('</select><B>cM error:</b> '+r['cm_error']+'<br>')
00601           else:
00602              found=False
00603              for xx in sorted(r['cm_mixed'], key=lambda k: tuple(s.lower() if isinstance(s,basestring) else s for s in k[view_and_sort])):
00604                  x=xx['cm_uoa'];  xu=xx['cm_uid'];  xa=xx['cm_alias'];  xd=xx[view_and_sort]
00605                  z=''
00606                  if 'browse_module_uoa' in i and (i['browse_module_uoa']==x or i['browse_module_uoa']==xu or i['browse_module_uoa']==xa): 
00607                     z=' SELECTED '
00608                     found=True
00609                  cm_kernel.print_for_web('<option value="'+xu+'"'+z+'>'+xd+'</option>')
00610              cm_kernel.print_for_con('</select><br>')
00611 
00612           # View
00613           browse_module_uid=''
00614           z=' disabled="disabled" ';
00615           if 'browse_module_uoa' in i and found: z=''
00616           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_module_view" value="View"'+z+'>')
00617           z=' disabled="disabled" ';
00618           if 'browse_repo_uoa' in i: z=''
00619           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_module_add" value="Add"'+z+'>')
00620           if 'browse_module_uoa' in i and found: 
00621              # Load module to get real UOA
00622              jj={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
00623                  'cm_action':'load',
00624                  'cm_data_uoa':i['browse_module_uoa']}
00625              rx=cm_kernel.access(jj)
00626              if rx['cm_return']==0:
00627                 browse_module_uid=rx['cm_uid']
00628                 q=rx['cm_data_obj']['cfg'].get('cm_module_py_ext','')
00629                 if q=='': q='module'
00630                 if q=='cm':
00631                    uoa='cm.py'
00632                 else:
00633                    uoa=rx['cm_uoa']+'/'+q+'.py'
00634                 uoa=uoa.replace('.','_8')
00635                 uoa=uoa.replace('/','_2')
00636                 uoa+='.html'
00637 
00638                 du=cm_kernel.ini['dcfg'].get('cm_documentation_uoa','')
00639                 if du!='':
00640                    s=du+'&cm_web_filename=html/'+uoa
00641                    cm_kernel.print_for_web('<br><small><a href="'+web['http_prefix']+'cm_menu=scenarios&cm_submenu=browse_cm_api&cid=internal:'+s+'" target="_blank">Module API</a>&nbsp;&nbsp;')
00642 
00643                    all_cid=cm_kernel.prepare_cid(jj)
00644                    cm_kernel.print_for_web('<a href="'+cm_kernel.ini['dcfg']['http_repo_descriptions']+all_cid['cm_string_uid']+'" target="_blank">Module Wiki</a></small>')
00645 
00646           cm_kernel.print_for_con('</div>')
00647           cm_kernel.print_for_con('</TD>')
00648           if 'browse_module_uoa' in i and not found: del(i['browse_module_uoa'])
00649 
00650           # Data ************************************************************************************
00651           cm_kernel.print_for_con('<TD valign="top" align="center">')
00652           cm_kernel.print_for_con('<div class="cm-round-div">')
00653 
00654           cm_kernel.print_for_con('<b>Data:</b><br>')
00655           cm_kernel.print_for_web('<select class="cm-select" size="'+web['default_selector_size']+'" onchange="document.web_browse.submit();" name="browse_data_uoa" style="width: 380px">')
00656           cm_kernel.print_for_con('<option value="">-</option>')
00657           data_uid=''
00658           if i.get('browse_module_uoa','')!='':
00659              ii={}
00660              ii['cm_run_module_uoa']=i['browse_module_uoa']
00661              if 'browse_repo_uoa' in i:
00662                 ii['cm_repo_uoa']=i['browse_repo_uoa']
00663              ii['cm_action']='list'
00664              ii['cm_console']='no'
00665              r=cm_kernel.access(ii)
00666              if r['cm_return']>0: 
00667                 cm_kernel.print_for_web('</select><br><B>cM error:</b> '+r['cm_error']+'<br>')
00668              else:
00669                 found=False
00670                 for xx in sorted(r['cm_mixed'], key=lambda k: tuple(s.lower() if isinstance(s,basestring) else s for s in k[view_and_sort])):
00671                     x=xx['cm_uoa'];  xu=xx['cm_uid'];  xa=xx['cm_alias'];  xd=xx[view_and_sort]
00672                     z=''
00673                     if 'browse_data_uoa' in i and (i['browse_data_uoa']==x or i['browse_data_uoa']==xu or i['browse_data_uoa']==xa): 
00674                        data_uid=xu
00675                        z=' SELECTED '
00676                        found=True
00677                     cm_kernel.print_for_web('<option value="'+xu+'"'+z+'>'+xd+'</option>')
00678                 if 'browse_data_uoa' in i and not found: del(i['browse_data_uoa'])
00679           cm_kernel.print_for_con('</select><br>')
00680 
00681           # View
00682           z=' disabled="disabled" ';
00683           if 'browse_data_uoa' in i and 'browse_module_uoa' in i and found: z=''
00684           z1=' disabled="disabled" ';
00685           if 'browse_module_uoa' in i: z1=''
00686           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_view" value="View"'+z+'>')
00687           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_update" value="Update"'+z+'>')
00688           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_add" value="Add"'+z1+'>')
00689           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_delete" value="Delete"'+z+'>')
00690           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_rename" value="Rename"'+z+'><br>')
00691           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_move" value="Move"'+z+'>')
00692           cm_kernel.print_for_web('<input type="submit" class="cm-button" name="cm_subaction_copy" value="Copy"'+z+'>')
00693 
00694           # Download
00695           ii={'http_prefix':web['http_prefix'],
00696               'cm_text':'Download',
00697               'cm_data':{'cm_web_action':'download'}}
00698           if 'browse_data_uoa' not in i or 'browse_module_uoa' not in i: 
00699              ii['cm_disabled']='yes'
00700           else: 
00701              ii['cm_data']['cm_data_uoa']=i['browse_data_uoa']
00702              ii['cm_data']['cm_module_uoa']=i['browse_module_uoa']
00703 
00704           r=create_button(ii)
00705           if r['cm_return']==0: cm_kernel.print_for_web(r['cm_string'])
00706 
00707           if z=='':
00708              cm_kernel.print_for_web('<br><small><a href="'+cm_kernel.ini['dcfg']['http_repo_descriptions']+browse_module_uid+':'+data_uid+'" target="_blank">Data Wiki</a></small><br>')
00709 
00710           cm_kernel.print_for_con('</div>')
00711           cm_kernel.print_for_con('</TD>')
00712 
00713        else:
00714           cm_kernel.print_for_con('<TD align="center" valign="middle">')
00715           cm_kernel.print_for_con('<div class="cm-round-div">')
00716 
00717           cm_kernel.print_for_con('<b>This repository is remote!</b><BR><br>')
00718           x=''
00719           if remote_url!='': 
00720              x=remote_url
00721              x+='&cm_menu=browse'
00722              if remote_repo_uoa!='': x+='&browse_repo_uoa='+remote_repo_uoa
00723 
00724           cm_kernel.print_for_con('Follow this <a href="'+x+'" target="_blank">link</a> to the remote website with this repository.')
00725 
00726           cm_kernel.print_for_con('</div>')
00727           cm_kernel.print_for_con('</TD>')
00728 
00729        cm_kernel.print_for_con('</TR>')
00730        cm_kernel.print_for_con('</TABLE>')
00731 
00732        # Check actions depending on the selection **************************************************************
00733        # Prepare info to build 'back' button
00734 
00735        ii={'cm_web_module_uoa':ini['cm_module_uid'],
00736            'cm_action':i['cm_action']}
00737        cm_kernel.copy_vars({'cm_input_array':i, 'cm_output_array':ii, 
00738                             'cm_vars':['cm_menu', 'browse_data_uoa', 'browse_module_uoa', 'browse_repo_uoa']})
00739        r=cm_kernel.convert_cm_array_to_uri({'cm_array':ii})
00740        if r['cm_return']==0: cm_kernel.print_for_web('<input type="hidden" name="cm_back_json" value="'+r['cm_string']+'">')
00741 
00742        cm_kernel.print_for_con('<input type="submit" class="cm-button" value="Refresh">')
00743        cm_kernel.print_for_con('<input type="submit" class="cm-button" name="cm_button_reset" value="Reset">')
00744 
00745        cm_kernel.print_for_con('</FORM>')
00746 
00747     return {'cm_return':0}
00748 
00749 # ============================================================================
00750 def welcome(i):
00751 
00752     """
00753     Welcome page
00754     TBD: should check if the version is up-to-date + development News ...
00755 
00756     Input:  {
00757             }
00758 
00759     Output: {
00760               cm_return  - return code >0 if error
00761             }
00762     """
00763 
00764     # Check styles, etc
00765     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
00766     else:
00767        return {'cm_return':1, 'cm_error':'web style is not defined'}
00768 
00769     # Check if customized view
00770     cm=web.get('customized_module_welcome','')
00771     if cm!='':
00772        r=cm_kernel.access({'cm_run_module_uoa':cm, 'cm_action':'welcome'})
00773        if r['cm_return']>0: return r
00774     else:
00775        # Check welcome page
00776        cm_kernel.print_for_con('<table border="0" cellpadding="6">')
00777 
00778        if web.get('cm_html_welcome_top','')!='':
00779           cm_kernel.print_for_con('<tr><td colspan="3" align="center" valign="top">')
00780           cm_kernel.print_for_web(web['cm_html_welcome_top'])
00781           cm_kernel.print_for_con('</td></tr>')
00782 
00783        cm_kernel.print_for_con('<tr><td align="center" valign="top">')
00784 
00785        if web.get('cm_html_welcome_left_up','')!='':
00786           cm_kernel.print_for_web(web['cm_html_welcome_left_up'])
00787 
00788        cm_kernel.print_for_con('<center><small><b>cM Stats</b></small></center>')
00789        cm_kernel.print_for_web(web['table_init']+'<tr><td>')
00790        r=cm_kernel.access({'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-internal'],
00791                            'cm_action':'view_stats'})
00792        #ignore errors
00793 
00794        left_down_html=web.get('left_down_html','')
00795        if left_down_html!='':
00796           cm_kernel.print_for_web(left_down_html)
00797 
00798        cm_kernel.print_for_con('</td></tr></table>')
00799 
00800        cm_kernel.print_for_con('</td><td valign="top">')
00801 
00802 #       cm_kernel.print_for_con('<center><small><b>Current "Lego" connections</b></small></center>')
00803 #       ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
00804 #           'cm_action':'visualize_connections',
00805 #           'cm_show_only_graph':'yes',
00806 #           'cm_width':'500',
00807 #           'cm_height':'500'}
00808 #       r=cm_kernel.access(ii)
00809 #       #ignore return code
00810 
00811        cm_kernel.print_for_con('<center><small><b>Crowd-tuning demo (using <a href="https://play.google.com/store/apps/details?id=com.collective_mind.node">Android Collective Mind Node<a/>)</b></small></center>')
00812        cm_kernel.print_for_web(web['table_init']+'<tr><td>')
00813        cm_kernel.print_for_web('<a href="'+web['http_prefix']+'cm_menu=scenarios&cm_submenu=ctuning_space_visualize&cm_json={^22^ct_axis_y_type^22^:%20^22^float^22^,%20^22^ct_repo_uoa^22^:%20^22^39d6acbf82c44c2e^22^,%20^22^ct_graph_type^22^:%20^22^Google%20Web%20Services:%202D%20Scatter%20chart^22^,%20^22^reverse_order_of_graphs^22^:%20^22^on^22^,%20^22^ct_module_uoa^22^:%20^22^4df5b2509a4feabf^22^,%20^22^ct_data_selection^22^:%20[^22^42d4a77984179a31^22^,%20^22^f818ca7ad2480e8e^22^,%20^22^c93766c94af8b14a^22^],%20^22^ct_axis_y^22^:%20^22^%23%23pipeline_output%23state%23cm_stat_characteristics%2375581c4a4e4072c8%23output%23global_execution_time_div_by_repeat%23min^22^,%20^22^ct_axis_x^22^:%20^22^%23%23pipeline_output%23state%239e4f2d963ccd037b%23output%23target_file_size^22^,%20^22^use_multiple_graphs^22^:%20^22^on^22^}" target="_blank"><img src="'+web['http_prefix']+'cm_web_module_uoa=ctuning.space&cm_web_action=visualize_selection&cm_file_ext=png&save_graph=yes&cm_json={^22^ct_axes^22^:%20[^22^%23%23pipeline_output%23state%239e4f2d963ccd037b%23output%23target_file_size^22^,%20^22^%23%23pipeline_output%23state%23cm_stat_characteristics%2375581c4a4e4072c8%23output%23global_execution_time_div_by_repeat%23min^22^],%20^22^ct_graph_type^22^:%20^22^Python%20MatPlotLib:%202D%20Scatter%20chart^22^,%20^22^ct_module_uoa^22^:%20^22^4df5b2509a4feabf^22^,%20^22^ct_data_selection^22^:%20[^22^c93766c94af8b14a^22^,%20^22^f818ca7ad2480e8e^22^,%20^22^42d4a77984179a31^22^],%20^22^mpl_extra_params^22^:%20{^22^mpl_detach_graph^22^:%20^22^^22^,%20^22^mpl_image_dpi^22^:%20^22^100^22^,%20^22^mpl_image_size_x^22^:%20^22^5^22^,%20^22^mpl_image_size_y^22^:%20^22^4^22^},%20^22^data_entry_to_sort^22^:%20^22^1^22^,%20^22^use_multiple_graphs^22^:%20^22^on^22^,%20^22^convert_text_axes_to_float^22^:%20^22^^22^,%20^22^ct_axes_desc^22^:%20{^22^%23%23pipeline_output%23state%23cm_stat_characteristics%2375581c4a4e4072c8%23output%23global_execution_time_div_by_repeat%23min^22^:%20{^22^default_value^22^:%20^22^-1^22^,%20^22^stat_characteristic^22^:%20^22^yes^22^,%20^22^dynamic_choice_desc^22^:%20{},%20^22^sort_index^22^:%20^22^1000^22^,%20^22^desc_text^22^:%20^22^Statistical%20characteristic:%20Program%20execution%20time%20normalized%20(with%20module%20overhead)%20(sec.)%20(MIN)^22^,%20^22^type^22^:%20^22^float^22^,%20^22^dynamic_choice^22^:%20[]},%20^22^%23%23pipeline_output%23state%239e4f2d963ccd037b%23output%23target_file_size^22^:%20{^22^dynamic_choice_desc^22^:%20{},%20^22^characteristic^22^:%20^22^yes^22^,%20^22^desc_text^22^:%20^22^Program%20binary%20size%20(bytes)^22^,%20^22^property^22^:%20^22^yes^22^,%20^22^type^22^:%20^22^integer^22^,%20^22^dynamic_choice^22^:%20[]}}}" border="0"></a>')
00814        cm_kernel.print_for_web('</td></tr></table>')
00815 
00816 
00817        cm_kernel.print_for_con('</td><td valign="top">')
00818 
00819        if 'cm_html_welcome_twitter' in web:
00820           cm_kernel.print_for_con('<center><small><b>Development and other news</b></small>')
00821           cm_kernel.print_for_web(web['table_init']+'<tr><td align="center">')
00822           cm_kernel.print_for_web(web['cm_html_welcome_twitter'])
00823           cm_kernel.print_for_con('</td></tr></table></center>')
00824 
00825        u=cm_kernel.ini['dcfg'].get('url_engine_version_update_check','')
00826        if u!='':
00827           r=cm_kernel.get_cm_version({})
00828           if r['cm_return']>0: return r
00829           cm_kernel.print_for_con('<center><small><b>cM engine version status</b></small></center>')
00830           cm_kernel.print_for_web(web['table_init']+'<tr><td>')
00831           cm_kernel.print_for_web('<iframe src="'+u+r['cm_string']+'.html" frameborder="0" height="60" scrolling="auto"></iframe>')
00832           #ignore errors
00833           cm_kernel.print_for_con('</td></tr></table>')
00834 
00835        cm_kernel.print_for_con('</td></tr></table>')
00836 
00837 #       if 'cm_html_welcome' in web:
00838 #          cm_kernel.print_for_web(web['cm_html_welcome'])
00839  
00840     return {'cm_return':0}
00841 
00842 # ============================================================================
00843 def view_data_through_web(i):
00844 
00845     """
00846     View data through web
00847 
00848     Input:  {
00849               browse_module_uoa  - module UOA
00850               browse_data_uoa    - data UOA 
00851               (browse_repo_uoa)  - repo UOA
00852               (cm_back_json)     - for back button
00853             }
00854 
00855     Output: {
00856               cm_return  - return code >0 if error
00857                                        -1 if entry exists
00858               cm_path    - path to created data entry
00859               cm_uid     - uid (from UOA)
00860               cm_alias   - alias (from UOA)
00861             }
00862     """
00863 
00864     # Load data
00865     ii={'cm_run_module_uoa':i['browse_module_uoa'],
00866         'cm_action':'load',
00867         'cm_data_uoa':i['browse_data_uoa']}
00868     if 'browse_repo_uoa' in i: ii['cm_repo_uoa']=i['browse_repo_uoa']
00869     rdata=cm_kernel.access(ii)
00870     if rdata['cm_return']>0: 
00871        if rdata['cm_return']==16:
00872           return {'cm_return':16, 'cm_error':'entry is either not found or accessible only for registered or admin users!'}
00873        else:
00874           return rdata
00875     d=rdata['cm_data_obj']
00876     p=rdata['cm_path']
00877 
00878     # Prepare CID
00879     all_cid=cm_kernel.prepare_cid(ii)
00880 
00881     # Get data description
00882     r=cm_kernel.get_data_description({'cm_module_uoa':i['browse_module_uoa']})
00883     if r['cm_return']>0: return r
00884     cm_data_desc=r['cm_data_desc']
00885 
00886     # Check styles, etc
00887     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
00888     else:
00889        return {'cm_return':1, 'cm_error':'web style is not defined'}
00890 
00891     # Prepare various variables
00892     s=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&cm_subaction_view&browse_cid='+all_cid['cm_string_uoa']
00893     sou=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&cm_subaction_view&browse_cid='+all_cid['cm_string_uid']
00894     sous=web['http_prefix']+'view_cid='+all_cid['cm_string_uid']
00895     souj=web['http_prefix']+'cm_web_module=core&cm_web_action=view&cm_console=json&cid='+all_cid['cm_string_uid']
00896     sf=web['http_prefix']+'cm_web_action=show&cid='+all_cid['cm_string_uoa']
00897 
00898     ss={}; ss['cm_string']=s
00899     ssou={}; ssou['cm_string']=sou
00900 
00901     ss1=json.dumps(ss)
00902     ss1=ss1.replace('&','%26')
00903     ss1=ss1.replace('"','&quot;')
00904 
00905     ss2=json.dumps(ssou)
00906     ss2=ss2.replace('&','%26')
00907     ss2=ss2.replace('"','&quot;')
00908 
00909     sd=web['http_prefix']+'cm_web_action=download&cid='+all_cid['cm_string_uoa']
00910     su=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&browse_module_uoa='+all_cid['cm_module_uoa']
00911     if 'cm_repo_uoa' in i: su+='&browse_repo_uoa='+all_cid['cm_repo_uoa']
00912 
00913     cm_kernel.print_for_con('<span class="cm-title">View data</span>')
00914 
00915     cm_kernel.print_for_con('<HR class="cm-hr">')
00916 
00917 #          cm_kernel.print_for_con('<table border="1"><tr><td align="center">')
00918     # Continue top info
00919 
00920     cm_kernel.print_for_con('<table border="0" width="100%"><tr>')
00921 #          cm_kernel.print_for_web(web['table_init'])
00922 
00923     # QR-code
00924     cm_kernel.print_for_con('<td width="158" align="center">')
00925     cm_kernel.print_for_web('<img src="'+web['http_prefix']+'cm_web_module_uoa=qr-code&cm_web_action=generate&cm_json='+ss2+'&qr_level=6&image_size=150" width="150" height="150">')
00926 
00927     hsp=web.get('cm_html_share_page','')
00928     if hsp!='':
00929        cm_kernel.print_for_web('<br>')
00930        hsp=hsp.replace(cm_kernel.convert_str_to_special('cm_web_page'), sous)
00931        hsp=hsp.replace(cm_kernel.convert_str_to_special('cm_web_page_safe'), urllib.quote(sous, ''))
00932        cm_kernel.print_for_web(hsp)
00933 
00934     cm_kernel.print_for_con('</td><td valign="top" align="left">')
00935 
00936     # Count ranking
00937     like=0
00938     if 'cm_rank' in d['cfg']: like=int(d['cfg']['cm_rank'])
00939     elif 'cm_updated' in d['cfg']:
00940        for x in d['cfg']['cm_updated']:
00941            if 'cm_like' in x and x['cm_like']=='yes': like+=1
00942 
00943     cm_kernel.print_for_con('<td width="160" align="center">')
00944     cm_kernel.print_for_con('<small><b>Like</b></small><br>')
00945     cm_kernel.print_for_con('<span style="font: 60px fantasy, cursive, Serif; font-weight: bold">')
00946     cm_kernel.print_for_web(str(like))
00947     cm_kernel.print_for_con('</span><br>')
00948 
00949     cm_kernel.print_for_web('<input type="button" class="cm-button-small" onClick="location.href=\''+su+'&browse_data_uoa='+all_cid['cm_data_uoa']+'&cm_subaction_update&cm_only_note_like=yes\'" value="Note / Like">')
00950 
00951     cm_kernel.print_for_con('</td><td valign="top" align="left">')
00952    
00953     # Prepare buttons
00954 #          cm_kernel.print_for_web(web['table_init']+'<tr><td>')
00955     cm_kernel.print_for_con('<table border="0"><tr><td>')
00956 
00957     # Download
00958     ii={'cm_run_module_uoa':ini['cm_module_uid'],
00959         'cm_action':'create_button',
00960         'cm_text':'Download',
00961         'http_prefix':web['http_prefix'],
00962         'cm_data':{'cm_web_action':'download',
00963                    'cm_module_uoa':all_cid['cm_module_uoa'],
00964                    'cm_data_uoa':all_cid['cm_data_uoa']}}
00965     if 'cm_repo_uoa' in i: ii['cm_data']['cm_repo_uoa']=all_cid['cm_repo_uoa']
00966     r=cm_kernel.access(ii)
00967     if r['cm_return']==0: cm_kernel.print_for_web(r['cm_string'])
00968 
00969     # Download whole entry
00970     ii={'cm_run_module_uoa':ini['cm_module_uid'],
00971         'cm_action':'create_button',
00972         'cm_text':'Download entry',
00973         'http_prefix':web['http_prefix'],
00974         'cm_data':{'cm_web_action':'download',
00975                    'cm_module_uoa':all_cid['cm_module_uoa'],
00976                    'cm_data_uoa':all_cid['cm_data_uoa'],
00977                    'cm_all_files':'yes'}}
00978     if 'cm_repo_uoa' in i: ii['cm_data']['cm_repo_uoa']=all_cid['cm_repo_uoa']
00979     r=cm_kernel.access(ii)
00980     if r['cm_return']==0: cm_kernel.print_for_web(r['cm_string'])
00981 
00982     if 'http_repo_descriptions' in cm_kernel.ini['dcfg']:
00983        cm_kernel.print_for_con('</td><td>')
00984        cm_kernel.print_for_web('<input type="button" class="cm-button" onclick="location.href=\''+cm_kernel.ini['dcfg']['http_repo_descriptions']+all_cid['cm_string_uid']+'\'" value="Wiki">')
00985 
00986     suback=''
00987     if 'cm_back_json' in i: suback='&cm_back_json='+i['cm_back_json']
00988 
00989     cm_kernel.print_for_web('</td><td><input type="button" class="cm-button" onclick="location.href=\''+su+suback+'&browse_data_uoa='+all_cid['cm_data_uoa']+'&cm_subaction_update\'" value="Update">')
00990     cm_kernel.print_for_web('</td><td><input type="button" class="cm-button" onclick="location.href=\''+su+suback+'&browse_data_uoa='+all_cid['cm_data_uoa']+'&cm_subaction_delete\'" value="Delete">')
00991     cm_kernel.print_for_web('</td><td><input type="button" class="cm-button" onclick="location.href=\''+su+suback+'&browse_data_uoa='+all_cid['cm_data_uoa']+'&cm_subaction_rename\'" value="Rename">')
00992     cm_kernel.print_for_web('</td><td><input type="button" class="cm-button" onclick="location.href=\''+su+suback+'&cm_subaction_add\'" value="Add new">')
00993 
00994     cm_kernel.print_for_con('</td><td>')
00995 
00996     if 'cm_back_json' in i: r1=create_button_back({'cm_back_json':i['cm_back_json']})
00997     cm_kernel.print_for_con('</td><td></table>')
00998 
00999     # Print UOA/UID
01000     cm_kernel.print_for_con('<TABLE BORDER="0"><TR><TD>')
01001     cm_kernel.print_for_web(web['table_init']+'<tr><td>')
01002     cm_kernel.print_for_con('<small>')
01003     cm_kernel.print_for_con('<table border="0"><tr><td>')
01004     cm_kernel.print_for_web(' CID with alias: </td><td><b>'+all_cid['cm_string_uoa']+'</b></td></tr>')
01005     cm_kernel.print_for_con('<tr><td>')
01006     cm_kernel.print_for_web(' CID with only UID: </td><td><b>'+all_cid['cm_string_uid']+'</b></td></tr><tr><td>')
01007     cm_kernel.print_for_con('</table></small>')
01008     cm_kernel.print_for_con('</td></tr></table>')
01009 
01010     # Show add info & param names
01011     cm_kernel.print_for_con('<center><small>')
01012 
01013     cm_kernel.print_for_web('<form action="'+s+'" name="customize_view" method="post" accept-charset="utf-8">')
01014 
01015     x=''
01016     if 'show_add_info' in i and i['show_add_info']=='on': x='checked'
01017     cm_kernel.print_for_web(' <input type="checkbox" name="show_add_info" '+x+' onchange="document.customize_view.submit();">Show additional info')
01018 
01019     cm_kernel.print_for_con('&nbsp;&nbsp;&nbsp;&nbsp;')
01020 
01021     x=''
01022     if 'show_param_names' in i and i['show_param_names']=='on': x='checked'
01023     cm_kernel.print_for_web(' <input type="checkbox" name="show_param_names" '+x+' onchange="document.customize_view.submit();">Show parameter names')
01024 
01025     if 'cm_back_json' in i: cm_kernel.print_for_web('<input type="hidden" name="cm_back_json" value="'+i['cm_back_json']+'">')
01026 
01027     cm_kernel.print_for_con('</form>')
01028 
01029     cm_kernel.print_for_con('</small></center>')
01030 
01031     cm_kernel.print_for_con('</td><td>')
01032 
01033     # Continue top stuff
01034     if 'jscript_copy_to_clipboard' in web:
01035        cm_kernel.print_for_web(web['table_init']+'<tr><td align="center">')
01036        cm_kernel.print_for_web(web['jscript_copy_to_clipboard'])
01037        cm_kernel.print_for_web('<input type="button" class="cm-button-small" onClick="copyToClipboard(\''+sou+'\');" value="Copy View URL to clipboard"><br>')
01038        cm_kernel.print_for_web('<input type="button" class="cm-button-small" onClick="copyToClipboard(\''+sd+'\');" value="Copy Download URL to clipboard"><br>')
01039        cm_kernel.print_for_web('<small><a href="'+sous+'">Self link</a> / <a href="'+souj+'">Entry JSON</a></small><BR>')
01040 
01041        #For FGG to show dir with FAR
01042        if 'far_manager_html' in web:
01043           cm_kernel.print_for_web(web['far_manager_html'].replace(cm_kernel.convert_str_to_special('cid'), all_cid['cm_string_uid']))
01044 
01045        cm_kernel.print_for_con('</td></tr></table>')
01046 
01047     cm_kernel.print_for_con('</TD></TR></TABLE>')
01048     cm_kernel.print_for_con('</td></tr></table>')
01049 
01050     cm_kernel.print_for_con('<HR class="cm-hr">')
01051 
01052     # Prepare special info
01053     common={}
01054     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common, 'cm_key':'cm_common_data_description'})
01055     common1={}
01056     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common1, 'cm_key':'cm_common_data_description1'})
01057     common4={}
01058     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common4, 'cm_key':'cm_common_data_description4'})
01059     common6={}
01060     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common6, 'cm_key':'cm_common_data_description6'})
01061     common7={} # open dissemination
01062     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common7, 'cm_key':'cm_common_data_description7'})
01063     common8={} # classification, dependencies, etc
01064     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':common8, 'cm_key':'cm_common_data_description8'})
01065 
01066     # Load local data desc and update main one
01067     cm_data_desc_local={}
01068     separate_common_from_data({'cm_array1':d['cfg'], 'cm_array2':cm_data_desc_local, 'cm_key':'cm_common_data_description5'})
01069     if 'cm_data_description' in cm_data_desc_local: cm_data_desc.update(cm_data_desc_local['cm_data_description'])
01070 
01071     # Brief info
01072     if 'cm_common_data_description1' in cm_kernel.ini['dcfg']:
01073        ii={'cm_run_module_uoa':ini['cm_module_uid'],
01074            'cm_action':'visualize_data',
01075            'cm_array':common1,
01076            'cm_separator':'#',
01077            'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description1']}
01078        if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01079        if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01080        r=cm_kernel.access(ii)
01081        if r['cm_return']>0: return r
01082        cm_kernel.print_for_con('<BR><B><small>Brief info</small></b><br>')
01083        cm_kernel.print_for_web(r['cm_string'])
01084 
01085     # Main data
01086     ii={'cm_run_module_uoa':ini['cm_module_uid'],
01087         'cm_action':'visualize_data',
01088         'cm_array':d['cfg'],
01089         'cm_separator':'#',
01090         'cm_data_desc':cm_data_desc,
01091         'cm_mode':'view'}
01092     if 'show_param_names' in i: ii['show_param_names']=i['show_param_names']
01093     if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01094     r=cm_kernel.access(ii)
01095     if r['cm_return']>0: return r
01096     cm_kernel.print_for_con('<br><small><b>Data</b></small>')
01097     cm_kernel.print_for_web(r['cm_string'])
01098 
01099     # Check if classification/dependencies/etc
01100     if len(common8)>0:
01101        if 'cm_common_data_description8' in cm_kernel.ini['dcfg']:
01102           ii={'cm_run_module_uoa':ini['cm_module_uid'],
01103               'cm_action':'visualize_data',
01104               'cm_separator':'#',
01105               'cm_array':common8,
01106               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description8']}
01107           if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01108           if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01109           r=cm_kernel.access(ii)
01110           if r['cm_return']>0: return r
01111           cm_kernel.print_for_con('<BR><B><small>Classification, properties and dependencies</small></b><br>')
01112           cm_kernel.print_for_web(r['cm_string'])
01113 
01114     # Check if dissemination
01115     if len(common7)>0:
01116        if 'cm_common_data_description7' in cm_kernel.ini['dcfg']:
01117           ii={'cm_run_module_uoa':ini['cm_module_uid'],
01118               'cm_action':'visualize_data',
01119               'cm_separator':'#',
01120               'cm_array':common7,
01121               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description7']}
01122           if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01123           if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01124           r=cm_kernel.access(ii)
01125           if r['cm_return']>0: return r
01126           cm_kernel.print_for_con('<BR><B><small>Open dissemination</small></b><br>')
01127           cm_kernel.print_for_web(r['cm_string'])
01128 
01129     # Then additional info
01130     if i.get('show_add_info','')=='on':
01131        cm_kernel.print_for_con('<br><HR class="cm-hr">')
01132        if 'cm_common_data_description' in cm_kernel.ini['dcfg']:
01133           ii={'cm_run_module_uoa':ini['cm_module_uid'],
01134               'cm_action':'visualize_data',
01135               'cm_array':common4,
01136               'cm_separator':'#',
01137               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description4']}
01138           if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01139           if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01140           r=cm_kernel.access(ii)
01141           if r['cm_return']>0: return r
01142           cm_kernel.print_for_con('<BR><B><small>Web access control</small></b><br>')
01143           cm_kernel.print_for_web(r['cm_string'])
01144 
01145        if 'cm_common_data_description' in cm_kernel.ini['dcfg']:
01146           ii={'cm_run_module_uoa':ini['cm_module_uid'],
01147               'cm_action':'visualize_data',
01148               'cm_separator':'#',
01149               'cm_array':common,
01150               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description']}
01151           if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01152           if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01153           r=cm_kernel.access(ii)
01154           if r['cm_return']>0: return r
01155           cm_kernel.print_for_con('<BR><B><small>Additional info</small></b><br>')
01156           cm_kernel.print_for_web(r['cm_string'])
01157 
01158     # List files
01159     cm_kernel.print_for_con('<br><div align="center">')
01160     cm_kernel.print_for_con('<small><b>Files</b></small><br>')
01161 
01162     r=list_files_through_web({'cm_path':p, 'limit':100, 'http_prefix':sf})
01163     if r['cm_return']>0: return r
01164 
01165     if len(r['cm_filelist'])==0:
01166        cm_kernel.print_for_con('<span style="color:blue"><b><i>None</i></b></span><br><br>')
01167 
01168     report=web.get('report_problematic_content','')
01169     if report!='':
01170        cm_kernel.print_for_con('<br><HR class="cm-hr">')
01171        report=report.replace(cm_kernel.convert_str_to_special('cid'), all_cid['cm_string_uoa'])
01172        cm_kernel.print_for_web(report)
01173 
01174 #    d=cm_kernel.ini['dcfg']['cm_common_data_description6']
01175 #    if '##cm_file_upload' in d: del(d['##cm_file_upload'])
01176 #    if 'cm_common_data_description6' in cm_kernel.ini['dcfg']:
01177 #       ii={'cm_run_module_uoa':ini['cm_module_uid'],
01178 #           'cm_action':'visualize_data',
01179 #           'cm_array':common6,
01180 #           'cm_separator':'#',
01181 #           'cm_data_desc':d}
01182 #       if 'show_param_names' in i: ii.update({'show_param_names':i['show_param_names']})
01183 #       if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
01184 #       r=cm_kernel.access(ii)
01185 #       if r['cm_return']>0: return r
01186 #       cm_kernel.print_for_web(r['cm_string'])
01187 
01188     return rdata
01189 
01190 # ============================================================================
01191 def list_files_through_web(i):
01192 
01193     """
01194     List files through web
01195 
01196     Input:  {
01197               cm_path          - path to entry
01198               limit            - limit
01199               http_prefix      - http prefix to view files
01200               skip_html_header - if 'yes', skip header
01201             }
01202 
01203     Output: {
01204               cm_return   - return code >0 if error
01205                                         -1 if entry exists
01206               cm_filelist - list of files
01207             }
01208     """
01209 
01210     # Check styles, etc
01211     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
01212     else:
01213        return {'cm_return':1, 'cm_error':'web style is not defined'}
01214 
01215     limit=1000
01216     if 'limit' in i: limit=int(i['limit'])
01217 
01218     filelist=[]
01219 
01220     r=cm_kernel.get_list_of_all_files(i)
01221     if r['cm_return']==0:
01222        filelist=r['cm_array']
01223        if len(filelist)>0:
01224 
01225           cm_kernel.print_for_web(web['table_init'])
01226 
01227           if 'number' in r and r['number']>limit:
01228              cm_kernel.print_for_web('<tr><td align="center"><br>Limited to '+str(limit)+' files<i></i></td></tr>')
01229 
01230           for f in filelist:
01231               cm_kernel.print_for_web('<tr><td align="left"><a href="'+i.get('http_prefix','')+'&cm_web_filename='+f+'" target="_blank">'+f+'</a></td></tr>')
01232 
01233           cm_kernel.print_for_con('</table>')
01234 
01235     return {'cm_return':0, 'cm_filelist':filelist}
01236 
01237 # ============================================================================
01238 def delete_data_through_web(i):
01239 
01240     """
01241     Delete data through web form
01242 
01243     Input:  {
01244               browse_module_uoa   - module UOA
01245               browse_data_uoa     - data UOA 
01246               (browse_repo_uoa)   - repo UOA
01247             }
01248 
01249     Output: {
01250               cm_return  - return code >0 if error
01251                                        -1 if entry exists
01252             }
01253     """
01254 
01255     # Load data
01256     ii={'cm_run_module_uoa':i['browse_module_uoa'],
01257         'cm_action':'load',
01258         'cm_data_uoa':i['browse_data_uoa']}
01259     if 'browse_repo_uoa' in i: ii['cm_repo_uoa']=i['browse_repo_uoa']
01260     rdata=cm_kernel.access(ii)
01261     if rdata['cm_return']>0: return rdata
01262     d=rdata['cm_data_obj']
01263     p=rdata['cm_path']
01264 
01265     to_delete=False
01266     if 'cm_subaction_delete_submit' in i:
01267        ii={'cm_run_module_uoa':i['browse_module_uoa'],
01268            'cm_action':'delete',
01269            'cm_data_uoa':i['browse_data_uoa']}
01270        if 'browse_repo_uoa' in i: ii['cm_repo_uoa']=i['browse_repo_uoa']
01271        r=cm_kernel.access(ii)
01272        if r['cm_return']>0: return r
01273 
01274        x='successfully'
01275        if cm_kernel.ini['dcfg'].get('cm_show_info_after_add_update','')=='yes': x='('+rdata['cm_path']+')'
01276        cm_kernel.print_for_web('<BR>Entry <i>'+rdata['cm_path']+'</i> deleted!<BR><BR>')
01277 
01278        return r
01279     elif 'cm_subaction_delete' in i:
01280        # Load module info
01281        ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
01282            'cm_action':'load',
01283            'cm_data_uoa':i['browse_module_uoa']}
01284        rm=cm_kernel.access(ii)
01285        if rm['cm_return']>0: return rm
01286 
01287        z='<div class="cm-title">Delete '
01288        y='data'
01289        if rm['cm_display_html']!='': y=rm['cm_display_html']
01290        z+=y
01291 
01292        z+=' <i>('+rdata['cm_uoa']+')</i><br>'
01293 
01294        z+='</div><BR>'
01295 
01296        cm_kernel.print_for_web(z)
01297 
01298        if cm_kernel.ini['dcfg'].get('cm_show_info_after_add_update','')=='yes':
01299           cm_kernel.print_for_web('You are about to delete<BR><i>'+rdata['cm_path']+'</i><BR><BR>')
01300        cm_kernel.print_for_con('<b>Are you sure ?</b><BR><BR>')
01301 
01302        cm_kernel.print_for_con('<FORM ACTION="" METHOD="POST" name="cm_subaction_delete_submit">')
01303        if 'cm_back_json' in i:      cm_kernel.print_for_web('<input type="hidden" name="cm_back_json" value="'+i['cm_back_json']+'">')
01304        if 'browse_repo_uoa' in i:   cm_kernel.print_for_web('<input type="hidden" name="browse_repo_uoa" value="'+i['browse_repo_uoa']+'">')
01305        if 'browse_module_uoa' in i: cm_kernel.print_for_web('<input type="hidden" name="browse_module_uoa" value="'+i['browse_module_uoa']+'">')
01306        if 'browse_data_uoa' in i:   cm_kernel.print_for_web('<input type="hidden" name="browse_data_uoa" value="'+i['browse_data_uoa']+'">')
01307        cm_kernel.print_for_con(' <input type="hidden" name="cm_subaction_delete" value="">')
01308        cm_kernel.print_for_con(' <input type="submit" class="cm-button" name="cm_subaction_delete_submit" value="Yes">')
01309        cm_kernel.print_for_con('</FORM>')
01310 
01311     return {'cm_return':0}
01312 
01313 # ============================================================================
01314 def add_data_through_web(i):
01315 
01316     """
01317     Add/update data through web form
01318 
01319     Input:  {
01320               browse_module_uoa   - module UOA
01321               browse_data_uoa     - data UOA 
01322               (browse_repo_uoa)   - repo UOA
01323               (cm_back_json)      - for back button
01324               (cm_only_note_like) - if 'yes', update only note and ranking
01325               cm_mode             - 'add' or 'update' to reuse the same function
01326               cm_array            - data array
01327 
01328               ...
01329             }
01330 
01331     Output: {
01332               cm_return  - return code >0 if error
01333                                        -1 if entry exists
01334 
01335                 If entry was created (not first web form), then:
01336 
01337               cm_path    - path to created data entry
01338               cm_uid     - uid (from UOA)
01339               cm_alias   - alias (from UOA)
01340             }
01341     """
01342 
01343     # Check styles, etc
01344     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
01345     else:
01346        return {'cm_return':1, 'cm_error':'web style is not defined'}
01347 
01348     # Calendar Pop Up
01349     cm_kernel.print_for_web('<script language="JavaScript" SRC="'+web['http_prefix']+'cm_web_action=show&cm_module_uoa=web&cm_data_uoa=default&cm_web_filename=CalendarPopup.js"></script>')
01350     cm_kernel.print_for_web('<script language="JavaScript">document.write(getCalendarStyles());</script>')
01351        
01352     # Detecting/restoring data from forms
01353     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form1'})
01354     if r['cm_return']>0: return r
01355     cm_form_array1=r['cm_array']
01356     cm_form_commands1=r['cm_commands']
01357 
01358     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array1, 
01359                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01360     if r['cm_return']>0: return r
01361     a1=r['cm_array']
01362 
01363     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form2'})
01364     if r['cm_return']>0: return r
01365     cm_form_array2=r['cm_array']
01366     cm_form_commands2=r['cm_commands']
01367 
01368     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array2, 
01369                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01370     if r['cm_return']>0: return r
01371     a2=r['cm_array']
01372 
01373     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form3'})
01374     if r['cm_return']>0: return r
01375     cm_form_array3=r['cm_array']
01376     cm_form_commands3=r['cm_commands']
01377 
01378     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array3, 
01379                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01380     if r['cm_return']>0: return r
01381     a3=r['cm_array']
01382 
01383     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form4'})
01384     if r['cm_return']>0: return r
01385     cm_form_array4=r['cm_array']
01386     cm_form_commands4=r['cm_commands']
01387 
01388     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array4, 
01389                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01390     if r['cm_return']>0: return r
01391     a4=r['cm_array']
01392 
01393     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form5'})
01394     if r['cm_return']>0: return r
01395     cm_form_array5=r['cm_array']
01396     cm_form_commands5=r['cm_commands']
01397 
01398     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array5, 
01399                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01400     if r['cm_return']>0: return r
01401     a5=r['cm_array']
01402 
01403     r=detect_form_params({'cm_array':i, 'cm_prefix':form6})
01404     if r['cm_return']>0: return r
01405     cm_form_array6=r['cm_array']
01406     cm_form_commands6=r['cm_commands']
01407 
01408     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array6, 
01409                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01410     if r['cm_return']>0: return r
01411     a6=r['cm_array']
01412 
01413     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form7'})
01414     if r['cm_return']>0: return r
01415     cm_form_array7=r['cm_array']
01416     cm_form_commands7=r['cm_commands']
01417 
01418     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array7, 
01419                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01420     if r['cm_return']>0: return r
01421     a7=r['cm_array']
01422 
01423     r=detect_form_params({'cm_array':i, 'cm_prefix':'#form8'})
01424     if r['cm_return']>0: return r
01425     cm_form_array8=r['cm_array']
01426     cm_form_commands8=r['cm_commands']
01427 
01428     r=cm_kernel.restore_flattened_array({'cm_array':cm_form_array8, 
01429                                          'cm_replace_in_keys':{'^35^':'#', '^64^':'@'}})
01430     if r['cm_return']>0: return r
01431     a8=r['cm_array']
01432       
01433     # Process submit 
01434     if 'cm_subaction_add_submit' in i or 'cm_subaction_update_submit' in i:
01435        # Check if file upload
01436        if 'cm_file_upload' in a6 and a6['cm_file_upload']=='': del(a6['cm_file_upload'])
01437 
01438        # Assemble array
01439        # Check if raw edit
01440        if i.get('cm_raw_edit', '')=='on' and 'cm_raw_edit_data' in i:
01441           try:
01442              a2=json.loads(i['cm_raw_edit_data'])
01443           except Exception as e:
01444              return {'cm_return':1, 'cm_error':'Can\'t parse json ('+format(e)+')'}
01445 
01446        ii={'cm_run_module_uoa':i['browse_module_uoa'],
01447            'cm_array':a2}
01448 
01449        if i.get('cm_mode','')=='update':
01450           ii['cm_action']='update'
01451           ii['cm_data_uoa']=i['browse_data_uoa']
01452        else:
01453           ii['cm_action']='add'
01454        ii.update(a1)
01455        if a1.get('browse_repo_uoa','')!='': 
01456           ii['cm_repo_uoa']=a1['browse_repo_uoa']
01457           
01458        if a1.get('cm_data_alias','')!='': ii['cm_data_uoa']=a1['cm_data_alias']
01459        ii.update(a3)
01460        ii['cm_array'].update(a4)
01461        ii['cm_array'].update(a7)
01462        ii['cm_array'].update(a8)
01463        ii.update(a6)
01464        if a6.get('cm_file_upload_tmp_uid','')!='': 
01465           del(a6['cm_file_upload_tmp_uid'])
01466           if a6.get('cm_file_upload_name','')!='' and a6.get('cm_archive','')!='already_archived_with_user_name': del(a6['cm_file_upload_name'])
01467           if 'cm_file_upload_type' in a6: del(a6['cm_file_upload_type'])
01468 #       ii['cm_array'].update(a6)
01469        if 'cm_skip_update_info' in i: ii['cm_skip_update_info']=i['cm_skip_update_info']
01470        if 'cm_update_only_index' in i: ii['cm_update_only_index']=i['cm_update_only_index']
01471        if 'cm_data_uid' in i: ii['cm_data_uid']=i['cm_data_uid']
01472 
01473        r=cm_kernel.access(ii)
01474        if r['cm_return']>0: return r
01475 
01476     # Build a form
01477     else:
01478        # Load module info
01479        ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
01480            'cm_action':'load',
01481            'cm_data_uoa':i['browse_module_uoa']}
01482        rm=cm_kernel.access(ii)
01483        if rm['cm_return']>0: return rm
01484 
01485        z='<div class="cm-title">'
01486        if i.get('cm_mode','')=='add': z+='Add '
01487        else:                          z+='Update '
01488 
01489        y='data'
01490        if rm['cm_display_html']!='': y=rm['cm_display_html']
01491        z+=y
01492 
01493        if i.get('cm_mode','')=='update':
01494           # Load data just for UOA
01495           ii={'cm_run_module_uoa':i['browse_module_uoa'],
01496               'cm_action':'load',
01497               'cm_data_uoa':i['browse_data_uoa']}
01498           if 'browse_repo_uoa' in i: ii['cm_repo_uoa']=i['browse_repo_uoa']
01499           r=cm_kernel.access(ii)
01500           if r['cm_return']>0: return r
01501 
01502           sp=r['cm_path']
01503 
01504           if 'cm_display_as_alias' in r and r['cm_display_as_alias']!='': z+=' "'+r['cm_display_as_alias']+'"'
01505           z+=' <i>('+r['cm_uoa']+')</i><br>'
01506 
01507           # Prepare CID
01508           all_cid=cm_kernel.prepare_cid(ii)
01509 
01510           # Prepare various variables
01511           sf=web['http_prefix']+'cm_web_action=show&cid='+all_cid['cm_string_uoa']
01512 
01513        z+='</div>'
01514 
01515        cm_kernel.print_for_web(z)
01516 
01517        # Load module to get description of data
01518        r=cm_kernel.get_data_description({'cm_module_uoa':i['browse_module_uoa']})
01519        if r['cm_return']>0: return r
01520        cm_data_desc=r['cm_data_desc']
01521        cm_data_cfg=r['cm_data_obj']['cfg']
01522 
01523        # If there is data in form, means that refresh
01524        forms_exists='yes'
01525        if len(cm_form_array1)==0 and len(cm_form_array2)==0 and len(cm_form_array3)==0 \
01526           and len(cm_form_array5)==0 and len(cm_form_array7)==0 and len(cm_form_array8)==0 : #and len(cm_form_array4)==0:
01527           # Load data if update or set some params if add
01528           forms_exists='no'
01529           if i.get('cm_mode','')=='update': 
01530              ii={'cm_run_module_uoa':i['browse_module_uoa'],
01531                  'cm_action':'load',
01532                  'cm_data_uoa':i['browse_data_uoa']}
01533              if 'browse_repo_uoa' in i: ii['cm_repo_uoa']=i['browse_repo_uoa']
01534              r=cm_kernel.access(ii)
01535              if r['cm_return']>0: return r
01536              a2=r['cm_data_obj']['cfg']
01537 
01538              # Prepare special info
01539              common={}
01540              separate_common_from_data({'cm_array1':a2, 'cm_array2':common, 'cm_key':'cm_common_data_description'})
01541              separate_common_from_data({'cm_array1':a2, 'cm_array2':common, 'cm_key':'cm_common_data_description3'})
01542              a1={}
01543              separate_common_from_data({'cm_array1':a2, 'cm_array2':a1, 'cm_key':'cm_common_data_description1'})
01544              a3={}
01545              separate_common_from_data({'cm_array1':a2, 'cm_array2':a3, 'cm_key':'cm_common_data_description2'})
01546              a4={}
01547              separate_common_from_data({'cm_array1':a2, 'cm_array2':a4, 'cm_key':'cm_common_data_description4'})
01548              a5={}
01549              separate_common_from_data({'cm_array1':a2, 'cm_array2':a5, 'cm_key':'cm_common_data_description5'})
01550              a6={}
01551              separate_common_from_data({'cm_array1':a2, 'cm_array2':a6, 'cm_key':'cm_common_data_description6'})
01552              a7={}
01553              separate_common_from_data({'cm_array1':a2, 'cm_array2':a7, 'cm_key':'cm_common_data_description7'})
01554              a8={}
01555              separate_common_from_data({'cm_array1':a2, 'cm_array2':a8, 'cm_key':'cm_common_data_description8'})
01556 
01557           else:
01558              if i.get('browse_repo_uoa','')=='': 
01559                 if cm_kernel.ini['dcfg'].get('cm_default_repo_for_add','')!='':
01560                    a1['browse_repo_uoa']=cm_kernel.ini['dcfg']['cm_default_repo_for_add']
01561              else:
01562                 a1['browse_repo_uoa']=i['browse_repo_uoa']
01563 
01564        # Load local data desc and update main one
01565        if 'cm_data_description' in a5: cm_data_desc.update(a5['cm_data_description'])
01566 
01567        # Start form
01568        x=''
01569        if i.get('cm_only_note_like','')=='yes': x='&cm_only_note_like=yes'
01570 
01571        cm_kernel.print_for_web('<FORM ACTION="'+web['http_prefix']+'cm_menu='+web['cm_menu_browse']+x+'" name="add_edit" METHOD="POST" enctype="multipart/form-data" accept-charset="utf-8">' )
01572 
01573        if 'cm_back_json' in i: cm_kernel.print_for_web('<input type="hidden" name="cm_back_json" value="'+i['cm_back_json']+'">')
01574 
01575        # Set variables as for browsing
01576        if 'browse_module_uoa' in i:  cm_kernel.print_for_web(' <input type="hidden" name="browse_module_uoa" value="'+i['browse_module_uoa']+'">')
01577        if i.get('cm_mode','')=='update': 
01578           if 'browse_data_uoa' in i:    cm_kernel.print_for_web(' <input type="hidden" name="browse_data_uoa" value="'+i['browse_data_uoa']+'">')
01579 
01580        if i.get('cm_mode','')=='update': cm_kernel.print_for_con(' <input type="hidden" name="cm_subaction_update" value="">')
01581        else:                             cm_kernel.print_for_con(' <input type="hidden" name="cm_subaction_add" value="">')
01582 
01583        # If not note/like
01584        if i.get('cm_only_note_like','')!='yes':
01585           # Form 1 with minimal info (internal alias, display as alias, repo) **********************************************
01586           if cm_data_cfg.get('edit_skip_misc_info','')!='yes':
01587              cm_kernel.print_for_con('<BR><B><small>Brief info</small></b><br>')
01588              ii={'cm_array':a1,
01589                  'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description1'],
01590                  'cm_separator':'#',
01591                  'cm_separator_form':'#form1#',
01592                  'cm_forms_exists':forms_exists}
01593              if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01594              if i.get('cm_mode','')=='add':
01595                 ii['cm_data_desc'].update(cm_kernel.ini['dcfg']['cm_common_data_description2'])
01596              r=visualize_data(ii)
01597              if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
01598              else: cm_kernel.print_for_web(r['cm_string'])
01599 
01600              # Form 2 with main data ******************************************************************************************
01601              cm_kernel.print_for_con('<br><small><b>Data</b></small>')
01602 
01603           # Check if cm_raw_edit_data was in the form (after checking and unchecking raw_edit box)
01604           if len(a2)==0 and 'cm_raw_edit_data' in i:
01605              try:
01606                 a2=json.loads(i['cm_raw_edit_data'])
01607              except Exception as e:
01608                 return {'cm_return':1, 'cm_error':'Can\'t parse json ('+format(e)+')'}
01609              del(i['cm_raw_edit_data'])
01610 
01611           ii={'cm_array':a2,
01612               'cm_data_desc':cm_data_desc,
01613               'cm_form_commands':cm_form_commands2,
01614               'cm_separator':'#',
01615               'cm_separator_form':'#form2#',
01616               'cm_forms_exists':forms_exists,
01617               'cm_support_raw_edit':'yes'}
01618           if 'cm_raw_edit' in i: ii['cm_raw_edit']=i['cm_raw_edit']
01619           if len(cm_data_desc)==0: ii['cm_raw_edit']='on'
01620           if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01621           if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01622           r=visualize_data(ii)
01623           if r['cm_return']>0: return r
01624           cm_kernel.print_for_web(r['cm_string'])
01625 
01626           # Process access control *******************************************************************************************
01627           ii={'cm_array':a4,
01628               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description4'],
01629               'cm_form_commands':cm_form_commands4,
01630               'cm_separator':'#',
01631               'cm_separator_form':'#form4#',
01632               'cm_forms_exists':forms_exists}
01633           if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01634           if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01635           r=visualize_data(ii)
01636           if r['cm_return']>0: return r
01637           cm_kernel.print_for_con('<BR><B><small>Web access control</small></b><br>')
01638           cm_kernel.print_for_web(r['cm_string'])
01639 
01640           if cm_data_cfg.get('edit_skip_misc_info','')!='yes':
01641              # Process open dependencies *******************************************************************************************
01642              ii={'cm_array':a8,
01643                  'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description8'],
01644                  'cm_form_commands':cm_form_commands8,
01645                  'cm_separator':'#',
01646                  'cm_separator_form':'#form8#',
01647                  'cm_forms_exists':forms_exists}
01648              if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01649              if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01650              r=visualize_data(ii)
01651              if r['cm_return']>0: return r
01652              cm_kernel.print_for_con('<BR><B><small>Classification, properties and dependencies</small></b><br>')
01653              cm_kernel.print_for_web(r['cm_string'])
01654 
01655              # Process classification *******************************************************************************************
01656              ii={'cm_array':a7,
01657                  'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description7'],
01658                  'cm_form_commands':cm_form_commands7,
01659                  'cm_separator':'#',
01660                  'cm_separator_form':'#form7#',
01661                  'cm_forms_exists':forms_exists}
01662              if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01663              if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01664              r=visualize_data(ii)
01665              if r['cm_return']>0: return r
01666              cm_kernel.print_for_con('<BR><B><small>Open dissemination</small></b><br>')
01667              cm_kernel.print_for_web(r['cm_string'])
01668 
01669              # Process files *******************************************************************************************
01670              ii={'cm_array':a6,
01671                  'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description6'],
01672                  'cm_form_commands':cm_form_commands6,
01673                  'cm_separator':'#',
01674                  'cm_separator_form':form6+'#',
01675                  'cm_forms_exists':forms_exists}
01676              if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01677              if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01678              r=visualize_data(ii)
01679              if r['cm_return']>0: return r
01680              cm_kernel.print_for_con('<BR><B><small>Files</small></b><br>')
01681 
01682              if a6.get('cm_file_upload_tmp_uid','')!='':
01683                 cm_kernel.print_for_con('<br><span style="color:red"><i><b>File cached</b></i><br></span>')
01684              cm_kernel.print_for_web(r['cm_string'])
01685 
01686              if i.get('cm_mode','')=='update':
01687                 rx=list_files_through_web({'cm_path':sp, 'limit':100, 'http_prefix':sf})
01688                 if rx['cm_return']>0: return rx
01689 
01690              # Process local data description ***********************************************************************************
01691              ii={'cm_array':a5,
01692                  'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description5'],
01693                  'cm_form_commands':cm_form_commands5,
01694                  'cm_separator':'#',
01695                  'cm_separator_form':'#form5#',
01696                  'cm_forms_exists':forms_exists}
01697              if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
01698              if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01699              r=visualize_data(ii)
01700              if r['cm_return']>0: return r
01701              cm_kernel.print_for_con('<BR><B><small>Local data description (if needed)</small></b><br>')
01702              cm_kernel.print_for_web(r['cm_string'])
01703 
01704        # Show note/like and other special stuff
01705        if i.get('cm_mode','')=='update' and cm_data_cfg.get('edit_skip_misc_info')!='yes': 
01706           cm_kernel.print_for_con('<BR><B><small>User notes and ranking</small></b><br>')
01707 
01708           ii={'cm_array':a3,
01709               'cm_data_desc':cm_kernel.ini['dcfg']['cm_common_data_description3'],
01710               'cm_separator':'#',
01711               'cm_separator_form':'#form3#',
01712               'cm_mode':'add',
01713               'cm_forms_exists':forms_exists}
01714           if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
01715           r=visualize_data(ii)
01716           if r['cm_return']>0: cm_kernel.print_for_web('<B>cM error:</b> '+r['cm_error'])
01717           else: cm_kernel.print_for_web(r['cm_string'])
01718 
01719        # Finish form
01720        if i.get('cm_mode','')=='update':
01721            cm_kernel.print_for_con('<br><input type="submit" class="cm-button" name="cm_subaction_update_submit" value="Update entry"><br><br>')
01722        else:
01723            cm_kernel.print_for_con('<br><input type="submit" class="cm-button" name="cm_subaction_add_submit" value="Add entry"><br><br>')
01724 
01725        cm_kernel.print_for_con('</FORM>')
01726  
01727        r={'cm_return':0}
01728 
01729     return r
01730 
01731 # ============================================================================
01732 def visualize_data(i):
01733     """
01734     Visualize data entry (with recursion)
01735 
01736     Input:  {
01737               cm_array                  - array to visualize
01738               (cm_array_orig)           - original array (not changing through the calls)
01739               (cm_data_desc)            - data description for visualization (always first level)
01740               (cm_desc_state)           - previous description in hierarchies
01741               (cm_form_commands)        - form commands
01742               (cm_form_explore)         - form explore parameters
01743               (cm_form_explore_color)   - prefix for style
01744               cm_separator              - appendable separator to deal with array hierarchy 
01745                                           (full - can reproduce hierarchy)
01746               cm_separator_form         - appendable separator to deal with array hierarchy 
01747                                           (full and with additional forms to deal with commands)
01748               (cm_separator_desc)       - appendable separator to deal with array hierarchy in descriptions
01749                                           (reduced - for example list number is skipped)
01750               (cm_mode)                 - 'add' or 'update'
01751               (cm_back_json)            - data to create back button
01752               (show_param_names)        - if =='on' show parameter names
01753               (cm_forms_exists)         - if 'yes', processing through forms (to avoid reinit of default vars)
01754               (cm_support_raw_edit)     - if 'yes', add check button to allow raw edit
01755               (cm_raw_edit)             - if 'on', raw edit
01756               (cm_explore)              - if 'yes', prepare exploration choices
01757               (cm_explore_commands)     - array with exploration commands
01758               (cm_explore_state)        - {} array with choices and exploration state
01759               (cm_explore_level)        - exploration level ('' - coarse-grain, '1' - next level, ...)
01760               (hide_add_new_object)     - if 'yes', do not show 'add new object'
01761               (ignore_desc_expand)      - if 'yes', ignore data description expansion from other sources
01762                                           (otherwise can be very slow for viewing)
01763             }
01764 
01765     Output: {
01766               cm_return        - return code >0 if error
01767               cm_string        - html string 
01768               cm_array         - updated array to visualize
01769               cm_explore_state - updated explore state
01770               cm_data_desc     - updated data description
01771             }
01772     """
01773 
01774     # Check styles, etc
01775     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
01776     else:
01777        return {'cm_return':1, 'cm_error':'web style is not defined in web/visualize_data'}
01778 
01779     # Check some vars
01780     if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not set in web/visualize_data'}
01781     a=i['cm_array']
01782 
01783     if 'cm_array_orig' not in i: i['cm_array_orig']=i['cm_array']
01784 
01785     s=''
01786 
01787     # Check if support raw mode
01788     if i.get('cm_support_raw_edit', '')=='yes':
01789        x=''
01790        if i.get('cm_raw_edit', '')=='on': x='checked="checked"'
01791        s=' <br><input type="checkbox" name="cm_raw_edit" '+x+' onchange="document.add_edit.submit();">Use raw json editor<br>'
01792 
01793        if i.get('cm_raw_edit', '')=='on': 
01794           # Prepare table
01795           s+=web['table_init']+'<tr><td>'
01796 
01797           v=json.dumps(a, indent=2)
01798 
01799           # Convert value to html (remove special characters)
01800           rx=cm_kernel.convert_string_to_html({'cm_string':v, 'cm_skip_br':'yes'})
01801           if rx['cm_return']>0: return rx
01802           vh=rx['cm_string']
01803 
01804           s+='<textarea cols="120" rows="20" spellcheck="false" name="cm_raw_edit_data">'
01805           s+=vh
01806           s+='</textarea>'
01807           s+='</td></tr></table>'
01808 
01809           return {'cm_return':0, 'cm_string':s, 'cm_array':a}
01810 
01811     # Explore
01812     form_explore=i.get('cm_form_explore',{})
01813     form_explore_color=i.get('cm_form_explore_color','')
01814     explore=i.get('cm_explore','')
01815     explore_commands=i.get('cm_explore_commands',{})
01816     explore_state=i.get('cm_explore_state',[])
01817     explore_level=i.get('cm_explore_level','')
01818 
01819     # Prepare description array
01820     desc={}
01821     if 'cm_data_desc' in i: desc=i['cm_data_desc']
01822 #    desc=i.get('cm_data_desc',{})
01823 
01824     desc_state={}
01825     if 'cm_desc_state' in i: desc_state=i['cm_desc_state']
01826 
01827     # Prepare commands array
01828     commands={}
01829     if 'cm_form_commands' in i: commands=i['cm_form_commands']
01830 
01831     # Prepare separators
01832     cs=''
01833     if 'cm_separator' in i: cs=i['cm_separator']
01834     csf=cs
01835     if 'cm_separator_form' in i: csf=i['cm_separator_form']
01836     # dealing with descriptions
01837     csd=cs
01838     if 'cm_separator_desc' in i: csd=i['cm_separator_desc']
01839 
01840     if   type(a)==dict: cs+='#'; csf+='#'; csd+='#'
01841     elif type(a)==list: cs+="@"; csf+='@'; csd+='@'
01842 
01843     # Check if need to add description from other sources
01844     if i.get('ignore_desc_expand','')!='yes':
01845        k2=desc.keys()
01846        for k1 in k2:
01847            d=desc[k1]
01848 
01849            # Restoring key
01850            if k1.startswith(csd): 
01851               k=k1[len(csd):]
01852               if string.find(k,'#')==-1 and string.find(k,'@')==-1 and k!='$':
01853                  # found correct level
01854                  xd=d.get('further_desc_from_module',{})
01855                  if len(xd)>0:
01856                     xxm=xd.get('cm_module_uoa','')
01857 
01858                     if xd.get('key','')!='':
01859                        rx=cm_kernel.get_data_description({'cm_module_uoa':xxm, 'cm_desc_key':xd['key']})
01860                     elif xd.get('flat_key','')!='':
01861                        rx=cm_kernel.get_data_description({'cm_module_uoa':xxm, 'cm_flat_desc_key':xd['flat_key']})
01862 
01863                     if rx['cm_return']>0: return rx
01864                     xxd=rx['cm_data_desc']
01865 
01866                     for q6 in xxd:
01867                         desc[k1+q6[1:]]=xxd[q6]
01868 
01869                  xd=d.get('expand_from_other_data',{}) 
01870                  if len(xd)>0:
01871                     xxm=xd.get('cm_module_uoa','')
01872                     xxk=xd.get('cm_key','')
01873                     xxsk=xd.get('cm_sub_key','')
01874                     xxskd=xd.get('cm_sub_key_desc','')
01875 
01876                     if xd.get('clean_before_updating','')=='yes':
01877                        if k in a: 
01878                           del(a[k])
01879 
01880                     rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':xxk})
01881                     if rg['cm_return']==0 and rg['cm_value']!=None: 
01882                        jj={'cm_run_module_uoa':xxm,
01883                            'cm_action':'load',
01884                            'cm_data_uoa':rg['cm_value']}
01885                        rg1=cm_kernel.access(jj)
01886                        if rg1['cm_return']==0:
01887                           foundx=False
01888 
01889                           rg2=cm_kernel.get_value_by_flattened_key({'cm_array':rg1['cm_data_obj']['cfg'], 'cm_key':xxskd})
01890                           if rg2['cm_return']==0 and rg2['cm_value']!=None: 
01891                              foundx=True
01892                              xxd=rg2['cm_value']
01893 
01894                              for q6 in xxd:
01895                                  desc[k1+q6[1:]]=xxd[q6]
01896 
01897                              # remove not needed ones
01898                              if k in a:
01899                                 q9=a[k].keys()
01900 
01901                                 for q8 in q9:
01902                                     if '##'+q8 not in xxd: del(a[k][q8])
01903 
01904                           rg2=cm_kernel.get_value_by_flattened_key({'cm_array':rg1['cm_data_obj']['cfg'], 'cm_key':xxsk})
01905                           if rg2['cm_return']==0 and rg2['cm_value']!=None:
01906                              foundx=True
01907                              dx=rg2['cm_value']
01908                              # remove not needed ones
01909                              if k in a:
01910                                 q9=a[k].keys()
01911                                 for q8 in q9:
01912                                     if q8 not in dx: del(a[k][q8])
01913                              else:
01914                                 a[k]={}
01915 
01916                              for q8 in dx:
01917                                  if q8 not in a[k]: a[k][q8]=dx[q8]
01918 
01919 
01920                           if not foundx:
01921                              a[k]={}
01922 
01923                        else:
01924                           if k in a: 
01925                              del(a[k])
01926                     else:
01927                        if k in a: 
01928                           del(a[k])
01929 
01930     # Update array from current description (add default values in 'add' mode)
01931     if (i.get('cm_mode','')=='add' or i.get('cm_mode','')=='update'):
01932         for k1 in desc:
01933             d=desc[k1]
01934             t=d.get('type','')
01935 
01936             # Restoring key
01937             if k1.startswith(csd): 
01938                k=k1[len(csd):]
01939                if string.find(k,'#')==-1 and string.find(k,'@')==-1 and k!='$':
01940                   # found correct level
01941                   # if key not in array, 
01942                   if type(a)==dict and (k not in a):
01943                      if d.get('only_for_exploration','')=='yes' and explore!='yes':
01944                         continue
01945 
01946                      if i.get('cm_mode','')=='add' and 'default_value' in d: 
01947                         if t=='list':               
01948                            if type(d['default_value'])!=list: a[k]=[d['default_value']]
01949                            else: a[k]=d['default_value']
01950                         elif t=='dict': 
01951                              if 'default_key' in d: a[k]={d['default_key']:d['default_value']}
01952                              else:                  a[k]={}
01953                         else:                       a[k]=d['default_value']
01954                      else:
01955                         if t=='dict':                                               a[k]={}
01956                         elif t=='list':                                             a[k]=[]
01957                         elif i.get('cm_mode')=='add' or d.get('dict_type')!='free': a[k]=''
01958 
01959     # Prepare some vars to change colors for each second line
01960     line=True; 
01961     x1=''
01962     if 'table_bgcolor_line1' in web: x1=' bgcolor="'+web['table_bgcolor_line1']+'" ' 
01963     x2=''
01964     if 'table_bgcolor_line2' in web: x2=' bgcolor="'+web['table_bgcolor_line2']+'" '
01965 
01966     # Prepare table
01967     s+='\n<a name="'+cs+'"></a>\n'
01968     s+='<table border="0"><tr><td valign="top">' # holder if we want to have serveral columns 
01969     s+=web['table_init']
01970 
01971     # If not array, prepare list with 1 element to unify iteration over all values
01972     at=a
01973     if type(a)!=list and type(a)!=dict: at=[a]
01974 
01975     if type(at)==list: ati=at
01976     else:              ati=at.keys()
01977 
01978     # Process commands
01979     u=0
01980     for k0 in ati:
01981         # Get value
01982         if   type(a)==dict: aa=a[k0]
01983         elif type(a)==list: aa=k0;   k0=str(u)
01984         else:               aa=a
01985 
01986         # Remove # and @
01987         k=k0.replace('#', '^35^')
01988         k=k.replace('@', '^64^')
01989 
01990         # Prepare form key for this hierarchy and find local description
01991         d={}
01992 
01993         if desc_state.get('skip_next_desc','')=='yes': dk=csd+'$'
01994         else:                                          dk=csd+k
01995 
01996         if type(at)==dict or type(at)==list:
01997            if len(dk)>2 and dk[2:] in desc: d=desc[dk[2:]]
01998            elif dk in desc: d=desc[dk]
01999 
02000         # Get type
02001         t=''
02002         if 'type' in d: t=d['type']
02003 
02004         tn=''
02005         if 'type_next' in d: tn=d['type_next'].strip()
02006 
02007         # Process commands
02008         if cs+k in commands:
02009            cx=commands[cs+k]
02010            cc=cx['command']
02011            ck=''
02012            if 'key' in cx: ck=cx['key']
02013            del(commands[cs+k])
02014 
02015            #FGG TBD: not all cases are checked below - should be checked on demand (when cases appear)
02016 
02017            if cc=='delete':
02018               if type(at)==list:
02019                  del(at[u])
02020               elif type(at)==dict:
02021                  del(at[k0])
02022               u-=1
02023            elif cc=='add_value':
02024               if type(at)==list:
02025                    v=''
02026                    if 'default_value' in d: v=d['default_value']
02027                    if t=='list': at[u].append(v)
02028                    elif ck!='': at[u][ck]=v
02029                    else: at.insert(u,v)
02030               elif type(at)==dict:
02031                    v=''
02032                    if 'default_value' in d: v=d['default_value']
02033                    if t=='list': at[k0].append(v)
02034                    elif ck!='': at[k0][ck]=v
02035                    else: at[k0].insert(u,v)
02036            elif cc=='add_list':
02037               if type(at)==list:
02038                    v=[]
02039                    if 'default_value' in d: v=d['default_value']
02040                    if t=='list': v=[v]
02041                    if ck!='': at[ck]=v
02042                    else: at.insert(u,v)
02043               elif type(at)==dict:
02044                    v=[]
02045                    if 'default_value' in d: v=d['default_value']
02046                    if t=='list': at[k0].append(v)
02047                    else: at[k0][ck]=v
02048            elif cc=='add_dict':
02049               if type(at[k0])==list:
02050                    v={}
02051                    if 'default_value' in d: v=d['default_value']
02052                    elif 'default_value' in desc_state: v=desc_state['default_value']
02053                    at[k0].insert(u,v)
02054               elif type(at[k0])==dict:
02055                    v={}
02056                    if 'default_value' in d: v=d['default_value']
02057                    at[k0][ck]=v
02058 
02059         u+=1
02060 
02061     # Sort if needed ********************************************************************************
02062     if type(at)==dict:
02063        d={}
02064        for k0 in at:
02065            k=k0.replace('#', '^35^')
02066            k=k.replace('@', '^64^')
02067            
02068            if desc_state.get('skip_next_desc','')=='yes': dk=csd+'$'
02069            else:                                                        dk=csd+k
02070 
02071            if len(dk)>2 and dk[2:] in desc: d[k0]=desc[dk[2:]]
02072            elif dk in desc: d[k0]=desc[dk]
02073 
02074        ati=sorted(at.keys(), key=lambda k: (int(d.get(k,{}).get('sort_index','999999')), d.get(k,{}).get('desc_text','').lower()))
02075     else: ati=at
02076 
02077     u=0
02078     for k0 in ati:
02079         # Get value
02080         if type(a)==dict: aa=a[k0]
02081         elif type(a)==list: aa=k0; k0=str(u)
02082         else: aa=a
02083 
02084         u+=1
02085 
02086         # Remove # and @ (special characters that we should not use in keys except data description)
02087         k=k0.replace('#', '^35^')
02088         k=k.replace('@', '^64^')
02089 
02090         # Prepare form key for this hierarchy and find local description
02091         d={}
02092         desc_key=''
02093 
02094         if desc_state.get('skip_next_desc','')=='yes': dk=csd+'$'
02095         else:                                          dk=csd+k
02096 
02097         if type(at)==dict or type(at)==list:
02098            if len(dk)>2 and dk[2:] in desc: 
02099               desc_key=dk[2:]
02100               d=desc[desc_key]
02101            elif dk in desc: 
02102               desc_key=dk
02103               d=desc[desc_key]
02104 
02105         # Skip if only during exploration
02106         if d.get('only_for_exploration','')=='yes' and i.get('cm_explore','')!='yes':
02107            continue
02108 
02109         # Skip if ignore_add_edit == yes
02110         if i.get('cm_mode','')=='add'    and d.get('ignore_add','')=='yes':    continue
02111         if i.get('cm_mode','')=='update' and d.get('ignore_update','')=='yes': continue
02112 
02113         # Skip if "hide_if"/"hide_if_not" is true
02114         if d.get('disable_if_update','')=='yes' and i.get('cm_mode','')=='update':
02115            continue
02116 
02117         disable=False
02118         if 'hide_if' in d:
02119            disable=True
02120            for g in d['hide_if']:
02121                v=d['hide_if'][g]
02122                rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':g})
02123                if rg['cm_return']>0: return rg
02124                if rg['cm_value']==None: rg['cm_value']=''
02125                if rg['cm_value']!=v: disable=False;break
02126 
02127         if not disable and ('hide_if_not' in d):
02128            disable=False
02129            for g in d['hide_if_not']:
02130                v=d['hide_if_not'][g]
02131                rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':g})
02132                if rg['cm_return']>0: return rg
02133                if rg['cm_value']==None: rg['cm_value']=''
02134                if rg['cm_value']!=v: disable=True;break
02135 
02136         if disable: continue
02137 
02138         # Get type
02139         t=''
02140         if 'type' in d: t=d['type'].strip()
02141 
02142         # Check if choices from other data
02143         o=d.get('cm_data_uoa_active', '')
02144         if o!='':
02145            if a[k0]==None or len(a[k0])==0:
02146               o1=o.get('cm_key','')
02147               if o1!='':
02148                  rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':o1})
02149                  if rg['cm_return']==0 and rg['cm_value']!=None: 
02150                     a[k0]=rg['cm_value']
02151                     aa=a[k0]
02152 
02153         o=d.get('choice_from_entry', '')
02154         if o!='':
02155            o1=o.get('cm_data_uoa','')
02156            o2=o.get('cm_module_uoa','')
02157            o3=o.get('cm_key','')
02158 
02159            if o1!='' and o2!='' and o3!='':
02160               jj={'cm_run_module_uoa':o2,
02161                   'cm_action':'load',
02162                   'cm_data_uoa':o1}
02163               rg1=cm_kernel.access(jj)
02164               if rg1['cm_return']==0:
02165                  rg2=cm_kernel.get_value_by_flattened_key({'cm_array':rg1['cm_data_obj']['cfg'], 'cm_key':o3})
02166                  if rg2['cm_return']==0 and rg2['cm_value']!=None:
02167                     do1=rg2['cm_value']
02168 
02169                     d['choice']=[]
02170                     d['choice_desc']={}
02171 
02172                     if o.get('add_empty','')=='yes': d['choice'].append('')
02173 
02174                     for qq in do1:
02175                         d['choice'].append(qq)
02176                         dx=do1[qq]
02177                         if 'desc_text' in dx:
02178                            d['choice_desc'][qq]={}
02179                            d['choice_desc'][qq]['desc_text']=dx['desc_text']
02180 
02181         o=d.get('data_from_other_data', {})
02182         if len(o)>0:
02183            o1=o.get('cm_key','')
02184            o2=o.get('cm_module_uoa','')
02185            o3=o.get('cm_sub_key','')
02186            o4=o.get('cm_sub_key_from_data','')
02187            o5=o.get('cm_sub_key_from_data1','')
02188 
02189            if o.get('clean_before_updating','')=='yes':
02190               if k0 in a: 
02191                  if t=='list':a[k0]=[]
02192                  else: a[k0]={}
02193 
02194            if o1!='' and o2!='' and o3!='':
02195 
02196               do4=''
02197               if o4!='':
02198                  rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':o4})
02199                  if rg['cm_return']==0 and rg['cm_value']!=None: do4=rg['cm_value']
02200 
02201               if o4=='' or (o4!='' and do4!=''):      
02202                  rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':o1})
02203                  if rg['cm_return']==0 and rg['cm_value']!=None: 
02204                     # Load data
02205                     jj={'cm_run_module_uoa':o2,
02206                         'cm_action':'load',
02207                         'cm_data_uoa':rg['cm_value']}
02208                     rg1=cm_kernel.access(jj)
02209                     if rg1['cm_return']==0:
02210                        rg2=cm_kernel.get_value_by_flattened_key({'cm_array':rg1['cm_data_obj']['cfg'], 'cm_key':o3})
02211                        if rg2['cm_return']==0 and rg2['cm_value']!=None:
02212                           dx=rg2['cm_value']
02213 
02214                           if type(dx)!=dict and type(dx)!=list: dx=[dx]
02215 
02216                           if do4!='': 
02217                              if o5=='': dx=dx.get(do4,[])
02218                              else: dx=dx.get(do4,{})
02219 
02220                           if o5!='': dx=dx.get(o5,[])
02221 
02222                           ot=o.get('type','')
02223                           if ot=='add_to_array':
02224                              a[k0]=dx
02225                              aa=a[k0]
02226                           if ot=='add_to_list':
02227                              for ee in dx:
02228                                  # Check that not in list
02229                                  found=False
02230                                  for ee1 in a[k0]:
02231                                      eek=ee1.keys()[0]
02232                                      eev=ee1[eek]
02233                                      if eek==ee:
02234                                         found=True
02235                                         break
02236                                  if not found:
02237                                     a[k0].append({ee:''})
02238                              aa=a[k0]
02239                           elif ot=='add_to_classes':
02240                              d['cm_classes_uoa']=dx
02241                           else:
02242                              d['choice']=[]
02243                              d['choice_desc']={}
02244 
02245                              for qq in dx:
02246                                  d['choice'].append(qq)
02247                                  if type(dx)==dict and type(dx[qq])!=dict and type(dx[qq])!=list and dx[qq]!='':
02248                                     d['choice_desc'][qq]={}
02249                                     d['choice_desc'][qq]['desc_text']=dx[qq]
02250 
02251         if d.get('select_value_from_other_value','')!='':
02252            rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':d['select_value_from_other_value']})
02253            if rg['cm_return']==0 and rg['cm_value']!=None: 
02254               a[k0]=rg['cm_value']
02255               aa=a[k0]
02256 
02257         if (d.get('force_select_first','')=='yes' and len(d.get('choice',[]))>0) or \
02258            (d.get('force_select_first_if_only_one','')=='yes' and len(d.get('choice',[]))==1):
02259            a[k0]=d['choice'][0]
02260            aa=a[k0]
02261 
02262         tn=''
02263         if 'type_next' in d: tn=d['type_next'].strip()
02264 
02265         tnext=''
02266         if 'type_next' in desc_state: tnext=desc_state['type_next'].strip()
02267 
02268         # Update description if expanded
02269 #        if desc_key!='':
02270 #           desc[desc_key]=d
02271 
02272         # Check data types
02273         if type(aa)==dict or type(aa)==list:
02274            ii={'cm_array':aa, 
02275                'cm_array_orig':i['cm_array_orig'],
02276                'cm_separator':cs+k, 
02277                'cm_separator_form':csf+k, 
02278                'cm_data_desc':desc,
02279                'cm_desc_state':d,
02280                'cm_form_commands':commands,
02281                'cm_form_explore':form_explore,
02282                'cm_form_explore_color':form_explore_color,
02283                'cm_explore':explore,
02284                'cm_explore_commands':explore_commands,
02285                'cm_explore_state':explore_state,
02286                'cm_explore_level':explore_level,
02287                'hide_add_new_object':i.get('hide_add_new_object','')}
02288 
02289            # If there is description, deal with hierarchy **************************************************
02290            if desc_state.get('skip_next_desc','')=='yes': ii['cm_separator_desc']=csd+'$' 
02291            else:                                          ii['cm_separator_desc']=csd+k
02292 
02293            if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
02294            if 'show_param_names' in i: ii['show_param_names']=i['show_param_names']
02295            if 'ignore_desc_expand' in i: ii['ignore_desc_expand']=i['ignore_desc_expand']
02296            r=visualize_data(ii)
02297            if r['cm_return']>0: v='Error'+r['cm_error']
02298            else: v=r['cm_string']
02299 
02300            if i.get('cm_mode','')=='add' or i.get('cm_mode','')=='update':
02301               if t=='list':
02302                  if tn=='values':  v+=' <input type="submit" class="cm-button-small" name="@add_value@'+csf+k+'" value="Add">\n'
02303                  elif tn=='dict':  v+=' <input type="submit" class="cm-button-small" name="@add_dict@'+csf+k+'" value="Add">\n'
02304                  elif tn=='list':  v+=' <input type="submit" class="cm-button-small" name="@add_list@'+csf+k+'" value="Add">\n'
02305               elif type(aa)==list:
02306                  v+=' <input type="submit" class="cm-button-small" name="@add_value@'+csf+k+'" value="Add value">\n'
02307               elif type(aa)==dict and (len(d)==0 or d.get('dict_type','')=='free'):
02308 
02309                  x=''
02310                  v+=' <small>New key:</small> <input type="text" size="10" spellcheck="false" name="@new_dict_key@'+csf+k+'" value="">\n'
02311                  if tn=='values' or tn=='':  
02312                              if tn=='': x=' value'
02313                              v+=' <input type="submit" class="cm-button-small" name="@add_value@'+csf+k+'" value="Add'+x+'">\n'
02314                  if tn=='dict' or tn=='':  
02315                              if tn=='': x=' dict'
02316                              v+=' <input type="submit" class="cm-button-small" name="@add_dict@'+csf+k+'" value="Add'+x+'">\n'
02317                  if tn=='list' or tn=='':  
02318                              if tn=='': x=' list'
02319                              v+=' <input type="submit" class="cm-button-small" name="@add_list@'+csf+k+'" value="Add'+x+'">\n'
02320 
02321         # Check types (simple dictionary) *****************************************************************
02322         else:
02323            if type(aa)!=unicode: aa=str(aa) # to avoid problems with non string values
02324            ii={'cm_key':k, 
02325                'cm_value':aa, 
02326                'cm_separator':cs, 
02327                'cm_separator_form':csf, 
02328                'cm_data_desc':d,
02329                'cm_cur_array':a,
02330                'cm_cur_key':k0,
02331                'cm_form_explore':form_explore,
02332                'cm_explore':explore,
02333                'cm_form_explore_color':form_explore_color,
02334                'cm_explore_commands':explore_commands,
02335                'cm_explore_state':explore_state,
02336                'cm_explore_level':explore_level,
02337                'hide_add_new_object':i.get('hide_add_new_object','')}
02338            if 'cm_mode' in i: ii['cm_mode']=i['cm_mode']
02339            if 'cm_back_json' in i: ii['cm_back_json']=i['cm_back_json']
02340            if 'cm_array_orig' in i: ii['cm_array_orig']=i['cm_array_orig']
02341            r=convert_field_to_html(ii)
02342            if r['cm_return']>0: v='Error'+r['cm_error']
02343            else: v='\n<a name="'+cs+k+'#"></a>\n'+r['cm_value_html']
02344 
02345         kc=''
02346         if i.get('cm_mode','')=='add' or i.get('cm_mode','')=='update':
02347            if type(at)==list:
02348               kc+=' <input type="submit" class="cm-button-small" name="@delete@'+csf+k+'" value="Del">'
02349               x=''
02350               if tnext=='values' or tnext=='':  
02351                           if tnext=='': x=' value'
02352                           kc+=' <input type="submit" class="cm-button-small" name="@add_value@'+csf+k+'" value="Add'+x+' above">\n'
02353               elif tnext=='dict' or tnext=='':  
02354                           if tnext=='': x=' dict'
02355                           kc+=' <input type="submit" class="cm-button-small" name="@add_dict@'+csf+k+'" value="Add'+x+' above">\n'
02356               elif tnext=='list' or tnext=='':  
02357                           if tnext=='': x=' list'
02358                           kc+=' <input type="submit" class="cm-button-small" name="@add_list@'+csf+k+'" value="Add'+x+' above">\n'
02359            elif type(at)==dict and desc_state.get('dict_type','')=='free':
02360               kc+=' <input type="submit" class="cm-button-small" name="@delete@'+csf+k+'" value="Del">'
02361 
02362         # Visualize node
02363         if line or d.get('start_new_column','')=='yes' or d.get('title_before','')!='': line=False; x=x1
02364         else: line=True; x=x2
02365 
02366         dt=''
02367         if 'desc_text' in d: dt=d['desc_text']
02368 
02369         ar={}
02370         if 'array'in d: ar=d['array']
02371 
02372         if dt!='': dt=dt[0].upper()+dt[1:]
02373 
02374         if desc_state.get('type')=='dict' and desc_state.get('key_from_module_uoa','')!='': 
02375            ii['cm_run_module_uoa']=desc_state['key_from_module_uoa']
02376            ii['cm_data_uoa']=k
02377            ii['cm_action']='load'
02378            rx=cm_kernel.access(ii)
02379            if rx['cm_return']==0: 
02380               dt=rx['cm_display_html']
02381 
02382         kk='';dd=''
02383 
02384         if i.get('show_param_names','')=='on':
02385            kk='<TD VALIGN="TOP" align="left"><span class="cm-data-key">'+k0+' '+kc+'</span></TD>\n'
02386            dd='<TD valign="TOP" align="left"><span class="cm-data-desc"><b>'+dt+'</b></span></TD>\n'
02387         else:
02388            if dt=='': dt='<i>'+k0+' '+kc+'</i>' 
02389            else: dt='<b>'+dt+' '+kc+'</b>'
02390            dd='<TD VALIGN="TOP" align="left"><span class="cm-data-desc" style="vertical-align:middle">'+dt+'</span></TD>\n'
02391 
02392         # Check if space and title 
02393         if d.get('start_new_column','')=='yes': 
02394            s+='</table></td><td valign="top">'+web['table_init']
02395 
02396         if d.get('space_before','')=='yes': s+='<TR><TD COLSPAN="2">&nbsp;</TD></TR>'
02397         if d.get('title_before','')!='': s+='<TR><TD COLSPAN="2"><B><I><SMALL>'+d.get('title_before')+'</SMALL></I></B><HR class="cm-hr"></TD></TR>'
02398 
02399         s+='<TR'+x+'>'+kk+dd+'<TD align="left"><span class="cm-data" style="vertical-align:middle">'+v+'</span></TD></TR>\n'
02400 
02401     s+='</TABLE>'
02402     s+='</td></tr></table>' # holder if we want to have serveral columns 
02403 
02404     return {'cm_return':0, 'cm_string':s, 'cm_array':a, 'cm_explore_state':explore_state, 'cm_data_desc':desc}
02405 
02406 # ============================================================================
02407 def convert_field_to_html(i):
02408 
02409     """
02410     Convert cM data field to html
02411 
02412     Input:  {
02413               cm_separator            - appendable separator to deal with json hierarchy
02414               cm_separator_form       - appendable separator to deal with array hierarchy (and with additional forms)
02415               cm_key                  - array key
02416               cm_value                - array value
02417               cm_data_desc            - data description in special cM format
02418               cm_mode                 - add | update
02419               (cm_back_json)          - array with previous cM state
02420               (cm_array_orig)         - original array (not changing through the calls)
02421               (cm_cur_array)          - current array to change if needed
02422               (cm_cur_key)            - current key to change array if needed
02423               (cm_form_explore)       - form explore parameters
02424               (cm_explore)            - if 'yes', prepare exploration choices
02425               (cm_form_explore_color) - prefix for style
02426               (cm_explore_commands)   - array with exploration commands
02427               (cm_explore_state)      - {} array with choices and exploration state
02428               (cm_explore_level)      - exploration level ('' - coarse-grain, '1' - next level, ...)
02429               (hide_add_new_object)   - if 'yes', do not show 'add new object'
02430               (cm_disable_coloring)   - if 'yes', disable coloring of dimensions, characteristics, properties, state, etc
02431               (cm_admin)              - if 'yes', override access control - only internal use,
02432                                         can not be used during web access (explicitly removed)
02433             }
02434 
02435     Output: {
02436               cm_return               - return code >0 if error
02437               cm_value_html           - prepared html
02438               cm_value_text           - text (in URL, etc)
02439             }
02440     """
02441 
02442     cs=''
02443     if 'cm_separator' in i: cs=i['cm_separator']
02444     csf=''
02445     if 'cm_separator_form' in i: csf=i['cm_separator_form']
02446 
02447     k=i['cm_key']
02448     v=i['cm_value']
02449     vv=''
02450     vt=''
02451     d=''
02452 
02453     form_explore=i.get('cm_form_explore',{})
02454     form_explore_color=i.get('cm_form_explore_color','')
02455     explore=i.get('cm_explore','')
02456     explore_commands=i.get('cm_explore_commands',{})
02457     explore_state=i.get('cm_explore_state',[])
02458     explore_level=i.get('cm_explore_level',[])
02459 
02460     # Convert value to html (remove special characters)
02461     rx=cm_kernel.convert_string_to_html({'cm_string':v, 'cm_skip_br':'yes'})
02462     if rx['cm_return']>0: return rx
02463     vh1=rx['cm_string']
02464 
02465     vx=v
02466     if type(v)!=unicode: vx=str(v) # to avoid problems with non string values
02467 
02468     vh=vh1.replace('\r\n', '<BR>').replace('\n', '<BR>')#.replace(' ', '&nbsp;')
02469 
02470     sw=''
02471     if int(i.get('cm_html_width','0'))>0:
02472        sw=' web="width: '+i['cm_html_width']+'px" '
02473 
02474     # Check styles, etc
02475     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
02476     else:
02477        return {'cm_return':1, 'cm_error':'web style is not defined'}
02478 
02479     # Check if disabled
02480     dis=''
02481     if i.get('cm_disabled','')=='yes': dis=' disabled="disabled" '
02482 
02483     add=False
02484     update=False
02485     if i.get('cm_mode','')=='add':    add=True 
02486     if i.get('cm_mode','')=='update': update=True 
02487 
02488     q={}
02489     if i.get('cm_data_desc',{})!=None and len(i['cm_data_desc'])!=0:
02490         q=i['cm_data_desc']
02491 
02492         if q.get('field_width','')!='':
02493            sw+=' style="width: '+q['field_width']+'px" '
02494 
02495         soc=''
02496         # If explicit request to refresh form on change (usually with a given form name)
02497         # otherwise, by default it's on for add_edit form unless skipped explicitly
02498 
02499         if q.get('skip_form_refresh','')!='yes':
02500            if i.get('cm_submit_on_change','')=='yes':    web_form='web_browse'
02501            else:                                         web_form='add_edit'
02502 
02503            if i.get('cm_web_form','')!='': web_form=i['cm_web_form']
02504 
02505            soc=' onchange="document.'+web_form+'.submit();" '
02506 
02507         has_choice=q.get('has_choice','')
02508         choice=q.get('choice',[])
02509         choice_desc=q.get('choice_desc', {})
02510         size=web['data_field_size']
02511         if q.get('field_size','')!='': size=q['field_size']
02512         t=q.get('type','')
02513 
02514         # Check if disabled
02515         if q.get('disable','')=='yes': dis=' readonly="readonly" style="font-style:italic;color:blue"'
02516 
02517         # Check type
02518         # **********************************************************************************************
02519         if has_choice=='yes':
02520            if update or add:
02521               if q.get('disable','')=='yes': 
02522                  vv='<input type="text" size="'+size+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02523               else:
02524                  v1='<select class="cm-select" width="auto" name="'+csf+k+'"'+soc+sw+dis+'>\n'
02525 
02526                  # Check if value in choice and if not, select one
02527                  if len(choice)>0 and (v=='' or (v!='' and v not in choice)): 
02528                     zx=q.get('default_value','')
02529                     if zx=='': zx=choice[0]
02530 
02531                     if 'cm_cur_array' in i:
02532                        i['cm_cur_array'][i['cm_cur_key']]=zx
02533                     v=zx
02534 
02535                  if q.get('no_sorting','')=='yes':
02536                     qq=choice
02537                  elif q.get('sort_by_desc','')=='yes':
02538                     qq=sorted(choice, key=lambda k: (choice_desc.get(k,{}).get('desc_text','').lower()))
02539                  else:
02540                     qq=sorted(choice)
02541 
02542                  for x in qq:
02543                      z=''
02544                      if v!='' and x==v: z=' SELECTED '
02545                      xx=x
02546                      if x in choice_desc and 'desc_text' in choice_desc[x]: xx=choice_desc[x]['desc_text']
02547                      v1+='<option value="'+x+'"'+z+'>'+xx+'</option>\n'
02548                  vv=v1+'</select>\n'
02549            else:
02550               vv=vh
02551         # **********************************************************************************************
02552         elif t=='text' or t=='integer' or t=='float':
02553            if update or add:
02554               vv='<input type="text" size="'+size+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02555            else:
02556               vv=vh
02557         # **********************************************************************************************
02558         elif t=='url':
02559            if update or add:
02560               vv='<input type="text" size="'+size+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02561            else:
02562               if str(v)!='': vv='<a href="'+str(v)+'">Link</a>'
02563         # **********************************************************************************************
02564         elif t=='email':
02565            if update or add:                 
02566               vv='<input type="text" size="'+size+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02567            else:
02568               if str(v)!='': vv='<a href="mailto:'+str(v)+'">'+str(v)+'</a>'
02569         # **********************************************************************************************
02570         elif t=='iso_datetime':
02571            if update or add:
02572 
02573               vv='<script language="JavaScript">'
02574               vv+='var vcp = new CalendarPopup("calendar_popup");'
02575 #                 vv+='var vcp = new CalendarPopup("");'
02576               vv+='vcp.setYearSelectStartOffset(500);'
02577               vv+='vcp.showNavigationDropdowns();'
02578               vv+='</script>'
02579               vv+='<input type="text" size="'+web['data_field_size']+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+ \
02580                   ' onclick="vcp.select(this, \'anchor'+csf+k+'\',\'yyyy/MM/ddTHH:mm:ss.00000\', this.value); return false;" id="anchor'+csf+k+'">'
02581               vv+='<div id="calendar_popup" style="visibility:hidden;background-color:white;layer-background-color:white;"></div>'
02582            else:
02583               # Doesn't take time zone into account
02584               if v!='':
02585                  rx=cm_kernel.convert_iso_time_to_str({'cm_iso_datetime':v})
02586                  if rx['cm_return']==0:
02587                     vv=rx['cm_string']
02588               else:
02589                  vv=v
02590         # **********************************************************************************************
02591         elif t=='password':
02592            if update or add:
02593               vv='<input type="password" size="'+size+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02594            else:
02595               vv='**********************'
02596         # **********************************************************************************************
02597         elif t=='textarea':
02598            if update or add:
02599               ncols=web['data_textarea_cols']
02600               if q.get('num_cols','')!='': ncols=q['num_cols']
02601               nrows=web['data_textarea_rows']
02602               if q.get('num_rows','')!='': nrows=q['num_rows']
02603               vv='<textarea cols="'+ncols+'" rows="'+nrows+'" spellcheck="true" name="'+csf+k+sw+dis+'">'
02604               vv+=vh1+'</textarea>'
02605            else:
02606               vv=vh
02607         # **********************************************************************************************
02608         elif t=='file':
02609            if update or add:
02610               vv='<input type="file" name="'+csf+k+sw+dis+'">'
02611            else:
02612               vv=vh
02613         # **********************************************************************************************
02614         elif t=='uoa':
02615            cm_module_uoa=q.get('cm_module_uoa','')
02616            cm_repo_uoa=q.get('cm_repo_uoa','')
02617 
02618            if q.get('cm_module_uoa_active','')!='' and 'cm_array_orig' in i:
02619               rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':q['cm_module_uoa_active']})
02620               if rg['cm_return']==0 and rg['cm_value']!=None: 
02621                  cm_module_uoa=rg['cm_value']
02622 
02623            if q.get('cm_repo_uoa_active','')!='' and 'cm_array_orig' in i:
02624               rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':q['cm_repo_uoa_active']})
02625               if rg['cm_return']==0 and rg['cm_value']!=None: 
02626                  cm_repo_uoa=rg['cm_value']
02627 
02628            if cm_module_uoa!='':
02629               if update or add:
02630                  if q.get('disable','')=='yes': 
02631                     vv='<input type="text" size="'+web['data_field_size']+'" spellcheck="false" name="'+csf+k+'" value="'+vh1+'" '+sw+dis+'>'
02632                  else:
02633                     vv='<select class="cm-select" name="'+csf+k+'"'+soc+sw+dis+'>\n'
02634 
02635                     vv+='<option value="">-</option>\n'
02636 
02637                     ii={}
02638                     ii['cm_run_module_uoa']=cm_module_uoa
02639                     if cm_repo_uoa!='': ii['cm_repo_uoa']=cm_repo_uoa
02640                     if len(choice)>0:
02641                        r={}
02642                        r['cm_mixed']=[]
02643                        for j in choice:
02644                            ii['cm_data_uoa']=j
02645                            ii['cm_action']='load'
02646                            rx=cm_kernel.access(ii)
02647                            if rx['cm_return']==0: 
02648                               r['cm_mixed'].append(rx)
02649                        r['cm_return']=0
02650                     else:
02651                        ii['cm_action']='list'
02652                        if q.get('cm_classes_uoa_from_key','')!='': ii['cm_classes_uoa']=[k]
02653                        elif len(q.get('cm_classes_from_data',{}))>0 and 'cm_array_orig' in i: 
02654                            for j in q['cm_classes_from_data']:
02655                                jj=q['cm_classes_from_data'][j]
02656 
02657                                rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':j})
02658                                if rg['cm_return']==0 and rg['cm_value']!=None: 
02659                                   if jj.get('cm_module_uoa','')!='':
02660                                      jx={}
02661                                      jx['cm_run_module_uoa']=jj['cm_module_uoa']
02662                                      jx['cm_data_uoa']=rg['cm_value']
02663                                      jx['cm_action']='load'
02664                                      rx=cm_kernel.access(jx)
02665                                      if rx['cm_return']==0:
02666                                         dc=rx['cm_data_obj']['cfg'].get('cm_classes_uoa',[])
02667                                         if len(dc)>0:
02668                                            ii['cm_classes_uoa']=dc
02669 
02670                        elif q.get('cm_classes_uoa_active','')!='' and 'cm_array_orig' in i: 
02671                            rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':q['cm_classes_uoa_active']})
02672                            if rg['cm_return']==0 and rg['cm_value']!=None: 
02673                               vxx=rg['cm_value']
02674                               if type(vxx)!=list and vxx!='': vxx=[vxx]
02675                               ii['cm_classes_uoa']=vxx
02676                        elif 'cm_classes_uoa' in q: ii['cm_classes_uoa']=q['cm_classes_uoa']
02677                        r=cm_kernel.access(ii)
02678 
02679                     # Prune by other class deps
02680                     deps=q.get('cm_class_dependencies_from_data',{})
02681                     if len(deps)>0:
02682                        deps_classes={}
02683 
02684                        for j in deps:
02685                            jj=deps[j]
02686 
02687                            rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':j})
02688                            if rg['cm_return']==0 and rg['cm_value']!=None: 
02689                               if jj.get('cm_module_uoa','')!='':
02690                                  jx={}
02691                                  jx['cm_run_module_uoa']=jj['cm_module_uoa']
02692                                  jx['cm_data_uoa']=rg['cm_value']
02693                                  jx['cm_action']='load'
02694                                  rx=cm_kernel.access(jx)
02695                                  if rx['cm_return']==0:
02696                                     dc=rx['cm_data_obj']['cfg'].get('cm_classes_uoa',[])
02697                                     if len(dc)>0:
02698                                        deps_classes[jj['cm_key']]=dc
02699 #                                       if k=='alchemist_plugin_code_uoa': 
02700 #                                          cm_kernel.print_for_web('<BR>deps_classes='+json.dumps(deps_classes))
02701 
02702                        if len(deps_classes)>0:
02703 #                          if k=='alchemist_plugin_code_uoa': print '<BR>xyz=',deps_classes
02704                           rz={}
02705                           rz['cm_mixed']=[]
02706                           rz['cm_return']=0
02707                           for j in r.get('cm_mixed',{}):
02708                               jx={}
02709                               jx['cm_run_module_uoa']=cm_module_uoa
02710                               jx['cm_data_uoa']=j['cm_uid']
02711                               jx['cm_action']='load'
02712                               rx=cm_kernel.access(jx)
02713                               if rx['cm_return']==0:  
02714                                  djx=rx['cm_data_obj']['cfg']
02715                                  kjx=djx.get('cm_dependencies',{})
02716                                  add=True
02717                                  for jy in kjx:
02718                                      if jy in deps_classes:
02719                                         found=False
02720                                         for jz in deps_classes[jy]:
02721                                             if jz in kjx[jy]: found=True; break
02722                                         if not found: add=False; break
02723                                  if add:
02724                                     rz['cm_mixed'].append(rx)
02725                           r=rz 
02726                     else:
02727                        deps=q.get('cm_real_dependencies_real_from_data',{})
02728                        if len(deps)>0:
02729 
02730                           deps_real={}
02731                           for j in deps:
02732                               jj=deps[j]
02733 
02734                               rg=cm_kernel.get_value_by_flattened_key({'cm_array':i['cm_array_orig'], 'cm_key':j})
02735                               if rg['cm_return']==0 and rg['cm_value']!=None: 
02736                                  deps_real[jj]=rg['cm_value']
02737 
02738                           if len(deps_real)>0:
02739                              rz={}
02740                              rz['cm_mixed']=[]
02741                              rz['cm_return']=0
02742                              for j in r.get('cm_mixed',[]):
02743                                  jx={}
02744                                  jx['cm_run_module_uoa']=cm_module_uoa
02745                                  jx['cm_data_uoa']=j['cm_uid']
02746                                  jx['cm_action']='load'
02747                                  rx=cm_kernel.access(jx)
02748                                  if rx['cm_return']==0:  
02749                                     djx=rx['cm_data_obj']['cfg']
02750                                     kjx=djx.get('cm_dependencies_real',{})
02751                                     add=True
02752                                     for jy in deps_real:
02753                                         if jy in kjx and kjx[jy]!=deps_real[jy]: 
02754                                            add=False
02755                                            break
02756                                     if add:
02757                                        rz['cm_mixed'].append(rx)
02758                              r=rz 
02759 
02760                     if r['cm_return']>0:
02761                        vv+='cM error: '+r['cm_error']
02762                     else:
02763                        selected=False
02764 
02765                        # Quickly scan to check if v is in the array
02766                        if v!='':
02767                           for xx in r['cm_mixed']:
02768                               x=xx['cm_uoa'];  xu=xx['cm_uid'];  xa=xx['cm_alias'];  xd=xx[view_and_sort]
02769                               if v==x or v==xu or v==xa: 
02770                                  selected=True
02771                                  break
02772 
02773                        first=True
02774                        choice=[]
02775                        zselected=''
02776                        for xx in sorted(r['cm_mixed'], key=lambda k: tuple(s.lower() if isinstance(s,basestring) else s for s in k[view_and_sort])):
02777                            x=xx['cm_uoa'];  xu=xx['cm_uid'];  xa=xx['cm_alias'];  xd=xx[view_and_sort]
02778                            choice.append(xu)
02779                            z=''
02780                            if selected:
02781                               if v!='' and (v==x or v==xu or v==xa): z=' SELECTED'; zselected=xu
02782                            elif q.get('force_select_first','')=='yes':
02783                               if first: z=' SELECTED'; first=False; zselected=xu
02784                            vv+='<option value="'+xu+'"'+z+'>'+xd+'</option>\n'
02785 
02786                        if zselected!='' and 'cm_cur_array' in i and type(i['cm_cur_array'])==dict:
02787                           i['cm_cur_array'][i['cm_cur_key']]=zselected
02788 
02789                     vv+='</select>\n'
02790 
02791                     su=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&browse_module_uoa='+cm_module_uoa+'&cm_subaction_add'
02792                     if i.get('hide_add_new_object','')!='yes':
02793                        vv+=' <small><i><a href="'+su+'" target="_blank">Add&nbsp;new&nbsp;object</a></i></small>'
02794               else:
02795                  if v!='':
02796 #                    lnk=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&browse_cid='+q['cm_module_uoa']+':'+str(v)+'&cm_subaction_view'
02797                     lnk=web['http_prefix']+'view_cid='+q['cm_module_uoa']+':'+str(v)
02798 #                    lnkm=web['http_prefix']+'cm_menu='+web['cm_menu_browse']+'&browse_cid='+ini['cfg']['cm_modules']['cm-module']+':'+q['cm_module_uoa']+'&cm_subaction_view'
02799 
02800                     if q.get('cm_view_as_text','')=='yes':
02801                        vv+='<a href="'+lnk+'">'
02802                     else:
02803                        vv+='<form action="'+lnk+'" method="post" accept-charset="utf-8">\n'
02804                        if 'cm_back_json' in i: vv+='<input type="hidden" name="cm_back_json" value="'+i['cm_back_json']+'">'
02805 
02806                     orig=q['cm_module_uoa']+':'+str(v)
02807 
02808                     m=''
02809                     # Load module
02810                     ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
02811                         'cm_action':'load',
02812                         'cm_data_uoa':q['cm_module_uoa'],
02813                         'cm_admin':i.get('cm_admin','')}
02814                     rm=cm_kernel.access(ii)
02815                     if rm['cm_return']>0:
02816 #                       vv+='<span style="color:red"><B><I>Module not found</I></B>'
02817                         vv+='<span style="color:red"><B><a href="'+lnk+'" target="_top">******</a></B></span>'
02818                     else:
02819                        # Load data
02820                        ii={'cm_run_module_uoa':q['cm_module_uoa'],
02821                            'cm_action':'load',
02822                            'cm_data_uoa':str(v),
02823                            'cm_admin':i.get('cm_admin','')}
02824                        rd=cm_kernel.access(ii)
02825                        if rd['cm_return']>0:
02826 #                          vv+='<span style="color:red"><B><I>'+q['cm_module_uoa']+':'+str(v)+' (not found)</I></B></span>'
02827                           vv+='<span style="color:red"><B><a href="'+lnk+'" target="_top">******</a></B></span>'
02828                        else:
02829                           x=''
02830                           if rm['cm_display_as_alias']=='' and rd['cm_display_as_alias']=='':
02831 
02832                              txt=rm['cm_uoa']+':'+rd['cm_uoa']
02833                              if q.get('cm_view_as_text','')=='yes':
02834                                 vv+='<span style="font-style:italic">'+rm['cm_uoa']+':'+rd['cm_uoa']+'</span>'
02835                              else:
02836                                 vv+='<input type="submit" class="cm-button" style="font-style:italic;color:red;" value="'+txt+'">'
02837                              vt=''
02838                           else:
02839                              if x!='': x+=' '
02840                              if rd['cm_display_as_alias']=='': 
02841                                 x+=rd['cm_uoa']
02842                              else:
02843                                 m1=rd['cm_display_as_alias']
02844 #                                   x+='&quot;'+m1[0].upper()+m1[1:]+'&quot;'
02845                                 x+=m1[0].upper()+m1[1:]
02846 
02847                              vt=x
02848                              if q.get('cm_view_as_text','')=='yes':
02849                                 vv+=u'<span style="">'+x+u'</span>'
02850                              else:
02851                                 vv+=u'<input type="submit" class="cm-button" value="'+x+u'">'
02852 
02853                     if q.get('cm_view_as_text','')=='yes':
02854                        vv+='</a>'
02855                     else:
02856                        vv+='</form>'
02857 
02858         q['dynamic_choice']=choice
02859         q['dynamic_choice_desc']=choice_desc
02860 
02861         cc=i.get('cm_disable_coloring', '')
02862 
02863         if cc!='yes':
02864            # If cost *************************************************************************
02865            if q.get('cost','')=='yes':
02866               stl='cm-round-table-cost'
02867               if q.get('cost_level','')!='':
02868                  stl+='-'+q['cost_level']
02869               vv1='<table class="'+stl+'"><TR><TD>'+vv+'</TD></TR></table>'
02870               vv=vv1
02871 
02872            # If state *************************************************************************
02873            if q.get('state','')=='yes':
02874               stl='cm-round-table-state'
02875               if q.get('state_level','')!='':
02876                  stl+='-'+q['state_level']
02877               vv1='<table class="'+stl+'"><TR><TD>'+vv+'</TD></TR></table>'
02878               vv=vv1
02879 
02880            # If characteristic *************************************************************************
02881            if q.get('characteristic','')=='yes':
02882               stl='cm-round-table-characteristic'
02883               if q.get('characteristic_level','')!='':
02884                  stl+='-'+q['characteristic_level']
02885               vv1='<table class="'+stl+'"><TR><TD>'+vv+'</TD></TR></table>'
02886               vv=vv1
02887 
02888            # If property *************************************************************************
02889            if q.get('property','')=='yes':
02890               stl='cm-round-table-property'
02891               if q.get('property_level','')!='':
02892                  stl+='-'+q['property_level']
02893               vv1='<table class="'+stl+'"><TR><TD>'+vv+'</TD></TR></table>'
02894               vv=vv1
02895 
02896         # If explore, parse commands *************************************************************************
02897         if q.get('explorable','')=='yes':
02898 
02899            if explore=='yes':
02900               # Visualize tuning dimension
02901               ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-choice'],
02902                   'cm_action':'prepare_tuning_dimension_for_web',
02903                   'key1':cs+k,
02904                   'key2':csf+k,
02905                   'key_ext':soc+sw+dis,
02906                   'form_name':'add_edit',
02907                   'form_explore':form_explore,
02908                   'cm_data_desc':q}
02909               ro=cm_kernel.access(ii)
02910               if ro['cm_return']>0: return ro
02911 
02912            vvx=q.get('explore_prefix','')
02913 
02914            if cc!='yes':
02915               stl='cm-round-table-explore'
02916               if q.get('explore_level','')!='':
02917                  stl+='-'+q['explore_level']
02918               elif form_explore_color!='':
02919                  stl+='-'+form_explore_color
02920               vv1='<table class="'+stl+'"><TR>'
02921               if vvx!='': vv1+='<TD>'+vvx+'</TD>'
02922               vv1+='<TD>'+vv+'</TD>'
02923               if explore=='yes': vv1+=ro['cm_string']
02924               vv1+='</TR></table>'
02925               vv=vv1
02926 
02927            # Add to explore state
02928            if explore=='yes' and q.get('explore_level','')==explore_level:
02929               ex={'index':cs+k, 'desc':q, 'choice':choice, 'value':v}
02930               if cs+k in form_explore: 
02931                  ex.update(form_explore[cs+k])
02932               explore_state.append(ex)
02933 
02934     elif add or update:
02935        #Just treat as text
02936        vv='<input type="text" spellcheck="false" name="'+csf+k+'" value="'+vh1+'">'
02937 
02938     if vv=='': vv=vh1
02939     if vt=='': vt=vv
02940 
02941 #    if k=='dataset_uoa': print d,q
02942 
02943     return {'cm_return':0, 'cm_value_html':vv, 'cm_value_text':vt}
02944 
02945 # ============================================================================
02946 def create_button_back(i):
02947 
02948     """
02949     Create 'back' button
02950 
02951     Input:  {
02952               cm_back_json    - array with previous cM state
02953             }
02954 
02955     Output: {
02956               cm_return  - return code >0 if error
02957             }
02958     """
02959 
02960     y=cm_kernel.check_cm_json({'cm_json':i['cm_back_json']})
02961     y['cm_action']=cm_action_index
02962 
02963     # Check styles, etc
02964     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
02965     else:
02966        return {'cm_return':1, 'cm_error':'web style is not defined'}
02967 
02968     s='<FORM ACTION="'+web['http_prefix']+'" METHOD="POST" NAME="web_browse" accept-charset="utf-8">'
02969     for k in y:
02970         if k!="cm_back":
02971            s+='<input type="hidden"  name="'+k+'"  value="'+str(y[k])+'">\n'
02972     s+='<input type="submit" class="cm-button" name="cm_button_back" value="Back">\n'
02973     s+='</FORM>'
02974     cm_kernel.print_for_web(s)
02975 
02976     return {'cm_return':0}
02977 
02978 # ============================================================================
02979 def create_button(i):
02980 
02981     """
02982     Create generic button
02983 
02984     Input:  {
02985               http_prefix - http prefix
02986               cm_text     - text to print
02987               cm_disabled - if 'yes', disable button
02988               cm_data     - adding to link
02989             }
02990 
02991     Output: {
02992               cm_return  - return code >0 if error
02993               cm_string  - html string
02994             }
02995     """
02996 
02997     if 'http_prefix' not in i: return {'cm_return':1, 'cm_error':'http_prefix is not defined in create_button'}
02998     pr=i['http_prefix'];
02999 
03000     t=''
03001     if 'cm_text' in i: t=i['cm_text'];
03002 
03003     z=' disabled="disabled" '
03004     if 'cm_disabled' not in i or i['cm_disabled']=="no": z=''
03005 
03006     s=''
03007     for k in i['cm_data']:
03008         if s!='': s+='&'
03009         s+=k+'='+i['cm_data'][k]
03010 
03011     return {'cm_return':0, 'cm_string':'<input type="button" class="cm-button" onclick="location.href=\''+pr+s+'\'" value="'+t+'"'+z+'>'}
03012 
03013 # ============================================================================
03014 def scenarios(i):
03015 
03016     """
03017     Show cM web scenarios
03018 
03019     Input:  {
03020               cm_submenu - scenario sub menu
03021             }
03022 
03023     Output: {
03024               cm_return  - return code >0 if error
03025             }
03026     """
03027 
03028     rr={'cm_return':0}
03029 
03030     # Check styles, etc
03031     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
03032     else:
03033        return {'cm_return':1, 'cm_error':'web style is not defined'}
03034 
03035     # Check if customized view
03036     cm=web.get('customized_module_scenarios','')
03037     # Select scenario
03038     if 'cm_submenu' not in i or i['cm_submenu']=='':
03039        cms=web['cm_menu_scenarios']
03040 
03041        if cm!='':
03042           # Load module
03043           ii={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-module'],
03044               'cm_action':'load',
03045               'cm_data_uoa':cm}
03046           r=cm_kernel.access(ii)
03047           if r['cm_return']>0: return r
03048 
03049           d=r['cm_data_obj']['cfg']
03050 
03051           if len(d.get('cm_menu_scenarios',{}))>0:
03052              cms=d['cm_menu_scenarios']
03053 
03054        # Show all scenarios
03055        ht={};fht={}
03056        ht["0"]=web['table_init']+'<TR><TD><ul>'
03057        ht["1"]=web['table_init']+'<TR><TD><ul>'
03058        fht["0"]=True
03059        fht["1"]=True
03060 
03061        for x in cms:
03062            text="Go"
03063            if 'menu_text' in x: text=x['menu_text']
03064 
03065            form="0"
03066            if 'menu_form' in x: form=x['menu_form']
03067 
03068            nw=''
03069            if x.get('open_in_new_window','')=='yes': nw=' target="_blank" '
03070 
03071            if 'menu_title_before' in x and x['menu_title_before']!='':
03072               if fht[form]: fht[form]=False
03073               else: ht[form]+='<BR><BR>'
03074               ht[form]+='<span class="cm-title">'+x['menu_title_before']+'</span><BR><BR>'
03075 #                 ht[form]+='<HR class="cm-hr">'
03076 
03077            show=True
03078            if x.get('only_for_admin','')=='yes':
03079               show=False
03080               if cm_kernel.ini['web_auth'].get('cm_admin','')=='yes':
03081                  show=True
03082            elif x.get('only_for_registered','')=='yes':
03083               show=False
03084               if cm_kernel.ini['web_auth'].get('cm_user_status','')=='logged_in' or \
03085                  cm_kernel.ini['web_auth'].get('cm_admin','')=='yes':
03086                  show=True
03087 
03088            if show:
03089               if x.get('menu_space_before','')=='yes':
03090                  ht[form]+='<BR><BR>'
03091 
03092               dc=''
03093               if 'direct_call_params' in x and len(x['direct_call_params'])>0:
03094                 for y in x['direct_call_params']:
03095                     if dc!='': dc+='&'
03096                     dc+=y+'='+str(x['direct_call_params'][y])
03097 
03098               if 'submenu' in x and x['submenu']!='': 
03099                  if dc!='': dc='&'+dc
03100                  ht[form]+='<li><a href="'+web['http_prefix']+'cm_menu=scenarios&cm_submenu='+x['submenu']+dc+'"'+nw+'>'+text+'</a>'
03101               else:
03102                 ht[form]+='<li><a href="'+web['http_prefix']+dc+'"'+nw+'>'+text+'</a>'
03103            else:
03104               if x.get('only_for_admin','')=='yes':
03105                  ht[form]+='<li><i><s>Only for admins</s></i>'
03106               else:
03107                  ht[form]+='<li><i><s>Only for registered users</s></i>'
03108 
03109        ht["0"]+='</ul></TD></TR></table>'
03110        ht["1"]+='</ul></TD></TR></table>'
03111 
03112        cm_kernel.print_for_web('<table border="0"><TR><TD valign="top" align="left">')
03113        cm_kernel.print_for_web(ht["0"])
03114        cm_kernel.print_for_web('</TD><TD valign="top" align="left">')
03115        cm_kernel.print_for_web(ht["1"])
03116        cm_kernel.print_for_web('</table>')
03117 
03118     else:
03119        found=False
03120        for x in web['cm_menu_scenarios']:
03121            if 'submenu' in x and x['submenu']==i['cm_submenu']:
03122               found=True
03123 
03124               if 'menu_module' in x and 'menu_action' in x:
03125                  ii={}; 
03126 #                 if 'direct_call_params' in x and len(x['direct_call_params'])>0:
03127 #                    ii=x['direct_call_params']
03128 #                    ii.update(i)
03129 #              else:
03130                  ii.update(i)
03131                  ii['cm_run_module_uoa']=x['menu_module']
03132                  ii['cm_action']=x['menu_action']
03133                  ii['cm_console']='web'
03134                  rr=cm_kernel.access(ii)
03135 #                 if rr['cm_return']>0: 
03136 #                    cm_kernel.print_for_web('<B>cM error:</B> '+rr['cm_error']+'<BR><BR>')
03137 
03138               else:
03139                  cm_kernel.print_for_con('<B>cM error:</B> wrong scenario description!<BR><BR>')
03140 
03141        if not found:
03142           cm_kernel.print_for_con('<B>cM error:</B> Submenu not found!<BR><BR>')
03143 
03144     if rr['cm_return']==0:
03145        cm_kernel.print_for_con('<FORM><INPUT TYPE="button" CLASS="cm-button" VALUE="Back" onClick="history.go(-1);return true;"></FORM>')
03146 
03147     return rr
03148 
03149 # ============================================================================
03150 def server(i):
03151 
03152     """
03153     Simple Web Server
03154 
03155     Input:  {
03156               cm_web_port  - web port
03157             }
03158 
03159     Output: {
03160               cm_return  - return code >0 if error
03161             }
03162     """
03163 
03164     cm_kernel.print_for_con("For now we can only start server indefinitely")
03165     cm_kernel.print_for_con("but we should add a nice start/stop/resume support one day ...")
03166 
03167     # Get default web configuration
03168     web=cm_kernel.ini['web_style'].get('cfg',{})
03169     if len(web)==0: 
03170        return {'cm_return':1, 'cm_error':'web style is not defined'}
03171 
03172     # Get default web host (or '' for localhost)
03173     host=web.get('cm_web_host','')
03174     if host=='':
03175        host=ini['cfg'].get('cm_default_web_host','')
03176 
03177     # Get default web port
03178     port=web.get('cm_web_port','')
03179     if port=='':
03180        port=ini['cfg'].get('cm_default_web_port','')
03181     if port=='':
03182        return {'cm_return':1, 'cm_error':'web port is not defined'}
03183 
03184     cm_kernel.print_for_con('')
03185     cm_kernel.print_for_con('Starting cM web server on default host and port '+port+' ...')
03186 
03187     try:
03188        server = ThreadedHTTPServer((host, int(port)), server_handler)
03189        # Prevent issues with socket reuse
03190        server.allow_reuse_address=True
03191        server.serve_forever()
03192     except KeyboardInterrupt:
03193        cm_kernel.print_for_con('Keyboard interrupt, terminating server ...')
03194        server.socket.close()
03195        return {'cm_return':1, 'cm_error':'web server was interrupted'}
03196     except OSError as e:
03197        return {'cm_return':1, 'cm_error':'problem starting web server ('+format(e)+')'}
03198 
03199     return {'cm_return':0}
03200 
03201 # ============================================================================
03202 class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
03203 
03204     """
03205     Class to handle requests in separate threads
03206     """
03207 
03208 # ============================================================================
03209 class server_handler(BaseHTTPRequestHandler):
03210 
03211     """
03212     Simple Web Server: request handler
03213 
03214     Input:  http handler
03215 
03216     Output: None
03217     """
03218 
03219     # Process only GET
03220     def do_GET(self):
03221         process_web_request({'http':self})
03222         return
03223      
03224     # Process GET and POST
03225     def do_POST(self):
03226         process_web_request({'http':self})
03227         return
03228 
03229     def log_request(self, code='-', size='-'):
03230         if cm_kernel.ini['dcfg'].get('log_web_requests','')=='yes':
03231            # logged by cM
03232            return
03233 
03234         self.log_message('"%s" %s %s',
03235                          self.requestline, str(code), str(size))
03236         return
03237 
03238     def log_error(self, format, *args):
03239         if cm_kernel.ini['dcfg'].get('log_web_requests','')=='yes':
03240            fn=os.path.join(cm_kernel.ini[cm_kernel.env_cm_root], cm_kernel.ini['dcfg']['log_dir'], cm_kernel.ini['dcfg']['log_web_server_errors'])
03241 
03242            q=''
03243            f=open(fn,'a')
03244            if os.fstat(f.fileno()).st_size>0: q=',\n'
03245            f.write("%s - - [%s] %s\n" %
03246                    (self.address_string(),
03247                     self.log_date_time_string(),
03248                     format%args))
03249            f.close()
03250            return
03251 
03252         self.log_message(format, *args)
03253         return
03254 
03255 # ============================================================================
03256 def process_web_request(ix):
03257 
03258 
03259     """
03260     Simple Web Server: process request
03261 
03262     Input:  {
03263               'http' : http object
03264             }
03265 
03266     Output: {
03267                Ignore
03268             }
03269     """
03270 
03271     # http object
03272     http=ix['http']
03273 
03274     # Check vars
03275     xget={}
03276     xput={}
03277 
03278     # Check GET
03279     if http.path!='':
03280        http.send_response(200)
03281 
03282        a=urlparse.urlparse(http.path)
03283        b=urlparse.parse_qs(a.query, keep_blank_values=True, )
03284 
03285        xget={}
03286        for k in b:
03287            xget[k]=b[k][0]
03288 
03289     # Check POST
03290     xpost={}
03291     xpost1={}
03292     try:
03293        ctype, pdict = cgi.parse_header(http.headers.getheader('content-type'))
03294 
03295        if ctype == 'multipart/form-data':
03296 #          print 'MULTIPART'
03297           xpost1 = cgi.parse_multipart(http.rfile, pdict)
03298        elif ctype == 'application/x-www-form-urlencoded':
03299           length = int(http.headers.getheader('content-length'))
03300           xpost1 = cgi.parse_qs(http.rfile.read(length), keep_blank_values=1)
03301     except:
03302        pass
03303 
03304     for k in xpost1:
03305         v=xpost1[k]
03306         if k.endswith('[]'): 
03307            k1=k[:-2]
03308            xpost[k1]=[]
03309            for l in v:
03310                xpost[k1].append(l)
03311         else: 
03312            xpost[k]=v[0]
03313 
03314     # Process cm_json
03315     if 'cm_json' in xpost:
03316        y=cm_kernel.check_cm_json({'cm_json':xpost['cm_json']})
03317        del (xpost['cm_json'])
03318        xpost.update(y)
03319 
03320     if 'cm_json' in xget:
03321        y=cm_kernel.check_cm_json({'cm_json':xget['cm_json']})
03322        del (xget['cm_json'])
03323        xget.update(y)
03324 
03325     # Process file upload
03326     if xpost.get('cm_file_upload_tmp_uid','')=='' and \
03327        ((('cm_file_upload' in xpost and len(xpost['cm_file_upload'])>0) or \
03328         ('cm_file_upload_base64' in xpost and len(xpost['cm_file_upload_base64'])>0) or \
03329         (form6+'##cm_file_upload' in xpost and len(xpost[form6+'##cm_file_upload'])>0)) or \
03330        (('cm_file_upload' in xget and len(xget['cm_file_upload'])>0) or \
03331         ('cm_file_upload_base64' in xget and len(xget['cm_file_upload_base64'])>0))):
03332 
03333        # Generate tmp file
03334        r=cm_kernel.gen_cm_tmp_file({})
03335        if r['cm_return']>0: return r
03336        tf=r['cm_path']
03337        uid=r['cm_uid']
03338 
03339        if form6+'##cm_file_upload' in xpost: 
03340           xn=xpost[form6+'##cm_file_upload']
03341           del(xpost[form6+'##cm_file_upload'])
03342           yn=form6+'##cm_file_upload_tmp_uid'
03343        elif 'cm_file_upload' in xpost: 
03344           xn=xpost['cm_file_upload']
03345           del(xpost['cm_file_upload'])
03346           yn='cm_file_upload_tmp_uid'
03347        elif 'cm_file_upload' in xget: 
03348           xn=xget['cm_file_upload']
03349           del(xget['cm_file_upload'])
03350           yn='cm_file_upload_tmp_uid'
03351        elif 'cm_file_upload_base64' in xpost:
03352           xn=base64.urlsafe_b64decode(str(xpost['cm_file_upload_base64'])) # convert from unicode to str since base64 works on strings
03353           del(xpost['cm_file_upload_base64'])
03354           yn='cm_file_upload_tmp_uid'
03355        elif 'cm_file_upload_base64' in xget:
03356           xn=base64.urlsafe_b64decode(str(xget['cm_file_upload_base64'])) # convert from unicode to str since base64 works on strings
03357           del(xget['cm_file_upload_base64'])
03358           yn='cm_file_upload_tmp_uid'
03359 
03360        fx=file(tf, 'wb')
03361        fx.write(xn)
03362        fx.close()
03363 
03364        xpost[yn]=uid
03365        
03366     # TBD: Read session 
03367     xsession={}
03368 
03369     # Read cookies
03370     xcookie={}
03371     if 'Cookie' in http.headers:
03372        c=Cookie.SimpleCookie(http.headers['Cookie'])
03373        for x in c:
03374            if c[x].value!='': xcookie[c[x].key]=c[x].value
03375 
03376     # Write log if needed
03377     if cm_kernel.ini['dcfg'].get('log_web_requests','')=='yes':
03378        request={}
03379        client_host, client_port = http.client_address[:2]
03380        request['client_host']=client_host
03381        request['client_port']=str(client_port)
03382        request['client_hostname']=http.address_string()
03383        request['client_date_time']=http.log_date_time_string()
03384        request['client_raw_requestline']=http.raw_requestline
03385        request['client_http_headers']={}
03386        kk=http.headers.keys()
03387        for q in kk:
03388            request['client_http_headers'][q]=http.headers[q]
03389        rx=cm_kernel.get_current_date_time({})
03390        request['server_iso_datetime']=rx['cm_iso_datetime']
03391        request['client_get']=xget
03392        request['client_post']={}
03393        kk=xpost.keys()
03394        for q in kk:
03395            if q!='cm_user_password' and q!='cm_user_password1' and q!='cm_user_password2' \
03396               and q!='cm_remote_user_password' and q!='cm_user_password_repeat' \
03397               and q!='#form2##cm_user_password_repeat' and q!='#form2##cm_user_password' \
03398               and not (q=='cm_array' and xpost[q].get('cm_user_password','')!=''):
03399               request['client_post'][q]=xpost[q]
03400 
03401        fn=os.path.join(cm_kernel.ini[cm_kernel.env_cm_root], cm_kernel.ini['dcfg']['log_dir'], cm_kernel.ini['dcfg']['log_web_server_requests'])
03402 
03403        q=''
03404        f=open(fn,'a')
03405        if os.fstat(f.fileno()).st_size>0: q=',\n'
03406        f.write(q+json.dumps(request, indent=2))
03407        f.close()
03408 
03409     # Force delete of cm_user_password2 which is used only in session or cookies
03410     if "cm_user_password2" in xpost: del(xpost['cm_user_password2'])
03411     if "cm_user_password2" in xget:  del(xget['cm_user_password2'])
03412 
03413     # Force delete of cm_admin - it can be only done internally
03414     if "cm_admin" in xpost:             del(xpost['cm_admin'])
03415     if "cm_admin" in xget:              del(xget['cm_admin'])
03416 
03417     # Preprocessing web request (we move most of the logic from php to cM python modules).
03418     # Later, it will be easier to use this functionality in cM standalone python web server.
03419     i={}
03420     i['cm_run_module_uoa']='web'
03421     i['cm_action']='preprocess'
03422     i['cm_console']='json'
03423     i['cm_web_session']=xsession
03424     i['cm_web_cookies']=xcookie
03425     i['cm_web_get']=xget
03426     i['cm_web_post']=xpost
03427     i['cm_web']='yes'
03428 
03429     # Pack username & password if in POST or SESSION
03430     if "cm_user_uoa" in xcookie:        i['cm_user_uoa']=xcookie['cm_user_uoa']
03431     if "cm_user_uoa" in xsession:       i['cm_user_uoa']=xsession['cm_user_uoa']
03432     if "cm_user_uoa" in xpost:          i['cm_user_uoa']=xpost['cm_user_uoa']
03433     if "cm_user_password" in xpost:     i['cm_user_password']=xpost['cm_user_password']
03434     if "cm_user_password1" in xpost:    i['cm_user_password1']=xpost['cm_user_password1']
03435     if "cm_user_password2" in xcookie:  i['cm_user_password2']=xcookie['cm_user_password2']
03436     if "cm_user_password2" in xsession: i['cm_user_password2']=xsession['cm_user_password2']
03437 
03438     # Check if detach console (only in the postprocessing)
03439     cdc=''
03440     if "cm_detach_console" in xpost: cdc=xpost["cm_detach_console"]; del(xpost["cm_detach_console"]) 
03441     if "cm_detach_console" in xget: cdc=xget["cm_detach_console"]; del(xget["cm_detach_console"]) 
03442 
03443     r=cm_kernel.access_fe_through_cmd(i)
03444 
03445     #Check console for output if errors!
03446     cm_console='web'
03447     if 'cm_console' in xget: cm_console=xget['cm_console']
03448     elif 'cm_console' in xpost: cm_console=xpost['cm_console']
03449 
03450     if 'cm_return' in r and r['cm_return']>0:
03451        http.send_header("Content-type", "text/html")
03452        http.end_headers()
03453        if cm_console=='json' or cm_console=='json_after_text':
03454           if cm_console=='json_after_text': http.wfile.write(cm_kernel.cm_json_with_text_sep+'\n')
03455           http.wfile.write(json.dumps(r)+'\n')
03456        else:
03457           http.wfile.write('<html><body><BR><B>cM error:</B> '+r['cm_error']+'!<BR></body></html>')
03458        return 1
03459     if 'cm_stderr' in r and r['cm_stderr']!='':
03460        http.send_header("Content-type", "text/html")
03461        http.end_headers()
03462        if cm_console=='json' or cm_console=='json_after_text':
03463           et='cM failure - please report to developers'
03464           if 'report_to_developers' in cm_kernel.ini['dcfg']: et+=' '+str(cm_kernel.ini['dcfg']['report_to_developers'])
03465           et+=':\n\n'
03466           if 'cm_stdout' in r and r['cm_stdout']!='': et+='STDOUT:\n'+r['cm_stdout']+'\n\n'
03467           et+='STDERR:\n'+r['cm_stderr']
03468           if cm_console=='json_after_text': http.wfile.write(cm_kernel.cm_json_with_text_sep+'\n')
03469           http.wfile.write(json.dumps({'cm_return':33, 'cm_error':et}))
03470        else:
03471           et='<html><body><BR><B>cM failure - please report to developers'
03472           if 'report_to_developers' in cm_kernel.ini['dcfg']: et+=' '+str(cm_kernel.ini['dcfg']['report_to_developers'])
03473           et+='</B>:<BR><BR>'
03474           if 'cm_stdout' in r and r['cm_stdout']!='': et+='<B>STDOUT:</B><BR><pre>'+r['cm_stdout']+'</pre><BR><BR>'
03475           et+='<B>STDERR:</B><BR><pre>'+r['cm_stderr']+'</pre></body></html>'
03476           http.wfile.write(et)
03477        return 1
03478 
03479     r=cm_kernel.check_cm_json({'cm_json':r['cm_stdout']})
03480     if (len(r)==0):
03481        http.send_header("Content-type", "text/html")
03482        http.end_headers()
03483        http.wfile.write('<br><b>cM front-end error:</B> can\'t parse json output during preprocessing!</b><br><br>')
03484        http.wfile.write('<pre><b>Module output:</b><br><br>')
03485        http.wfile.write(str(r['cm_stdout']))
03486        http.wfile.write(str(r['cm_stderr']))
03487        http.wfile.write('</pre><br>')
03488        return 1
03489     if 'cm_return' in r and r['cm_return']>0:
03490        http.send_header("Content-type", "text/html")
03491        http.end_headers()
03492        if cm_console=='json' or cm_console=='json_after_text':
03493           if cm_console=='json_after_text': http.wfile.write(cm_kernel.cm_json_with_text_sep+'\n')
03494           http.wfile.write(json.dumps(r)+'\n')
03495        else:
03496           http.wfile.write('<BR><B>cM error:</B> '+r['cm_error']+'!<BR>')
03497        return 1
03498     if 'cm_stderr' in r and r['cm_stderr']!='':
03499        http.send_header("Content-type", "text/html")
03500        http.end_headers()
03501        et='<html><body><BR><B>cM failure - please report to developers'
03502        if 'report_to_developers' in cm_kernel.ini['dcfg']: et+=' '+str(cm_kernel.ini['dcfg']['report_to_developers'])
03503        et+='</B>:<BR><BR>'
03504        if 'cm_stdout' in r and r['cm_stdout']!='': et+='<B>STDOUT:</B><BR><pre>'+r['cm_stdout']+'</pre><BR><BR>'
03505        et+='<B>STDERR:</B><BR><pre>'+r['cm_stderr']+'</pre></body></html>'
03506        http.wfile.write(et)
03507        return 1
03508 
03509     # Check if set or destroy session/cookies
03510     if r.get('cm_web_destroy_cookies','')=='yes' or \
03511        r.get('cm_web_destroy_session','')=='yes': 
03512        if 'cm_web_cookies' in r:
03513           vars=r['cm_web_cookies']
03514           for key in vars:
03515               c=Cookie.SimpleCookie()
03516               c[str(key)]=''
03517               c[str(key)]['max-age'] = 0
03518               http.send_header('Set-Cookie', c.output(header=''));
03519 
03520 #    if r.get('cm_web_destroy_session','')=='yes':
03521 #      $_SESSION = array()
03522 #      session_destroy()
03523 
03524     # Check if set cookies
03525     if r.get('cm_web_set_cookies','')=='yes':
03526        if 'cm_web_cookies' in r:
03527           vars=r['cm_web_cookies']
03528           time=604800
03529           if 'cm_web_cookies_expire_time' in r: time=r['cm_web_cookies_expire_time']
03530 
03531           for value in vars:
03532               c=Cookie.SimpleCookie()
03533               c[str(value[0])]=str(value[1])
03534               c[str(value[0])]['max-age'] = time
03535               http.send_header('Set-Cookie', c.output(header=''));
03536 
03537     # FGG TBD: NEED TO MAKE PROPER SESSION HANDLING (FOR NOW - JUST PUT EVERYTHING TO COOKIES)
03538     if r.get('cm_web_set_session','')=='yes':
03539        if 'cm_web_vars' in r:
03540           vars=r['cm_web_vars']
03541           time=604800
03542 
03543           for value in vars:
03544               c=Cookie.SimpleCookie()
03545               c[str(value[0])]=str(value[1])
03546               c[str(value[0])]['max-age'] = time
03547               http.send_header('Set-Cookie', c.output(header=''));
03548 
03549     # Check if set header
03550     if r.get('cm_web_set_headers','')=='yes':
03551       if 'cm_web_headers' in r:
03552          vars=r['cm_web_headers']
03553          for value in vars:
03554              value1=value.split(':', 1)
03555              http.send_header(value1[0].strip(), value1[1].strip())
03556 
03557     http.end_headers()
03558 
03559     # Check if download
03560     if r.get('cm_web_download','')=='yes':
03561        #read raw file
03562        if 'cm_full_filename' in r:
03563           if os.path.isfile(r['cm_full_filename']):
03564              s=''
03565              try:
03566                 f=open(r['cm_full_filename'], 'rb')
03567                 while True:
03568                    x = f.read(32768);
03569                    if not x: break
03570                    s+=x
03571                 f.close()
03572              except Exception as e:
03573                 cm_kernel.print_for_con('cM Error: '+format(e))
03574 
03575              http.wfile.write(s)
03576 
03577     # Check if need to delete file
03578     if r.get('cm_delete_file_after_view','')=='yes':
03579        if 'cm_full_filename' in r and r['cm_full_filename']!='':
03580           os.remove(r['cm_full_filename'])
03581 
03582     # Check if postprocess
03583     if r.get('cm_web_postprocess','')=='yes':
03584        # Postprocessing web request (we move most of the logic from php to cM python modules).
03585        # Later, it will be easier to use this functionality in cM standalone python web server.
03586        i1={}
03587        i1['cm_run_module_uoa']='web'
03588        i1['cm_action']='postprocess'
03589        i1['cm_web_preprocess_return']=r
03590        i1['cm_web_session']=xsession
03591        i1['cm_web_get']=xget
03592        i1['cm_web_post']=xpost
03593        i1['cm_web']='yes'
03594 
03595        # Pack username & password if in POST or SESSION
03596        if "cm_user_uoa" in xcookie:        i1['cm_user_uoa']=xcookie['cm_user_uoa']
03597        if "cm_user_uoa" in xsession:       i1['cm_user_uoa']=xsession['cm_user_uoa']
03598        if "cm_user_uoa" in xpost:          i1['cm_user_uoa']=xpost['cm_user_uoa']
03599        if "cm_user_password" in xpost:     i1['cm_user_password']=xpost['cm_user_password']
03600        if "cm_user_password1" in xpost:    i1['cm_user_password1']=xpost['cm_user_password1']
03601        if "cm_user_password2" in xcookie:  i1['cm_user_password2']=xcookie['cm_user_password2']
03602        if "cm_user_password2" in xsession: i1['cm_user_password2']=xsession['cm_user_password2']
03603 
03604        #Set console here!
03605        if 'cm_console' in xget: i1['cm_console']=xget['cm_console']
03606        elif 'cm_console' in xpost: i1['cm_console']=xpost['cm_console']
03607        else: i1['cm_console']='web'
03608 
03609        # Check console detaching
03610        if cdc!='': i1['cm_detach_console']=cdc
03611 
03612        r=cm_kernel.access_fe_through_cmd(i1)
03613 
03614        if r['cm_return']>0:
03615           http.wfile.write('<html><body><BR><B>cM error:</B> '+r['cm_error']+'!<BR></body></html>')
03616           return 1
03617 
03618        if r['cm_stdout']!='': http.wfile.write(r['cm_stdout'])
03619        if r['cm_stderr']!='': http.wfile.write(r['cm_stderr'])
03620 
03621     return
03622 
03623 # ============================================================================
03624 def prepare_content_header(i):
03625 
03626     """
03627     Prepare content header
03628 
03629     Input:  {
03630               (cm_web_content) - explicit type (jpg, etc)
03631               (cm_filename)    - filename
03632             }
03633 
03634     Output: {
03635               cm_return        - return code >0 if error
03636               cm_web_headers   - list of headers
03637             }
03638     """
03639 
03640     # Check styles, etc
03641     if 'cfg' in cm_kernel.ini['web_style']: web=cm_kernel.ini['web_style']['cfg']
03642     else:
03643        return {'cm_return':1, 'cm_error':'web style is not defined'}
03644 
03645     # Check if cm_web_contents exist
03646     if 'cm_web_contents' not in web:
03647        return {'cm_return':1, 'cm_error':'"cm_web_contents" is not in web interface entry'}
03648 
03649     # Check if file in the input
03650     filename=''
03651     if 'cm_filename' in i:
03652        filename=i['cm_filename'].strip()
03653 
03654     if 'cm_web_content' in i:
03655        c=i['cm_web_content']
03656     else:
03657        # Try to detect from the filename
03658        if filename=='':
03659           return {'cm_return':1, 'cm_error': '"cm_filename" not defined'}
03660 
03661        fn, c = os.path.splitext(filename)
03662 
03663     wh=[]
03664 
03665     # Prepare headers
03666     if c in web['cm_web_contents']:
03667        wh=web['cm_web_contents'][c]
03668     elif 'unknown' in web['cm_web_contents']:
03669        wh=web['cm_web_contents']['unknown']
03670     else:   
03671        return {'cm_return':1, 'cm_error':'can\'t detect content of the file'} 
03672 
03673     return {'cm_return':0, 'cm_web_headers':wh}
03674 
03675 # ============================================================================
03676 def show(i):
03677 
03678     """
03679     Show file from the repository or tmp directory.
03680     Only web preprocess!
03681 
03682     Input:  {
03683               cm_web_filename                 - file to show
03684               (cm_web_content)                - extension known by cM to prepare html header.
03685                                                 If not set, this function will try to detect
03686                                                 it from the cm_web_filename extension
03687               (cm_module_uoa and cm_data_uoa) - entry to take file from. 
03688                                                 If not set, file is taken from the temporary directory
03689               (cm_repo_uoa)                   - repo UOA
03690             }
03691 
03692     Output: {
03693               cm_return             - return code >0 if error
03694               cm_web_headers        - web headers
03695               cm_web_postprocess=no - force cM not to postprocess
03696 
03697             }
03698     """
03699 
03700     ii={}
03701 
03702     # Check input variables
03703     if 'cm_web_filename' not in i:
03704        return {'cm_return':1, 'cm_error':'"cm_web_filename" is not set'}
03705 
03706     fn, fe = os.path.splitext(i['cm_web_filename'])
03707     filename=os.path.basename(i['cm_web_filename'])
03708     fullfilename=i['cm_web_filename']
03709 
03710     # Find file for download
03711     if 'cm_data_uoa' in i and 'cm_module_uoa' in i:
03712        r1={'cm_module_uoa':i['cm_module_uoa'],
03713            'cm_data_uoa':i['cm_data_uoa']}
03714        if 'cm_repo_uoa' in i: r1['cm_repo_uoa']=i['cm_repo_uoa']
03715        
03716        r1['cm_run_module_uoa']=ini['cfg']['cm_modules']['cm-core']
03717        r1['cm_action']='load'
03718        r1['cm_web']='yes' # Forcing here to start web access control if on !
03719        r2=cm_kernel.access(r1)
03720        if r2['cm_return']>0: return r2
03721 
03722        p=r2['cm_path']
03723     else:
03724        # By default, use cM tmp directory
03725        p=cm_kernel.ini[cm_kernel.env_cm_tmp]
03726        ii['cm_delete_file_after_view']='yes' # for tmp files!
03727 
03728     # SECURITY
03729     # Check that doesn't have ../  etc ...
03730     p1=os.path.abspath(p)
03731     p2=os.path.abspath(os.path.join(p1, fullfilename))
03732 
03733     if not p2.startswith(p1):
03734        return {'cm_return':1, 'cm_error': 'security problem - filename points to external directories'}
03735 
03736     if not os.path.isfile(p2):
03737        return {'cm_return':1, 'cm_error': 'file not found'}
03738 
03739     ii['cm_full_filename']=p2
03740     ii['cm_web_download']='yes'
03741     ii['cm_web_set_headers']='yes'
03742 
03743     # Prepare content header
03744     ii1={}
03745     if 'cm_web_content' in i: ii1['cm_web_content']=i['cm_web_content']
03746     ii1['cm_filename']=filename
03747     r=prepare_content_header(ii1)
03748     if r['cm_return']>0: return r
03749 
03750     # Substitute special variables
03751     wh=[]
03752     for x in r['cm_web_headers']:
03753         wh.append(x.replace(cm_kernel.convert_str_to_special('filename'), filename))
03754 
03755     ii['cm_web_headers']=wh
03756 
03757     ii['cm_web_postprocess']='no'
03758     ii['cm_return']=0
03759 
03760     return ii
03761 
03762 # ============================================================================
03763 def show_html(i):
03764 
03765     """
03766     Show file from the repository or tmp directory.
03767 
03768     Input:  {
03769               cm_web_filename                 - file to show
03770               (cm_web_content)                - extension known by cM to prepare html header.
03771                                                 If not set, this function will try to detect
03772                                                 it from the cm_web_filename extension
03773               (cm_module_uoa and cm_data_uoa) - entry to take file from. 
03774                                                 If not set, file is taken from the temporary directory
03775             }
03776 
03777     Output: {
03778               cm_return             - return code >0 if error
03779             }
03780     """
03781 
03782     r=show(i)
03783     if r['cm_return']>0: return r
03784 
03785     if not os.path.isfile(r['cm_full_filename']):
03786        return {'cm_return':1, 'cm_error':'can\'t find file'}
03787 
03788     f=file(r['cm_full_filename'],'r')
03789 
03790     cm_kernel.print_for_con('<div align="left">')
03791     while True:
03792         line = f.readline()
03793         if not line: break
03794         line=line.rstrip('\r\n')
03795         cm_kernel.print_for_web(line)
03796     f.close()
03797     cm_kernel.print_for_con('</div>')
03798 
03799     cm_kernel.print_for_con('<BR><HR class="cm-hr">')
03800     return {'cm_return':0}
03801 
03802 # ============================================================================
03803 def download(i):
03804 
03805     """
03806     Download data entry
03807 
03808     Input:  {
03809               cm_run_module_uoa | cm_module_uoa - module UOA
03810               cm_data_uoa                       - data UOA 
03811               (cm_repo_uoa)                     - repo UOA
03812               cm_all_files                      - if 'yes', download .cm description files 
03813                                                   this is needed for the future cloning of repositories
03814                                                   to avoid using all the time SVN/GIT for simple sharing ...
03815             }
03816 
03817     Output: {
03818               cm_return   - return code >0 if error
03819               ...         - various parameters to set http headers, etc
03820             }
03821     """
03822 
03823     ii={}
03824 
03825     # Load data to check if there is already archive
03826     r1={'cm_run_module_uoa':ini['cfg']['cm_modules']['cm-core'],
03827         'cm_action':'load'}
03828     if 'cm_data_uoa' in i: r1['cm_data_uoa']=i['cm_data_uoa']
03829     if 'cm_module_uoa' in i: r1['cm_module_uoa']=i['cm_module_uoa']
03830     if 'cm_repo_uoa' in i: r1['cm_repo_uoa']=i['cm_repo_uoa']
03831     if 'cid' in i: r1['cid']=i['cid']
03832     r2=cm_kernel.access(r1)
03833     if r2['cm_return']>0: return r2
03834 
03835     d=r2['cm_data_obj']
03836     p=r2['cm_path']
03837 
03838     # Check if it's cM zip archive already, otherwise archive directory
03839     if i.get('cm_all_files','')!='yes' and d['cfg'].get('cm_archive','')=='already_archived_with_internal_name':
03840        ii['cm_delete_file_after_view']='no'
03841        # Already cM archive in 1 file cm_archive.zip, just copy
03842        tf=os.path.join(p, cm_kernel.ini['dcfg']['cm_archive_filename'])
03843        if not os.path.isfile(tf):
03844           return {'cm_return':1, 'cm_error':'archive file not found in data entry'}
03845     elif i.get('cm_all_files','')!='yes' and d['cfg'].get('cm_archive','')=='already_archived_with_user_name' and d['cfg'].get('cm_file_upload_name','')!='':
03846        ii['cm_delete_file_after_view']='no'
03847        # Already cM archive in 1 file cm_archive.zip, just copy
03848        tf=os.path.join(p, d['cfg'].get('cm_file_upload_name',''))
03849        if not os.path.isfile(tf):
03850           return {'cm_return':1, 'cm_error':'archive file not found in data entry'}
03851     else:
03852        ii['cm_delete_file_after_view']='yes' # for tmp files!
03853 
03854        # Generate tmp file
03855        r=cm_kernel.gen_cm_tmp_file({})
03856        if r['cm_return']>0: return r
03857        tf=r['cm_path']
03858        uid=r['cm_uid']
03859        zip_method=zipfile.ZIP_DEFLATED
03860 
03861        # Prepare list of files
03862        filelist=[]
03863        if i.get('cm_all_files','')!='yes' and 'cm_files' in d['cfg']: 
03864           filelist=d['cfg']['cm_files']
03865        else:
03866           # Make list of files
03867           ii={'cm_path':p}
03868           if 'cm_all_files' in i: ii['cm_all_files']=i['cm_all_files']
03869           r=cm_kernel.get_list_of_all_files(ii)
03870           if r['cm_return']>0: return r
03871           filelist=r['cm_array']
03872 
03873        # Prepare archive
03874        try:
03875           f=file(tf, 'wb')
03876           z=zipfile.ZipFile(f, 'w', zip_method)
03877           for fn in filelist:
03878               p1=os.path.join(p, fn)
03879               z.write(p1, fn, zip_method)
03880           z.close()
03881           f.close()
03882 
03883        except Exception as e:
03884           return {'cm_return':1, 'cm_error':'failed to prepare archive ('+format(e)+')'}
03885 
03886     ii['cm_full_filename']=tf
03887 
03888     ii['cm_web_download']='yes'
03889     ii['cm_web_set_headers']='yes'
03890 
03891     # Prepare upload file name
03892     upload_file_name=cm_kernel.ini['dcfg']['cm_archive_filename']
03893     if i.get('cm_all_files','')!='yes' and (d['cfg'].get('cm_archive','')=='already_archived_with_user_name' and \
03894           d['cfg'].get('cm_file_upload_name','')!=''):
03895        upload_file_name=d['cfg'].get('cm_file_upload_name','')
03896 
03897     # Prepare content header
03898     ii1={'cm_web_content':'.zip',
03899          'cm_filename':upload_file_name}
03900     r=prepare_content_header(ii1)
03901     if r['cm_return']>0: return r
03902 
03903     # Substitute special variables
03904     wh=[]
03905     for x in r['cm_web_headers']:
03906         wh.append(x.replace(cm_kernel.convert_str_to_special('filename'), upload_file_name))
03907 
03908     ii['cm_web_headers']=wh
03909 
03910     ii['cm_web_postprocess']='no'
03911     ii['cm_return']=0
03912 
03913     return ii
03914 
03915 # ============================================================================
03916 def logout(i):
03917 
03918     """
03919     Example of loging out and destroying cookies if needed.
03920     Only web preprocess!
03921 
03922     Input:  { TBD
03923             }
03924 
03925     Output: {
03926               cm_return             - return code >0 if error
03927               cm_web_headers        - web headers
03928               cm_web_postprocess=no - force cM not to postprocess
03929 
03930             }
03931     """
03932 
03933     ii={}
03934 
03935     ii['cm_web_destroy_session']='yes'
03936 
03937     ii['cm_web_destroy_cookies']='yes'
03938     ii['cm_web_cookies']=['cm_user_uoa',
03939                           'cm_user_password2']
03940 
03941     ii['cm_web_set_headers']='yes'
03942 #    ii['cm_web_headers']=['Location: http://www.yahoo.com']
03943 
03944     ii['cm_web_postprocess']='no'
03945     ii['cm_return']=0
03946 
03947     # Set default user if needed
03948     r=cm_kernel.auth_user_and_ini_cm({})
03949     # ignore output
03950 
03951     return ii
03952 
03953 # ============================================================================
03954 def login(i):
03955 
03956     """
03957     Example of loging in and saving cookies if needed.
03958     Only web preprocess!
03959 
03960     Input:  { TBD
03961             }
03962 
03963     Output: {
03964               cm_return             - return code >0 if error
03965               cm_web_headers        - web headers
03966               cm_web_postprocess=no - force cM not to postprocess
03967 
03968             }
03969     """
03970 
03971     # Check if auth is on
03972     if cm_kernel.ini['dcfg'].get('allow_web_user_auth','')!='yes' and \
03973        cm_kernel.ini['dcfg'].get('force_web_login','')!='yes':
03974        return {'cm_return':1, 'cm_error':'authentication is disabled'}
03975 
03976     ii1={}
03977     if 'cm_user_uoa' in i: ii1['cm_user_uoa']=i['cm_user_uoa']
03978     if 'cm_user_password' in i: ii1['cm_user_password']=i['cm_user_password']
03979     if 'cm_user_password1' in i: ii1['cm_user_password1']=i['cm_user_password1']
03980     if 'cm_user_password2' in i: ii1['cm_user_password2']=i['cm_user_password2'] # Only in web environment
03981     ii1['cm_web']='yes'
03982     r=cm_kernel.auth_user_and_ini_cm(ii1)
03983     if r['cm_return']>0: return r
03984 
03985     ii={}
03986 
03987     ii['cm_web_set_session']='yes'
03988     ii['cm_web_vars']=[['cm_user_uoa', i['cm_user_uoa']]]
03989     if 'cm_user_password1' in r: ii['cm_web_vars'].append(['cm_user_password1', r['cm_user_password1']]) 
03990 
03991     if 'cm_web_set_cookies' in i and i['cm_web_set_cookies']=='yes':
03992        ii['cm_web_set_cookies']='yes'
03993        ii['cm_web_cookies']=[['cm_user_uoa', i['cm_user_uoa']]]
03994        if 'cm_user_password2' in r: ii['cm_web_cookies'].append(['cm_user_password2', r['cm_user_password2']]) 
03995        if 'cm_web_cookies_expire_time' in i and i['cm_web_cookies_expire_time']!='':
03996           ii['cm_web_cookies_expire_time']=i['cm_web_cookies_expire_time']
03997 
03998     ii['cm_web_set_headers']='yes'
03999 #    ii['cm_web_headers']=['Location: http://www.google.com']
04000 
04001     ii['cm_web_postprocess']='no'
04002     ii['cm_return']=0
04003 
04004     return ii
04005 
04006 # ============================================================================
04007 def preprocess_web_request(i):
04008 
04009     """
04010     Preprocess web request (convert $_GET and $_POST into one array and envoke cM module)
04011 
04012     Input:  {
04013               (cm_web_session)    - $_SESSION
04014               (cm_web_get)        - $_GET
04015               (cm_web_post)       - $_POST
04016               (cm_web_cookie)     - cookies
04017               (cm_user_uoa)       - user UOA
04018               (cm_user_password)  - user password in plain text 
04019                                     (not secure, usually used for web form authentication)
04020               (cm_user_password1) - user password in SHA1
04021                                     (more secure, can be stored in environment, session or cookies)
04022                                      cM authenicates by taking SHA1(cm_user_password1)...
04023 
04024               (cm_web_module_uoa) - module to envoke
04025               (cm_web_action)     - action for the module
04026             }
04027 
04028     Output: {
04029               cm_return  - return code >0 if error
04030               ...        - output from the envoked module
04031             }
04032     """
04033 
04034     # Prepare call (flatten $_GET & $_POST)
04035     ii={};
04036     if 'cm_web_session' in i: ii['cm_web_session']=i['cm_web_session']
04037     if 'cm_web_cookie' in i:  ii['cm_web_cookie']=i['cm_web_cookie']
04038     if 'cm_web_get' in i and i['cm_web_get']!=None:
04039        ii['cm_web_get']=cm_kernel.check_cm_json(i['cm_web_get'])
04040        ii.update(ii['cm_web_get']) # We merge cm_web_get with ii and keep also it separately if function needs it later
04041     if 'cm_web_post' in i and i['cm_web_post']!=None: 
04042        ii.update(cm_kernel.check_cm_json(i['cm_web_post']))
04043 
04044     # Check user and password
04045     if 'cm_user_uoa' in i: ii['cm_user_uoa']=i['cm_user_uoa']
04046     if 'cm_user_password1' in i: ii['cm_user_password1']=i['cm_user_password1']
04047     if 'cm_user_password2' in i: ii['cm_user_password2']=i['cm_user_password2']
04048 
04049     # Check main module and action
04050     cm_module_uoa=''
04051     cm_action=''
04052     if 'cm_web_module_uoa' in ii: cm_module_uoa=ii['cm_web_module_uoa']
04053     if 'cm_web_action' in ii: cm_action=ii['cm_web_action']
04054 
04055     # If module and action is not defined, use default
04056     if cm_module_uoa=='': cm_module_uoa=ini['cm_module_uoa']
04057     if cm_action=='': cm_action=cm_action_index
04058 
04059     cm_menu=''
04060     if 'cm_menu' in i: cm_menu=i['cm_menu']
04061 
04062     # Prepare module/action to call
04063     ii['cm_run_module_uoa']=cm_module_uoa
04064     ii['cm_action']=cm_action
04065     ii['cm_web_preprocess']='yes'
04066 
04067     # Set that web environment
04068     ii['cm_web']='yes'
04069 
04070     # Check auth and forward to login page if needed
04071     if cm_kernel.ini['dcfg'].get('force_web_login','')=='yes':
04072        cm_data_uoa=''
04073        if 'cm_data_uoa' in ii: cm_data_uoa=ii['cm_data_uoa']
04074        if (cm_module_uoa==ini['cm_module_uoa'] or cm_module_uoa==ini['cm_module_uid']) and \
04075           ((cm_action==cm_action_index and (cm_menu==cm_menu_login or cm_menu==cm_menu_logout)) or \
04076            (cm_action==cm_action_show and cm_data_uoa==cm_data_uoa_default)):
04077           # Allow access for login, logout or show images and html from default web for the first page
04078           pass
04079        else:
04080           rx=cm_kernel.auth_user(ii)
04081           if rx['cm_return']>0: 
04082 #             # If not web, quit
04083 #             if ii.get('cm_console','')!='web': return rx
04084              # Otherwise redirect to login page
04085              ii['cm_run_module_uoa']=ini['cm_module_uoa']
04086              ii['cm_action']=cm_action_index
04087              ii['cm_menu']=cm_menu_login 
04088 
04089     return cm_kernel.access(ii) # Access but don't process output
04090 
04091 # ============================================================================
04092 def postprocess_web_request(i):
04093 
04094     """
04095     Postprocess web request
04096 
04097     Input:  {
04098               (cm_web_session)    - $_SESSION
04099               (cm_web_get)        - $_GET
04100               (cm_web_post)       - $_POST
04101               (cm_web_cookie)     - cookies
04102               (cm_user_uoa)       - user UOA
04103               (cm_user_password)  - user password in plain text 
04104                                     (not secure, usually used for web form authentication)
04105               (cm_user_password1) - user password in SHA1
04106                                     (more secure, can be stored in environment, session or cookies)
04107                                      cM authenicates by taking SHA1(cm_user_password1)...
04108 
04109               (cm_web_module_uoa) - module to envoke
04110               (cm_web_action)     - action for the module
04111             }
04112 
04113     Output: {
04114               cm_return  - return code >0 if error
04115             }
04116     """
04117 
04118     # Prepare call
04119     ii={};
04120     if 'cm_web_session' in i: ii['cm_web_session']=i['cm_web_session']
04121     if 'cm_web_cookie' in i:  ii['cm_web_cookie']=i['cm_web_cookie']
04122     if 'cm_web_get' in i and i['cm_web_get']!=None: 
04123        ii['cm_web_get']=cm_kernel.check_cm_json(i['cm_web_get'])
04124        ii.update(ii['cm_web_get']) # We merge cm_web_get with ii and keep also it separately if function needs it later
04125     if 'cm_web_post' in i and i['cm_web_post']!=None: 
04126        ii.update(cm_kernel.check_cm_json(i['cm_web_post']))
04127 
04128     # Check user and password
04129     if 'cm_user_uoa' in i: ii['cm_user_uoa']=i['cm_user_uoa']
04130     if 'cm_user_password1' in i: ii['cm_user_password1']=i['cm_user_password1']
04131     if 'cm_user_password2' in i: ii['cm_user_password2']=i['cm_user_password2']
04132 
04133     # Check main module, action and output
04134     cm_module_uoa=''
04135     cm_action=''
04136     if 'cm_web_module_uoa' in ii: cm_module_uoa=ii['cm_web_module_uoa']
04137     if 'cm_web_action' in ii: cm_action=ii['cm_web_action']
04138 
04139     # If module and action is not defined, use default
04140     if cm_module_uoa=='': cm_module_uoa=ini['cm_module_uoa']
04141     if cm_action=='': cm_action=cm_action_index
04142 
04143     cm_menu=''
04144     if 'cm_menu' in i: cm_menu=i['cm_menu']
04145 
04146     # Prepare module/action to call
04147     ii['cm_run_module_uoa']=cm_module_uoa
04148     ii['cm_action']=cm_action
04149 
04150     # Set that web environment
04151     ii['cm_web']='yes'
04152 
04153     # Check console
04154     cm_console=''
04155     if 'cm_console' in i: cm_console=i['cm_console']
04156 
04157     # Check auth and quit if needed
04158     if cm_kernel.ini['dcfg'].get('force_web_login','')=='yes':
04159        cm_data_uoa=''
04160        if 'cm_data_uoa' in ii: cm_data_uoa=ii['cm_data_uoa']
04161        if (cm_module_uoa==ini['cm_module_uoa'] or cm_module_uoa==ini['cm_module_uid']) and \
04162           ((cm_action==cm_action_index and (cm_menu==cm_menu_login or cm_menu==cm_menu_logout)) or \
04163            (cm_action==cm_action_show and cm_data_uoa==cm_data_uoa_default)):
04164           # Allow access for login, logout or show images and html from default web for the first page
04165           pass
04166        else:
04167           rx=cm_kernel.auth_user(ii)
04168           if rx['cm_return']>0: 
04169              # If not web, quit
04170              if cm_console!='web': return rx
04171              # Otherwise redirect to login page
04172              ii['cm_run_module_uoa']=ini['cm_module_uoa']
04173              ii['cm_action']=cm_action_index
04174              ii['cm_menu']=cm_menu_login 
04175 
04176     return cm_kernel.access(ii) # Access and process output
04177 
04178 # ============================================================================
04179 def separate_common_from_data(i):
04180 
04181     """
04182     Separate common variables from data entry
04183 
04184     Input:  {
04185               cm_array1 - array with data from entry
04186               cm_array2 - array where common data will be moved
04187               cm_key    - key to remove
04188             }
04189 
04190     Output: {
04191               cm_return  - return code >0 if error
04192             }
04193     """
04194 
04195     d=i['cm_array1']
04196     common=i['cm_array2']
04197     key=i['cm_key']
04198 
04199     if key in cm_kernel.ini['dcfg']: 
04200        for k in cm_kernel.ini['dcfg'][key]:
04201            if k.startswith('##'): k=k[2:]
04202            if k in d:
04203               common[k]=copy.deepcopy(d[k])
04204               del(d[k])
04205 
04206     return {'cm_return':0}
04207 
04208 # ============================================================================
04209 def detect_form_params(i):
04210 
04211     """
04212     Detect various parameters (commands) in cM web forms 
04213 
04214     Input:  {
04215               cm_array  - array of form #prefix#var or #prefix@command
04216               cm_prefix - prefix
04217             }
04218 
04219     Output: {
04220               cm_return   - return code >0 if error
04221               cm_array    - parsed array with keys
04222               cm_commands - parsed array with commands
04223               cm_explore  - parsed array with exploration dimensions
04224             }
04225     """
04226 
04227     if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not defined in web/detect_param_forms'}
04228 
04229     a={}
04230     b={}
04231     e={}
04232 
04233     c=i['cm_array']
04234 
04235     prefix=i.get('cm_prefix','')
04236     prefix1=prefix+'#'
04237 
04238     for k in c:
04239         cc=c[k]
04240         if k.startswith("@"): 
04241            j=string.find(k, '@', 1)
04242            if j!=-1:
04243               command=k[1:j]
04244               k=k[j+1:]
04245               if prefix=='' or (prefix!='' and k.startswith(prefix1)):
04246                  if prefix!='' and k.startswith(prefix1): k1=k[len(prefix):]
04247                  if command=='new_dict_key':
04248                     if cc!='':
04249                        if k1 not in b: b[k1]={}
04250                        b[k1]['key']=cc
04251                  elif command.startswith('explore_'):
04252                     command1=command[8:]
04253                     if k1 not in e: e[k1]={}
04254                     e[k1][command1]=cc
04255                  else:
04256                     if k1 not in b: b[k1]={}
04257                     b[k1]['command']=command
04258 
04259         else:
04260            if prefix=='' or (prefix!='' and k.startswith(prefix1)):
04261               if prefix!='' and k.startswith(prefix1): k1=k[len(prefix):]
04262               a[k1]=c[k]
04263 
04264     return {'cm_return':0, 'cm_array':a, 'cm_commands': b, 'cm_explore': e}

Generated on Wed May 28 02:49:02 2014 for Collective Mind Framework by DoxyGen 1.6.1
Concept, design and coordination: Grigori Fursin (C) 1993-2013