Exemple #1
0
def writeEvent(request, event_text, event_name, event_location,
               event_time_unix, posted_by):
    posted_time = time.time()
    if config.db_type == 'mysql':
        request.cursor.execute(
            """INSERT into events
               (uid, event_time, posted_by, text, location, event_name,
                posted_time, posted_by_ip, wiki_id)
               values (NULL, %(event_time_unix)s, %(posted_by)s,
                       %(event_text)s, %(event_location)s, %(event_name)s,
                       %(posted_time)s, %(userip)s, %(wiki_id)s)""",
            {'id':id, 'event_time_unix':event_time_unix, 'posted_by':posted_by,
             'event_text':event_text, 'event_location':event_location,
             'event_name':event_name, 'posted_time':posted_time,
             'userip':request.remote_addr, 'wiki_id':request.config.wiki_id},
            isWrite=True)
    else:
        request.cursor.execute(
            """INSERT into events
               (uid, event_time, posted_by, text, location, event_name,
                posted_time, posted_by_ip, wiki_id)
               values (NEXTVAL('events_seq'), %(event_time_unix)s,
                       %(posted_by)s, %(event_text)s, %(event_location)s,
                       %(event_name)s, %(posted_time)s, %(userip)s,
                       %(wiki_id)s)""",
            {'id':id, 'event_time_unix':event_time_unix, 'posted_by':posted_by,
             'event_text':event_text, 'event_location':event_location,
             'event_name':event_name, 'posted_time':posted_time,
             'userip':request.remote_addr,
             'wiki_id':request.config.wiki_id}, isWrite=True)
    
    if config.memcache:
        # clear out today's events cache if the event is for today
        event_time_struct = time.gmtime(event_time_unix +
                                        request.config.tz_offset)
        event_day_unix = calendar.timegm(
            list(event_time_struct[0:3]) + [0,0,0,0,0,0])

        today_struct = time.gmtime(posted_time+request.config.tz_offset)
        today = list(today_struct[0:3]) + [0,0,0,0,0,0]
        today_unix = calendar.timegm(today)
        if event_day_unix == today_unix:
            request.mc.delete("today_events")
        caching.updateRecentChanges(Page("Events Board", request))
Exemple #2
0
def writeEvent(request, event_text, event_name, event_location,
               event_time_unix, posted_by):
    posted_time = time.time()
    if config.db_type == 'mysql':
        request.cursor.execute(
            """INSERT into events
               (uid, event_time, posted_by, text, location, event_name,
                posted_time, posted_by_ip, wiki_id)
               values (NULL, %(event_time_unix)s, %(posted_by)s,
                       %(event_text)s, %(event_location)s, %(event_name)s,
                       %(posted_time)s, %(userip)s, %(wiki_id)s)""",
            {'id':id, 'event_time_unix':event_time_unix, 'posted_by':posted_by,
             'event_text':event_text, 'event_location':event_location,
             'event_name':event_name, 'posted_time':posted_time,
             'userip':request.remote_addr, 'wiki_id':request.config.wiki_id},
            isWrite=True)
    else:
        request.cursor.execute(
            """INSERT into events
               (uid, event_time, posted_by, text, location, event_name,
                posted_time, posted_by_ip, wiki_id)
               values (NEXTVAL('events_seq'), %(event_time_unix)s,
                       %(posted_by)s, %(event_text)s, %(event_location)s,
                       %(event_name)s, %(posted_time)s, %(userip)s,
                       %(wiki_id)s)""",
            {'id':id, 'event_time_unix':event_time_unix, 'posted_by':posted_by,
             'event_text':event_text, 'event_location':event_location,
             'event_name':event_name, 'posted_time':posted_time,
             'userip':request.remote_addr,
             'wiki_id':request.config.wiki_id}, isWrite=True)
    
    if config.memcache:
        # clear out today's events cache if the event is for today
        event_time_struct = time.gmtime(event_time_unix +
                                        request.config.tz_offset)
        event_day_unix = calendar.timegm(
            list(event_time_struct[0:3]) + [0,0,0,0,0,0])

        today_struct = time.gmtime(posted_time+request.config.tz_offset)
        today = list(today_struct[0:3]) + [0,0,0,0,0,0]
        today_unix = calendar.timegm(today)
        if event_day_unix == today_unix:
            request.mc.delete("today_events")
        caching.updateRecentChanges(Page("Events Board", request))
Exemple #3
0
def revert_to_page(oldpg, request, pg, comment=None, permanent=False,
                   showrc=True):
    _ = request.getText
    if permanent:
        delete_all_newer(oldpg, request, showrc)  
        if not showrc:
            set_current_pagetext(oldpg, request)
    
    try:
        # don't log on RC if admin doesn't want it
        if not (permanent and not showrc):
            pg.saveText(oldpg.get_raw_body(), '0', stripspaces=0, notify=1,
                        comment=comment, action="SAVE/REVERT")
            pagename = pg.proper_name()
        else:
            #doing hard work ourselves..
            # should be abstracted into the page object.
            pg.set_raw_body(oldpg.get_raw_body()) 
            # deal with the case of macros / other items that change state
            # by /not/ being in the page
            search.add_to_index(pg)
            pg.buildCache()
            caching.CacheEntry(pg.page_name, request).clear()
            caching.updateRecentChanges(pg)
            # if we revert to a version with a differently-cased pagename
            pagename = _set_proper_pagename(request, oldpg)
        savemsg = _("Page reverted to version %s" % oldpg.version)
    except pg.Unchanged:
        savemsg = _("The current page is the same as the older page you wish "
                    "to revert to!")
    except pg.SaveError:
        savemsg = _("An error occurred while reverting the page.")
    
    # clear req cache so user sees proper page state (exist)
    request.req_cache['pagenames'][(
        pagename.lower(), request.config.wiki_name)] = pagename

    return savemsg
Exemple #4
0
def revert_to_page(oldpg, request, pg, comment=None, permanent=False,
                   showrc=True):
    _ = request.getText
    if permanent:
        delete_all_newer(oldpg, request, showrc)  
        if not showrc:
            set_current_pagetext(oldpg, request)
    
    try:
        # don't log on RC if admin doesn't want it
        if not (permanent and not showrc):
            pg.saveText(oldpg.get_raw_body(), '0', stripspaces=0, notify=1,
                        comment=comment, action="SAVE/REVERT")
            pagename = pg.proper_name()
        else:
            #doing hard work ourselves..
            # should be abstracted into the page object.
            pg.set_raw_body(oldpg.get_raw_body()) 
            # deal with the case of macros / other items that change state
            # by /not/ being in the page
            search.add_to_index(pg)
            pg.buildCache()
            caching.CacheEntry(pg.page_name, request).clear()
            caching.updateRecentChanges(pg)
            # if we revert to a version with a differently-cased pagename
            pagename = _set_proper_pagename(request, oldpg)
        savemsg = _("Page reverted to version %s" % oldpg.version)
    except pg.Unchanged:
        savemsg = _("The current page is the same as the older page you wish "
                    "to revert to!")
    except pg.SaveError:
        savemsg = _("An error occurred while reverting the page.")
    
    # clear req cache so user sees proper page state (exist)
    request.req_cache['pagenames'][(
        pagename.lower(), request.config.wiki_name)] = pagename

    return savemsg
Exemple #5
0
    def handle_file_delete():
        request.cursor.execute(
            """SELECT name from files
               where name=%(filename)s and
                     attached_to_pagename=%(pagename)s and
                     wiki_id=%(wiki_id)s""", dict)
        has_file = request.cursor.fetchone()
        if has_file:
            if not permanent:
                # backup file
                request.cursor.execute("""
                    INSERT into oldFiles
                        (name, attached_to_pagename, file, uploaded_by,
                         uploaded_time, deleted_time, deleted_by,
                         uploaded_by_ip, deleted_by_ip,
                         attached_to_pagename_propercased, wiki_id)
                    values
                        (%(filename)s, %(pagename)s,
                         (select file from files
                              where name=%(filename)s and
                                    attached_to_pagename=%(pagename)s and
                                    wiki_id=%(wiki_id)s
                         ),
                         (select uploaded_by from files
                              where name=%(filename)s and
                                    attached_to_pagename=%(pagename)s and
                                    wiki_id=%(wiki_id)s
                         ),
                         (select uploaded_time from files
                              where name=%(filename)s and
                                    attached_to_pagename=%(pagename)s and
                                    wiki_id=%(wiki_id)s
                         ),
                         %(deleted_time)s, %(deleted_by)s,
                         (select uploaded_by_ip from files
                              where name=%(filename)s and
                                    attached_to_pagename=%(pagename)s and
                                    wiki_id=%(wiki_id)s
                         ),
                         %(deleted_by_ip)s,
                         (select attached_to_pagename_propercased from files
                              where name=%(filename)s and
                                    attached_to_pagename=%(pagename)s and
                                    wiki_id=%(wiki_id)s
                         ),
                         %(wiki_id)s)""", dict, isWrite=True)
            else:
                # nuke all old cached versions of the file
                caching.deleteAllFileInfo(dict['filename'], dict['pagename'],
                                          request)
                # nuke all old versions
                request.cursor.execute(
                    """DELETE from oldFiles
                           where name=%(filename)s and
                                 attached_to_pagename=%(pagename)s and
                                 wiki_id=%(wiki_id)s""", dict, isWrite=True)

            if is_image:
                if not permanent:
                    # backup image info
                    request.cursor.execute(
                        """INSERT into oldImageInfo
                           (name, attached_to_pagename, xsize, ysize,
                            uploaded_time, wiki_id)
                           values
                           (%(filename)s, %(pagename)s,
                            (select xsize from imageInfo
                                 where name=%(filename)s and
                                       attached_to_pagename=%(pagename)s and
                                       wiki_id=%(wiki_id)s
                            ),
                            (select ysize from imageInfo
                                 where name=%(filename)s and
                                       attached_to_pagename=%(pagename)s and
                                       wiki_id=%(wiki_id)s
                            ),
                            (select uploaded_time from files
                                  where name=%(filename)s and
                                        attached_to_pagename=%(pagename)s and
                                        wiki_id=%(wiki_id)s
                            ),
                            %(wiki_id)s)""", dict, isWrite=True)
                
                else:
                    # nuke all old versions
                    request.cursor.execute(
                        """DELETE from oldImageInfo
                           where name=%(filename)s and
                                 attached_to_pagename=%(pagename)s and
                                 wiki_id=%(wiki_id)s""", dict, isWrite=True)
                # delete image info
                request.cursor.execute(
                    """DELETE from imageInfo
                       where name=%(filename)s and
                             attached_to_pagename=%(pagename)s and
                             wiki_id=%(wiki_id)s""", dict, isWrite=True)
            # delete file 
            request.cursor.execute(
                """DELETE from files
                   where name=%(filename)s and
                         attached_to_pagename=%(pagename)s and
                         wiki_id=%(wiki_id)s""", dict, isWrite=True)

            caching.updateRecentChanges(page)
Exemple #6
0
    def handle_file_add():
        request.cursor.execute(
            """SELECT name from files
               where name=%(filename)s and
                     attached_to_pagename=%(pagename)s and
                     wiki_id=%(wiki_id)s""", dict)
        exists = request.cursor.fetchone()
        if exists:
            # backup file, then remove it  
            replaced_image = True
            request.cursor.execute(
                """INSERT into oldFiles
                       (name, file, uploaded_time, uploaded_by,
                        attached_to_pagename, deleted_time, deleted_by,
                        uploaded_by_ip, deleted_by_ip,
                        attached_to_pagename_propercased, wiki_id)
                   values
                       (%(filename)s,
                        (select file from files where name=%(filename)s and
                            attached_to_pagename=%(pagename)s and
                            wiki_id=%(wiki_id)s
                        ),
                        (select uploaded_time from files where
                            name=%(filename)s and
                            attached_to_pagename=%(pagename)s and
                            wiki_id=%(wiki_id)s
                        ),
                        (select uploaded_by from files where
                            name=%(filename)s and
                            attached_to_pagename=%(pagename)s and
                            wiki_id=%(wiki_id)s
                        ),
                        %(pagename)s, %(uploaded_time)s, %(uploaded_by)s,
                        (select uploaded_by_ip from files where
                            name=%(filename)s and
                            attached_to_pagename=%(pagename)s and
                            wiki_id=%(wiki_id)s
                        ),
                        %(uploaded_by_ip)s, %(pagename_propercased)s,
                        %(wiki_id)s)""", dict, isWrite=True)
            if is_image:
                request.cursor.execute(
                    """INSERT into oldImageInfo
                           (name, attached_to_pagename, xsize, ysize,
                            uploaded_time, wiki_id)
                       values
                           (%(filename)s, %(pagename)s,
                            (select xsize from imageInfo where
                                name=%(filename)s and
                                attached_to_pagename=%(pagename)s and
                                wiki_id=%(wiki_id)s
                            ),
                            (select ysize from imageInfo where
                                name=%(filename)s and
                                attached_to_pagename=%(pagename)s and
                                wiki_id=%(wiki_id)s
                            ),
                            (select uploaded_time from files where
                                name=%(filename)s and
                                attached_to_pagename=%(pagename)s and
                                wiki_id=%(wiki_id)s
                            ),
                            %(wiki_id)s)""", dict, isWrite=True)
                request.cursor.execute(
                    """DELETE from imageInfo
                       where name=%(filename)s and
                             attached_to_pagename=%(pagename)s and
                             wiki_id=%(wiki_id)s""", dict, isWrite=True)

            request.cursor.execute(
                """DELETE from files
                   where name=%(filename)s and
                         attached_to_pagename=%(pagename)s and
                         wiki_id=%(wiki_id)s""", dict, isWrite=True)

        request.cursor.execute(
            """INSERT into files
                   (name, file, uploaded_time, uploaded_by,
                    attached_to_pagename, uploaded_by_ip,
                    attached_to_pagename_propercased, wiki_id)
               values
                   (%(filename)s, %(filecontent)s, %(uploaded_time)s,
                    %(uploaded_by)s, %(pagename)s, %(uploaded_by_ip)s,
                    %(pagename_propercased)s, %(wiki_id)s)""",
            dict, isWrite=True)
        if is_image:
            request.cursor.execute(
                """INSERT into imageInfo
                       (name, attached_to_pagename, xsize, ysize, wiki_id)
                   values
                       (%(filename)s, %(pagename)s, %(xsize)s, %(ysize)s,
                        %(wiki_id)s)""", dict, isWrite=True)
      
        caching.updateRecentChanges(page)
Exemple #7
0
def execute(pagename, request):
    _ = request.getText
    actname = __name__.split('.')[-1]
    page = PageEditor(pagename, request)
    msg = ''
    oldtext = page.get_raw_body().lower()

    events_page = Page("Events Board", request) 

    # Do we want an RSS feed?
    if (request.form.has_key('rss') and request.form.get("rss")[0] == '1' and
        request.user.may.read(events_page)):
        request.http_headers(more_headers=[('Content-type', 'application/rss+xml')]) # added content-type header so the right mimetype goes out 2008/05/12 rtucker
        request.write(doRSS(request))
        raise util.SycamoreNoFooter
        return

    # be extra paranoid
    elif (actname in config.excluded_actions or
          not request.user.valid or not request.user.may.edit(events_page) or
          not request.user.may.edit(page)):
        msg = _('You are not allowed to edit this page. '
                '(You need an account in most cases)')
    # check to make sure the events macro is in the page
    elif string.find(oldtext,"[[events]]") == -1:
        msg = _('Not allowed to add an event')

    # check whether page exists at all
    elif not page.exists():
        msg = _('This page does not exist.')

    # check whether the user filled out the form
    elif request.form.has_key('uid') and request.form.has_key('del'):
        if (request.form.get('del')[0] == "1" and
            request.user.may.admin(Page("Events Board", request))):
            # let's try and delete the event!
            uid = request.form.get('uid')[0]
            request.cursor.execute(
                "SELECT event_name from events where uid=%(uid)s", {'uid':uid})
            name = request.cursor.fetchone()[0]
            request.cursor.execute(
                "DELETE from events where uid=%(uid)s", {'uid':uid},
                isWrite=True)
            msg = 'Event "%s" <b>deleted</b>!' % name

        elif request.form.get('del')[0] == "1":
            uid = request.form.get('uid')[0]
            request.cursor.execute(
                "SELECT event_name from events where uid=%(uid)s", {'uid':uid})
            name = request.cursor.fetchone()[0]
            request.cursor.execute(
                """DELETE from events where uid=%(uid)s and
                             posted_by=%(username)s""",
                {'uid':uid, 'username':request.user.propercased_name},
                isWrite=True)
            msg = 'Event "%s" <b>deleted</b>!' % name
    
        if config.memcache:
            request.mc.set("today_events", None)
            caching.updateRecentChanges(Page("Events Board", request))

    elif (request.form.has_key('button') and 
          request.form.has_key('event_text') and
          request.form.has_key('event_name') and
          request.form.has_key('event_location') and
          request.form.has_key('month') and
          request.form.has_key('day') and
          request.form.has_key('hour') and
          request.form.has_key('minute') and
          request.form.has_key('ticket')):
        # check whether this is a valid renaming request (make outside
        # attacks harder by requiring two full HTTP transactions)
        if not _checkTicket(request.form['ticket'][0]):
            msg = _('Please use the web interface to change the page!')
        else:
            event_text = request.form.get('event_text')[0]
            event_name = request.form.get('event_name')[0]
            event_location = request.form.get('event_location')[0]
            month = int(request.form.get('month')[0])
            day = int(request.form.get('day')[0])
            hour = int(request.form.get('hour')[0])
            minute = int(request.form.get('minute')[0])
            year = int(request.form.get('year')[0])
            posted_by = request.user.propercased_name
            now = request.user.getFormattedDateTime(time.time(),
                                                    global_time=True)
    
            # WE NEED TO VALIDATE THE TEXT AND THE OTHER FIELDS
            if (isValid(event_text, event_name, event_location, month, day,
                       hour, minute, year) and not
               hasPassed(month, day, hour,minute, year, request)):
                event_time_unix = wikiutil.timeInTzToUTC(
                    request.config.tz,
                    (year, month, day, hour, minute, 0, 0))
                writeEvent(request, event_text, event_name,
                           event_location, event_time_unix, posted_by)
                msg = _('Your event has been added!')
            elif hasPassed(month,day,hour,minute,year,request):
                msg = _('Event time is in the past!  '
                        'Please choose a time in the future.')
            else:
                msg = _('Event <b>NOT</b> posted. '
                        'You entered some invalid text into the form.  '
                        'No HTML is allowed.')
   
    else:
        msg = _('Please fill out all fields of the form.')
        
    return page.send_page(msg)
Exemple #8
0
def execute(pagename, request):
    _ = request.getText
    actname = __name__.split('.')[-1]
    page = PageEditor(pagename, request)
    msg = ''
    oldtext = page.get_raw_body().lower()

    events_page = Page("Events Board", request) 

    # Do we want an RSS feed?
    if (request.form.has_key('rss') and request.form.get("rss")[0] == '1' and
        request.user.may.read(events_page)):
        request.http_headers()
        request.write(doRSS(request))
        raise util.SycamoreNoFooter
        return

    # be extra paranoid
    elif (actname in config.excluded_actions or
          not request.user.valid or not request.user.may.edit(events_page) or
          not request.user.may.edit(page)):
        msg = _('You are not allowed to edit this page. '
                '(You need an account in most cases)')
    # check to make sure the events macro is in the page
    elif string.find(oldtext,"[[events]]") == -1:
        msg = _('Not allowed to add an event')

    # check whether page exists at all
    elif not page.exists():
        msg = _('This page does not exist.')

    # check whether the user filled out the form
    elif request.form.has_key('uid') and request.form.has_key('del'):
        if (request.form.get('del')[0] == "1" and
            request.user.may.admin(Page("Events Board", request))):
            # let's try and delete the event!
            uid = request.form.get('uid')[0]
            request.cursor.execute(
                "SELECT event_name from events where uid=%(uid)s", {'uid':uid})
            name = request.cursor.fetchone()[0]
            request.cursor.execute(
                "DELETE from events where uid=%(uid)s", {'uid':uid},
                isWrite=True)
            msg = 'Event "%s" <b>deleted</b>!' % name

        elif request.form.get('del')[0] == "1":
            uid = request.form.get('uid')[0]
            request.cursor.execute(
                "SELECT event_name from events where uid=%(uid)s", {'uid':uid})
            name = request.cursor.fetchone()[0]
            request.cursor.execute(
                """DELETE from events where uid=%(uid)s and
                             posted_by=%(username)s""",
                {'uid':uid, 'username':request.user.propercased_name},
                isWrite=True)
            msg = 'Event "%s" <b>deleted</b>!' % name
    
        if config.memcache:
            request.mc.set("today_events", None)
            caching.updateRecentChanges(Page("Events Board", request))

    elif (request.form.has_key('button') and 
          request.form.has_key('event_text') and
          request.form.has_key('event_name') and
          request.form.has_key('event_location') and
          request.form.has_key('month') and
          request.form.has_key('day') and
          request.form.has_key('hour') and
          request.form.has_key('minute') and
          request.form.has_key('ticket')):
        # check whether this is a valid renaming request (make outside
        # attacks harder by requiring two full HTTP transactions)
        if not _checkTicket(request.form['ticket'][0]):
            msg = _('Please use the web interface to change the page!')
        else:
            event_text = request.form.get('event_text')[0]
            event_name = request.form.get('event_name')[0]
            event_location = request.form.get('event_location')[0]
            month = int(request.form.get('month')[0])
            day = int(request.form.get('day')[0])
            hour = int(request.form.get('hour')[0])
            minute = int(request.form.get('minute')[0])
            year = int(request.form.get('year')[0])
            posted_by = request.user.propercased_name
            now = request.user.getFormattedDateTime(time.time(),
                                                    global_time=True)
    
            # WE NEED TO VALIDATE THE TEXT AND THE OTHER FIELDS
            if (isValid(event_text, event_name, event_location, month, day,
                       hour, minute, year) and not
               hasPassed(month, day, hour,minute, year, request)):
                event_time_unix = wikiutil.timeInTzToUTC(
                    request.config.tz,
                    (year, month, day, hour, minute, 0, 0))
                writeEvent(request, event_text, event_name,
                           event_location, event_time_unix, posted_by)
                msg = _('Your event has been added!')
            elif hasPassed(month,day,hour,minute,year,request):
                msg = _('Event time is in the past!  '
                        'Please choose a time in the future.')
            else:
                msg = _('Event <b>NOT</b> posted. '
                        'You entered some invalid text into the form.  '
                        'No HTML is allowed.')
   
    else:
        msg = _('Please fill out all fields of the form.')
        
    return page.send_page(msg)
Exemple #9
0
    def saveText(self, newtext, datestamp, **kw):
        """
        Save new text for a page.

        @param newtext: text to save for this page
        @param datestamp: ...
        @keyword stripspaces: strip whitespace from line ends (default: 0)
        @keyword notify: send email notice tp subscribers (default: 0)
        @keyword comment: comment field (when preview is true)
        @keyword action: action for log (default: SAVE)
        @keyword proper_name: properly-cased pagename (for renames)
        @keyword ignore_edit_conflicts: force a save regardless of status
                                        (boolean)
        @keyword force_save: ignore "page content the same" error
        @rtype: string
        @return: error msg
        """
        self.page_name = self.page_name.strip() # to ensure consistency
        _ = self._
        newtext = self._normalize_text(newtext, **kw)

        # for inline editing we want things to be as smooth as we can
        no_save_msg = False
        if (self.request.form.has_key('no_save_msg') and
            self.request.form['no_save_msg'][0]):
            no_save_msg = True

        msg = ""
        merged_changes = False
        ignore_edit_conflicts = kw.get('ignore_edit_conflicts', False)
        if not self.request.user.may.save(self, newtext, datestamp, **kw):
            msg = _('You are not allowed to edit this page!')
            raise self.AccessDenied, msg
        elif not newtext.strip():
            msg = _('You cannot save empty pages.')
            raise self.EmptyPage, msg
        elif (not ignore_edit_conflicts and datestamp != '0' and
              (datestamp < self.mtime()) and self.exists()):
            from Sycamore.util import diff3
            savetext = newtext
            original_text = Page(self.page_name, self.request,
                                 prev_date=datestamp).get_raw_body()
            saved_text = self.get_raw_body()
            verynewtext, had_conflict = diff3.text_merge(
                original_text, saved_text, savetext,
                marker1='----- /!\ Edit conflict! Your version: -----\n',
                marker2='----- /!\ Edit conflict! Other version: -----\n',
                marker3='----- /!\ End of edit conflict -----\n')
            msg = _("Someone else changed this page while you were editing.")

            if (had_conflict and self.request.user.valid and
                (self.request.user.id == self.last_edit_info()[1])):
               # user pressed back button or did something weird
               had_conflict = False
               msg = None
            else:
                # we did some sort of merging or we had a conflict,
                # so let them know
                if had_conflict:
                    raise self.EditConflict, (msg, verynewtext)
                merged_changes = True
                msg = _("""%s Your changes were successfully merged! """ % msg)
                newtext = verynewtext
        elif (newtext == self.get_raw_body() and not
              self._rename_lowercase_condition() and
              kw.get('action') != 'SAVE/REVERT' and not
              kw.get('force_save')):
            # check to see if they're saving the page with the same content
            # it had before
            msg = _('You did not change the page content, not saved!')
            raise self.Unchanged, msg
        elif (config.max_page_size and 
            len(newtext.encode(config.charset)) > (config.max_page_size*1024)):
            msg = _('This page is too big!  Pages can be, at most, %sK.  '
                    'Consider splitting the page up into multiple pages '
                    'instead!' % config.max_page_size)
            raise self.TooBig, msg

        # save only if no error occured (msg is empty)
        if not msg or merged_changes:
            # set success msg
            if not merged_changes and not no_save_msg:
              msg = _("Thank you for your changes. "
                      "Your attention to detail is appreciated. ")

            # determine action for edit logging
            action = kw.get('action', 'SAVE')
            if action=='SAVE' and not self.exists():
                action = 'SAVENEW'
                           
            # write the page file
            mtime = self._write_to_db(newtext, action, kw.get('comment',''),
                                      self.request.remote_addr,
                                      kw.get('proper_name',None))
            # deal with the case of macros / other items that change state by
            # /not/ being in the page
            wikiutil.macro_delete_checks(self)
            
            # we'll try to change the stats early-on
            if self.request.user.name:
                self.userStatAdd(self.request.user, action, self.page_name)

            # add the page to the search index or update its index
            if action != 'DELETE':
                search.add_to_index(self)

            # note the change in recent changes.  this explicit call is needed
            # because of the way we cache our change information
            caching.updateRecentChanges(self)

            return msg
Exemple #10
0
    def saveText(self, newtext, datestamp, **kw):
        """
        Save new text for a page.

        @param newtext: text to save for this page
        @param datestamp: ...
        @keyword stripspaces: strip whitespace from line ends (default: 0)
        @keyword notify: send email notice tp subscribers (default: 0)
        @keyword comment: comment field (when preview is true)
        @keyword action: action for log (default: SAVE)
        @keyword proper_name: properly-cased pagename (for renames)
        @keyword ignore_edit_conflicts: force a save regardless of status
                                        (boolean)
        @keyword force_save: ignore "page content the same" error
        @rtype: string
        @return: error msg
        """
        self.page_name = self.page_name.strip()  # to ensure consistency
        _ = self._
        newtext = self._normalize_text(newtext, **kw)

        # for inline editing we want things to be as smooth as we can
        no_save_msg = False
        if (self.request.form.has_key('no_save_msg')
                and self.request.form['no_save_msg'][0]):
            no_save_msg = True

        msg = ""
        merged_changes = False
        ignore_edit_conflicts = kw.get('ignore_edit_conflicts', False)
        if not self.request.user.may.save(self, newtext, datestamp, **kw):
            msg = _('You are not allowed to edit this page!')
            raise self.AccessDenied, msg
        elif not newtext.strip():
            msg = _('You cannot save empty pages.')
            raise self.EmptyPage, msg
        elif (not ignore_edit_conflicts and datestamp != '0'
              and (datestamp < self.mtime()) and self.exists()):
            from Sycamore.util import diff3
            savetext = newtext
            original_text = Page(self.page_name,
                                 self.request,
                                 prev_date=datestamp).get_raw_body()
            saved_text = self.get_raw_body()
            verynewtext, had_conflict = diff3.text_merge(
                original_text,
                saved_text,
                savetext,
                marker1='----- /!\ Edit conflict! Your version: -----\n',
                marker2='----- /!\ Edit conflict! Other version: -----\n',
                marker3='----- /!\ End of edit conflict -----\n')
            msg = _("Someone else changed this page while you were editing.")

            if (had_conflict and self.request.user.valid
                    and (self.request.user.id == self.last_edit_info()[1])):
                # user pressed back button or did something weird
                had_conflict = False
                msg = None
            else:
                # we did some sort of merging or we had a conflict,
                # so let them know
                if had_conflict:
                    raise self.EditConflict, (msg, verynewtext)
                merged_changes = True
                msg = _("""%s Your changes were successfully merged! """ % msg)
                newtext = verynewtext
        elif (newtext == self.get_raw_body()
              and not self._rename_lowercase_condition()
              and kw.get('action') != 'SAVE/REVERT'
              and not kw.get('force_save')):
            # check to see if they're saving the page with the same content
            # it had before
            msg = _('You did not change the page content, not saved!')
            raise self.Unchanged, msg
        elif (config.max_page_size and len(newtext.encode(config.charset)) >
              (config.max_page_size * 1024)):
            msg = _('This page is too big!  Pages can be, at most, %sK.  '
                    'Consider splitting the page up into multiple pages '
                    'instead!' % config.max_page_size)
            raise self.TooBig, msg

        # save only if no error occured (msg is empty)
        if not msg or merged_changes:
            # set success msg
            if not merged_changes and not no_save_msg:
                msg = _("Thank you for your changes. "
                        "Your attention to detail is appreciated. ")

            # determine action for edit logging
            action = kw.get('action', 'SAVE')
            if action == 'SAVE' and not self.exists():
                action = 'SAVENEW'

            # write the page file
            mtime = self._write_to_db(newtext, action, kw.get('comment', ''),
                                      self.request.remote_addr,
                                      kw.get('proper_name', None))
            # deal with the case of macros / other items that change state by
            # /not/ being in the page
            wikiutil.macro_delete_checks(self)

            # we'll try to change the stats early-on
            if self.request.user.name:
                self.userStatAdd(self.request.user, action, self.page_name)

            # add the page to the search index or update its index
            if action != 'DELETE':
                search.add_to_index(self)

            # note the change in recent changes.  this explicit call is needed
            # because of the way we cache our change information
            caching.updateRecentChanges(self)

            return msg
Exemple #11
0
class PageEditor(Page):
    """Editor for a wiki page."""

    # exceptions for .saveText()
    class SaveError(Exception):
        pass

    class AccessDenied(SaveError):
        pass

    class Immutable(AccessDenied):
        pass

    class NoAdmin(AccessDenied):
        pass

    class EmptyPage(SaveError):
        pass

    class Unchanged(SaveError):
        pass

    class EditConflict(SaveError):
        pass

    class TooBig(SaveError):
        pass

    def __init__(self, page_name, request, **keywords):
        """
        Create page editor object.
        
        @param page_name: name of the page
        @param request: the request object
        @keyword do_revision_backup: if 0, suppress making a page backup
                                     per revision
        """
        self.request = request
        self._ = request.getText
        Page.__init__(self, page_name, request, **keywords)

        self.do_revision_backup = keywords.get('do_revision_backup', 1)

    def sendEditor(self, **kw):
        """
        Send the editor form page.

        @keyword preview: if given, show this text in preview mode
        @keyword staytop: don't go to #preview
        @keyword comment: comment field (when preview is true)
        @keyword had_conflict: we had an edit conflict on a save.
        """
        import re

        try:
            from Sycamore.action import SpellCheck
        except ImportError:
            SpellCheck = None

        form = self.request.form
        _ = self._
        self.request.http_headers([("Content-Type", "text/html; charset=%s" %
                                    config.charset)] + self.request.nocache)
        msg = None
        preview = kw.get('preview', None)
        emit_anchor = not kw.get('staytop', 0)
        proper_name = self.proper_name()

        from Sycamore.formatter.text_html import Formatter
        self.request.formatter = Formatter(self.request,
                                           store_pagelinks=1,
                                           preview=preview)

        base_uri = "%s/%s?action=edit" % (self.request.getScriptname(),
                                          wikiutil.quoteWikiname(
                                              self.proper_name()))
        backto = form.get('backto', [None])[0]
        if backto:
            base_uri += '&amp;' + util.web.makeQueryString(backto=backto)

        # check edit permissions
        if not self.request.user.may.edit(self):
            msg = _('You are not allowed to edit this page.')
        elif self.prev_date:
            # Trying to edit an old version, this is not possible via
            # the web interface, but catch it just in case...
            msg = _('Cannot edit old revisions!')

        # Did one of the prechecks fail?
        if msg and not kw.get('had_conflict', None):
            self.send_page(msg=msg)
            return

        # check for preview submit
        if preview is None:
            title = _('Edit "%(pagename)s"')
        else:
            title = _('Preview of "%(pagename)s"')
            self.set_raw_body(preview.replace("\r", ""), 1)

        page_needle = self.page_name
        if config.allow_subpages and page_needle.count('/'):
            page_needle = '/' + page_needle.split('/')[-1]

        wikiutil.send_title(
            self.request,
            self.proper_name(),
            pagename=self.proper_name(),
            has_link=True,
            strict_title='Editing "%s"' % self.proper_name(),
            body_onload="sizeForIE('savetext', 100, 'editorComment', 99);")

        # start content div
        self.request.write('<div id="content" class="content">\n')

        # get request parameters
        text_rows = None
        if form.has_key('rows'):
            text_rows = int(form['rows'][0])
            if self.request.user.valid:
                # possibly update user's pref
                if text_rows != self.request.user.edit_rows:
                    self.request.user.edit_rows = text_rows
                    self.request.user.save()
        else:
            text_rows = config.edit_rows
            if self.request.user.valid:
                text_rows = int(self.request.user.edit_rows)

        if form.has_key('cols'):
            text_cols = int(form['cols'][0])
            if self.request.user.valid:
                # possibly update user's pref
                if text_rows != self.request.user.edit_rows:
                    self.request.user.edit_rows = text_rows
                    self.request.user.save()
        else:
            text_cols = 80
            if self.request.user.valid:
                text_cols = int(self.request.user.edit_cols)

        # check datestamp (version) of the page our edit is based on
        if preview is not None:
            # propagate original datestamp
            mtime = float(form['datestamp'][0])

            # did someone else change the page while we were editing?
            conflict_msg = None
            if not self.exists():
                # page does not exist, are we creating it?
                if mtime:
                    conflict_msg = _('<p>Someone else <b>deleted</b> this '
                                     'page while you were editing!')
            elif mtime != self.mtime():
                conflict_msg = _('<p>Someone else changed this page while '
                                 'you were editing.')
                # merge conflicting versions
                allow_conflicts = 1
                from Sycamore.util import diff3
                savetext = self.get_raw_body()
                oldpg = Page(self.page_name, self.request, prev_date=mtime)
                original_text = oldpg.get_raw_body()
                saved_text = Page(self.page_name, self.request).get_raw_body()
                verynewtext, had_conflict = diff3.text_merge(
                    original_text,
                    saved_text,
                    savetext,
                    marker1='----- /!\ Edit conflict! Your version: -----\n',
                    marker2='----- /!\ Edit conflict! Other version: -----\n',
                    marker3='----- /!\ End of edit conflict -----\n')
                if had_conflict and self.request.user.valid and (
                        self.request.user.id == self.last_edit_info()[1]):
                    # user pressed back button or did something weird
                    conflict_msg = None
                elif had_conflict:
                    conflict_msg = _(conflict_msg +
                                     'There was an <b>edit conflict between '
                                     'your changes!</b></p>'
                                     '<p>Please review the conflicts and '
                                     'merge the changes.</p>')
                    mtime = self.mtime()
                    self.set_raw_body(verynewtext, 1)
                else:
                    conflict_msg = _(conflict_msg +
                                     'Your changes were sucessfully merged!')
                    mtime = self.mtime()
                    self.set_raw_body(verynewtext)

            if conflict_msg:
                self.request.write('<div id="message"><div>%s'
                                   '</div></div>' % conflict_msg)
                emit_anchor = 0  # make this msg visible!
        elif self.exists():
            # datestamp of existing page
            mtime = self.mtime()
        else:
            # page creation
            mtime = 0

        # output message
        message = kw.get('msg', '')
        if message:
            self.request.write('<div id="message">%s</div>' % (message))

        # get the text body for the editor field
        if form.has_key('template'):
            # "template" parameter contains the name of the template page
            template_page = wikiutil.unquoteWikiname(form['template'][0])
            raw_body = Page(template_page, self.request).get_raw_body()
        else:
            raw_body = self.get_raw_body()

        # send text above text area

        # button toolbar
        self.request.write('<div id="editArea">')
        self.request.write(
            "<script type=\"text/javascript\">"
            "var buttonRoot = '%s';</script>" % (os.path.join(
                config.url_prefix, self.request.theme.name, 'img', 'buttons')))
        if self.request.user.name:
            if config.user_page_prefix:
                self.request.write(
                    "<script type=\"text/javascript\">"
                    "var userPageLink = '[\"%s%s\"]';</script>" %
                    (config.user_page_prefix,
                     self.request.user.propercased_name))
            else:
                self.request.write("<script type=\"text/javascript\">"
                                   "var userPageLink = '[\"%s\"]';</script>" %
                                   (config.user_page_prefix,
                                    self.request.user.propercased_name))
        else:
            self.request.write("<script type=\"text/javascript\">"
                               "var userPageLink = '%s';</script>" %
                               (self.request.remote_addr))

        if config.wiki_farm:
            self.request.write(
                "<script type=\"text/javascript\" "
                "src=\"http://%s%s%s/edit.js\"></script>\n" %
                (config.wiki_base_domain, config.web_dir, config.url_prefix))
        else:
            self.request.write("<script type=\"text/javascript\" "
                               "src=\"%s%s/edit.js\"></script>\n" %
                               (config.web_dir, config.url_prefix))

        # send form
        self.request.write('<form name="editform" id="editform" '
                           'method="post" action="%s/%s#preview">' %
                           (self.request.getScriptname(),
                            wikiutil.quoteWikiname(proper_name)))

        self.request.write(
            str(html.INPUT(type="hidden", name="action", value="savepage")))
        if backto:
            self.request.write(
                str(html.INPUT(type="hidden", name="backto", value=backto)))

        # generate default content
        if not raw_body:
            if self.isTalkPage():
                raw_body = _('This page is for discussing the '
                             'contents of ["%s"].') % self.proper_name()[:-5]
            else:
                raw_body = _('Describe %s here.') % (self.proper_name(), )

        # replace CRLF with LF
        raw_body = self._normalize_text(raw_body)

        # send datestamp (version) of the page our edit is based on
        self.request.write('<input type="hidden" name="datestamp" '
                           'value="%s">' % repr(mtime))

        # Print the editor textarea and the save button
        self.request.write('<textarea id="savetext" name="savetext" '
                           'rows="%d" cols="%d" style="width:100%%;">%s'
                           '</textarea>' %
                           (text_rows, text_cols, wikiutil.escape(raw_body)))

        # make sure we keep the template notice on a resize of the editor
        template_param = ''
        if form.has_key('template'):
            template_param = '&amp;template=' + form['template'][0]

    # draw edit size links
        self.request.write(
            _('<div class="pageEditInfo" id="editorSize">'
              'editor size:'))
        self.request.write('<a href="#" onclick="return sizeEditor(\'bigger\','
                           '\'%s&amp;preview=1&amp;cols=60%s\')">%s'
                           '</a>' % (base_uri, template_param, '+'))
        self.request.write(
            ',<a href="#" onclick="return sizeEditor(\'smaller\','
            '\'%s&amp;preview=1&amp;cols=60%s\')">%s'
            '</a>' % (base_uri, template_param, '-'))
        self.request.write('</div>')
        self.request.write('</p>')  # close textarea

        self.request.write(
            '<div id="editComment" id="editorResizeButtons"> '
            '%s<br><input type="text" class="formfields" '
            'name="comment" id="editorComment" value="%s" '
            'size="%d" maxlength="80" style="width:99%%;">'
            '</div>' % (_("<font size=\"+1\">Please comment "
                          "about this change:</font>"),
                        wikiutil.escape(kw.get('comment', ''), 1), text_cols))

        spam_catch_button = (
            '<span style="position: absolute; top: 0px; left: 0px;'
            'height: 0px; width: 0px; overflow: hidden;">'
            'dont enter into this box:'
            '<input type="text" name="text_dont"/>'
            '</span>'
            '<span style="position: absolute; top: 0px; left: 0px;'
            'height: 0px; width: 0px; overflow: hidden;">'
            '<input class="formbutton" type="submit" name="button_dont" '
            'value="Dont press me">\n'
            '</span>')
        self.request.write(spam_catch_button)

        # button bar
        button_spellcheck = (
            SpellCheck and
            '<input type="submit" class="formbutton" name="button_spellcheck"'
            ' value="%s">' % _('Check Spelling')) or ''

        save_button_text = _('Save Changes')
        cancel_button_text = _('Cancel')

        self.request.write("</div>")

        if self.request.user.may.admin(self):
            security_button = ('<input type="button" class="formbutton" '
                               'onClick="location.href='
                               '\'%s/%s?action=Security\'" '
                               'value="Security">') % (
                                   self.request.getScriptname(),
                                   wikiutil.quoteWikiname(proper_name))
        else:
            security_button = ''

        if self.request.user.may.delete(self):
            delete_button = ('<input type="button" class="formbutton" '
                             'onClick="location.href='
                             '\'%s/%s?action=DeletePage\'" value="Delete">'
                             ) % (self.request.getScriptname(),
                                  wikiutil.quoteWikiname(proper_name))
            rename_button = ('<input type="button" class="formbutton" '
                             'onClick="location.href=\'%s/%s?action=Rename\'"'
                             ' value="Rename">') % (self.request.getScriptname(
                             ), wikiutil.quoteWikiname(proper_name))
        else:
            delete_button = ''
            rename_button = ''

        self.request.write(
            '<div id="editButtonRow">'
            '<span>'
            '<input type="submit" class="formbutton" '
            'name="button_preview" value="%s"> '
            '<input type="submit" class="formbutton" '
            'name="button_save" value="%s"> '
            '<input type="submit" class="formbutton" '
            'name="button_cancel" value="%s"> '
            '</span>'
            '<span class="editActions">'
            '<input type="button" class="formbutton" '
            'onClick="window.open(\'%s/%s?action=Files\', '
            '\'files\', \'width=800,height=600,'
            'scrollbars=1\')" value="Upload Files"> '
            '%s '
            '%s '
            '%s '
            '%s</span>'
            '</div>' %
            (_('Preview'), save_button_text, cancel_button_text,
             self.request.getScriptname(), wikiutil.quoteWikiname(proper_name),
             button_spellcheck, delete_button, rename_button, security_button))

        if self.request.config.edit_agreement_text:
            self.request.write(self.request.config.edit_agreement_text)

        badwords_re = None
        if preview is not None:
            if SpellCheck and (form.has_key('button_spellcheck')
                               or form.has_key('button_newwords')):
                badwords, badwords_re, msg = SpellCheck.checkSpelling(
                    self, self.request, own_form=0)
                self.request.write("<p>%s</p>" % msg)
        self.request.write("</form>")

        if config.wiki_farm:
            from Sycamore import farm
            help_link = farm.link_to_page(farm.getBaseWikiName(),
                                          "Help with Editing",
                                          self.request.formatter,
                                          force_farm=True)
        else:
            help_link = Page("Help with Editing", self.request).link_to()

        # QuickHelp originally by Georg Mischler <*****@*****.**>
        self.request.write(
            '<h2>Editing quick-help</h2>\n'
            '<dl><div style="float: right; margin: 10px; border: 1px solid; '
            'padding: 3pt;">See <b>%s</b> for more information.</div>' %
            (help_link) +
            _("<dt>Emphasis:</dt>\n"
              "<dd>''<em>italics</em>''; '''<strong>bold</strong>''';"
              "'''''<strong><em>bold italics</em></strong>''''';"
              "''<em>mixed '''<strong>bold</strong>''' and "
              "italics</em>''; ---- horizontal rule.</dd>"
              "<dt>Headings:</dt>"
              "<dd>= Title 1 =; == Title 2 ==; === Title 3 ===;"
              "==== Title 4 ====; ===== Title 5 =====.</dd>"
              "<dt>Lists:</dt>"
              "<dd>space and one of * bullets; 1., a., A., i., I. "
              "numbered items;"
              "  1.#n start numbering at n; space alone indents.</dd>"
              "<dt>Links:</dt>"
              "<dd>[\"brackets and double quotes\"]; [\"the exact "
              "page name\" label];"
              "  url; [url]; [url label].</dd>"
              "<dt>Tables:</dt>"
              "<dd>|| cell text |||| cell text spanning two columns ||;"
              "  no trailing white space allowed after tables or titles."
              "</dd></dl>"))

        if preview is not None:
            if not emit_anchor:
                preview_name = "previewHide"
            else:
                preview_name = "preview"
            self.request.write('<div id="%s" class="preview">' % preview_name)
            self.send_page(content_only=1,
                           hilite_re=badwords_re,
                           preview=preview)
            self.request.write('</div>')

        self.request.write('</div>\n')  # end content div

        wikiutil.send_after_content(self.request)

        self.request.theme.emit_custom_html(config.page_footer1)
        self.request.theme.emit_custom_html(config.page_footer2)

        self.request.write('</body></html>')

    def sendCancel(self, newtext, datestamp):
        """
        User clicked on Cancel button.
        
        @param newtext: the edited text (which has been cancelled)
        @param datestamp: ...
        """
        _ = self._

        backto = self.request.form.get('backto', [None])[0]
        page = backto and Page(backto, self.request) or self
        page.send_page(msg=_('Edit was cancelled.'))

    def deletePage(self, comment=None, permanent=False, showrc=True):
        """
        Delete the page (but keep the backups)
        
        @param comment: Comment given by user
        @param permanent: Do we permanently delete all past versions of
                          the page?
        @param showrc: Do we log this revert to recent changes?
                       This option assumes permanent is True.
        """
        from Sycamore import caching
        if permanent:
            # nuke all cached page information
            caching.deleteAllPageInfo(self.page_name, self.request)
            # nuke all old versions!  wwheewwwahawwww
            self.request.cursor.execute("""DELETE from allPages
                where name=%(page_name)s and wiki_id=%(wiki_id)s""", {
                'page_name': self.page_name,
                'wiki_id': self.request.config.wiki_id
            },
                                        isWrite=True)
            # nuke all map points!  wwheewwwahawwww
            self.request.cursor.execute("""DELETE from oldMapPoints
                where pagename=%(page_name)s and wiki_id=%(wiki_id)s""", {
                'page_name': self.page_name,
                'wiki_id': self.request.config.wiki_id
            },
                                        isWrite=True)
            self.request.cursor.execute("""DELETE from mapPoints
                where pagename=%(page_name)s and wiki_id=%(wiki_id)s""", {
                'page_name': self.page_name,
                'wiki_id': self.request.config.wiki_id
            },
                                        isWrite=True)

        # First save a final backup copy of the current page
        # (recreating the page allows access to the backups again)
        if not (permanent and not showrc):
            try:
                self.saveText("deleted",
                              '0',
                              comment=comment or '',
                              action='DELETE')
            except self.SaveError, msg:
                return msg

        # Then really delete it
        self.request.cursor.execute("""DELETE from curPages
            where name=%(page_name)s and wiki_id=%(wiki_id)s""", {
            'page_name': self.page_name,
            'wiki_id': self.request.config.wiki_id
        },
                                    isWrite=True)

        from Sycamore import caching, search

        if config.memcache:
            pagecount = wikidb.getPageCount(self.request) - 1
            self.request.mc.set('active_page_count', pagecount)
            if permanent and not showrc:
                caching.updateRecentChanges(self)

        self.request.req_cache['pagenames'][(self.page_name,
                                             self.wiki_name)] = False

        cache = caching.CacheEntry(self.page_name, self.request)
        cache.clear(type='page save delete')

        # remove entry from the search databases
        search.remove_from_index(self)

        return ''