~ubuntu-branches/ubuntu/intrepid/moin/intrepid-updates

« back to all changes in this revision

Viewing changes to MoinMoin/request.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2006-02-14 16:09:24 UTC
  • mfrom: (0.2.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20060214160924-fyrx3gvknzqvt4vj
Tags: 1.5.2-1ubuntu1
Drop python2.3 package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
"""
9
9
 
10
10
import os, time, sys, cgi, StringIO
11
 
from MoinMoin import config, wikiutil, user
 
11
import copy
 
12
from MoinMoin import config, wikiutil, user, caching
12
13
from MoinMoin.util import MoinMoinNoFooter, IsWin9x
13
14
 
14
15
# Timing ---------------------------------------------------------------
101
102
        # not on external non-Apache servers
102
103
        self.forbidden = False
103
104
        if self.request_uri.startswith('http://'):
104
 
            self.makeForbidden()
 
105
            self.makeForbidden403()
105
106
 
106
107
        # Init
107
108
        else:
108
109
            self.writestack = []
109
110
            self.clock = Clock()
110
111
            # order is important here!
 
112
            self.__dict__.update(properties)
111
113
            self._load_multi_cfg()
112
114
            
113
115
            # Set decode charsets.  Input from the user is always in
141
143
            self.rootpage = Page(self, rootname, is_rootpage=1)
142
144
 
143
145
            self.user = self.get_user()
 
146
            
 
147
            if not self.query_string.startswith('action=xmlrpc'):
 
148
                if self.surge_protect():
 
149
                    self.makeUnavailable503()
144
150
 
145
151
            from MoinMoin import i18n
146
152
 
149
155
            self.mode_getpagelinks = 0
150
156
            self.no_closing_html_code = 0
151
157
 
152
 
            self.__dict__.update(properties)
153
 
 
154
158
            self.i18n = i18n
155
159
            self.lang = i18n.requestLanguage(self) 
156
160
            # Language for content. Page content should use the wiki
162
166
            self.opened_logs = 0
163
167
            self.reset()
164
168
        
 
169
    def surge_protect(self):
 
170
        """ check if someone requesting too much from us """
 
171
        validuser = self.user.valid
 
172
        current_id = validuser and self.user.name or self.remote_addr
 
173
        current_action = self.form.get('action', ['show'])[0]
 
174
        if not validuser and current_id.startswith('127.'): # localnet
 
175
            return False
 
176
        
 
177
        limits = self.cfg.surge_action_limits
 
178
        default_limit = self.cfg.surge_action_limits.get('default', (30, 60))
 
179
        
 
180
        now = int(time.time())
 
181
        surgedict = {}
 
182
        surge_detected = False
 
183
        
 
184
        try:
 
185
            cache = caching.CacheEntry(self, 'surgeprotect', 'surge-log')
 
186
            data = cache.content()
 
187
            data = data.split("\n")
 
188
            for line in data:
 
189
                try:
 
190
                    id, t, action, surge_indicator = line.split("\t")
 
191
                    t = int(t)
 
192
                    maxnum, dt = limits.get(action, default_limit)
 
193
                    if t >= now - dt:
 
194
                        events = surgedict.setdefault(id, copy.copy({}))
 
195
                        timestamps = events.setdefault(action, copy.copy([]))
 
196
                        timestamps.append((t, surge_indicator))
 
197
                except StandardError, err:
 
198
                    pass
 
199
        
 
200
            maxnum, dt = limits.get(current_action, default_limit)
 
201
            events = surgedict.setdefault(current_id, copy.copy({}))
 
202
            timestamps = events.setdefault(current_action, copy.copy([]))
 
203
            surge_detected = len(timestamps) > maxnum
 
204
            surge_indicator = surge_detected and "!" or ""
 
205
            timestamps.append((now, surge_indicator))
 
206
            if surge_detected:
 
207
                if len(timestamps) < maxnum*2:
 
208
                    timestamps.append((now + self.cfg.surge_lockout_time, surge_indicator)) # continue like that and get locked out
 
209
        
 
210
            data = []
 
211
            for id, events in surgedict.items():
 
212
                for action, timestamps in events.items():
 
213
                    for t, surge_indicator in timestamps:
 
214
                        data.append("%s\t%d\t%s\t%s" % (id, t, action, surge_indicator))
 
215
            data = "\n".join(data)
 
216
            cache.update(data)
 
217
        except StandardError, err:
 
218
            pass
 
219
 
 
220
        return surge_detected   
 
221
        
165
222
    def getDicts(self):
166
223
        """ Lazy initialize the dicts on the first access """
167
224
        if self._dicts is None:
454
511
        # during the rendering of a page by lang macros
455
512
        self.current_lang = self.cfg.language_default
456
513
 
457
 
        self._footer_fragments = {}
458
514
        self._all_pages = None
459
515
        # caches unique ids
460
516
        self._page_ids = {}
506
562
        self.content_lang = lang
507
563
        self.current_lang = lang
508
564
 
509
 
    def add2footer(self, key, htmlcode):
510
 
        """ Add a named HTML fragment to the footer, after the default links
511
 
        """
512
 
        self._footer_fragments[key] = htmlcode
513
 
 
514
565
    def getPragma(self, key, defval=None):
515
566
        """ Query a pragma value (#pragma processing instruction)
516
567
 
894
945
        """ Get the user agent. """
895
946
        return self.http_user_agent
896
947
 
897
 
    def makeForbidden(self):
898
 
        self.forbidden = True
 
948
    def makeForbidden(self, resultcode, msg):
 
949
        statusmsg = {
 
950
            403: 'FORBIDDEN',
 
951
            503: 'Service unavailable',
 
952
        }
899
953
        self.http_headers([
900
 
            'Status: 403 FORBIDDEN',
 
954
            'Status: %d %s' % (resultcode, statusmsg[resultcode]),
901
955
            'Content-Type: text/plain'
902
956
        ])
903
 
        self.write('You are not allowed to access this!\r\n')
904
 
        self.setResponseCode(403)
 
957
        self.write(msg)
 
958
        self.setResponseCode(resultcode)
 
959
        self.forbidden = True
 
960
 
 
961
    def makeForbidden403(self):
 
962
        self.makeForbidden(403, 'You are not allowed to access this!\r\n')
 
963
 
 
964
    def makeUnavailable503(self):
 
965
        self.makeForbidden(503, "Warning:\r\n"
 
966
                   "You triggered the wiki's surge protection by doing too many requests in a short time.\r\n"
 
967
                   "Please make a short break reading the stuff you already got.\r\n"
 
968
                   "When you restart doing requests AFTER that, slow down or you might get locked out for a longer time!\r\n")
905
969
 
906
970
    def initTheme(self):
907
971
        """ Set theme - forced theme, user theme or wiki default """
916
980
        if self.failed or self.forbidden:
917
981
            return self.finish()
918
982
        if self.isForbidden():
919
 
            self.makeForbidden()
 
983
            self.makeForbidden403()
920
984
            if self.forbidden:
921
985
                return self.finish()
922
986
 
1072
1136
        @param url: relative or absolute url, ascii using url encoding.
1073
1137
        """
1074
1138
        url = self.getQualifiedURL(url)
1075
 
        self.http_headers(["Status: 302", "Location: %s" % url])
 
1139
        self.http_headers(["Status: 302 Found", "Location: %s" % url])
1076
1140
 
1077
1141
    def setHttpHeader(self, header):
1078
1142
        """ Save header for later send. """
1331
1395
 
1332
1396
    def __init__(self, properties={}):
1333
1397
        try:
1334
 
            self._setup_vars_from_std_env(os.environ)
1335
 
            RequestBase.__init__(self, properties)
1336
 
 
1337
1398
            # force input/output to binary
1338
1399
            if sys.platform == "win32":
1339
1400
                import msvcrt
1340
1401
                msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
1341
1402
                msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
1342
1403
 
 
1404
            self._setup_vars_from_std_env(os.environ)
 
1405
            RequestBase.__init__(self, properties)
 
1406
 
1343
1407
        except Exception, err:
1344
1408
            self.fail(err)
1345
1409