##// END OF EJS Templates
Unicode fixes, added safe_str method for global str() operations +better test sandboxing
marcink -
r1401:b7563ad4 beta
parent child Browse files
Show More
@@ -61,7 +61,7 b' def load_environment(global_conf, app_co'
61 from rhodecode.lib.utils import create_test_env, create_test_index
61 from rhodecode.lib.utils import create_test_env, create_test_index
62 from rhodecode.tests import TESTS_TMP_PATH
62 from rhodecode.tests import TESTS_TMP_PATH
63 create_test_env(TESTS_TMP_PATH, config)
63 create_test_env(TESTS_TMP_PATH, config)
64 create_test_index(TESTS_TMP_PATH, True)
64 create_test_index(TESTS_TMP_PATH, config, True)
65
65
66 #MULTIPLE DB configs
66 #MULTIPLE DB configs
67 # Setup the SQLAlchemy database engine
67 # Setup the SQLAlchemy database engine
@@ -38,7 +38,7 b' from vcs.exceptions import RepositoryErr'
38 from vcs.nodes import FileNode, NodeKind
38 from vcs.nodes import FileNode, NodeKind
39 from vcs.utils import diffs as differ
39 from vcs.utils import diffs as differ
40
40
41 from rhodecode.lib import convert_line_endings, detect_mode
41 from rhodecode.lib import convert_line_endings, detect_mode, safe_str
42 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
42 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
43 from rhodecode.lib.base import BaseRepoController, render
43 from rhodecode.lib.base import BaseRepoController, render
44 from rhodecode.lib.utils import EmptyChangeset
44 from rhodecode.lib.utils import EmptyChangeset
@@ -153,7 +153,7 b' class FilesController(BaseRepoController'
153 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
153 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
154
154
155 response.content_disposition = 'attachment; filename=%s' % \
155 response.content_disposition = 'attachment; filename=%s' % \
156 f_path.split(os.sep)[-1].encode('utf8', 'replace')
156 safe_str(f_path.split(os.sep)[-1])
157
157
158 response.content_type = file_node.mimetype
158 response.content_type = file_node.mimetype
159 return file_node.content
159 return file_node.content
@@ -198,7 +198,7 b' class FilesController(BaseRepoController'
198
198
199 if dispo == 'attachment':
199 if dispo == 'attachment':
200 dispo = 'attachment; filename=%s' % \
200 dispo = 'attachment; filename=%s' % \
201 f_path.split(os.sep)[-1].encode('utf8', 'replace')
201 safe_str(f_path.split(os.sep)[-1])
202
202
203 response.content_disposition = dispo
203 response.content_disposition = dispo
204 response.content_type = mimetype
204 response.content_type = mimetype
@@ -160,7 +160,7 b' def generate_api_key(username, salt=None'
160 def safe_unicode(_str, from_encoding='utf8'):
160 def safe_unicode(_str, from_encoding='utf8'):
161 """
161 """
162 safe unicode function. In case of UnicodeDecode error we try to return
162 safe unicode function. In case of UnicodeDecode error we try to return
163 unicode with errors replace
163 unicode with errors replaceed
164
164
165 :param _str: string to decode
165 :param _str: string to decode
166 :rtype: unicode
166 :rtype: unicode
@@ -178,6 +178,28 b" def safe_unicode(_str, from_encoding='ut"
178 return u_str
178 return u_str
179
179
180
180
181 def safe_str(_unicode, to_encoding='utf8'):
182 """
183 safe str function. In case of UnicodeEncode error we try to return
184 str with errors replaceed
185
186 :param _unicode: unicode to encode
187 :rtype: str
188 :returns: str object
189 """
190
191 if isinstance(_unicode, str):
192 return _unicode
193
194 try:
195 safe_str = str(_unicode)
196 except UnicodeEncodeError:
197 safe_str = _unicode.encode(to_encoding, 'replace')
198
199 return safe_str
200
201
202
181 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
203 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
182 """
204 """
183 Custom engine_from_config functions that makes sure we use NullPool for
205 Custom engine_from_config functions that makes sure we use NullPool for
@@ -37,7 +37,7 b' from string import lower'
37 from pylons import config
37 from pylons import config
38 from pylons.i18n.translation import _
38 from pylons.i18n.translation import _
39
39
40 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP
40 from rhodecode.lib import LANGUAGES_EXTENSIONS_MAP, safe_str
41 from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \
41 from rhodecode.lib.celerylib import run_task, locked_task, str2bool, \
42 __get_lockkey, LockHeld, DaemonLock
42 __get_lockkey, LockHeld, DaemonLock
43 from rhodecode.lib.helpers import person
43 from rhodecode.lib.helpers import person
@@ -66,7 +66,6 b' except ImportError:'
66 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
66 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
67
67
68
68
69
70 def get_session():
69 def get_session():
71 if CELERY_ON:
70 if CELERY_ON:
72 engine = engine_from_config(config, 'sqlalchemy.db1.')
71 engine = engine_from_config(config, 'sqlalchemy.db1.')
@@ -112,8 +111,7 b' def get_commits_stats(repo_name, ts_min_'
112 co_day_auth_aggr = {}
111 co_day_auth_aggr = {}
113 commits_by_day_aggregate = {}
112 commits_by_day_aggregate = {}
114 repos_path = get_repos_path()
113 repos_path = get_repos_path()
115 p = os.path.join(repos_path, repo_name)
114 repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
116 repo = get_repo(p)
117 repo_size = len(repo.revisions)
115 repo_size = len(repo.revisions)
118 #return if repo have no revisions
116 #return if repo have no revisions
119 if repo_size < 1:
117 if repo_size < 1:
@@ -358,8 +356,7 b' def create_repo_fork(form_data, cur_user'
358
356
359 def __get_codes_stats(repo_name):
357 def __get_codes_stats(repo_name):
360 repos_path = get_repos_path()
358 repos_path = get_repos_path()
361 p = os.path.join(repos_path, repo_name)
359 repo = get_repo(safe_str(os.path.join(repos_path, repo_name)))
362 repo = get_repo(p)
363 tip = repo.get_changeset()
360 tip = repo.get_changeset()
364 code_stats = {}
361 code_stats = {}
365
362
@@ -36,7 +36,7 b' from webhelpers.html.tags import _set_in'
36
36
37 from vcs.utils.annotate import annotate_highlight
37 from vcs.utils.annotate import annotate_highlight
38 from rhodecode.lib.utils import repo_name_slug
38 from rhodecode.lib.utils import repo_name_slug
39 from rhodecode.lib import str2bool, safe_unicode
39 from rhodecode.lib import str2bool, safe_unicode, safe_str
40
40
41 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
41 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
42 """
42 """
@@ -502,7 +502,7 b' def gravatar_url(email_address, size=30)'
502
502
503 if isinstance(email_address, unicode):
503 if isinstance(email_address, unicode):
504 #hashlib crashes on unicode items
504 #hashlib crashes on unicode items
505 email_address = email_address.encode('utf8', 'replace')
505 email_address = safe_str(email_address)
506 # construct the url
506 # construct the url
507 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
507 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
508 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
508 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
@@ -69,6 +69,7 b' from dulwich.web import HTTPGitApplicati'
69 from paste.auth.basic import AuthBasicAuthenticator
69 from paste.auth.basic import AuthBasicAuthenticator
70 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
70 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
71
71
72 from rhodecode.lib import safe_str
72 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
73 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
73 from rhodecode.lib.utils import invalidate_cache, check_repo_fast
74 from rhodecode.lib.utils import invalidate_cache, check_repo_fast
74 from rhodecode.model.user import UserModel
75 from rhodecode.model.user import UserModel
@@ -147,8 +148,8 b' class SimpleGit(object):'
147 #==============================================================
148 #==============================================================
148
149
149 if not REMOTE_USER(environ):
150 if not REMOTE_USER(environ):
150 self.authenticate.realm = self.config['rhodecode_realm'].\
151 self.authenticate.realm = \
151 encode('utf8', 'replace')
152 safe_str(self.config['rhodecode_realm'])
152 result = self.authenticate(environ)
153 result = self.authenticate(environ)
153 if isinstance(result, str):
154 if isinstance(result, str):
154 AUTH_TYPE.update(environ, 'basic')
155 AUTH_TYPE.update(environ, 'basic')
@@ -35,6 +35,7 b' from mercurial.hgweb.request import wsgi'
35 from paste.auth.basic import AuthBasicAuthenticator
35 from paste.auth.basic import AuthBasicAuthenticator
36 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
36 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
37
37
38 from rhodecode.lib import safe_str
38 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
39 from rhodecode.lib.auth import authfunc, HasPermissionAnyMiddleware
39 from rhodecode.lib.utils import make_ui, invalidate_cache, \
40 from rhodecode.lib.utils import make_ui, invalidate_cache, \
40 check_repo_fast, ui_sections
41 check_repo_fast, ui_sections
@@ -112,8 +113,8 b' class SimpleHg(object):'
112 #==============================================================
113 #==============================================================
113
114
114 if not REMOTE_USER(environ):
115 if not REMOTE_USER(environ):
115 self.authenticate.realm = self.config['rhodecode_realm'].\
116 self.authenticate.realm = \
116 encode('utf8', 'replace')
117 safe_str(self.config['rhodecode_realm'])
117 result = self.authenticate(environ)
118 result = self.authenticate(environ)
118 if isinstance(result, str):
119 if isinstance(result, str):
119 AUTH_TYPE.update(environ, 'basic')
120 AUTH_TYPE.update(environ, 'basic')
@@ -458,18 +458,22 b' def get_current_revision():'
458 #==============================================================================
458 #==============================================================================
459 # TEST FUNCTIONS AND CREATORS
459 # TEST FUNCTIONS AND CREATORS
460 #==============================================================================
460 #==============================================================================
461 def create_test_index(repo_location, full_index):
461 def create_test_index(repo_location, config, full_index):
462 """Makes default test index
462 """
463 :param repo_location:
463 Makes default test index
464
465 :param config: test config
464 :param full_index:
466 :param full_index:
465 """
467 """
468
466 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
469 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
467 from rhodecode.lib.pidlock import DaemonLock, LockHeld
470 from rhodecode.lib.pidlock import DaemonLock, LockHeld
468 import shutil
471
472 repo_location = repo_location
469
473
470 index_location = os.path.join(repo_location, 'index')
474 index_location = os.path.join(config['app_conf']['index_dir'], 'index')
471 if os.path.exists(index_location):
475 if not os.path.exists(index_location):
472 shutil.rmtree(index_location)
476 os.makedirs(index_location)
473
477
474 try:
478 try:
475 l = DaemonLock(file=jn(dn(index_location), 'make_index.lock'))
479 l = DaemonLock(file=jn(dn(index_location), 'make_index.lock'))
@@ -42,7 +42,7 b' from vcs.exceptions import RepositoryErr'
42 from vcs.utils.lazy import LazyProperty
42 from vcs.utils.lazy import LazyProperty
43 from vcs.nodes import FileNode
43 from vcs.nodes import FileNode
44
44
45 from rhodecode.lib import str2bool, json
45 from rhodecode.lib import str2bool, json, safe_str
46 from rhodecode.model.meta import Base, Session
46 from rhodecode.model.meta import Base, Session
47 from rhodecode.model.caching_query import FromCache
47 from rhodecode.model.caching_query import FromCache
48
48
@@ -479,7 +479,11 b' class Repository(Base, BaseModel):'
479 Session.add(inv)
479 Session.add(inv)
480 Session.commit()
480 Session.commit()
481
481
482 return _c(self.repo_name)
482 # TODO: remove this trick when beaker 1.6 is released
483 # and have fixed this issue
484 rn = safe_str(self.repo_name)
485
486 return _c(rn)
483
487
484 def __get_instance(self):
488 def __get_instance(self):
485
489
@@ -497,7 +501,8 b' class Repository(Base, BaseModel):'
497 return
501 return
498
502
499 if alias == 'hg':
503 if alias == 'hg':
500 repo = backend(repo_full_path, create=False,
504
505 repo = backend(safe_str(repo_full_path), create=False,
501 baseui=self._ui)
506 baseui=self._ui)
502 #skip hidden web repository
507 #skip hidden web repository
503 if repo._get_hidden():
508 if repo._get_hidden():
@@ -33,6 +33,8 b' from sqlalchemy.orm import joinedload, m'
33 from vcs.utils.lazy import LazyProperty
33 from vcs.utils.lazy import LazyProperty
34 from vcs.backends import get_backend
34 from vcs.backends import get_backend
35
35
36 from rhodecode.lib import safe_str
37
36 from rhodecode.model import BaseModel
38 from rhodecode.model import BaseModel
37 from rhodecode.model.caching_query import FromCache
39 from rhodecode.model.caching_query import FromCache
38 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
40 from rhodecode.model.db import Repository, RepoToPerm, User, Permission, \
@@ -171,13 +173,12 b' class RepoModel(BaseModel):'
171
173
172 try:
174 try:
173 if fork:
175 if fork:
174 #force str since hg doesn't go with unicode
176 repo_name = form_data['fork_name']
175 repo_name = str(form_data['fork_name'])
177 org_name = form_data['repo_name']
176 org_name = str(form_data['repo_name'])
178 org_full_name = org_name
177 org_full_name = org_name#str(form_data['fork_name_full'])
178
179
179 else:
180 else:
180 org_name = repo_name = str(form_data['repo_name'])
181 org_name = repo_name = form_data['repo_name']
181 repo_name_full = form_data['repo_name_full']
182 repo_name_full = form_data['repo_name_full']
182
183
183 new_repo = Repository()
184 new_repo = Repository()
@@ -302,21 +303,23 b' class RepoModel(BaseModel):'
302 """
303 """
303 from rhodecode.lib.utils import check_repo
304 from rhodecode.lib.utils import check_repo
304
305
305
306 if new_parent_id:
306 if new_parent_id:
307 paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
307 paths = Group.get(new_parent_id).full_path.split(Group.url_sep())
308 new_parent_path = os.sep.join(paths)
308 new_parent_path = os.sep.join(paths)
309 else:
309 else:
310 new_parent_path = ''
310 new_parent_path = ''
311
311
312 repo_path = os.path.join(self.repos_path, new_parent_path, repo_name)
312 repo_path = os.path.join(*map(lambda x:safe_str(x),
313 [self.repos_path, new_parent_path, repo_name]))
313
314
314 if check_repo(repo_name, self.repos_path):
315 if check_repo(repo_path, self.repos_path):
315 log.info('creating repo %s in %s @ %s', repo_name, repo_path,
316 log.info('creating repo %s in %s @ %s', repo_name, repo_path,
316 clone_uri)
317 clone_uri)
317 backend = get_backend(alias)
318 backend = get_backend(alias)
319
318 backend(repo_path, create=True, src_url=clone_uri)
320 backend(repo_path, create=True, src_url=clone_uri)
319
321
322
320 def __rename_repo(self, old, new):
323 def __rename_repo(self, old, new):
321 """
324 """
322 renames repository on filesystem
325 renames repository on filesystem
@@ -27,12 +27,7 b' import time'
27 import traceback
27 import traceback
28 import logging
28 import logging
29
29
30 from mercurial import ui
31
32 from sqlalchemy.exc import DatabaseError
30 from sqlalchemy.exc import DatabaseError
33 from sqlalchemy.orm import make_transient
34
35 from beaker.cache import cache_region, region_invalidate
36
31
37 from vcs import get_backend
32 from vcs import get_backend
38 from vcs.utils.helpers import get_scm
33 from vcs.utils.helpers import get_scm
@@ -42,15 +37,14 b' from vcs.nodes import FileNode'
42
37
43 from rhodecode import BACKENDS
38 from rhodecode import BACKENDS
44 from rhodecode.lib import helpers as h
39 from rhodecode.lib import helpers as h
40 from rhodecode.lib import safe_str
45 from rhodecode.lib.auth import HasRepoPermissionAny
41 from rhodecode.lib.auth import HasRepoPermissionAny
46 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
42 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
47 action_logger
43 action_logger
48 from rhodecode.model import BaseModel
44 from rhodecode.model import BaseModel
49 from rhodecode.model.user import UserModel
45 from rhodecode.model.user import UserModel
50 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
46 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 UserFollowing, UserLog
47 UserFollowing, UserLog
53 from rhodecode.model.caching_query import FromCache
54
48
55 log = logging.getLogger(__name__)
49 log = logging.getLogger(__name__)
56
50
@@ -182,7 +176,10 b' class ScmModel(BaseModel):'
182 klass = get_backend(path[0])
176 klass = get_backend(path[0])
183
177
184 if path[0] == 'hg' and path[0] in BACKENDS.keys():
178 if path[0] == 'hg' and path[0] in BACKENDS.keys():
185 repos_list[name] = klass(path[1], baseui=baseui)
179
180 # for mercurial we need to have an str path
181 repos_list[name] = klass(safe_str(path[1]),
182 baseui=baseui)
186
183
187 if path[0] == 'git' and path[0] in BACKENDS.keys():
184 if path[0] == 'git' and path[0] in BACKENDS.keys():
188 repos_list[name] = klass(path[1])
185 repos_list[name] = klass(path[1])
@@ -364,10 +361,10 b' class ScmModel(BaseModel):'
364
361
365 # decoding here will force that we have proper encoded values
362 # decoding here will force that we have proper encoded values
366 # in any other case this will throw exceptions and deny commit
363 # in any other case this will throw exceptions and deny commit
367 content = content.encode('utf8')
364 content = safe_str(content)
368 message = message.encode('utf8')
365 message = safe_str(message)
369 path = f_path.encode('utf8')
366 path = safe_str(f_path)
370 author = author.encode('utf8')
367 author = safe_str(author)
371 m = IMC(repo)
368 m = IMC(repo)
372 m.change(FileNode(path, content))
369 m.change(FileNode(path, content))
373 tip = m.commit(message=message,
370 tip = m.commit(message=message,
@@ -7,8 +7,9 b' class TestSearchController(TestControlle'
7 def test_index(self):
7 def test_index(self):
8 self.log_user()
8 self.log_user()
9 response = self.app.get(url(controller='search', action='index'))
9 response = self.app.get(url(controller='search', action='index'))
10 print response.body
10
11 assert 'class="small" id="q" name="q" type="text"' in response.body, 'Search box content error'
11 self.assertTrue('class="small" id="q" name="q" type="text"' in
12 response.body)
12 # Test response...
13 # Test response...
13
14
14 def test_empty_search(self):
15 def test_empty_search(self):
@@ -16,20 +17,21 b' class TestSearchController(TestControlle'
16 raise SkipTest('skipped due to existing index')
17 raise SkipTest('skipped due to existing index')
17 else:
18 else:
18 self.log_user()
19 self.log_user()
19 response = self.app.get(url(controller='search', action='index'), {'q':HG_REPO})
20 response = self.app.get(url(controller='search', action='index'),
20 assert 'There is no index to search in. Please run whoosh indexer' in response.body, 'No error message about empty index'
21 {'q':HG_REPO})
22 self.assertTrue('There is no index to search in. '
23 'Please run whoosh indexer' in response.body)
21
24
22 def test_normal_search(self):
25 def test_normal_search(self):
23 self.log_user()
26 self.log_user()
24 response = self.app.get(url(controller='search', action='index'), {'q':'def repo'})
27 response = self.app.get(url(controller='search', action='index'),
25 print response.body
28 {'q':'def repo'})
26 assert '10 results' in response.body, 'no message about proper search results'
29 self.assertTrue('10 results' in response.body)
27 assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
30 self.assertTrue('Permission denied' not in response.body)
28
29
31
30 def test_repo_search(self):
32 def test_repo_search(self):
31 self.log_user()
33 self.log_user()
32 response = self.app.get(url(controller='search', action='index'), {'q':'repository:%s def test' % HG_REPO})
34 response = self.app.get(url(controller='search', action='index'),
33 print response.body
35 {'q':'repository:%s def test' % HG_REPO})
34 assert '4 results' in response.body, 'no message about proper search results'
36 self.assertTrue('4 results' in response.body)
35 assert 'Permission denied' not in response.body, 'Wrong permissions settings for that repo and user'
37 self.assertTrue('Permission denied' not in response.body)
General Comments 0
You need to be logged in to leave comments. Login now