diff --git a/rhodecode/controllers/changeset.py b/rhodecode/controllers/changeset.py --- a/rhodecode/controllers/changeset.py +++ b/rhodecode/controllers/changeset.py @@ -31,11 +31,10 @@ from webob.exc import HTTPForbidden, HTT from pylons import tmpl_context as c, url, request, response from pylons.i18n.translation import _ from pylons.controllers.util import redirect -from pylons.decorators import jsonify +from rhodecode.lib.utils import jsonify -from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetError, \ +from rhodecode.lib.vcs.exceptions import RepositoryError, \ ChangesetDoesNotExistError -from rhodecode.lib.vcs.nodes import FileNode import rhodecode.lib.helpers as h from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator @@ -47,8 +46,8 @@ from rhodecode.model.db import Changeset from rhodecode.model.comment import ChangesetCommentsModel from rhodecode.model.changeset_status import ChangesetStatusModel from rhodecode.model.meta import Session +from rhodecode.model.repo import RepoModel from rhodecode.lib.diffs import LimitedDiffContainer -from rhodecode.model.repo import RepoModel from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError from rhodecode.lib.vcs.backends.base import EmptyChangeset from rhodecode.lib.utils2 import safe_unicode diff --git a/rhodecode/controllers/files.py b/rhodecode/controllers/files.py --- a/rhodecode/controllers/files.py +++ b/rhodecode/controllers/files.py @@ -31,7 +31,7 @@ import tempfile from pylons import request, response, tmpl_context as c, url from pylons.i18n.translation import _ from pylons.controllers.util import redirect -from pylons.decorators import jsonify +from rhodecode.lib.utils import jsonify from rhodecode.lib import diffs from rhodecode.lib import helpers as h diff --git a/rhodecode/controllers/pullrequests.py b/rhodecode/controllers/pullrequests.py --- a/rhodecode/controllers/pullrequests.py +++ b/rhodecode/controllers/pullrequests.py @@ -33,7 +33,6 @@ from itertools import groupby from pylons import request, response, session, tmpl_context as c, url from pylons.controllers.util import abort, redirect from pylons.i18n.translation import _ -from pylons.decorators import jsonify from rhodecode.lib.compat import json from rhodecode.lib.base import BaseRepoController, render @@ -41,7 +40,10 @@ from rhodecode.lib.auth import LoginRequ NotAnonymous from rhodecode.lib import helpers as h from rhodecode.lib import diffs -from rhodecode.lib.utils import action_logger +from rhodecode.lib.utils import action_logger, jsonify +from rhodecode.lib.vcs.exceptions import EmptyRepositoryError +from rhodecode.lib.vcs.backends.base import EmptyChangeset +from rhodecode.lib.diffs import LimitedDiffContainer from rhodecode.model.db import User, PullRequest, ChangesetStatus,\ ChangesetComment from rhodecode.model.pull_request import PullRequestModel @@ -50,10 +52,6 @@ from rhodecode.model.repo import RepoMod from rhodecode.model.comment import ChangesetCommentsModel from rhodecode.model.changeset_status import ChangesetStatusModel from rhodecode.model.forms import PullRequestForm -from rhodecode.lib.vcs.exceptions import EmptyRepositoryError -from rhodecode.lib.vcs.backends.base import EmptyChangeset -from rhodecode.lib.diffs import LimitedDiffContainer -from rhodecode.lib.utils2 import str2bool log = logging.getLogger(__name__) diff --git a/rhodecode/lib/utils.py b/rhodecode/lib/utils.py --- a/rhodecode/lib/utils.py +++ b/rhodecode/lib/utils.py @@ -32,6 +32,8 @@ import paste import beaker import tarfile import shutil +import decorator +import warnings from os.path import abspath from os.path import dirname as dn, join as jn @@ -714,3 +716,27 @@ def check_git_version(): 'for the system to function properly. Make sure ' 'its version is at least %s' % (ver, req_ver)) return _ver + + +@decorator.decorator +def jsonify(func, *args, **kwargs): + """Action decorator that formats output for JSON + + Given a function that will return content, this decorator will turn + the result into JSON, with a content-type of 'application/json' and + output it. + + """ + from pylons.decorators.util import get_pylons + from rhodecode.lib.ext_json import json + pylons = get_pylons(args) + pylons.response.headers['Content-Type'] = 'application/json; charset=utf-8' + data = func(*args, **kwargs) + if isinstance(data, (list, tuple)): + msg = "JSON responses with Array envelopes are susceptible to " \ + "cross-site data leak attacks, see " \ + "http://wiki.pylonshq.com/display/pylonsfaq/Warnings" + warnings.warn(msg, Warning, 2) + log.warning(msg) + log.debug("Returning JSON wrapped action output") + return json.dumps(data, encoding='utf-8') \ No newline at end of file