00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 import imp
00011 import sys
00012 import os
00013 import json
00014 import uuid
00015 import random
00016 import re
00017 import datetime
00018 import string
00019 import urllib2
00020 import json
00021 import shutil
00022 import tempfile
00023 import subprocess
00024 import time
00025 import signal
00026 import hashlib
00027 import cgi
00028 import base64
00029 import copy
00030 import getpass
00031 import zipfile
00032 import shlex
00033 import platform
00034
00035
00036
00037
00038
00039
00040
00041 env_cm_root='CM_ROOT'
00042 env_cm_bin='CM_BIN'
00043 env_cm_tmp='CM_TMP'
00044 env_cm_cfg='CM_DEFAULT_CFG'
00045 env_cm_cfg_path='CM_DEFAULT_CFG_PATH'
00046 env_cm_default_repo='CM_DEFAULT_REPO'
00047 env_cm_local_repo='CM_LOCAL_REPO'
00048 env_cm_user_uoa='CM_USER_UOA'
00049 env_cm_user_password='CM_USER_PASSWORD'
00050 env_cm_user_password1='CM_USER_PASSWORD1'
00051 env_cm_remote_repo_proxy_http='CM_REMOTE_REPO_PROXY_HTTP'
00052 env_cm_remote_repo_proxy_https='CM_REMOTE_REPO_PROXY_HTTPS'
00053
00054 var_cm_info='.cm'
00055 var_cm_data='data.json'
00056 var_cm_cfg_local='local'
00057 var_cm_cfg_default='default'
00058
00059 cm_module_default='core'
00060 cm_module_default_access='access'
00061 cm_action_default='default'
00062 cm_unparsed_sep='--'
00063
00064 cm_json_with_text_sep='*** ### --- CM JSON SEPARATOR --- ### ***'
00065
00066 ini={
00067
00068
00069
00070
00071 'init':-1,
00072 'loaded_module_by_path':{},
00073 'loaded_module_by_path_last_modification':{},
00074 'loaded_data_by_path':{},
00075 'loaded_data_by_path_last_modification':{},
00076 'pcfg':'',
00077 'cfg':{},
00078 'dcfg':{},
00079 'path':'',
00080 'web':'no',
00081 'web_auth':{},
00082 'web_style':{},
00083 'remote_repo':{}
00084 }
00085
00086
00087 cm_kernel=None
00088
00089 print_on=True
00090
00091
00092 def init(i):
00093
00094 """
00095 Module init
00096
00097 Input: {}
00098
00099 Output: {
00100 cm_return - return code = 0, if successful
00101 (cm_error) - error text if return code > 0
00102 }
00103 """
00104
00105 global cm_kernel, ini
00106
00107
00108 if cm_kernel==None:
00109 cm_kernel=sys.modules[__name__]
00110
00111
00112 if not env_cm_cfg in os.environ.keys() and not env_cm_cfg_path in os.environ.keys():
00113 return {'cm_return':1, 'cm_error':'neither of environment variables '+env_cm_cfg+' and '+env_cm_cfg_path+' are defined!'}
00114
00115 pcfg=''
00116 if env_cm_cfg in os.environ.keys() and os.environ[env_cm_cfg]!='':
00117 pcfg=os.environ[env_cm_cfg]
00118 elif env_cm_cfg_path in os.environ.keys() and os.environ[env_cm_cfg_path]!='':
00119 p=os.path.join(os.environ[env_cm_cfg_path], var_cm_cfg_local, var_cm_info, var_cm_data)
00120 if os.path.isfile(p): pcfg=p
00121 else:
00122 p=os.path.join(os.environ[env_cm_cfg_path], var_cm_cfg_default, var_cm_info, var_cm_data)
00123 if os.path.isfile(p): pcfg=p
00124
00125 if pcfg=='':
00126 return {'cm_return':1, 'cm_error':'can\'t detect default kernel config file'}
00127
00128 r=load_json_file({'cm_filename':pcfg})
00129 if r['cm_return']>0: return r
00130
00131 ini['dcfg']=r['cm_array']
00132 ini['pcfg']=pcfg
00133
00134
00135 if env_cm_root in os.environ.keys():
00136 ini[env_cm_root]=os.environ[env_cm_root]
00137 else:
00138 return {'cm_return':1, 'cm_error':'environment variable '+env_cm_root+' is not defined!'}
00139
00140
00141 if env_cm_bin in os.environ.keys():
00142 ini[env_cm_bin]=os.environ[env_cm_bin]
00143 else:
00144 ini[env_cm_bin]=os.path.normpath(os.path.join(ini[env_cm_root], ini['dcfg']['bin_dir']))
00145
00146
00147 if env_cm_tmp in os.environ.keys():
00148 ini[env_cm_tmp]=os.environ[env_cm_tmp]
00149 else:
00150 return {'cm_return':1, 'cm_error':'environment variable '+env_cm_tmp+' is not defined!'}
00151
00152
00153 if env_cm_local_repo in os.environ.keys():
00154 ini['cm_local_repo']=os.path.normpath(os.environ[env_cm_local_repo])
00155
00156
00157 if env_cm_default_repo in os.environ.keys():
00158 ini['cm_default_repo']=os.path.normpath(os.environ[env_cm_default_repo])
00159 else:
00160 ini['cm_default_repo']=os.path.normpath(os.path.join(ini[env_cm_root], ini['dcfg']['cm_default_repo_path'], ini['dcfg']['cmr_ext']))
00161
00162 return {'cm_return':0}
00163
00164
00165 def is_windows():
00166 """
00167 Is Windows?
00168
00169 Input: None
00170
00171 Output: True if Windows
00172 """
00173
00174 win=False
00175
00176 if platform.system().lower().startswith('win'):
00177 win=True
00178
00179 return win
00180
00181
00182 def load_data(i):
00183 """
00184 Load and cache cM data
00185
00186 Input: {
00187 cm_module_uoa - UOA of the module
00188 cm_data_uoa - UOA of the data
00189 (cm_path) - path to repository
00190 (cm_path_array) - array of paths to search
00191 (lock_acquire) - if 'yes', acquire lock
00192 (lock_retry_num) - number of retries to acquire lock (default=6)
00193 (lock_retry_delay) - delay in sec before retrying to acquire lock (default=11)
00194 (lock_expire) - for how long to acquire lock (secs)
00195 (unlock_uid) - unlock data (FGG note: I changed lock_uid to unlock_uid
00196 not to interfere with update locking)
00197 (cm_admin) - if 'yes', override access control - only internal use,
00198 can not be used during web access (explicitly removed)
00199 }
00200
00201 Output: {
00202 cm_return - return code = 0, if successful
00203 (cm_error) - error text if return code > 0
00204 cm_data_obj - cM data object
00205 cm_path - path to data entry
00206 cm_path_module - path to module entry with this entry
00207 cm_path_repo - path to the repository of this entry
00208 cm_uid - uid (from UOA)
00209 cm_alias - alias (from UOA)
00210 cm_uoa - cm_data_uoa (alias or uid if alias=='')
00211 cm_module_uoa - module UOA
00212 cm_module_uid - module UID
00213 cm_display_as_alias - taken from the data
00214 cm_display_html - prepare display: "display as alias" or <I>alias</I> or UID
00215 (lock_uid) - UID of the aquired lock
00216 }
00217 """
00218
00219 if 'cm_module_uoa' not in i or i['cm_module_uoa']=='':
00220 return {'cm_return':1, 'cm_error':'parameter "cm_module_uoa" is not defined'}
00221
00222 if 'cm_data_uoa' not in i or i['cm_data_uoa']=='':
00223 return {'cm_return':1, 'cm_error':'parameter "cm_data_uoa" is not defined'}
00224
00225
00226 if 'cm_path_array' in i: path_repo=i['cm_path_array']
00227 else: path_repo=[]
00228
00229 if 'cm_path' in i and i['cm_path']!='': path_repo.append(i['cm_path'])
00230
00231 if len(path_repo)==0:
00232 r=find_path_to_work_repositories({})
00233 if r['cm_return']>0: return r
00234 for x in r['cm_array']:
00235 if x not in path_repo: path_repo.append(x)
00236
00237 module_uoa=i['cm_module_uoa']
00238 module_uid=''
00239 uoa=i['cm_data_uoa']
00240
00241
00242 found=False
00243 for p in path_repo:
00244 y=find_path_to_entry({'cm_path':p, 'cm_data_uoa':i['cm_module_uoa']})
00245 if y['cm_return']>0: return y
00246 elif y['cm_return']==0:
00247 module_uoa=y['cm_uoa']
00248 module_uid=y['cm_uid']
00249 pm=y['cm_path']
00250 y1=find_path_to_entry({'cm_path':pm, 'cm_data_uoa':i['cm_data_uoa']})
00251 if y1['cm_return']>0: return y1
00252 elif y1['cm_return']==0:
00253 found=True
00254 uid=y1['cm_uid']
00255 alias=y1['cm_alias']
00256 uoa=y1['cm_uoa']
00257 if alias!='': uoa=alias
00258 break
00259
00260 if not found:
00261 return {'cm_return':16, 'cm_error':'can\'t find path to data "'+module_uoa+':'+uoa+'"'}
00262
00263 pd=y1['cm_path']
00264
00265 p0=os.path.join(pd, ini['dcfg']['dcm'])
00266 p1=os.path.join(p0, ini['dcfg']['fconfig'])
00267 p5=os.path.join(p0, ini['dcfg']['flock'])
00268
00269
00270 locks={}
00271 if i.get('lock_acquire','')=='yes' or i.get('unlock_uid','')!='':
00272
00273 luid=''
00274 if os.path.isfile(p5):
00275
00276 try:
00277 f=file(p5)
00278 luid=f.readline().strip()
00279 exp=f.readline().strip()
00280 f.close()
00281 except Exception as e:
00282 return {'cm_return':1, 'cm_error':'problem reading locking file'}
00283
00284
00285 if i.get('lock_acquire','')=='yes':
00286
00287 retry=int(ini['dcfg'].get('flock_retry_num','6'))
00288 if i.get('lock_retry_num','')!='': retry=int(i['lock_retry_num'])
00289 retryd=float(ini['dcfg'].get('flock_retry_delay','11'))
00290 if i.get('lock_retry_delay','')!='': retry=float(i['lock_retry_delay'])
00291
00292 if exp=='': exp=ini['dcfg'].get('flock_expire_max','60')
00293
00294 dt=os.path.getmtime(p5)+float(exp)-time.time()
00295 if dt>0:
00296 while retry>0 and os.path.isfile(p5) and dt>0:
00297 retry-=1
00298 time.sleep(retryd)
00299 if os.path.isfile(p5): dt=os.path.getmtime(p5)+float(exp)-time.time()
00300
00301 if retry==0 or os.path.isfile(p5):
00302 return {'cm_return':32, 'cm_error':'data is locked'}
00303
00304 luid=''
00305 if os.path.isfile(p5): os.remove(p5)
00306
00307 if luid!='' and i.get('unlock_uid','')!='':
00308 if luid!=i['unlock_uid']:
00309 return {'cm_return':32, 'cm_error': 'data is locked with another UID'}
00310 luid=''
00311 os.remove(p5)
00312
00313 if i.get('lock_acquire','')=='yes':
00314
00315 r=gen_uid({})
00316 if r['cm_return']>0: return r
00317 luid=r['cm_uid']
00318 exp1=i.get('lock_expire','')
00319 if exp1=='' or float(exp1)<1: exp1=ini['dcfg'].get('flock_expire_max','60')
00320
00321 f=open(p5,'w')
00322 f.write(luid+'\n')
00323 f.write(exp1+'\n')
00324 f.close()
00325
00326 locks['lock_uid']=luid
00327
00328
00329 cached=None
00330 cm_display_as_alias=''
00331 cm_display_html=''
00332 if pd in ini['loaded_data_by_path'] and ini['loaded_data_by_path_last_modification'][pd]==os.path.getmtime(p1):
00333
00334 cached=ini['loaded_data_by_path'][pd]
00335
00336
00337 cached['cm_path']=pd
00338 xcfg=cached['cm_data_obj']['cfg']
00339 else:
00340
00341 r1=load_json_file({'cm_filename':p1})
00342 if r1['cm_return']>0: return r1
00343 xcfg=r1['cm_array']
00344 if 'cm_display_as_alias' in xcfg and xcfg['cm_display_as_alias']!='':
00345 cm_display_as_alias=xcfg['cm_display_as_alias']
00346 cm_display_html=cm_display_as_alias[0].upper()+cm_display_as_alias[1:]
00347 elif alias!='':
00348 cm_display_html=alias
00349 else:
00350 cm_display_html=uid
00351
00352
00353 ac=ini['dcfg'].get('access_control',{})
00354 if i.get('cm_admin','')!='yes' and ini['web']=='yes' and ac.get('use','')=='yes':
00355 rx=access_control({'dcfg':xcfg, 'module_uoa':module_uoa, \
00356 'module_uid':module_uid, 'data_uoa':uoa, 'key':'read'})
00357 if rx['cm_return']>0: return rx
00358
00359
00360 if cached!=None:
00361 cached.update(locks)
00362 return cached
00363
00364
00365 d={}
00366 d['cm_path']=pd
00367 d['cfg']=xcfg
00368
00369
00370
00371 o={'cm_return':0, 'cm_data_obj':d, \
00372 'cm_path':pd, \
00373 'cm_path_module':pm, \
00374 'cm_path_repo':p, \
00375 'cm_uid':uid, \
00376 'cm_alias':alias, \
00377 'cm_uoa':uoa, \
00378 'cm_module_uoa':module_uoa, \
00379 'cm_module_uid':module_uid, \
00380 'cm_display_as_alias':cm_display_as_alias, \
00381 'cm_display_html':cm_display_html}
00382 ini['loaded_data_by_path'][pd]=o
00383
00384 ini['loaded_data_by_path_last_modification'][pd]=os.path.getmtime(p1)
00385
00386
00387 o.update(locks)
00388
00389 return o
00390
00391
00392 def load_module(i):
00393 """
00394 Load and cache cM module
00395
00396 Input: {
00397 cm_module_uoa - UOA of the module
00398 (cm_path)
00399 }
00400
00401 Output: {
00402 cm_return - return code = 0, if successful
00403 cm_code - python code object
00404 external_module - if 'yes', module is external
00405 cm_path - path to data entry
00406 cm_uid - uid (from UOA)
00407 cm_alias - alias (from UOA)
00408
00409 }
00410 """
00411
00412 if 'cm_module_uoa' not in i:
00413 return {'cm_return':1, 'cm_error':'parameter "cm_module_uoa" is not defined'}
00414
00415 external=False
00416 if i['cm_module_uoa'].startswith('cme.'): external=True
00417
00418 if external:
00419
00420 p2=''
00421 p3=i['cm_module_uoa']
00422 if p3.endswith('.py'): p3=p3[:-3]
00423
00424 else:
00425
00426 ii={'cm_module_uoa':ini['dcfg']['cmr_module'],
00427 'cm_data_uoa':i['cm_module_uoa']}
00428 if 'cm_path' in i: ii.update({'cm_path':i['cm_path']})
00429
00430 r=load_data(ii)
00431 if r['cm_return']>0: return r
00432 elif r['cm_return']<0:
00433 return {'cm_return':16, 'cm_error':'can\'t find path to module "'+i['cm_module_uoa']+'"'}
00434 path=r['cm_path']
00435 uid=r['cm_uid']
00436 alias=r['cm_alias']
00437
00438 p1=os.path.join(path, ini['dcfg']['dcm'], ini['dcfg']['fconfig'])
00439
00440
00441 if path in ini['loaded_module_by_path'] and ini['loaded_module_by_path_last_modification'][path]==os.path.getmtime(p1):
00442
00443 return ini['loaded_module_by_path'][path]
00444
00445
00446 r=load_json_file({'cm_filename':p1})
00447 if r['cm_return']>0: return r
00448 xcfg=r['cm_array']
00449
00450
00451 subdir=xcfg['cm_module_py_dir']
00452 p2=os.path.join(path, subdir)
00453 p3=xcfg['cm_module_py_ext']
00454
00455 r=load_code({'cm_path':p2, 'cm_code_name':p3})
00456 if r['cm_return']>0: return r
00457 c=r['code']
00458
00459
00460 c.cm_kernel=cm_kernel
00461
00462 if not external:
00463 c.ini['cm_code']=c
00464 c.ini['cm_module_uoa']=i['cm_module_uoa']
00465 c.ini['cm_module_uid']=uid
00466 c.ini['cm_module_alias']=alias
00467 c.ini['cfg']=xcfg
00468 c.ini['path']=path
00469
00470 r=c.init(i)
00471 if r['cm_return']>0: return r
00472
00473
00474 o={'cm_return':0, 'cm_code':c, 'cm_path':path, 'cm_uid':uid, 'cm_alias':alias}
00475 ini['loaded_module_by_path'][path]=o
00476
00477 ini['loaded_module_by_path_last_modification'][path]=os.path.getmtime(p1)
00478 else:
00479 o={'cm_return':0, 'cm_code':c, 'external_module':'yes'}
00480
00481 return o
00482
00483
00484 def load_code(i):
00485 """
00486 Load python code
00487
00488 Input: {
00489 cm_path - path
00490 cm_code_name - name of the python native module
00491 }
00492
00493 Output: {
00494 cm_return - return code = 0, if successful
00495 code - python code object
00496 }
00497 """
00498
00499
00500 try:
00501 x=imp.find_module(i['cm_code_name'], [i['cm_path']])
00502 except ImportError as e:
00503 return {'cm_return':1, 'cm_error':'can\'t find code (path='+i['cm_path']+', name='+i['cm_code_name']+', err='+format(e)+')'}
00504
00505
00506
00507
00508
00509 r=gen_uid({})
00510 if r['cm_return']>0: return r
00511 ruid='runtime-'+r['cm_uid']
00512
00513 try:
00514 c=imp.load_module(ruid, x[0], x[1], x[2])
00515 except ImportError as e:
00516 return {'cm_return':1, 'cm_error':'can\'t load code (path='+i['cm_path']+', name='+i['cm_code_name']+', err='+format(e)+')'}
00517
00518 x[0].close()
00519
00520 return {'cm_return':0, 'code':c}
00521
00522
00523 def gen_uid(i):
00524 """
00525 Generate cM UID
00526
00527 Input: {}
00528
00529 Output: {
00530 cm_return - return code = 0, if successful
00531 cm_uid - cM UID in string format (16 characters 0..9,a..f)
00532 }
00533 """
00534
00535 uid=str(uuid.uuid4().hex)
00536
00537 if len(uid)!=32:
00538 return {'cm_return':1, 'cm_error':'problem generating UID : len='+str(len(uid))+' !=32'}
00539
00540 random.seed
00541
00542 x=random.randrange(0,16)
00543 return {'cm_return':0, 'cm_uid':uid[x:x+16]}
00544
00545
00546 def is_uid(str):
00547 """
00548 Check if string is cM UID
00549
00550 Input: string to check
00551
00552 Output: True if UID, otherwise False
00553 """
00554
00555 if len(str)!=16:
00556 return False
00557
00558 pattern = r'[^\.a-f0-9]'
00559 if re.search(pattern, str.lower()):
00560 return False
00561
00562 return True
00563
00564
00565 def cid2array(i):
00566 """
00567 Convert cid to array
00568
00569 Input: {
00570 cid - in format (REPO_UOA:)KEY_UOA:DATA_UOA
00571 (prefix) - add prefic to output variables (<prefix>_repo_uoa:...)
00572 }
00573
00574 Output: {
00575 cm_return - return code = 0 if successful
00576 cm_array - array
00577 }
00578 """
00579
00580 prefix='cm'
00581 if 'prefix' in i and i['prefix']!='': prefix=i['prefix']
00582
00583 array={}
00584 if 'cid' in i and i['cid']!='':
00585 id=i['cid'].split(":")
00586 if (len(id)<2):
00587 return {'cm_return':1, 'cm_error':'unknown cid format'}
00588 elif (len(id)<3):
00589 array[prefix+'_module_uoa']=id[0]
00590 array[prefix+'_data_uoa']=id[1]
00591 elif (len(id)<4):
00592 array[prefix+'_repo_uoa']=id[0]
00593 array[prefix+'_module_uoa']=id[1]
00594 array[prefix+'_data_uoa']=id[2]
00595 return {'cm_return':0, 'cm_array':array}
00596
00597
00598
00599 def web_print_array_for_debug(i):
00600 """
00601 Print array for debug purposes (use <pre> and <div align="left")
00602
00603 Input: {
00604 some array
00605 }
00606
00607 Output: {
00608 cm_return - 0
00609 }
00610 """
00611
00612 print '<pre><div align="left">'+json.dumps(i, indent=2, sort_keys=True)+'</div></pre>'
00613
00614
00615 return {'cm_return':0}
00616
00617
00618 def find_path_to_entry(i):
00619 """
00620 Find path to an UOA entry (check UID or alias).
00621
00622 Input: {
00623 cm_path - path to a repository
00624 cm_data_uoa - data UOA
00625 }
00626
00627 Output: {
00628 cm_return - return code = 0 if found path to entry
00629 = -1 if not found path to entry
00630 > 0 if error
00631
00632 cm_path_orig - i['cm_path']
00633 cm_path - path to data entry
00634 cm_uid - uid (from UOA)
00635 cm_alias - alias (from UOA)
00636 cm_uoa - alias or uid, if alias==''
00637 }
00638 """
00639
00640 if ('cm_path' not in i):
00641 return {'cm_return':1, 'cm_error':'parameter "'+'cm_path'+'" is not defined'}
00642 if ('cm_data_uoa' not in i):
00643 return {'cm_return':1, 'cm_error':'parameter "cm_data_uoa" is not defined'}
00644
00645
00646 alias=''
00647 if is_uid(i['cm_data_uoa']):
00648
00649 uid=i['cm_data_uoa']
00650
00651
00652 p1=os.path.join(i['cm_path'], ini['dcfg']['dcm'], ini['dcfg']['falias-u'] + uid)
00653 found_alias=False
00654 if os.path.isfile(p1):
00655 try:
00656 f=file(p1)
00657 alias=f.readline().strip()
00658 f.close()
00659 found_alias=True
00660 except Exception as e:
00661 None
00662
00663
00664 if found_alias:
00665 p2=os.path.join(i['cm_path'], alias)
00666 if not os.path.isdir(p2):
00667
00668 try:
00669 os.mkdir(p2)
00670 except Exception as e:
00671 return {'cm_return':1, 'cm_error':format(e)}
00672
00673 return {'cm_return':0, 'cm_path':p2, 'cm_uid':uid, 'cm_alias':alias, 'cm_uoa':alias}
00674
00675 p2=os.path.join(i['cm_path'], uid)
00676 if os.path.isdir(p2):
00677 return {'cm_return':0, 'cm_path':p2, 'cm_uid':uid, 'cm_alias':'', 'cm_uoa':uid}
00678
00679 return {'cm_return':-1}
00680
00681
00682 alias=i['cm_data_uoa']
00683
00684 p1=os.path.join(i['cm_path'], alias)
00685 if os.path.isdir(p1):
00686
00687 p2=os.path.join(i['cm_path'], ini['dcfg']['dcm'], ini['dcfg']['falias-a'] + alias)
00688 try:
00689 f=file(p2)
00690 uid=f.readline().strip()
00691 f.close()
00692 except Exception as e:
00693 return {'cm_return':10, 'cm_error':'inconsistent entry: alias "'+alias+'" exists, but not the uid in file '+p2, 'cm_path_orig':i['cm_path'], 'cm_path':p1, 'cm_alias':alias}
00694
00695 return {'cm_return':0, 'cm_path_orig': i['cm_path'], 'cm_path':p1, 'cm_uid':uid, 'cm_alias':alias, 'cm_uoa':alias}
00696
00697 return {'cm_return':-1}
00698
00699
00700 def create_entry(i):
00701 """
00702 Create an UOA entry directory structure.
00703
00704 Input: {
00705 cm_path - path to a repository
00706 (cm_data_uoa) - data UOA
00707 (cm_data_uid) - if cm_data_uoa==alias, we can force a given UID through this variable
00708 (lock_uid) - UID of the aquired lock
00709 }
00710
00711 Output: {
00712 cm_return - return code = 0 if created entry
00713 = -1 if already exist
00714 > 0 if error
00715
00716 cm_path - path to data entry
00717 cm_uid - uid (from UOA)
00718 cm_alias - alias (from UOA)
00719 cm_uoa - alias or uid if alias==''
00720 }
00721 """
00722
00723 if ('cm_path' not in i):
00724 return {'cm_return':1, 'cm_error':'parameter "'+'cm_path'+'" is not defined'}
00725
00726
00727 alias=''
00728 uid=''
00729 if ('cm_data_uoa' not in i or i['cm_data_uoa']==''):
00730 if 'cm_data_uid' not in i or i['cm_data_uid']=='':
00731 r=gen_uid({})
00732 if r['cm_return']>0: return r
00733 uid=r['cm_uid']
00734 else:
00735 uid=i['cm_data_uid']
00736
00737
00738 ii={}
00739 ii.update(i)
00740 ii['cm_data_uoa']=uid
00741 r=find_path_to_entry(ii)
00742 if r['cm_return']>0: return r
00743 elif r['cm_return']==0:
00744 r1={}; r1.update(r); r1['cm_return']=-1
00745 return r1
00746
00747 alias=''
00748 else:
00749
00750 r=find_path_to_entry(i)
00751 if r['cm_return']>0: return r
00752 elif r['cm_return']==0:
00753 r1={}; r1.update(r); r1['cm_return']=-1
00754 return r1
00755
00756 if is_uid(i['cm_data_uoa']):
00757 uid=i['cm_data_uoa']; alias=''
00758 else:
00759 alias=i['cm_data_uoa']
00760 if 'cm_data_uid' in i: uid=i['cm_data_uid']
00761 else:
00762 r=gen_uid({})
00763 if r['cm_return']>0: return r
00764 uid=r['cm_uid']
00765
00766 if alias!='':
00767 p=os.path.join(i['cm_path'], alias)
00768 else:
00769 p=os.path.join(i['cm_path'], uid)
00770
00771
00772 if alias!='':
00773 p1=os.path.join(i['cm_path'], ini['dcfg']['dcm'])
00774 if not os.path.isdir(p1):
00775
00776 try:
00777 os.mkdir(p1)
00778 except Exception as e:
00779 return {'cm_return':1, 'cm_error':format(e)}
00780
00781
00782 p3=os.path.join(p1, ini['dcfg']['falias-a'] + alias)
00783 if os.path.isfile(p3):
00784 try:
00785 fx=file(p3)
00786 uid1=fx.readline().strip()
00787 fx.close()
00788 except Exception as e:
00789 None
00790
00791 if uid1!=uid:
00792 return {'cm_return':1, 'cm_error':'different alias->uid disambiguator already exists ('+p3+')'}
00793
00794 try:
00795 f=file(p3, 'w')
00796 f.write(uid+'\n')
00797 f.close()
00798 found_alias=True
00799 except Exception as e:
00800 None
00801
00802
00803 p2=os.path.join(p1, ini['dcfg']['falias-u'] + uid)
00804 if os.path.isfile(p2):
00805 try:
00806 fx=file(p2)
00807 alias1=fx.readline().strip()
00808 fx.close()
00809 except Exception as e:
00810 None
00811
00812 if alias1!=alias:
00813 return {'cm_return':1, 'cm_error':'different uid->alias disambiguator already exists ('+p2+')'}
00814
00815 try:
00816 f=file(p2, 'w')
00817 f.write(alias+'\n')
00818 f.close()
00819 found_alias=True
00820 except Exception as e:
00821 None
00822
00823
00824 if not os.path.exists(p):
00825 try:
00826 os.mkdir(p)
00827 except Exception as e:
00828 return {'cm_return':1, 'cm_error':format(e)}
00829
00830 uoa=uid
00831 if alias!='': uoa=alias
00832
00833 return {'cm_return':0, 'cm_path':p, 'cm_uid':uid, 'cm_alias':alias, 'cm_uoa':uoa}
00834
00835
00836 def check_global_writing(i):
00837 """
00838 Check global writing to repository
00839
00840 Input: {
00841 }
00842
00843 Output: {
00844 cm_return - return code >0 if writing is not allowed
00845 }
00846 """
00847
00848 if cm_kernel.ini['dcfg'].get('forbid_write','')=='yes':
00849 return {'cm_return':1, 'cm_error':'any writing is forbidden by configuration'}
00850
00851 return {'cm_return':0}
00852
00853
00854 def delete_entry(i):
00855 """
00856 Delete entry
00857
00858 Input: {
00859 cm_path - path to the entry
00860 cm_path_module - part of the path with module
00861 cm_uid - uid (from UOA), needed to delete alias disambiguator if exists
00862 cm_alias - alias (from UOA), needed to delete alias disambiguator if exists
00863 }
00864
00865 Output: {
00866 cm_return - return code >0 if error
00867 }
00868 """
00869
00870 r=check_global_writing({})
00871 if r['cm_return']>0: return r
00872
00873
00874 if i['cm_alias']!='':
00875
00876 r=cm_kernel.delete_alias({'cm_path':i['cm_path_module'], 'cm_alias':i['cm_alias'], 'cm_uid':i['cm_uid']})
00877 if r['cm_return']>0: return r
00878
00879
00880 return cm_kernel.delete_directory({'cm_path':i['cm_path']})
00881
00882
00883 def delete_alias(i):
00884 """
00885 Delete alias
00886
00887 Input: {
00888 cm_path - path to the entry
00889 cm_uid - uid (from UOA)
00890 cm_alias - alias (from UOA)
00891 }
00892
00893 Output: {
00894 cm_return - return code >0 if error
00895 }
00896 """
00897
00898 p=i['cm_path']
00899 uid=''
00900
00901 if 'cm_alias' in i:
00902 alias=i['cm_alias']
00903 if alias!='' and os.path.isdir(p):
00904 p1=os.path.join(p, ini['dcfg']['dcm'], ini['dcfg']['falias-a'] + alias)
00905 if os.path.isfile(p1):
00906 try:
00907 f=file(p1)
00908 uid=f.readline().strip()
00909 f.close()
00910 except Exception as e:
00911 None
00912 os.remove(p1)
00913
00914 if uid=='': uid=i['cm_uid']
00915
00916 if uid!='':
00917 p1=os.path.join(p, ini['dcfg']['dcm'], ini['dcfg']['falias-u'] + uid)
00918 if os.path.isfile(p1):
00919 os.remove(p1)
00920
00921 return {'cm_return':0}
00922
00923
00924 def substitute_str_in_file(i):
00925 """
00926 Substitute string in file
00927
00928 Input: {
00929 cm_file - file
00930 cm_string1 - string to be replaced
00931 cm_string2 - replace string
00932 }
00933
00934 Output: {
00935 cm_return - return code >0 if error
00936 }
00937 """
00938
00939 import codecs
00940
00941 fil=i['cm_file']
00942 s1=i['cm_string1']
00943 s2=i['cm_string2']
00944
00945 f=open(fil, 'r')
00946 x=f.read().decode('utf-8')
00947 f.close()
00948
00949 x=x.replace(s1,s2)
00950
00951 f=codecs.open(fil,'w','utf-8')
00952 f.write(x)
00953 f.close()
00954
00955 return {'cm_return':0}
00956
00957
00958 def create_data_entry(i):
00959 """
00960 Create data entry
00961
00962 Input: {
00963 cm_path - path to the repository
00964 cm_module_uoa - module UOA
00965 cm_data_uoa - data UOA
00966 (cm_data_uid) - if cm_data_uoa==alias, we can force a given UID through this variable
00967 (cm_array) - array to add to the entry
00968 If not set, the whole array will be added
00969 including all working variables - we do not suggest to do that
00970 (cm_add_default) - if 'yes', add default params from descriptions (module/kernel)
00971 (cm_update) - if 'yes', update entry
00972 (cm_description) - description of the data entry
00973 (cm_display_as_alias) - user readable alias to display instead of module:data
00974 (cm_skip_update_info) - if == 'yes', do not write 'cm_updated'
00975 (cm_note) - note about this data entry
00976 (cm_like) - if 'yes' add +1 for this user to the entry
00977
00978 (cm_file_upload_tmp_uid) - normally generated automatically by web server
00979 when uploading files
00980 (cm_file_upload_name) - preffered uploaded file name
00981 (cm_file_upload_type) - type of file (if .zip, it will be automatically unziped)
00982 (cm_archive) - if file should be kept as archive
00983
00984 ... - if 'cm_array' not present, add everything else from this array
00985 to the entry
00986 (lock_uid) - unlock data
00987 }
00988
00989 Output: {
00990 cm_return - return code >0 if error
00991 -1 if entry exists
00992 cm_path - path to created data entry
00993 cm_uid - uid (from UOA)
00994 cm_alias - alias (from UOA)
00995 }
00996 """
00997
00998 r=check_global_writing({})
00999 if r['cm_return']>0: return r
01000
01001
01002 upload_file_uid=i.get('cm_file_upload_tmp_uid','')
01003 upload_file_name=i.get('cm_file_upload_name','')
01004 upload_file_type=i.get('cm_file_upload_type','')
01005 upload_archive=i.get('cm_archive','')
01006 if upload_file_uid!='':
01007 del(i['cm_file_upload_tmp_uid'])
01008 if 'upload_file_type' in i: del(i['cm_file_upload_type'])
01009 if upload_file_name!='' and i.get('cm_archive','')!='already_archived_with_user_name': del(i['cm_file_upload_name'])
01010
01011 if upload_file_name=='' and 'cm_file_upload_name' in i: del(i['cm_file_upload_name'])
01012 if upload_file_type=='' and 'cm_file_upload_type' in i: del(i['cm_file_upload_type'])
01013
01014
01015 cm_user_uid=''
01016 cm_user_uoa=''
01017 if 'cm_user_uid' in ini['web_auth']:
01018 cm_user_uid=ini['web_auth']['cm_user_uid']
01019 cm_user_uoa=ini['web_auth']['cm_user_uoa']
01020
01021 p=i['cm_path']
01022
01023
01024
01025 r=load_data({'cm_module_uoa':ini['dcfg']['cmr_module'],
01026 'cm_data_uoa':i['cm_module_uoa']})
01027 if r['cm_return']>0: return r
01028 elif r['cm_return']<0:
01029 return {'cm_return':16, 'cm_error':'can\'t find path to module "'+i['cm_module_uoa']+'"'}
01030 uid=r['cm_uid']
01031 alias=r['cm_alias']
01032 module_desc=r['cm_data_obj']['cfg']
01033
01034 if alias=='': alias=uid
01035
01036 r=create_entry({'cm_path':p, 'cm_data_uoa':alias, 'cm_data_uid':uid})
01037 if r['cm_return']>0: return r
01038 p1=r['cm_path']
01039
01040
01041 i1={}; i1['cm_path']=p1
01042 if 'cm_data_uoa' in i: i1['cm_data_uoa']=i['cm_data_uoa']
01043 if 'cm_data_uid' in i: i1['cm_data_uid']=i['cm_data_uid']
01044 r=create_entry(i1)
01045 if r['cm_return']>0: return r
01046
01047
01048 p2=r['cm_path']
01049 p3=os.path.join(p2, ini['dcfg']['dcm'])
01050 p4=os.path.join(p3, ini['dcfg']['fconfig'])
01051 p5=os.path.join(p3, ini['dcfg']['flock'])
01052
01053 a={}
01054 if r['cm_return']<0:
01055 if i.get('cm_update','')=='yes':
01056
01057 if os.path.isfile(p5):
01058 try:
01059 f=file(p5)
01060 luid=f.readline().strip()
01061 exp=f.readline().strip()
01062 f.close()
01063 except Exception as e:
01064 return {'cm_return':1, 'cm_error':'problem reading locking file'}
01065
01066
01067 if exp=='': exp=ini['dcfg'].get('flock_expire_max','60')
01068
01069 dt=os.path.getmtime(p5)+float(exp)-time.time()
01070 if dt<0:
01071
01072 if i.get('lock_uid','')=='':
01073 os.remove(p5)
01074 else:
01075 return {'cm_return':32, 'cm_error':'data lock UID is not matching'}
01076
01077 else:
01078 if i.get('lock_uid','')=='':
01079 return {'cm_return':32, 'cm_error':'data is locked'}
01080 elif i.get('lock_uid','')!=luid:
01081 return {'cm_return':32, 'cm_error':'data is locked with different UID'}
01082
01083 elif i.get('lock_uid','')!='':
01084 return {'cm_return':32, 'cm_error':'lock removed or expired'}
01085
01086
01087 r['cm_return']=0
01088 r2=load_json_file({'cm_filename':p4})
01089 if r2['cm_return']>0: return r2
01090 a=copy.deepcopy(r2['cm_array'])
01091
01092 else:
01093
01094 if not os.path.isdir(p3):
01095 try:
01096 os.mkdir(p3)
01097 except Exception as e:
01098 return {'cm_return':1, 'cm_error':format(e)}
01099
01100
01101 cma={}
01102
01103
01104 if i.get('cm_add_default','')=='yes':
01105 df={}
01106
01107 if 'cm_common_data_description7' in ini['dcfg']:
01108 rz=create_default_array_from_description({'cm_data_desc':ini['dcfg']['cm_common_data_description7']})
01109 if rz['cm_return']>0: return rz
01110 merge_arrays({'cm_array':df, 'cm_array1':rz['cm_array']})
01111
01112 if 'cm_common_data_description8' in ini['dcfg']:
01113 rz=create_default_array_from_description({'cm_data_desc':ini['dcfg']['cm_common_data_description8']})
01114 if rz['cm_return']>0: return rz
01115 merge_arrays({'cm_array':df, 'cm_array1':rz['cm_array']})
01116
01117 if 'cm_data_description' in module_desc:
01118 rz=create_default_array_from_description({'cm_data_desc':module_desc['cm_data_description']})
01119 if rz['cm_return']>0: return rz
01120 merge_arrays({'cm_array':df, 'cm_array1':rz['cm_array']})
01121
01122 if len(df)>0:
01123 merge_arrays({'cm_array':cma, 'cm_array1':df})
01124
01125 if 'cm_array' in i:
01126 merge_arrays({'cm_array':cma, 'cm_array1':i['cm_array']})
01127
01128
01129 merge_arrays({'cm_array':a, 'cm_array1':cma})
01130
01131 if 'cm_description' in i: a['cm_description']=i['cm_description']
01132 if 'cm_display_as_alias' in i: a['cm_display_as_alias']=i['cm_display_as_alias']
01133
01134 if 'powered_by' not in a:
01135 a['powered_by']={}
01136 a['powered_by']['name']='Collective Mind Engine'
01137 rq=get_cm_version({})
01138 if rq['cm_return']>0: return rq
01139 a['powered_by']['version']=rq['cm_string']
01140
01141
01142 if i.get('cm_skip_update_info','')!='yes':
01143 u={}
01144 if cm_user_uid!='':
01145 u['cm_user_uoa']=cm_user_uid
01146 u['cm_person_uoa']=cm_user_uid
01147 if 'cm_note' in i: u['cm_note']=i['cm_note']
01148 if 'cm_validated' in i: u['cm_validated']=i['cm_validated']
01149 if 'cm_like' in i and i['cm_like']=='yes':
01150
01151 rank=1
01152 if 'cm_updated' in a:
01153 found=False
01154 for x in a['cm_updated']:
01155 if x.get('cm_like','')=='yes':
01156 if 'cm_user_uoa' in x and (cm_user_uid!='' or cm_user_uoa!='') and \
01157 (x['cm_user_uoa']==cm_user_uid or x['cm_user_uoa']==cm_user_uoa):
01158 found=True
01159 else:
01160 rank+=1
01161 if not found:
01162 u['cm_like']=i['cm_like']
01163
01164 a['cm_rank']=rank
01165
01166 r5=get_current_date_time({})
01167 u['cm_iso_datetime']=r5['cm_iso_datetime']
01168 u['cm_module_uid']=uid
01169
01170 if 'cm_updated' not in a:
01171 a['cm_updated']=[]
01172 a['cm_updated'].append(u)
01173
01174
01175 if 'cm_access_control' in a:
01176 pass
01177 elif 'cm_access_control' in i:
01178 a.update({'cm_access_control':i['cm_access_control']})
01179 elif 'cm_access_control_default' in cm_kernel.ini['dcfg']:
01180 a.update({'cm_access_control':cm_kernel.ini['dcfg']['cm_access_control_default']})
01181
01182 r4=save_array_to_file_as_json({'cm_filename':p4, 'cm_array':a})
01183 if r4['cm_return']>0: return r4
01184
01185
01186 pp1=''
01187 if upload_file_uid!='':
01188 pp1=os.path.join(ini[cm_kernel.env_cm_tmp], ini['dcfg']['cm_tmp_prefix']+upload_file_uid+ini['dcfg']['cm_tmp_postfix'])
01189 else:
01190
01191 if ('cm_file_upload' in i and len(i['cm_file_upload'])>0) or \
01192 ('cm_file_upload_base64' in i and len(i['cm_file_upload_base64'])>0):
01193
01194 if ('cm_file_upload' in i and len(i['cm_file_upload'])>0):
01195 xn=i['cm_file_upload']
01196 elif ('cm_file_upload_base64' in i and len(i['cm_file_upload_base64'])>0):
01197 xn=base64.urlsafe_b64decode(str(i['cm_file_upload_base64']))
01198
01199 px=os.path.join(p2,i.get('cm_file_upload_name','default_name'))
01200 fx=file(px, 'wb')
01201 fx.write(xn)
01202 fx.close()
01203
01204 pp1=px
01205
01206 if pp1!='':
01207 if upload_file_type=='.zip' and upload_archive!='already_archived_with_user_name':
01208 upload_file_name=''
01209
01210 if upload_file_type=='' or upload_archive!='':
01211
01212 if os.path.isfile(pp1):
01213 x=upload_file_name
01214 if x=='': x=ini['dcfg']['cm_default_upload_filename']
01215 if upload_archive=='already_archived_with_internal_name': x=ini['dcfg']['cm_archive_filename']
01216 pp2=os.path.join(p2, x)
01217 shutil.move(pp1,pp2)
01218 elif upload_file_type=='.zip':
01219
01220 f=open(pp1,'rb')
01221 z=zipfile.ZipFile(f)
01222 for d in z.namelist():
01223 if not d.startswith('.') and not d.startswith('/') and not d.startswith('\\'):
01224 if d.endswith('/'):
01225
01226 pp2=os.path.join(p2,d)
01227 if not os.path.exists(pp2): os.makedirs(pp2)
01228 else:
01229
01230 pp2=os.path.join(p2, d)
01231 fo=open(pp2, 'wb')
01232 fo.write(z.read(d))
01233 fo.close()
01234 f.close()
01235 os.remove(pp1)
01236
01237
01238 if i.get('lock_uid','')!='' and os.path.isfile(p5):
01239 os.remove(p5)
01240
01241 return r
01242
01243
01244 def create_default_array_from_description(i):
01245 """
01246 Create array with default parameters from data description
01247
01248 Input: {
01249 cm_data_desc - cM data description
01250 }
01251
01252 Output: {
01253 cm_return - return code =0 if successful
01254 >0 if error
01255 cm_array - array with default parameters
01256 }
01257 """
01258
01259 a={}
01260
01261 for x in i['cm_data_desc']:
01262 y=i['cm_data_desc'][x]
01263
01264 if '$' not in x:
01265 d=''
01266
01267 t=y.get('type','')
01268 if t=='list': d=[]
01269 elif t=='dict': d={}
01270
01271 if 'default_value' in d: d=y['default_value']
01272
01273 set_value_by_flattened_key({'cm_array':a, 'cm_key':x, 'cm_value':d})
01274
01275 return {'cm_return':0, 'cm_array':a}
01276
01277
01278 def convert_file_to_upload_string(i):
01279 """
01280 Convert file to upload string
01281
01282 Input: {
01283 cm_full_filename - file name to convert
01284 }
01285
01286 Output: {
01287 cm_return - return code =0 if successful
01288 >0 if error
01289 cm_file_upload_base64 - string that can be used to upload file
01290 }
01291 """
01292
01293 fn=i['cm_full_filename']
01294
01295 if not os.path.isfile(fn):
01296 return {'cm_return':1, 'cm_error':'file '+fn+' not found'}
01297
01298 s=''
01299 try:
01300 f=open(fn, 'rb')
01301 while True:
01302 x = f.read(32768);
01303 if not x: break
01304 s+=x
01305 f.close()
01306 except Exception as e:
01307 return {'cm_return':1, 'cm_error':'error reading file ('+format(e)+')'}
01308
01309 r={'cm_return':0}
01310 r['cm_file_upload_base64']=base64.urlsafe_b64encode(s)
01311
01312 return r
01313
01314
01315 def get_current_date_time(i):
01316 """
01317 Get current date and time
01318
01319 Input: {}
01320
01321 Output: {
01322 cm_return - return code =0 if successful
01323 >0 if error
01324 cm_array - array with date and time
01325 cm_iso_datetime - date and time in ISO format
01326 }
01327 """
01328
01329 a={}
01330
01331 now1=datetime.datetime.now()
01332 now=now1.timetuple()
01333
01334 a["cm_date_year"]=str(now[0])
01335 a["cm_date_month"]=str(now[1])
01336 a["cm_date_day"]=str(now[2])
01337 a["cm_time_hour"]=str(now[3])
01338 a["cm_time_minute"]=str(now[4])
01339 a["cm_time_second"]=str(now[5])
01340
01341
01342 return {'cm_return':0, 'cm_array':a, 'cm_iso_datetime':now1.isoformat()}
01343
01344
01345 def convert_iso_time_to_str(i):
01346 """
01347 Get current date and time
01348
01349 Input: {
01350 cm_iso_datetime - date and time in ISO format
01351 (cm_custom_format) - customize view
01352 }
01353
01354 Output: {
01355 cm_return - return code =0 if successful
01356 >0 if error
01357 cm_string - user friendly date/time
01358 }
01359 """
01360
01361 if 'cm_iso_datetime' not in i: return {'cm_return':1, 'cm_error':'"cm_iso_datetime" is not set in kernel/convert_iso_time_to_str'}
01362
01363 d=datetime.datetime(*map(int, re.split('[^\d]', i['cm_iso_datetime'])[:-1]))
01364
01365 format=i.get('cm_custom_format','')
01366 if format=='':
01367 format='%Y-%B-%d (%A) %H:%M:%S'
01368 s=d.strftime(format)
01369
01370 return {'cm_return':0, 'cm_string':s}
01371
01372
01373 def find_index_in_array(i):
01374 """
01375 Find index in array of formart [{cm_index:'a', ...}, {cm_index='b', ...}, ...]
01376 We use such array instead of simple associative array
01377 when we need to keep an order such as for actions ...
01378
01379 Input: {
01380 cm_array - array of format
01381 cm_index - index
01382 }
01383
01384 Output: {
01385 cm_return - return code = 0 if successful
01386 -1 if not found
01387 cm_array - sub-array with given index
01388 }
01389 """
01390
01391 for x in i['cm_array']:
01392 if 'cm_index' in x and x['cm_index']==i['cm_index']:
01393 return {'cm_return':0, 'cm_array':x}
01394
01395 return {'cm_return':-1}
01396
01397
01398
01399 def find_path_to_current_repository(i):
01400 """
01401 Finds local repository (recursively checks
01402 all upper directories until it finds the repository)
01403
01404 Input: {
01405 cm_get_uid - if 'yes' load data to get UID besides UOA
01406 }
01407
01408 Output: {
01409 cm_return - return code >0 if error
01410 -1 if doesn't exist
01411 cm_path - path to the local repository
01412 (cm_module_uoa) - module UOA of the current path
01413 (cm_module_uid) - module UID of the current path
01414 (cm_data_uoa) - data UOA of the current path
01415 (cm_data_uid) - data UID of the current path
01416 }
01417 """
01418
01419 pe=ini['dcfg']['cmr_ext']
01420
01421 px=os.path.join(os.getcwd())
01422 py="dummy"
01423
01424 paths=[]
01425
01426 p=os.path.join(px,pe)
01427 if os.path.isdir(p)==True:
01428 return {'cm_return':0, 'cm_path':p}
01429
01430 while py!="":
01431 px0=os.path.split(px)
01432 px=px0[0]
01433 px1=px0[1]
01434 py=os.path.split(px)[1]
01435 p=os.path.join(px,pe)
01436 if os.path.isdir(p):
01437 r={'cm_return':0, 'cm_path':p}
01438 if len(paths)==1:
01439 r['cm_module_uoa']=paths[0]
01440 elif len(paths)>=2:
01441 l=len(paths)
01442 r['cm_module_uoa']=paths[l-1]
01443 r['cm_data_uoa']=paths[l-2]
01444
01445 if i.get('cm_get_uid','')=='yes' and r.get('cm_data_uoa','')!='':
01446 r1=copy.deepcopy(r)
01447 rx=load_data(r1)
01448 if rx['cm_return']>0: return rx
01449
01450 r['cm_module_uid']=rx['cm_module_uid']
01451 r['cm_data_uid']=rx['cm_uid']
01452 return r
01453 else:
01454 paths.append(px1)
01455
01456 return {'cm_return':-1}
01457
01458
01459 def find_path_to_work_repositories(i):
01460 """
01461 Find path to work and local repositories
01462
01463 Input: {
01464 }
01465
01466 Output: {
01467 cm_return - return code >0 if error
01468 cm_array - array of paths
01469 }
01470 """
01471
01472 a=[]
01473
01474 r=find_path_to_current_repository({})
01475 if r['cm_return']>0: return r
01476 elif r['cm_return']==0:
01477 a.append(r['cm_path'])
01478
01479
01480 if 'cm_local_repo' in cm_kernel.ini:
01481 p=cm_kernel.ini['cm_local_repo']
01482 found=False
01483 for q in a:
01484 if os.stat(q)==os.stat(p):
01485 found=True
01486 break
01487 if not found: a.append(p)
01488
01489
01490 p=cm_kernel.ini['cm_default_repo']
01491 found=False
01492 for q in a:
01493 if os.stat(q)==os.stat(p):
01494 found=True
01495 break
01496 if not found: a.append(p)
01497
01498 return {'cm_return':0, 'cm_array':a}
01499
01500
01501 def load_json_file(i):
01502 """
01503 Load json from file
01504
01505 Input: {
01506 cm_filename - file name with json
01507 }
01508
01509 Output: {
01510 cm_return - return code = 0 if successful
01511 cm_array - array from json file
01512 }
01513 """
01514
01515 if 'cm_filename' not in i:
01516 return {'cm_return':1, 'cm_error':'parameter "cm_filename" is not defined'}
01517
01518 try:
01519 f=file(i['cm_filename'])
01520 except Exception as e:
01521 return {'cm_return':1, 'cm_error':format(e)}
01522
01523 try:
01524 array=json.loads(f.read())
01525 except Exception as e:
01526 f.close()
01527 return {'cm_return':1, 'cm_error':'problem loading array from file='+i['cm_filename']+' ('+format(e)+')'}
01528
01529 f.close()
01530
01531 return {'cm_return':0, 'cm_array': array}
01532
01533
01534 def save_array_to_file_as_json(i):
01535 """
01536 Save array to file
01537
01538 Input: {
01539 cm_filename - file name with json
01540 cm_array - array to save
01541 }
01542
01543 Output: {
01544 cm_return - return code = 0 if successful
01545 }
01546 """
01547
01548 if 'cm_filename' not in i:
01549 return {'cm_return':1, 'cm_error':'parameter "cm_filename" is not defined'}
01550
01551 if 'cm_array' not in i:
01552 return {'cm_return':1, 'cm_error':'parameter "cm_array" is not defined'}
01553
01554 s = json.dumps(i['cm_array'], indent=2, sort_keys=True, encoding="utf-8")
01555
01556 try:
01557 f=file(i['cm_filename'], 'w')
01558 except Exception as e:
01559 return {'cm_return':1, 'cm_error':format(e)}
01560
01561 try:
01562 f.write(s+'\n')
01563 except Exception as e:
01564 f.close()
01565 return {'cm_return':1, 'cm_error':'problem writing array to file='+i['cm_filename']+' ('+format(e)+')'}
01566
01567 f.close()
01568
01569 return {'cm_return':0}
01570
01571
01572 def load_array_from_file(i):
01573 """
01574 Load array from file
01575
01576 Input: {
01577 cm_filename - file name
01578 }
01579
01580 Output: {
01581 cm_return - return code = 0 if successful
01582 cm_array - array
01583 }
01584 """
01585
01586 if 'cm_filename' not in i:
01587 return {'cm_return':1, 'cm_error':'parameter "cm_filename" is not defined'}
01588
01589 array=[]
01590
01591 try:
01592 f=file(i['cm_filename'])
01593 except Exception as e:
01594 return {'cm_return':1, 'cm_error':format(e)}
01595
01596 try:
01597 for line in f:
01598 array.append(line)
01599 except Exception as e:
01600 f.close()
01601 return {'cm_return':1, 'cm_error':'problem loading array from file='+i['cm_filename']+' ('+format(e)+')'}
01602
01603 f.close()
01604
01605 return {'cm_return':0, 'cm_array': array}
01606
01607
01608 def save_flat_array_to_file(i):
01609 """
01610 Load array from file
01611
01612 Input: {
01613 cm_array - array to save (only flat one)
01614 cm_filename - file name
01615 separate_lines - if 'yes', put key and value on separate lines
01616 }
01617
01618 Output: {
01619 cm_return - return code = 0 if successful
01620 }
01621 """
01622
01623 if 'cm_filename' not in i: return {'cm_return':1, 'cm_error':'parameter "cm_filename" is not defined'}
01624 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'parameter "cm_array" is not defined'}
01625
01626 separate=False
01627 if i.get('separate_lines','')=='yes': separate=True
01628
01629 a=i['cm_array']
01630
01631 try:
01632 f=file(i['cm_filename'], 'w')
01633 for x in a:
01634 if separate:
01635 f.write(str(x)+'\n')
01636 f.write(str(a[x])+'\n')
01637 else:
01638 f.write(str(x)+'='+str(a[x])+'\n')
01639 f.close()
01640 except Exception as e:
01641 return {'cm_return':1, 'cm_error':format(e)}
01642
01643 return {'cm_return':0}
01644
01645
01646 def flatten_array(i):
01647 """
01648 Flatten array
01649 Any list item is converted to @number=value
01650 Any dict item is converted to #key=value
01651 # is always added at the beginning
01652
01653 Input: {
01654 cm_array - full array
01655 prefix - prefix (for recursion)
01656 }
01657
01658 Output: {
01659 cm_return - if =0, success
01660 cm_array - flattened array
01661 }
01662 """
01663
01664
01665 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'parameter "cm_array" is not defined in "kernel flatten_array"'}
01666
01667 prefix='#'
01668 if 'prefix' in i: prefix=i['prefix']
01669
01670 a=i['cm_array']
01671 aa={}
01672
01673 flatten_array_internal(a, aa, prefix)
01674
01675 return {'cm_return':0, 'cm_array': aa}
01676
01677
01678 def flatten_array_internal(a, aa, prefix):
01679
01680 if type(a) is dict or type(a) is list:
01681 i=0
01682 for x in a:
01683 if type(a) is dict:
01684 v=a[x]
01685 prefix1=prefix+'#'+x
01686 else:
01687 prefix1=prefix+'@'+str(i)
01688 v=x
01689 if type(v) is dict or type(v) is list:
01690 flatten_array_internal(v, aa, prefix1)
01691 else:
01692 aa[prefix1]=v
01693 i+=1
01694 else:
01695 aa[prefix]=a
01696
01697 return {'cm_return':0, 'cm_array': a}
01698
01699
01700 def get_value_by_flattened_key(i):
01701 """
01702 Get value from array using flattened key
01703
01704 Input: {
01705 cm_array - array
01706 cm_key - flattened key
01707 }
01708
01709 Output: {
01710 cm_return - if =0, success
01711 cm_value - value or None
01712 }
01713 """
01714
01715 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not defined in "kernel get_value_by_flattened_key"'}
01716 if 'cm_key' not in i: return {'cm_return':1, 'cm_error':'"cm_key" is not defined in "kernel get_value_by_flattened_key"'}
01717
01718 v=None
01719
01720 a=i['cm_array']
01721 k=i['cm_key']
01722
01723
01724 if len(k)>0 and k[0:1]=='#': k=k[1:]
01725
01726 k1=''
01727 kt=''
01728 x=0
01729 finish=False
01730
01731 while not finish:
01732 y=k[x]
01733 x+=1
01734
01735 if y=='#' or y=='@':
01736 if kt=='#':
01737 if k1 not in a: break
01738 a=a[k1]
01739 elif kt=='@':
01740 if len(a)<=long(k1): break
01741 a=a[long(k1)]
01742 k1=''
01743 kt=y
01744 else:
01745 k1+=y
01746
01747 if x>=len(k): break
01748
01749 if k1!='' and kt!='':
01750 if kt=='#':
01751 if k1 in a: v=a[k1]
01752 else:
01753 if len(a)>long(k1): v=a[long(k1)]
01754
01755 return {'cm_return':0, 'cm_value': v}
01756
01757
01758 def set_value_by_flattened_key(i):
01759 """
01760 Set value in array using flattened key
01761
01762 Input: {
01763 cm_array - array (it will be directly changed!)
01764 cm_key - flattened key (or not if doesn't start with #)
01765 cm_value - value to set
01766 cm_replace_in_keys - array with strings to replace in keys
01767 (used in forms to process # and @ through ^35^ and ^64^ for example)
01768 }
01769
01770 Output: {
01771 cm_return - if =0, success
01772 cm_array - modified array
01773 }
01774 """
01775
01776 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not defined in "kernel get_value_by_flattened_key"'}
01777 if 'cm_key' not in i: return {'cm_return':1, 'cm_error':'"cm_key" is not defined in "kernel get_value_by_flattened_key"'}
01778 if 'cm_value' not in i: return {'cm_return':1, 'cm_error':'"cm_value" is not defined in "kernel get_value_by_flattened_key"'}
01779
01780 rep={}
01781 if 'cm_replace_in_keys' in i: rep=i['cm_replace_in_keys']
01782
01783 a=i['cm_array']
01784 k=i['cm_key']
01785 v=i['cm_value']
01786
01787 if len(k)>0 and k[0]!='#':
01788 k=replace_from_dict(k, rep)
01789 a[k]=v
01790 else:
01791
01792 if len(k)>0 and k[0:1]=='#': k=k[1:]
01793
01794 k1=''
01795 kt=''
01796 x=0
01797 finish=False
01798
01799 while not finish:
01800 y=k[x]
01801 x+=1
01802
01803 if y=='#' or y=='@':
01804 if kt=='#':
01805 k1=replace_from_dict(k1, rep)
01806 if k1 not in a:
01807 if y=='#': a[k1]={}
01808 else: a[k1]=[]
01809 a=a[k1]
01810 elif kt=='@':
01811 if len(a)<=long(k1):
01812 for q in range(len(a)-1,long(k1)):
01813 if y=='#': a.append({})
01814 else: a.append([])
01815 a=a[long(k1)]
01816 k1=''
01817 kt=y
01818 else:
01819 k1+=y
01820
01821 if x>=len(k): break
01822
01823 if k1!='' and kt!='':
01824 if kt=='#':
01825 k1=replace_from_dict(k1, rep)
01826 a[k1]=v
01827 else:
01828 if len(a)<=long(k1):
01829 for q in range(len(a)-1,long(k1)):
01830 if y=='#': a.append({})
01831 else: a.append([])
01832 a[long(k1)]=v
01833
01834 return {'cm_return':0, 'cm_array': i['cm_array']}
01835
01836
01837 def replace_from_dict(s, rep):
01838 """
01839 Replace substrings from array rep in string s
01840
01841 Input: s - string
01842 rep - array with substrings to replace
01843
01844 Output: new string
01845 """
01846
01847 for x in rep:
01848 s=s.replace(x, rep[x])
01849
01850 return s
01851
01852
01853 def restore_flattened_array(i):
01854 """
01855 Restore flattened array
01856
01857 Input: {
01858 cm_array - flattened array
01859 (cm_replace_in_keys) - array with strings to replace in keys
01860 (used in forms to process # and @ through ^35^ and ^64^ for example)
01861 }
01862
01863 Output: {
01864 cm_return - if =0, success
01865 cm_array - restored array
01866 }
01867 """
01868
01869 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not defined in "kernel restore_flattened_key"'}
01870
01871 rep={}
01872 if 'cm_replace_in_keys' in i: rep=i['cm_replace_in_keys']
01873
01874 a={}
01875 b=i['cm_array']
01876 first=True
01877 for x in b:
01878 if first:
01879 first=False
01880 y=x[1:2]
01881 if y=='@': a=[]
01882 else: a={}
01883
01884 cm_kernel.set_value_by_flattened_key({'cm_array':a, 'cm_key':x, 'cm_value':b[x], 'cm_replace_in_keys':rep})
01885
01886 return {'cm_return':0, 'cm_array': a}
01887
01888
01889 def delete_directory(i):
01890 """
01891 Delete a given directory with subdirectories (be careful)
01892
01893 Input: {
01894 cm_path - path to delete
01895 }
01896
01897 Output: {
01898 cm_return - return code = 0 if successful
01899 }
01900 """
01901
01902 r=check_global_writing({})
01903 if r['cm_return']>0: return r
01904
01905 if 'cm_path' not in i:
01906 return {'cm_return':1, 'cm_error':'parameter "cm_path" is not defined'}
01907 p=i['cm_path']
01908
01909 if not os.path.isdir(p):
01910 return {'cm_return':1, 'cm_error':p+' is not directory'}
01911
01912 forbid=False
01913 if os.path.isdir(ini['cm_default_repo']) and os.stat(p)==os.stat(ini['cm_default_repo']): forbid=True
01914 if os.path.isdir(ini[env_cm_root]) and os.stat(p)==os.stat(ini[env_cm_root]): forbid=True
01915
01916 if 'forbid_deletion_of_dirs' in ini['dcfg']:
01917 for x in ini['dcfg']['forbid_deletion_of_dirs']:
01918 if os.path.isdir(x) and os.stat(p)==os.stat(x): forbid=True; break
01919
01920 if forbid:
01921 return {'cm_return':1, 'cm_error': 'forbidden to delete '+p}
01922
01923 shutil.rmtree(p)
01924
01925 return {'cm_return':0}
01926
01927
01928 def convert_string_to_html(i):
01929 """
01930 Convert string to html (remove special characters)
01931
01932 Input: {
01933 cm_string - string to process
01934 cm_skip_br - if 'yes', do not add <BR>
01935 }
01936
01937 Output: {
01938 cm_return - return code = 0 if successful
01939 cm_string - processed string
01940 }
01941 """
01942
01943 if 'cm_string' not in i: return {'cm_return':1, 'cm_error':'parameter "cm_string" is not defined in kernel/convert_string_to_html'}
01944
01945 s=i['cm_string']
01946 s=s.replace('&', '&')
01947 s=s.replace('<', '<')
01948 s=s.replace('>', '>')
01949 s=s.replace('"', '"')
01950 s=s.replace('\r', '')
01951
01952
01953 if i.get('cm_skip_br', '')!='yes':
01954 s=s.replace('\n', '<BR>')
01955
01956 return {'cm_return':0, 'cm_string':s}
01957
01958
01959 def flatten_classification(i):
01960 """
01961 Flatten classification ["class", "subclass", ..."] to class.subclass. ...
01962
01963 Input: {
01964 cm_classification=[]
01965 }
01966
01967 Output: {
01968 cm_return - return code = 0 if successful
01969 cm_string - classification as string
01970 }
01971 """
01972
01973 if 'cm_classification' not in i: return {'cm_return':1, 'cm_error':'parameter "cm_classification" is not defined in kernel/flatten_classification'}
01974
01975 cc=i['cm_classification']
01976 cs=''
01977
01978 first=True; y=''
01979 for x in cc:
01980 if first: first=False
01981 else: y+='.'
01982 y+=x
01983
01984 return {'cm_return':0, 'cm_string':y}
01985
01986
01987 def set_print_mode(i):
01988 """
01989 Set print mode
01990
01991 Input: {
01992 'mode' = 'on' | 'off'
01993 }
01994
01995 Output:
01996 """
01997 global print_on
01998
01999 mode=i.get('mode','on')
02000 if mode=='on': print_on=True
02001 else: print_on=False
02002
02003 return {'cm_return':0}
02004
02005
02006 def print_for_web(s):
02007 """
02008 Print string in UTF-8
02009
02010 Input: s - string
02011
02012 Output:
02013 """
02014
02015 if print_on:
02016 print(s.encode("utf-8", 'ignore'))
02017
02018 return
02019
02020
02021 def print_for_con(s):
02022 """
02023 Print string
02024
02025 Input: s - string
02026
02027 Output:
02028 """
02029
02030 if print_on:
02031 print(s)
02032
02033 return
02034
02035
02036 def get_all_uoa(i):
02037 """
02038 Get a list of all entries in the repository
02039
02040 Input: {
02041 cm_path - path to repository
02042 (cm_module_uoa) - module UOA. If =='', return available modules in the repository
02043 (or use cm_only_available_modules explicitly)
02044 cm_only_uid - 'yes' to show only UIDs
02045 (cm_classes_uoa) - prune by classes UOA
02046 (prune_data_uoa) - prune by data UOA
02047 (cm_only_available_modules) - if 'yes', return only available modules in a given repository
02048 (skip_data_cfg) - if 'yes', do not add data cfg
02049 (cm_admin) - if 'yes', override access control - only internal use,
02050 can not be used during web access (explicitly removed)
02051 }
02052
02053 Output: {
02054 cm_return - return code = 0 if successful
02055 cm_array - list of UOA or only UID
02056 cm_mixed - list of {cm_uid, cm_alias, cm_uoa, cm_display_as_alias, cm_display_html, cm_data_obj_cfg}
02057 }
02058 """
02059
02060 if 'cm_path' not in i:
02061 return {'cm_return':1, 'cm_error':'parameter "cm_path" is not defined'}
02062
02063 sdc=False
02064 if i.get('skip_data_cfg','')=='yes': sdc=True
02065
02066 array=[]
02067 mixed=[]
02068
02069 pp=i['cm_path']
02070
02071 module_uoa=i.get('cm_module_uoa','')
02072 if i.get('cm_only_available_modules','')!='yes' and module_uoa!='':
02073 r=find_path_to_entry({'cm_path':pp, 'cm_data_uoa':module_uoa})
02074 if r['cm_return']>0: return r
02075 elif r['cm_return']<0:
02076
02077 return {'cm_return':0, 'cm_array':array, 'cm_mixed':mixed}
02078
02079 p=r['cm_path']
02080 else:
02081 module_uoa=ini['dcfg']['cm_module_module_uoa']
02082 p=pp
02083 pp=''
02084
02085 only_uid=False
02086 if i.get('cm_only_uid','')=='yes': only_uid=True
02087
02088 if os.path.isdir(p):
02089 dirList=os.listdir(p)
02090 for fn in dirList:
02091 p1=os.path.join(p,fn)
02092 if fn!=ini['dcfg']['dcm'] and fn not in ini['dcfg']['ignore_entries'] and os.path.isdir(p1):
02093
02094 ii={'cm_path':pp,
02095 'cm_module_uoa':module_uoa,
02096 'cm_data_uoa':fn}
02097 if i.get('cm_admin','')!='': ii['cm_admin']=i['cm_admin']
02098 r1=load_data(ii)
02099 if r1['cm_return']==0:
02100 d=r1['cm_data_obj']['cfg']
02101
02102 if i.get('prune_data_uoa','')!='':
02103 if (r1['cm_uid']!=i['prune_data_uoa'] and r1['cm_uoa']!=i['prune_data_uoa']):
02104 break
02105
02106 if 'cm_classes_uoa' in i:
02107 add=True
02108 if 'cm_classes_uoa' not in d:
02109 add=False
02110 else:
02111 for q in i['cm_classes_uoa']:
02112 if q not in d['cm_classes_uoa']:
02113 add=False
02114 break
02115 if not add: continue
02116
02117 if only_uid:
02118 x=r1['cm_uid']
02119 else:
02120 x=fn
02121
02122 array.append(x)
02123
02124 jj={'cm_uid':r1['cm_uid'], \
02125 'cm_alias':r1['cm_alias'], \
02126 'cm_uoa':r1['cm_uoa'], \
02127 'cm_module_uid':r1['cm_module_uid'], \
02128 'cm_module_uoa':r1['cm_module_uoa'], \
02129 'cm_display_as_alias':r1['cm_display_as_alias'], \
02130 'cm_display_html':r1['cm_display_html'], \
02131 }
02132 if not sdc: jj['cm_data_obj_cfg']=d
02133 mixed.append(jj)
02134
02135 return {'cm_return':0, 'cm_array':array, 'cm_mixed':mixed}
02136
02137
02138 def get_list_of_all_files(i):
02139 """
02140 Get a list of all files in a given directory recursively
02141
02142 Input: {
02143 cm_path - path
02144 cm_path_ext - path extension
02145 limit - limit number of files (if huge directories)
02146 number - cur. number of files
02147 cm_all_files - if 'yes' do not ignore special files (like .cm)
02148 }
02149
02150 Output: {
02151 cm_return - return code = 0 if successful
02152 cm_array - list of files
02153 }
02154 """
02155
02156 number=0
02157 if 'number' in i: number=i['number']
02158
02159 limit=-1
02160 if 'limit' in i: limit=i['limit']
02161
02162 a=[]
02163
02164 pe=''
02165 if 'cm_path_ext' in i: pe=i['cm_path_ext']
02166
02167 try:
02168 dirList=os.listdir(i['cm_path'])
02169 except Exception as e:
02170 None
02171 else:
02172 for fn in dirList:
02173
02174 if fn!='.svn':
02175 p=os.path.join(i['cm_path'], fn)
02176 if i.get('cm_all_files','')=='yes' or (fn!=ini['dcfg']['dcm'] and fn not in ini['dcfg']['ignore_entries']):
02177 if os.path.isdir(p):
02178 r=get_list_of_all_files({'cm_path':os.path.join(p), 'cm_path_ext':os.path.join(pe, fn), 'number':number})
02179 if r['cm_return']>0: return r
02180 a.extend(r['cm_array'])
02181 else:
02182 a.append(os.path.join(pe, fn))
02183
02184 number=len(a)
02185 if limit!=-1 and number>limit: break
02186
02187 return {'cm_return':0, 'cm_array':a, 'number':number}
02188
02189
02190 def get_data_description(i):
02191
02192 """
02193 Get data entry description
02194
02195 Input: {
02196 cm_run_module_uoa | cm_module_uoa - module UOA
02197 (cm_desc_key) - if this key is specified, take description from this key
02198 (cm_flat_desc_key) - if this flat key is specified, take description from this flat key
02199 (cm_action_key) - action key
02200 cm_which_action - action
02201 (cm_key) - if action is specified, use this key instead of default one
02202 }
02203
02204 Output: {
02205 cm_return - return code >0 if error
02206 cm_data_desc - data description
02207 cm_params_default - data description
02208 ... - other parameters from load_data
02209 }
02210 """
02211
02212
02213 a={}
02214
02215
02216 b={}
02217
02218
02219 r1={}
02220 if 'cm_repo_uoa' in i: r1['cm_repo_uoa']=i['cm_repo_uoa']
02221 r1['cm_data_uoa']=i['cm_module_uoa']
02222 r1['cm_module_uoa']=cm_kernel.ini['dcfg']['cmr_module']
02223 r=load_data(r1)
02224 if r['cm_return']>0: return r
02225 d=r['cm_data_obj']
02226
02227 if i.get('cm_desc_key','')!='':
02228 a.update(d['cfg'].get(i['cm_desc_key'],{}))
02229 elif i.get('cm_flat_desc_key','')!='':
02230 rx=cm_kernel.get_value_by_flattened_key({'cm_array':d['cfg'], 'cm_key':i['cm_flat_desc_key']})
02231 if rx['cm_return']==0 and rx['cm_value']!=None:
02232 a.update(rx['cm_value'])
02233 else:
02234 ak=i.get('cm_action_key','')
02235 if ak=='': ak='cm_actions'
02236
02237 if 'cm_which_action' in i:
02238 if ak in d['cfg']:
02239 r1=cm_kernel.find_index_in_array({
02240 'cm_array':d['cfg'][ak],
02241 'cm_index':i['cm_which_action']
02242 })
02243 if r1['cm_return']==0:
02244 key=i.get('cm_key','')
02245 if key=='' and 'params_desc' in r1['cm_array']: a.update(r1['cm_array']["params_desc"])
02246 elif key!='' and key in r1['cm_array']: a.update(r1['cm_array'][key])
02247 if 'params_default' in r1['cm_array']: b.update(r1['cm_array']["params_default"])
02248 else:
02249
02250
02251 red=d['cfg'].get('cm_data_description_from_other_module',{})
02252 if red.get('cm_module_uoa','')!='':
02253
02254 ii={'cm_run_module_uoa':cm_kernel.ini['dcfg']['cmr_module'],
02255 'cm_action':'load',
02256 'cm_data_uoa':red['cm_module_uoa']}
02257 r=cm_kernel.access(ii)
02258 if r['cm_return']>0: return r
02259 d=r['cm_data_obj']
02260
02261 if 'cm_data_description' in d['cfg']:
02262 a.update(d['cfg']['cm_data_description'])
02263
02264 ii={}; ii.update(r)
02265 ii['cm_return']=0
02266 ii['cm_data_desc']=a
02267 ii['cm_params_default']=b
02268 return ii
02269
02270
02271 def system(i):
02272
02273 """
02274 System call with timeout (careful, may cause overheads)
02275
02276 Input: {
02277 cmd - command line
02278 (timeout) - timeout in seconds (granularity 0.01 sec) - may cause overheads ...
02279 }
02280
02281 Output: {
02282 cm_return - return code =0 if success
02283 =1 if timedout and killed
02284 (cm_error) - error text if return code > 0
02285 cm_return_code - return code of a program
02286 }
02287 """
02288
02289 rc=0
02290 if 'timeout' not in i or i['timeout']=='' or float(i['timeout'])==0:
02291 rc=os.system(i['cmd'])
02292 else:
02293 tstart=time.time()
02294 t=0
02295 tx=float(i['timeout'])
02296
02297 p=subprocess.Popen(i['cmd'], shell=True)
02298
02299 while p.poll() == None and t<tx:
02300 time.sleep(0.01)
02301 t=time.time()-tstart
02302
02303 if t>=tx and p.poll()==None:
02304 p.kill()
02305
02306 return {'cm_return':1, 'cm_error':'process timed out and was killed'}
02307
02308 rc=p.returncode
02309
02310 return {'cm_return':0, 'cm_return_code':rc}
02311
02312
02313 def gen_cm_tmp_file(i):
02314
02315 """
02316 Generate tmp file name
02317
02318 Input: {}
02319
02320 Output: {
02321 cm_return - return code >0 if error
02322 cm_path - path to file
02323 cm_path1 - path to file without extension
02324 (for example, a script will create many sub-files with different extensions)
02325 cm_uid - generated uid
02326 }
02327 """
02328
02329 r=gen_uid({})
02330 if r['cm_return']>0: return r
02331 uid=r['cm_uid']
02332
02333 p1=os.path.join(ini[env_cm_tmp], ini['dcfg']['cm_tmp_prefix']+uid)
02334 p=p1+ini['dcfg']['cm_tmp_postfix']
02335
02336 return {'cm_return':0, 'cm_path':p, 'cm_uid':uid, 'cm_path1':p1}
02337
02338
02339 def array2cm(a):
02340 """
02341 Convert list to cm array
02342
02343 cm_module_uoa cm_action A=B C=D ... @file1.json E=F ... -- <unparsed arguments>
02344
02345 if extension of @file is .tmp, it will be deleted after read!
02346
02347 Input: input array
02348
02349 Output: {
02350 cm_return - return code = 0 if successful
02351 cm_array - array
02352 cm_console - if 'cm_console' in array, set it to the value of 'cm_console' parameter
02353 }
02354 """
02355 obj={}
02356 con=''
02357
02358 la=len(a)
02359
02360 obj['cm_run_module_uoa']=cm_module_default
02361 obj['cm_action']=cm_action_default
02362
02363 if la>0: obj['cm_run_module_uoa']=a[0]
02364
02365
02366 for x in range(1, len(a)):
02367 p=a[x].rstrip()
02368 if p==cm_unparsed_sep:
02369
02370 obj['cm_unparsed']=a[x+1:]
02371 break
02372
02373 elif p.startswith("@@"):
02374 jd=p[2:]
02375 if len(jd)<2:
02376 return {'cm_return':1, 'cm_error':'can\'t parse command line option '+p, 'cm_console':con}
02377 je=check_cm_json({'cm_json':jd})
02378 obj.update(je)
02379
02380 elif p.startswith("@"):
02381 name=p[1:]
02382 if len(name)<2:
02383 return {'cm_return':1, 'cm_error':'can\'t parse command line option '+p, 'cm_console':con}
02384
02385 y=load_json_file({'cm_filename':name})
02386 if y['cm_return']>0:
02387
02388 ii={}; ii.update(y); ii.update({'cm_console':con})
02389 return ii
02390
02391 if name.endswith('.tmp'):
02392 os.remove(name)
02393
02394 merge_arrays({'cm_array':obj, 'cm_array1':y['cm_array']})
02395 else:
02396 if x==1:
02397 obj['cm_action']=p
02398 else:
02399 p1=p
02400 p2=''
02401 q=p.find("=")
02402 if q>0:
02403 p1=p[0:q]
02404 if len(p)>q:
02405 p2=p[q+1:]
02406
02407 obj[p1]=p2
02408 if p1=='cm_console': con=p2
02409
02410 return {'cm_return':0, 'cm_array':obj, 'cm_console':con}
02411
02412
02413 def convert_text_to_value(i):
02414 """
02415 Convert cm text to cm value
02416
02417 Input: {
02418 cm_text - text to convert
02419 cm_type - type: {float, integer, string, uoa}
02420
02421 Output: {
02422 cm_return - return code = 0 if successful
02423 cm_value - value in python format
02424 }
02425 """
02426
02427 v=None
02428
02429 if 'cm_text' not in i: return {'cm_return':1, 'cm_error':'"cm_text" is not defined in kernel/convert_text_to_value'}
02430 if 'cm_type' not in i: return {'cm_return':1, 'cm_error':'"cm_type" is not defined in kernel/convert_text_to_value'}
02431
02432 t=i['cm_text']
02433 tp=i['cm_type']
02434
02435 if tp=='float':
02436 try:
02437 v=float(t)
02438 except ValueError:
02439 return {'cm_return':16, 'cm_error':'can\'t convert '+str(t)+' to float'}
02440 elif tp=='integer':
02441 try:
02442 v=int(t)
02443 except ValueError:
02444 return {'cm_return':16, 'cm_error':'can\'t convert '+str(t)+' to int'}
02445 elif tp=='uoa' or tp=='string' or tp=='text':
02446 v=str(t)
02447 else:
02448 return {'cm_return':16, 'cm_error':'can\'t recognize type '+tp}
02449
02450 return {'cm_return':0, 'cm_value':v}
02451
02452
02453 def find_keys_by_prefix(i):
02454 """
02455 Find keys by prefix
02456
02457 Input: {
02458 cm_array - array to search
02459 cm_prefix - prefix to search
02460 cm_sort_key_int - sort key (int)
02461 cm_sort_key_text - sort key (text)
02462 }
02463
02464 Output: {
02465 cm_return - return code = 0 if successful
02466 keys - list of keys
02467 }
02468 """
02469
02470 prefix=i.get('cm_prefix','')
02471 ski=i.get('cm_sort_key_int','')
02472 skt=i.get('cm_sort_key_text','')
02473
02474 keys=[]
02475
02476 a=i.get('cm_array',{})
02477 if ski!='':
02478 b=sorted(a.keys(), key=lambda k: (int(a[k].get(ski,'999999'))))
02479 elif skt!='':
02480 b=sorted(a.keys(), key=lambda k: (a[k].get(skt,'').lower()))
02481 else:
02482 b=a
02483
02484 for k in b:
02485 if k.startswith(prefix): keys.append(k)
02486
02487 return {'cm_return':0, 'cm_keys':keys}
02488
02489
02490 def merge_arrays_ll(a, b):
02491 """
02492 Intelligently merge cm_array with cm_array1
02493
02494 Input: a - merge this array with cm_array1 (will be directly modified!)
02495 b - cM array
02496
02497 Output: {
02498 cm_return - return code = 0 if successful
02499 }
02500 """
02501 return merge_arrays({'cm_array':a, 'cm_array1':b})
02502
02503
02504 def merge_arrays(i):
02505 """
02506 Intelligently merge cm_array with cm_array1
02507
02508 Input: {
02509 cm_array - merge this array with cm_array1 (will be directly modified!)
02510 cm_array1 - cM array
02511
02512 Output: {
02513 cm_return - return code = 0 if successful
02514 cm_array - output array
02515 }
02516 """
02517
02518 if 'cm_array' not in i: return {'cm_return':1, 'cm_error':'"cm_array" is not defined in "cm_kernel merge_arrays"'}
02519 if 'cm_array1' not in i: return {'cm_return':1, 'cm_error':'"cm_array1" is not defined in "cm_kernel merge_arrays"'}
02520
02521 a=i['cm_array']
02522 b=i['cm_array1']
02523
02524 for k in b:
02525 v=b[k]
02526 if type(v) is dict:
02527 if k not in a:
02528 a.update({k:b[k]})
02529 elif type(a[k])==dict:
02530 merge_arrays({'cm_array':a[k], 'cm_array1':b[k]})
02531 else:
02532 a[k]=b[k]
02533 elif type(v) is list:
02534
02535
02536 a[k]=[]
02537 for y in v:
02538 a[k].append(y)
02539 else:
02540 a[k]=b[k]
02541
02542 return {'cm_return':0, 'cm_array':a}
02543
02544
02545 def str2cm(i):
02546 """
02547 Convert string to cM array
02548
02549 Input: string
02550
02551 Output: {
02552 cm_return - return code = 0 if successful
02553 cm_array - array
02554 }
02555 """
02556
02557
02558 a=shlex.split(i)
02559 return array2cm(a)
02560
02561
02562 def array2str(i):
02563 """
02564 Convert array to string with space
02565
02566 Input: array
02567
02568 Output: {
02569 cm_return - 0
02570 cm_string - string
02571 }
02572 """
02573 s=string.join(i, ' ')
02574 return {'cm_return':0, 'cm_string':s}
02575
02576
02577 def get_var(a,p):
02578 """
02579 Check if parameter 'p' is in array 'a' and return a[p] or '' otherwise
02580
02581 Input: a - array
02582 p - parameter
02583
02584 Output: a[p], if 'p' in 'a'
02585 '', if 'p' not in 'a'
02586
02587 """
02588
02589 if p not in a: return ''
02590 return a[p]
02591
02592
02593 def prepare_final_out(i, j):
02594 """
02595 Prepare final output of cM access function depending on cm_console
02596
02597 Input: i= {
02598 cm_return - return code (check "access" function for full description)
02599 (cm_error) - error text (check "access" function for full description)
02600 ...
02601 }
02602
02603 j= {
02604 (cm_console) - cm_console (check "access" function for full description)
02605 (cm_output) - if !='', save output to file
02606 ...
02607 }
02608
02609 Output: {}
02610
02611 """
02612
02613
02614 if i['cm_return']>0:
02615 if j.get('cm_console','')=='txt': print_for_con('cM error: '+i['cm_error']+'!')
02616 if j.get('cm_console','')=='web': print_for_web('<br><pre>cM error: '+i['cm_error']+'!</pre><br>')
02617
02618
02619 if j.get('cm_output','')!='':
02620 rx=save_array_to_file_as_json({'cm_filename':j['cm_output'], 'cm_array':i})
02621 if rx['cm_return']>0:
02622 print_for_con('cM error: '+rx['cm_error']+'!')
02623
02624
02625 if j.get('cm_console','')=='json':
02626 print_for_con(json.dumps(i))
02627 if j.get('cm_console','')=='json_after_text':
02628 print_for_con(cm_json_with_text_sep)
02629 print_for_con(json.dumps(i))
02630 elif j.get('cm_console','')=='json_with_indent':
02631 print_for_con(json.dumps(i, indent=2, sort_keys=True))
02632
02633 return {}
02634
02635
02636 def check_cm_json(i):
02637 """
02638 Check if 'cm_json' exist in array and decode it
02639
02640 Input: {
02641 cm_json - array to check
02642 }
02643
02644 Output: {...} - returned array where cm_json is decoded
02645 """
02646
02647 ii={}
02648 ii.update(i)
02649
02650 if 'cm_json' in i:
02651 s=i['cm_json']
02652 s=s.replace('^22^', '"')
02653 s=s.replace('%22', '"')
02654 s=s.replace('%26quot;', '"')
02655 s=s.replace('"', '"')
02656 success=False
02657 try:
02658 j=json.loads(s)
02659 success=True
02660 except:
02661 pass
02662 if success:
02663 del (ii['cm_json'])
02664 ii.update(j)
02665
02666 return ii
02667
02668
02669 def convert_cm_array_to_uri(i):
02670 """
02671 Convert cM array to uri (convert various special parameters)
02672
02673 Input: {
02674 cm_array - array to convert to uri
02675 }
02676
02677 Output: {
02678 cm_return - return code (check "access" function for full description)
02679 (cm_error) - error text (check "access" function for full description)
02680 cm_string - converted string
02681 cm_string1 - converted string (for urlopen)
02682 }
02683 """
02684
02685 if 'cm_array' not in i:
02686 return {'cm_return':1, 'cm_error':'"cm_array" is not set in kernel/convert_cm_array_to_uri'}
02687
02688 ca=i['cm_array']
02689 cca=copy.deepcopy(ca)
02690
02691 if 'cm_user_uoa' in cca: del(cca['cm_user_uoa'])
02692
02693 s=json.dumps(cca)
02694 s=s.replace('"', '^22^')
02695 s=s.replace('#', '%23')
02696
02697 s=s.replace('+', '%2B')
02698
02699 s1=s.replace('>', '%3E')
02700 s1=s1.replace('<', '%3C')
02701
02702 s1=s1.replace('[', '%5B')
02703 s1=s1.replace(']', '%5D')
02704 s1=s1.replace(' ', '%20')
02705
02706 s=cgi.escape(s)
02707
02708 return {'cm_return':0, 'cm_string':s, 'cm_string1':s1}
02709
02710
02711 def copy_vars(i):
02712 """
02713 Convert cM array to uri (convert various special parameters)
02714
02715 Input: {
02716 cm_input_array - input array
02717 cm_output_array - output array
02718 cm_vars - list of variables to copy
02719 }
02720
02721 Output: {
02722 cm_return - return code (check "access" function for full description)
02723 }
02724 """
02725
02726 if 'cm_input_array' not in i: return {'cm_return':1, 'cm_error':'"cm_input_array" is not defined in kernel/copy_vars'}
02727 if 'cm_output_array' not in i: return {'cm_return':1, 'cm_error':'"cm_output_array" is not defined in kernel/copy_vars'}
02728 if 'cm_vars' not in i: return {'cm_return':1, 'cm_error':'"cm_vars" is not defined in kernel/copy_vars'}
02729
02730 inp=i['cm_input_array']
02731 out=i['cm_output_array']
02732
02733 vr=i['cm_vars']
02734
02735 inp1=inp.keys()
02736 if len(vr)>0: inp1=vr
02737
02738 for x in inp1:
02739 if x in inp: out[x]=inp[x]
02740
02741 return {'cm_return':0}
02742
02743
02744 def convert_str_to_special(s):
02745 """
02746 Convert string to a special cM string that is used to substitute variables in text
02747
02748 Input: string
02749
02750 Output: special string
02751 """
02752
02753 return '$#'+s+'#$'
02754
02755
02756 def get_cm_version(i):
02757
02758 """
02759 Get cM version
02760
02761 Input: {
02762 }
02763
02764 Output: {
02765 cm_return - return code >0 if not authentificated
02766 cm_array - array with version
02767 cm_string - version
02768 }
02769 """
02770
02771 a={}
02772 x=''
02773
02774 if 'cm_version' in ini['dcfg']:
02775 a=ini['dcfg']['cm_version']
02776
02777 if 'major' in a: x+=str(a['major'])
02778 if 'minor' in a: x+='.'+str(a['minor'])
02779 if 'build' in a: x+='.'+str(a['build'])
02780 if 'extra' in a: x+='.'+str(a['extra'])
02781
02782 return {'cm_return':0, 'cm_array':a, 'cm_string':x}
02783
02784
02785 def convert_str_to_sha1(i):
02786
02787 """
02788 Convert string to sha1
02789
02790 Input: {
02791 cm_string - string
02792 }
02793
02794 Output: {
02795 cm_return - return code >0 if not authentificated
02796 cm_string_sha1 - password in SHA1 (digest)
02797 cm_string_sha1_hex - password in SHA1 (digest in hex)
02798 cm_string_sha1_base64 - BASE64 (SHA1 digest) - compatible with htpasswd format
02799 }
02800 """
02801
02802 if 'cm_string' not in i:
02803 return {'cm_return':1, 'cm_error':'"cm_string" is not set'}
02804
02805 x=hashlib.sha1()
02806 x.update(i['cm_string'])
02807 y=x.digest().strip()
02808 z=x.hexdigest().strip()
02809 b=base64.encodestring(y).strip()
02810
02811 return {'cm_return':0, 'cm_string_sha1':y, 'cm_string_sha1_hex':z, 'cm_string_sha1_base64':b}
02812
02813
02814 def prepare_cid(i):
02815
02816 """
02817 Prepare cid
02818
02819 Input: {
02820 (cm_repo_uoa) - repository UOA
02821 cm_run_module_uoa | cm_module_uoa - module UOA
02822 cm_data_uoa - data UOA
02823 }
02824
02825 Output: {
02826 cm_return - 0
02827 cm_string_uid - cid with only uid
02828 cm_string_with_repo_uid - cid with only uid
02829 cm_string_uoa - cid with alias or uid
02830 cm_string_with_repo_uoa - cid with alias or uid
02831 cm_repo_uid - cm_repo_uid
02832 cm_repo_uoa - cm_repo_uoa
02833 cm_module_uid - cm_module_uid
02834 cm_module_uoa - cm_module_uoa
02835 cm_data_uid - cm_data_uid
02836 cm_data_uoa - cm_data_uoa
02837 }
02838 """
02839
02840 cm_repo_uid=''
02841 cm_repo_uoa=''
02842 cm_module_uid=''
02843 cm_module_uoa=''
02844 cm_data_uid=''
02845 cm_data_uoa=''
02846
02847
02848 if 'cm_repo_uoa' in i and i['cm_repo_uoa']!='':
02849 ii={'cm_run_module_uoa':ini['dcfg']['cmr_repo'],
02850 'cm_data_uoa':i['cm_repo_uoa'],
02851 'cm_action':'load'}
02852 r=cm_kernel.access(ii)
02853 if r['cm_return']==0:
02854 cm_repo_uid=r['cm_uid']
02855 cm_repo_uoa=cm_repo_uid
02856 if r['cm_alias']!='': cm_repo_uoa=r['cm_alias']
02857 else:
02858 cm_repo_uoa=i['cm_repo_uoa']
02859
02860
02861 if 'cm_module_uoa' in i and i['cm_module_uoa']!='':
02862 ii={'cm_run_module_uoa':ini['dcfg']['cmr_module'],
02863 'cm_data_uoa':i['cm_module_uoa'],
02864 'cm_action':'load'}
02865 r=cm_kernel.access(ii)
02866 if r['cm_return']==0:
02867 cm_module_uid=r['cm_uid']
02868 cm_module_uoa=cm_module_uid
02869 if r['cm_alias']!='': cm_module_uoa=r['cm_alias']
02870 else:
02871 cm_module_uoa=i['cm_module_uoa']
02872
02873
02874 if 'cm_data_uoa' in i and i['cm_data_uoa']!='':
02875 ii={'cm_run_module_uoa':i['cm_module_uoa'],
02876 'cm_data_uoa':i['cm_data_uoa'],
02877 'cm_action':'load'}
02878 r=cm_kernel.access(ii)
02879 if r['cm_return']==0:
02880 cm_data_uid=r['cm_uid']
02881 cm_data_uoa=cm_data_uid
02882 if r['cm_alias']!='': cm_data_uoa=r['cm_alias']
02883 else:
02884 cm_data_uoa=i['cm_data_uoa']
02885
02886
02887 r={'cm_return':0}
02888 r['cm_string_uid']=cm_module_uid+':'+cm_data_uid
02889 if cm_repo_uid!='': r['cm_string_with_repo_uid']=cm_repo_uid+':'+r['cm_string_uid']
02890 r['cm_string_uoa']=cm_module_uoa+':'+cm_data_uoa
02891 if cm_repo_uoa!='': r['cm_string_with_repo_uoa']=cm_repo_uoa+':'+r['cm_string_uoa']
02892
02893 r['cm_repo_uid']=cm_repo_uid
02894 r['cm_repo_uoa']=cm_repo_uoa
02895 r['cm_module_uid']=cm_module_uid
02896 r['cm_module_uoa']=cm_module_uoa
02897 r['cm_data_uid']=cm_data_uid
02898 r['cm_data_uoa']=cm_data_uoa
02899
02900 return r
02901
02902
02903 def access_control(i):
02904
02905 """
02906 Control access
02907
02908 Input: {
02909 dcfg - cfg of the current entry
02910 module_uoa - module UOA of the entry
02911 module_uid - module UID of the entry
02912 data_uoa - data UOA of the entry
02913 key - 'read' or 'write'
02914 }
02915
02916 Output: {
02917 cm_return - 0, if Ok; ==32 if access denied
02918 cm_error - if access is denied
02919 }
02920 """
02921
02922 cm_user_uid=ini['web_auth'].get('cm_user_uid','')
02923 cm_user_uoa=ini['web_auth'].get('cm_user_uoa','')
02924 xcfg=i.get('dcfg',{})
02925
02926 module_uoa=i.get('module_uoa','')
02927 module_uid=i.get('module_uid','')
02928 data_uoa=i.get('data_uoa','')
02929
02930 key=i.get('key','')
02931
02932 ac=xcfg.get('access_control',{})
02933
02934 aread=xcfg.get('cm_access_control',{}).get(key+'_groups','')
02935
02936 access=False
02937
02938 if aread=='all':
02939 access=True
02940 elif cm_user_uoa!='' and cm_user_uid!='':
02941 if cm_user_uoa in ini['dcfg'].get('admin_users',[]) or \
02942 cm_user_uid in ini['dcfg'].get('admin_users',[]):
02943 access=True
02944 else:
02945 access=False
02946
02947
02948 if module_uid==ini['dcfg']['cm_user_module_uoa'] and \
02949 data_uoa==cm_user_uoa or data_uoa==cm_user_uid:
02950 access=True
02951 else:
02952
02953 if aread=='registered':
02954 access=True
02955 elif aread=='owner':
02956
02957 cmu=xcfg.get('cm_updated',[])
02958 if len(cmu)>0:
02959 owner_uoa=cmu[0].get('cm_user_uoa','')
02960 if owner_uoa==cm_user_uoa or owner_uoa==cm_user_uid:
02961 access=True
02962
02963 else:
02964
02965 if aread=='' or aread=='registered' or aread=='owner':
02966 access=False
02967
02968 if not access:
02969 if ini['web_auth']['cm_user_status']=='failed':
02970 return {'cm_return':32, 'cm_error':key+' access denied to "'+module_uoa+':'+data_uoa+'" (user authentication failed: '+ini['web_auth']['cm_error']+')!'}
02971 else:
02972 return {'cm_return':32, 'cm_error':key+' access denied to "'+module_uoa+':'+data_uoa+'" (user likely have to be registered, be administrator or owner of this data)!'}
02973
02974 return {'cm_return':0}
02975
02976
02977 def auth_user(i):
02978
02979 """
02980 Authenticate user
02981
02982 Input: {
02983 cm_user_uoa - user UOA
02984 cm_user_password - user password in plain text
02985 (not secure, usually used for web form authentication)
02986 cm_user_password1 - user password in SHA1
02987 (more secure, can be stored in environment, session or cookies)
02988 cM authenicates by taking SHA1(cm_user_password1)...
02989 cm_user_password2 - only should be set here by web environment!
02990 }
02991
02992 Output: {
02993 cm_return - return code = 0 if authenticated
02994 (cm_error) - error text, if cm_return > 0
02995 cm_user_cfg - user config if authenticated (to check groups, etc)
02996 cm_user_password2 - user password in SHA1(SHA1)
02997 cm_user_uid - user UID
02998 cm_user_uoa - user UOA
02999 cm_user_alias - user alias
03000 cm_user_path - user path
03001 }
03002 """
03003
03004
03005
03006
03007
03008
03009 if 'cm_user_uoa' not in i or i['cm_user_uoa']=='':
03010 if env_cm_user_uoa in os.environ.keys():
03011 i['cm_user_uoa']=os.environ[env_cm_user_uoa].strip()
03012
03013 if 'cm_user_password' not in i or i['cm_user_password']=='':
03014 if env_cm_user_password in os.environ.keys():
03015 i['cm_user_password']=os.environ[env_cm_user_password].strip()
03016
03017 if 'cm_user_password1' not in i or i['cm_user_password1']=='':
03018 if env_cm_user_password1 in os.environ.keys():
03019 i['cm_user_password1']=os.environ[env_cm_user_password1].strip()
03020
03021
03022 if 'cm_user_uoa' not in i or i['cm_user_uoa']=='':
03023 return {'cm_return':127, 'cm_error': '"cm_user_uoa" is not set in auth_user'}
03024
03025
03026 pwd1=''
03027 pwd2=''
03028 if 'cm_user_password' in i and i['cm_user_password']!='':
03029 r=convert_str_to_sha1({'cm_string':i['cm_user_password']})
03030 if r['cm_return']>0: return r
03031 pwd1=r['cm_string_sha1_base64']
03032 elif 'cm_user_password1' in i and i['cm_user_password1']!='':
03033 pwd1=i['cm_user_password1']
03034 elif 'cm_user_password2' in i and i['cm_user_password2']!='':
03035 pwd2=i['cm_user_password2']
03036
03037 if pwd2=='':
03038 if pwd1=='':
03039 return {'cm_return':127, 'cm_error':'authentication is required for this operation, but password is not set'}
03040
03041
03042 r=convert_str_to_sha1({'cm_string':pwd1})
03043 if r['cm_return']>0: return r
03044 pwd2=r['cm_string_sha1_base64']
03045
03046
03047 r=cm_kernel.access({'cm_run_module_uoa':ini['dcfg']['cm_user_module_uoa'],
03048 'cm_action':'load',
03049 'cm_data_uoa':i['cm_user_uoa'],
03050 'cm_admin':'yes'})
03051 if r['cm_return']>0:
03052 if r['cm_return']==16: r={'cm_return':16, 'cm_error':'can\'t find user "'+i['cm_user_uoa']+'"'}
03053 return r
03054
03055 user_cfg=r['cm_data_obj']['cfg']
03056 user_path=r['cm_path']
03057 user_uid=r['cm_uid']
03058 user_uoa=r['cm_uoa']
03059 user_alias=r['cm_alias']
03060
03061 if r['cm_uoa'] in ini['dcfg'].get('admin_users',[]) or \
03062 r['cm_uid'] in ini['dcfg'].get('admin_users',[]):
03063 ini['web_auth']['cm_admin']='yes'
03064
03065
03066 if 'cm_user_password2' not in user_cfg:
03067 return {'cm_return':127, 'cm_error':'user "'+i['cm_user_uoa']+'" doesn\'t have a password'}
03068
03069
03070 if pwd2!=user_cfg['cm_user_password2']:
03071 return {'cm_return':127, 'cm_error':'authentication failed (passwords do not match)'}
03072
03073
03074 return {'cm_return':0, 'cm_user_cfg':user_cfg, 'cm_user_password2':pwd2, 'cm_user_uid':user_uid,
03075 'cm_user_uoa':user_uoa, 'cm_user_alias':user_alias, 'cm_user_path':user_path}
03076
03077
03078 def auth_user_and_ini_cm(i):
03079
03080 """
03081 Check if need to auth user, try to auth and set cM vars
03082
03083 Input: {
03084 cm_user_uoa - user UOA
03085 cm_user_password - user password in plain text
03086 (not secure, usually used for web form authentication)
03087 cm_user_password1 - user password in SHA1
03088 (more secure, can be stored in environment, session or cookies)
03089 cM authenicates by taking SHA1(cm_user_password1)...
03090 cm_user_password2 - only should be set here by web environment!
03091 }
03092
03093 Output: {
03094 cm_return - return code = 0 if authenticated
03095 (cm_error) - error text, if cm_return > 0
03096
03097 If needed to auth or default user:
03098 cm_user_cfg - user config if authenticated (to check groups, etc)
03099 cm_user_password1 - user password in SHA1
03100 cm_user_uid - user UID
03101 cm_user_uoa - user UOA
03102 cm_user_alias - user alias
03103 cm_user_path - user path
03104 cm_user_status - 'no_user', 'default', 'logged_in' or 'failed'
03105 }
03106 """
03107
03108 rx={'cm_return':0}
03109
03110
03111 ini['web_auth']['cm_user_status']='no_user'
03112 if (i.get('cm_web','')!='yes' or ini['dcfg'].get('force_web_login','')!='yes') and \
03113 ini['dcfg'].get('cm_default_user_uoa','')!='':
03114
03115
03116 user=ini['dcfg']['cm_default_user_uoa']
03117 r=access({'cm_run_module_uoa':ini['dcfg']['cm_user_module_uoa'],
03118 'cm_action':'load',
03119 'cm_data_uoa':user,
03120 'cm_admin':'yes'})
03121 if r['cm_return']>0:
03122 if r['cm_return']==16: r={'cm_return':16, 'cm_error':'can\'t load default user "'+user+' - please, run configure.sh"'}
03123 return r
03124
03125 rx={'cm_user_cfg':r['cm_data_obj']['cfg'],
03126 'cm_user_uid':r['cm_uid'],
03127 'cm_user_uoa':r['cm_uoa'],
03128 'cm_user_alias':r['cm_alias'],
03129 'cm_user_path':r['cm_path'],
03130 'cm_user_status':'default'}
03131
03132 ini['web_auth']=copy.deepcopy(rx)
03133 rx['cm_return']=0
03134
03135 if r['cm_uoa'] in ini['dcfg'].get('admin_users',[]) or \
03136 r['cm_uid'] in ini['dcfg'].get('admin_users',[]):
03137 ini['web_auth']['cm_admin']='yes'
03138
03139
03140 if i.get('cm_web','')=='yes':
03141 if (ini['dcfg'].get('force_web_login','')=='yes' or \
03142 ini['dcfg'].get('allow_web_user_auth','')=='yes'):
03143
03144 ini['web_auth']['cm_admin']='no'
03145
03146 if ini['dcfg'].get('force_web_login','')!='yes' and \
03147 (i.get('cm_user_uoa','')!='' and ini['dcfg'].get('cm_default_user_uoa','')!='' and \
03148 (i['cm_user_uoa']==ini['web_auth']['cm_user_uid'] or i['cm_user_uoa']==ini['web_auth']['cm_user_alias'])):
03149 ini['web_auth']['cm_error']='user already logged in'
03150
03151 if i['cm_user_uoa'] in ini['dcfg'].get('admin_users',[]):
03152 ini['web_auth']['cm_admin']='yes'
03153
03154 else:
03155 rx=auth_user(i)
03156 if rx['cm_return']>0:
03157
03158 ini['web_auth']['cm_user_status']='failed'
03159 ini['web_auth']['cm_error']=rx['cm_error']
03160 else:
03161 ini['web_auth'].update(rx)
03162 ini['web_auth']['cm_user_status']='logged_in'
03163
03164 if rx['cm_user_uoa'] in ini['dcfg'].get('admin_users',[]) or \
03165 rx['cm_user_uid'] in ini['dcfg'].get('admin_users',[]):
03166 ini['web_auth']['cm_admin']='yes'
03167
03168 rx['cm_return']=0
03169
03170
03171 if ini['web_auth'].get('cm_user_status','')=='failed' and \
03172 ini['dcfg'].get('cm_default_user_uoa','')!='':
03173
03174
03175 user=ini['dcfg']['cm_default_user_uoa']
03176 r=access({'cm_run_module_uoa':ini['dcfg']['cm_user_module_uoa'],
03177 'cm_action':'load',
03178 'cm_data_uoa':user,
03179 'cm_admin':'yes'})
03180 if r['cm_return']>0:
03181 if r['cm_return']==16: r={'cm_return':16, 'cm_error':'can\'t load default user "'+user+' - please, run configure.sh"'}
03182 return r
03183
03184 rx={'cm_user_cfg':r['cm_data_obj']['cfg'],
03185 'cm_user_uid':r['cm_uid'],
03186 'cm_user_uoa':r['cm_uoa'],
03187 'cm_user_alias':r['cm_alias'],
03188 'cm_user_path':r['cm_path'],
03189 'cm_user_status':'default'}
03190
03191 ini['web_auth']=copy.deepcopy(rx)
03192 rx['cm_return']=0
03193
03194 if r['cm_uoa'] in ini['dcfg'].get('admin_users',[]) or \
03195 r['cm_uid'] in ini['dcfg'].get('admin_users',[]):
03196 ini['web_auth']['cm_admin']='yes'
03197
03198
03199 cm_default_web_uoa=''
03200 if i.get('cm_web_uoa','')!='':
03201 cm_default_web_uoa=i['cm_web_uoa']
03202 else:
03203 cm_default_web_uoa=''
03204 if ini['dcfg'].get('cm_default_web_uoa','')!='':
03205 cm_default_web_uoa=ini['dcfg']['cm_default_web_uoa']
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215 if cm_default_web_uoa=='': cm_default_web_uoa=var_cm_cfg_default
03216
03217 ini['web_style']['uoa']=cm_default_web_uoa
03218
03219 r=cm_kernel.access({'cm_run_module_uoa':ini['dcfg']['cm_web_module_uoa'],
03220 'cm_action':'load',
03221 'cm_data_uoa':cm_default_web_uoa,
03222 'cm_admin':'yes'})
03223 if r['cm_return']>0: return r
03224
03225 ini['web_style']['cfg']=r['cm_data_obj']['cfg']
03226 ini['web_style']['path']=r['cm_path']
03227
03228 return rx
03229
03230
03231 def access_fe_as_string(s):
03232 """
03233 Front-end to single entry 'access' function as string (if someone finds it easier).
03234
03235 Input: string that will be converted to array (See "access" function).
03236 Output: See "access" function.
03237 """
03238
03239 r=str2cm(s)
03240 if r['cm_return']>0: return r
03241
03242 return access(r['cm_array'])
03243
03244
03245 def access_fe_through_cmd(i):
03246 """
03247 FGG TBD: Currently used only in cM web server.
03248 Should be cleaned and updated!
03249 Should check that tmp files are deleted!
03250
03251 Main function to access cM through a command line (useful for web server, etc).
03252
03253 Input: {
03254 ... - see "access" function from this module
03255 (cm_detach_console) - if 'yes', detach console (for installations or experiments)
03256 }
03257 Output: {
03258 cm_return - return code = 0 if successful
03259 cm_stdout - stdout
03260 cm_stderr - stderr
03261 }
03262 """
03263
03264
03265 if 'cm_run_module_uoa' not in i:
03266 return {'cm_return':1, 'cm_error':'no module specified'}
03267 module=i['cm_run_module_uoa']
03268
03269
03270 if 'cm_action' not in i:
03271 return {'cm_return':1, 'cm_error':'no action specified for module '+i['cm_run_module_uoa']}
03272 action=i['cm_action']
03273
03274 cm_stdout=''
03275 cm_stderr=''
03276
03277 i1={}; i1.update(i)
03278 del (i1['cm_run_module_uoa'])
03279 del (i1['cm_action'])
03280
03281 if i.get('cm_detach_console','')=='yes':
03282
03283 i1['cm_console']='txt'
03284 if 'cm_web' in i1: del(i1['cm_web'])
03285
03286 rr={};
03287 rr['cm_stdout']=''
03288 rr['cm_stderr']=''
03289
03290
03291 rx=cm_kernel.gen_cm_tmp_file({})
03292 if rx['cm_return']>0:
03293 rr['cm_return']=rx['cm_return']
03294 rr['cm_stderr']=rx['cm_error']
03295 return rr
03296 tf=rx['cm_path']
03297
03298 r=save_array_to_file_as_json({'cm_filename':tf, 'cm_array':i1})
03299 if r['cm_return']>0:
03300 rr['cm_return']=r['cm_return']
03301 rr['cm_stderr']=r['cm_error']
03302 return rr
03303
03304 cmd='cm '+module+' '+action+' @'+tf
03305 if i.get('cm_detach_console','')=='yes':
03306
03307 if ini['dcfg'].get('forbid_detached_console','')=='yes' or \
03308 (i.get('cm_web','')=='yes' and \
03309 ini['dcfg'].get('forbid_detached_console_in_web','')=='yes' and \
03310 i.get('cm_user_uoa','')!='' and i.get('cm_user_uoa','') not in ini['dcfg'].get('admin_users',[])):
03311 rr['cm_return']=0
03312 rr['cm_stdout']='<B>cM error:</B> Detaching console is explicitly forbidden in the kernel'
03313 return rr
03314
03315
03316 os_uoa=ini['dcfg'].get('cm_default_os_uoa','')
03317
03318 if os_uoa=='':
03319 rr['cm_return']=1
03320 rr['cm_stderr']='detached console is requested but default os uoa is not in kernel'
03321 return rr
03322
03323 ii={'cm_run_module_uoa':ini['dcfg']['cm_os_module_uoa'],
03324 'cm_data_uoa':os_uoa,
03325 'cm_action':'load'}
03326 rx=access(ii)
03327 if rx['cm_return']>0:
03328 rr['cm_return']=rx['cm_return']
03329 rr['cm_stderr']=rx['cm_error']
03330 return rr
03331 dos=rx['cm_data_obj']['cfg']
03332
03333 dcmd=dos.get('cmd_for_detached_console','')
03334 if dcmd=='':
03335 rr['cm_return']=1
03336 rr['cm_stderr']='detached console is requested but cmd is not defined in OS'
03337 return rr
03338
03339 dcmd=dcmd.replace(convert_str_to_special('cmd'), cmd)
03340 if dos.get('use_create_new_console_flag','')=='yes':
03341 process=subprocess.Popen(dcmd, stdin=None, stdout=None, stderr=None, shell=True, close_fds=True, creationflags=subprocess.CREATE_NEW_CONSOLE)
03342 else:
03343
03344 try:
03345 pid=os.fork()
03346 except OSError, e:
03347 rr['cm_return']=1
03348 rr['cm_stderr']='forking detached console failed!'
03349 return rr
03350
03351 if pid==0:
03352 os.setsid()
03353
03354 pid=os.fork()
03355 if pid!=0: os._exit(0)
03356
03357 try:
03358 maxfd=os.sysconf("SC_OPEN_MAX")
03359 except (AttributeError, ValueError):
03360 maxfd=1024
03361
03362 for fd in range(maxfd):
03363 try:
03364 os.close(fd)
03365 except OSError:
03366 pass
03367
03368 os.open('/dev/null', os.O_RDWR)
03369 os.dup2(0, 1)
03370 os.dup2(0, 2)
03371
03372
03373 process=os.system(dcmd)
03374 os._exit(0)
03375
03376 if i.get('cm_console')=='web':
03377 cm_stdout=dos.get('html_for_detached_console','')
03378 cm_stderr=''
03379 else:
03380 cm_stdout='Console was detached!'
03381 cm_stderr=''
03382 else:
03383 process=subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
03384 cm_stdout,cm_stderr=process.communicate()
03385
03386 rr['cm_return']=0
03387 rr['cm_stdout']=cm_stdout
03388 rr['cm_stderr']=cm_stderr
03389
03390 return rr
03391
03392
03393 def access_fe_from_cmd(a):
03394 """
03395 Front-end to single entry 'access' function from command line (bash, windows shell, etc)
03396 If cm_console=='', it will be set to 'txt'
03397 If cm_user_uoa and cm_user_password1 are not in input but in environment, they will be also used
03398
03399 Input: cmd list that will be converted to array (See "access" function)
03400 Output: See "access" function
03401 """
03402 r=array2cm(a)
03403 if r['cm_return']>0:
03404 con=r['cm_console']
03405 if con=='': con='txt'
03406 prepare_final_out(r, {'cm_console':con, 'cm_output':r.get('cm_output','')})
03407 return r
03408
03409 i=r['cm_array']
03410
03411
03412 if 'cm_console' not in i or i['cm_console']=='': i.update({'cm_console':'txt'})
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423 return access_fe(i)
03424
03425
03426 def access_fe(i):
03427
03428 """
03429 Front-end to single entry 'access' function
03430 cM will be initialized if needed
03431
03432 Input: See "access" function
03433 Output: See "access" function
03434 """
03435
03436 global ini
03437
03438
03439 if ini['init']==1:
03440 r={'cm_return':1, 'cm_error':'cM initialization failed', 'cm_console':i['cm_console']}
03441 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03442 return r
03443
03444
03445 if ini['init']==-1:
03446 ini['init']=1
03447
03448 r=init(i)
03449 if r['cm_return']>0:
03450 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03451 return r
03452
03453 ini['init']=0
03454
03455
03456 if 'cm_run_module_uoa' not in i:
03457 r={'cm_return':1, 'cm_error':'no module specified'}
03458 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03459 return r
03460
03461
03462 if 'cm_action' not in i:
03463 r={'cm_return':1, 'cm_error':'no action specified for module '+i['cm_run_module_uoa']}
03464 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03465 return r
03466
03467
03468
03469
03470
03471 rx=auth_user_and_ini_cm(i)
03472 if rx['cm_return']>0:
03473 prepare_final_out(rx, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03474 return rx
03475
03476
03477 if i.get('cm_user_password2','')!='': del(i['cm_user_password2'])
03478
03479
03480 if i.get('cm_web')=='yes': ini['web']='yes'
03481
03482 r=access(i)
03483
03484 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03485 return r
03486
03487
03488 def remote_access(i):
03489
03490 """
03491 Remote access to cM
03492
03493 Input: {
03494 cm_remote_url - remote URL
03495 (cm_user_uoa) -
03496 (cm_user_password) -
03497 (cm_user_password1) -
03498 (remote_repo_uoa)
03499
03500 (remote_pre_auth) - if 'yes', need standard http login/password pre-authentication
03501 (cm_remote_user_name) - remote username
03502 (cm_remote_user_password) - remote password
03503
03504 (cm_web_module_uoa) - module to run
03505 (cm_web_action) - action to perform
03506 if =='download', prepare entry/file download through Internet
03507
03508 (cm_save_to_file) - if cm_web_action==download,
03509 save output to this file
03510
03511 ... - all other request parameters
03512 }
03513
03514 Output: {
03515 cm_return - return code = 0 if successful
03516 > 0 if error
03517 < 0 if warning (rarely used at this moment)
03518 (cm_error) - error text, if cm_return > 0
03519 }
03520 """
03521
03522
03523 post=''
03524
03525 url=i.get('cm_remote_url','')
03526 if url=='':
03527 return {'cm_return':1, 'cm_error':'cm_remote_url is not defined'}
03528 del(i['cm_remote_url'])
03529
03530 if i.get('cm_user_uoa','')!='':
03531 if post!='': post+='&'
03532 post+='cm_user_uoa='+i['cm_user_uoa']
03533 del(i['cm_user_uoa'])
03534
03535 if i.get('cm_user_password','')!='':
03536 if post!='': post+='&'
03537 post+='cm_user_password='+i['cm_user_password']
03538 del(i['cm_user_password'])
03539
03540 if i.get('cm_user_password1','')!='':
03541 if post!='': post+='&'
03542 post+='cm_user_password1='+i['cm_user_password1']
03543 del(i['cm_user_password1'])
03544
03545 if i.get('remote_repo_uoa','')!='':
03546 if post!='': post+='&'
03547 post+='cm_repo_uoa='+i['remote_repo_uoa']
03548 del(i['remote_repo_uoa'])
03549
03550
03551 base64string=''
03552 if i.get('remote_pre_auth', '')=='yes':
03553 del(i['remote_pre_auth'])
03554
03555 username=''
03556 if i.get('cm_remote_user_name','')!='':
03557 username=i['cm_remote_user_name']
03558 del(i['cm_remote_user_name'])
03559
03560 password=''
03561 if i.get('cm_remote_user_password','')!='':
03562 password=i['cm_remote_user_password']
03563 del(i['cm_remote_user_password'])
03564
03565 base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
03566
03567
03568 download=False
03569 if i.get('cm_web_action','')=='download' or i.get('cm_web_action','')=='show':
03570 download=True
03571 if post!='': post+='&'
03572 post+='cm_web_module_uoa=web&cm_web_action='+i['cm_web_action']
03573 del(i['cm_web_action'])
03574 if i.get('cm_web_module_uoa','')!='': del(i['cm_web_module_uoa'])
03575 if i.get('cm_console','')!='': del(i['cm_console'])
03576 else:
03577 if post!='': post+='&'
03578 post+='cm_console=json'
03579
03580
03581 r=convert_cm_array_to_uri({'cm_array':i})
03582 if post!='': post+='&'
03583 post+='cm_json='+unicode(r['cm_string1'])
03584
03585
03586 request = urllib2.Request(url, post)
03587
03588 if base64string!='':
03589 request.add_header("Authorization", "Basic %s" % base64string)
03590
03591
03592 aproxy={}
03593 if env_cm_remote_repo_proxy_https in os.environ.keys():
03594 aproxy['https']=os.environ[env_cm_remote_repo_proxy_https].strip()
03595 if env_cm_remote_repo_proxy_http in os.environ.keys():
03596 aproxy['http']=os.environ[env_cm_remote_repo_proxy_http].strip()
03597
03598 if len(aproxy)>0:
03599 proxy = urllib2.ProxyHandler(aproxy)
03600 opener = urllib2.build_opener(proxy)
03601 urllib2.install_opener(opener)
03602
03603
03604 try:
03605 f=urllib2.urlopen(request)
03606 except Exception as e:
03607 return {'cm_return':1, 'cm_error':'Remote access failed ('+format(e)+')'}
03608
03609
03610 try:
03611 s=str(f.read())
03612 f.close()
03613 except Exception as e:
03614 return {'cm_return':1, 'cm_error':'Failed reading stream from remote server ('+format(e)+')'}
03615
03616 request=None
03617
03618 r={'cm_return':0}
03619
03620
03621 if download:
03622 name='default_download_name.dat'
03623
03624 if i.get('cm_web_filename','')!='':
03625 name=os.path.basename(i['cm_web_filename'])
03626 if i.get('cm_save_to_file','')!='':
03627
03628
03629 name=i['cm_save_to_file']
03630
03631 try:
03632 f=open(name,'wb')
03633 f.write(s)
03634 f.close()
03635 except Exception as e:
03636 return {'cm_return':1, 'cm_error':'problem saving downloaded file ('+format(e)+')'}
03637
03638 else:
03639 try:
03640 r=json.loads(s)
03641 except:
03642 return {'cm_return':32, 'cm_error':'Can\'t decode JSON ('+s+')'}
03643
03644 return r
03645
03646
03647 def access(i):
03648
03649 """
03650 Single entry point to access all cM functions.
03651
03652 Input: {
03653 Set of global cM variables:
03654
03655 cm_run_module_uoa - UOA of the module to run
03656 cm_action - module action (function)
03657
03658 (cm_console) - by default, do not output anything except errors
03659 if 'txt' then output as plain text
03660 if 'web' then output for web (html, image, etc)
03661 if 'json' then output as json
03662
03663 cm_web - if 'yes', function was called from web environment
03664 cm_web_preprocess - if 'yes', we in the preprocessing stage in the web environment,
03665 where we can still change the http headers, etc ...
03666
03667 If cM Web access or fully remote access:
03668 cm_user_uoa - user UOA
03669
03670 If requires user authentication in web environment!
03671 After authentication, passwords will be removed from the array
03672
03673 cm_user_password - user password in plain text
03674 (not secure, usually used for web form authentication)
03675 cm_user_password1 - user password in SHA1
03676 (more secure, can be stored in environment, session or cookies)
03677 cM authenicates by taking SHA1(cm_user_password1)...
03678
03679 If access to remote repository or fully remote access:
03680
03681 cm_remote_user_uoa - remote user UOA
03682 cm_remote_user_password - remote user password
03683
03684 Set of parameters depending on the called module and action (function)
03685 }
03686
03687 Output: {
03688 cm_return - return code = 0 if successful
03689 > 0 if error
03690 < 0 if warning (rarely used at this moment)
03691 (cm_error) - error text, if cm_return > 0
03692
03693 Set of output parameters depending on the called module and action (function)
03694 }
03695 """
03696
03697
03698 if 'cm_run_module_uoa' not in i: return {'cm_return':1, 'cm_error':'"cm_run_module_uoa" is not set'}
03699 if 'cm_action' not in i: return {'cm_return':1, 'cm_error':'"cm_action" is not set'}
03700
03701
03702 if i.get('cm_detach_console','')=='yes' and ini['dcfg'].get('forbid_detached_console','')=='yes':
03703 r={'cm_return':1, 'cm_error':'Detaching console is explicitly forbidden in the kernel'}
03704 prepare_final_out(r, {'cm_console':i.get('cm_console',''), 'cm_output':i.get('cm_output','')})
03705 return r
03706
03707
03708 if 'cid' in i and i['cid']!='':
03709 rx=cm_kernel.cid2array(i)
03710 if rx['cm_return']>0: return rx
03711
03712 i.update(rx['cm_array'])
03713 del(i['cid'])
03714
03715
03716 if ('cm_module_uoa' not in i or i['cm_module_uoa']=='') and \
03717 'cm_run_module_uoa' in i and i['cm_run_module_uoa']!='':
03718 i['cm_module_uoa']=i['cm_run_module_uoa']
03719
03720
03721 if (i.get('cm_repo_uoa','')!=''):
03722 cm_repo_uoa=i['cm_repo_uoa']
03723
03724 r=cm_kernel.access({'cm_run_module_uoa':ini['dcfg']['cm_repo_module_uoa'],
03725 'cm_action':'find_path_to_repository',
03726 'find_repo_uoa':cm_repo_uoa})
03727 if r['cm_return']>0: return r
03728
03729 d=r['cm_data_obj']['cfg']
03730 repo_uoa=r['cm_uoa']
03731 repo_uid=r['cm_uid']
03732
03733 if 'path_type' in d and d['path_type']=='remote_url':
03734 cur_console=''
03735 if 'cm_console' in i and i['cm_console']!='': cur_console=i['cm_console']
03736
03737
03738 if i.get('cm_remote_url','')=='': i['cm_remote_url']=d['url']
03739
03740 if 'cm_run_module_uoa' in i and i['cm_run_module_uoa']!='':
03741 i['cm_web_module_uoa']=i['cm_run_module_uoa']
03742 del(i['cm_run_module_uoa'])
03743 elif 'cm_module_uoa' in i and i['cm_module_uoa']!='':
03744 i['cm_web_module_uoa']=i['cm_module_uoa']
03745 del(i['cm_module_uoa'])
03746 if 'cm_action' in i:
03747 i['cm_web_action']=i['cm_action']
03748 del(i['cm_action'])
03749 if 'cm_repo_uoa' in i: del(i['cm_repo_uoa'])
03750
03751 i['cm_console']='json'
03752
03753 username=''
03754 password=''
03755 password1=''
03756
03757
03758 if d.get('remote_auth', '')=='yes':
03759 x1='\nRemote repository "'+repo_uoa+'" requires authentication!'
03760 x2=True
03761
03762 if d.get('remote_auth_as_user', '')=='yes':
03763 username=ini['web_auth'].get('cm_user_cfg',{}).get('cm_username','')
03764
03765 if username=='' and d.get('remote_auth_user', '')!='':
03766 username=d['remote_auth_user']
03767
03768 if username=='' and ini['dcfg'].get('cm_default_user_uoa', '')!='':
03769 username=ini['dcfg']['cm_default_user_uoa']
03770
03771 if env_cm_user_uoa in os.environ.keys() and os.environ[env_cm_user_uoa]!='':
03772 username=os.environ[env_cm_user_uoa].strip()
03773
03774 if i.get('cm_remote_user_uoa','')!='':
03775 username=i['cm_remote_user_uoa']
03776
03777 if username=='':
03778 if i.get('cm_web','')=='yes':
03779 return {'cm_return':1, 'cm_error':'remote authentication is required but "cm_remote_user_uoa" is not set!'}
03780 else:
03781 if cm_repo_uoa in ini['remote_repo'] and ini['remote_repo'][cm_repo_uoa].get('username','')!='':
03782 username=ini['remote_repo'][cm_repo_uoa]['username']
03783 else:
03784 if x2:
03785 print_for_con(x1)
03786 x2=False
03787 username=raw_input('Enter username (or Enter to terminate operation): ')
03788 if username=='': return {'cm_return':1, 'cm_error':'user terminated operation'}
03789 if cm_repo_uoa not in ini['remote_repo']: ini['remote_repo'][cm_repo_uoa]={}
03790 ini['remote_repo'][cm_repo_uoa]['username']=username
03791
03792 if i.get('cm_remote_user_password','')!='':
03793 password=i['cm_remote_user_password']
03794 elif env_cm_user_password in os.environ.keys() and os.environ[env_cm_user_password]!='':
03795 password=os.environ[env_cm_user_password].strip()
03796 elif env_cm_user_password1 in os.environ.keys() and os.environ[env_cm_user_password1]!='':
03797 password1=os.environ[env_cm_user_password1].strip()
03798 else:
03799 if i.get('cm_web','')=='yes': return {'cm_return':1, 'cm_error':'remote authentication is required but "cm_remote_user_password" is not set!'}
03800 else:
03801 if cm_repo_uoa in ini['remote_repo'] and ini['remote_repo'][cm_repo_uoa].get('password','')!='':
03802 password=ini['remote_repo'][cm_repo_uoa]['password']
03803 else:
03804 if x2:
03805 print_for_con(x1)
03806 x2=False
03807 password=getpass.getpass('Enter password for '+str(username)+' (or Enter to terminate operation): ')
03808 password=password.strip()
03809 if password=='': return {'cm_return':1, 'cm_error':'user terminated operation'}
03810 if cm_repo_uoa not in ini['remote_repo']: ini['remote_repo'][cm_repo_uoa]={}
03811 ini['remote_repo'][cm_repo_uoa]['password']=password
03812
03813 rep=''
03814 if i.get('remote_repo_uoa','')!='':
03815 rep=i['remote_repo_uoa']
03816 elif d.get('remote_repo_uoa','')!='':
03817 rep=d['remote_repo_uoa']
03818 if rep!='': i['remote_repo_uoa']=rep
03819
03820 i['cm_user_uoa']=username
03821
03822 if password!='':
03823 i['cm_user_password']=password
03824 if password1!='':
03825 i['cm_user_password1']=password1
03826
03827
03828 if d.get('remote_pre_auth', '')=='yes':
03829 i['remote_pre_auth']='yes'
03830
03831 x1='Remote repository requires http pre-authentication!'
03832 x2=True
03833
03834 if username=='':
03835 if d.get('remote_auth_as_user', '')=='yes':
03836 username=ini['web_auth'].get('cm_user_cfg',{}).get('cm_username','')
03837 elif d.get('remote_auth_user', '')!='':
03838 username=d['remote_auth_user']
03839 elif i.get('cm_remote_user_uoa','')!='':
03840 username=i['cm_remote_user_uoa']
03841 else:
03842 if i.get('cm_web','')=='yes':
03843 return {'cm_return':1, 'cm_error':'remote authentication is required but "cm_remote_user_uoa" is not set!'}
03844 else:
03845 if x2:
03846 print_for_con(x1)
03847 x2=False
03848 username=raw_input('Enter username (or Enter to terminate operation): ')
03849 if username=='': return {'cm_return':1, 'cm_error':'user terminated operation'}
03850
03851 if password=='':
03852 if i.get('cm_remote_user_password','')!='':
03853 password=i['cm_remote_user_password']
03854 else:
03855 if i.get('cm_web','')=='yes': return {'cm_return':1, 'cm_error':'remote authentication is required but "cm_remote_password" is not set!'}
03856 else:
03857 if x2:
03858 print_for_con(x1)
03859 x2=False
03860 password=getpass.getpass('Enter password for '+str(username)+' (or Enter to terminate operation): ')
03861 if password=='': return {'cm_return':1, 'cm_error':'user terminated operation'}
03862
03863 i['cm_remote_user_name']=username
03864 i['cm_remote_user_password']=password
03865
03866
03867 r=remote_access(i)
03868
03869
03870 if cur_console!='': i['cm_console']=cur_console
03871
03872 return r
03873
03874
03875 for q in range(0,2):
03876
03877 if q==0:
03878 module=i['cm_run_module_uoa']
03879 actions='cm_actions'
03880 else:
03881 module='core'
03882 actions='cm_common_actions'
03883
03884
03885 ii={}
03886 ii['cm_module_uoa']=module
03887 if 'cm_web' in i: ii['cm_web']=i['cm_web']
03888 r=load_module(ii)
03889 if r['cm_return']>0:
03890 return r
03891 c=r['cm_code']
03892 e=r.get('external_module','')
03893
03894
03895 if e=='yes':
03896 a=getattr(c, i['cm_action'])
03897 return a(i)
03898
03899 elif actions in c.ini['cfg']:
03900 r=find_index_in_array({
03901 'cm_array':c.ini['cfg'][actions],
03902 'cm_index':i['cm_action']
03903 })
03904
03905 if r['cm_return']==0:
03906
03907 if i.get('cm_web_preprocess','')=='yes' \
03908 and r['cm_array'].get('cm_web_preprocess','')!='yes':
03909 return {'cm_return':0, 'cm_web_postprocess':'yes'}
03910
03911 f=r['cm_array']['func']; a=getattr(c, f)
03912 ii={}
03913 if q!=0: ii['cm_common_func']='yes'
03914 if 'params_default' in r['cm_array']:
03915 merge_arrays({'cm_array':ii, 'cm_array1':r['cm_array']['params_default']})
03916 merge_arrays({'cm_array':ii, 'cm_array1':i})
03917
03918 if 'cm_web' in i: ii['cm_web']=i['cm_web']
03919
03920 return a(ii)
03921
03922 return {'cm_return':1, 'cm_error':'action "'+i['cm_action']+'" not found in module '+i['cm_run_module_uoa']}
03923
03924
03925 if __name__ == "__main__":
03926
03927 '''
03928 cM command line wrapper
03929 cm <cm object> <action> parameters
03930
03931 '''
03932
03933 r=access_fe_from_cmd(sys.argv[1:])
03934 exit(r['cm_return'])