示例#1
0
def monitor(request):
    params = QueryParams()
    params.add('format', default='html', choices=('html', 'plain'))
    params.add('deleted', type=boolish, default=False, choices=(True, False))
    params.parse(request.GET)
    # If one of the parameters was invalid, redirect to a fixed url.
    # - QueryParams object will automatically set the parameter to a valid value.
    if params.invalid_value:
        return HttpResponseRedirect(reverse('notepad:monitor') + str(params))
    if params['deleted']:
        pages = Page.objects.order_by('name')
        pages = sorted(pages, key=lambda page: page.name.lower())
    else:
        notes = Note.objects.filter(deleted=False).distinct('page')
        pages = sorted([note.page for note in notes],
                       key=lambda page: page.name.lower())
    if params['format'] == 'plain':
        text = '\n'.join([page.name for page in pages])
        return HttpResponse(text, content_type=settings.PLAINTEXT)
    else:
        if params['deleted']:
            deleted_query_str = str(params.but_with(deleted=False))
        else:
            deleted_query_str = str(params.but_with(deleted=True))
        context = {
            'pages': pages,
            'deleted': params['deleted'],
            'deleted_query_str': deleted_query_str,
        }
        return render(request, 'notepad/monitor.tmpl', context)
示例#2
0
def deleteitem(request, page):
    params = QueryParams()
    params.add('type', choices=('item', 'listitem'))
    params.add('key')
    params.add('id', type=int)
    params.parse(request.POST)
    item_type = ITEM_TYPES.get(params['type'])
    if not item_type:
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    item = get_by_key_or_id(item_type, page, params['key'], params['id'])
    item.deleted = True
    item.deleting_visit = request.visit
    item.note.deleted = True
    item.note.deleting_visit = request.visit
    item.save()
    item.note.save()
    return HttpResponseRedirect(get_view_url(page))
示例#3
0
def deleteitemform(request, page):
    params = QueryParams()
    params.add('type', choices=('item', 'listitem'))
    params.add('key')
    params.add('id', type=int)
    params.parse(request.POST)
    item_type = ITEM_TYPES.get(params['type'])
    if not item_type:
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    item = get_by_key_or_id(item_type, page, params['key'], params['id'])
    context = {
        'editing': True,
        'deleting_text': True,
        'item': item,
        'type': params['type']
    }
    return show_page(request, page, context)
示例#4
0
def shares(request):
  params = QueryParams()
  params.add('version', type=int, choices=(1, 2, 3))
  params.parse(request.GET)
  if not params['version']:
    return HttpResponseRedirect(reverse('horcrux:main'))
  threshold = THRESHOLDS[params['version']]
  share_nums = range(1, threshold+1)
  context = {'version':params['version'], 'share_nums':share_nums}
  return render(request, 'horcrux/shares.tmpl', context)
示例#5
0
def monitor(request):
  # The query string parameters and their defaults.
  params = QueryParams()
  params.add('p', type=int, default=1, min=1)
  params.add('perpage', default=PER_PAGE_DEFAULT, type=int, min=1)
  params.add('include_me', type=boolish, default=False, choices=(True, False))
  params.add('bot_thres', default=None, type=int)
  params.add('user', default=None, type=int)
  params.parse(request.GET)
  # If one of the parameters was invalid, redirect to a fixed url.
  # - QueryParams object will automatically set the parameter to a valid value.
  if params.invalid_value:
    return HttpResponseRedirect(reverse('traffic_monitor')+str(params))
  admin = is_admin_and_secure(request)
  # Non-admins can only view their own traffic.
  if not admin:
    this_user = request.visit.visitor.user.id
    if params['user']:
      # If they gave a user, but it's not themselves, redirect back to themself.
      if params['user'] != this_user:
        return HttpResponseRedirect(reverse('traffic_monitor')+str(params.but_with(user=None)))
    else:
      # If they gave no user, that's fine. Silently show only themself.
      params['user'] = this_user
      params.params['user'].default = this_user
  # Obtain visits list from database.
  if params['user'] is not None:
    visits = Visit.objects.filter(visitor__user__id=params['user'])
  elif params['include_me']:
    visits = Visit.objects.all()
  else:
    visits = Visit.objects.exclude(visitor__user__id=1)
  # Exclude robots, if requested.
  if params['bot_thres'] is not None and params['user'] is None:
    visits = visits.filter(visitor__bot_score__lt=params['bot_thres'])
  # Order by id.
  visits = visits.order_by('-id')
  # Create a Paginator.
  pages = django.core.paginator.Paginator(visits, params['perpage'])
  try:
    page = pages.page(params['p'])
  except django.core.paginator.EmptyPage:
    return HttpResponseRedirect(reverse('traffic_monitor')+str(params.but_with(p=pages.num_pages)))
  # Construct the navigation links.
  links = collections.OrderedDict()
  if page.has_previous():
    links['Later'] = str(params.but_with(p=page.previous_page_number()))
  if admin:
    if params['include_me']:
      links['Hide me'] = str(params.but_with(include_me=None))
    else:
      links['Include me'] = str(params.but_with(include_me=True))
    if params['bot_thres'] is not None and params['bot_thres'] != 0:
      links['Show all'] = str(params.but_with(bot_thres=None))
    if params['bot_thres'] is None or params['bot_thres'] > categorize.SCORES['bot_in_ua']:
      links['Hide robots'] = str(params.but_with(bot_thres=categorize.SCORES['bot_in_ua']))
    if params['bot_thres'] is None or params['bot_thres'] > categorize.SCORES['sent_cookies']+1:
      links['Show humans'] = str(params.but_with(bot_thres=categorize.SCORES['sent_cookies']+1))
  if page.has_next():
    links['Earlier'] = str(params.but_with(p=page.next_page_number()))
  context = {
    'visits': page,
    'admin':admin,
    'links': links,
    'this_visit': request.visit,
    'timezone': set_timezone(request),  # Set and retrieve timezone.
    'ua_exact_thres': categorize.SCORES['ua_exact'],
    'referrer_exact_thres': categorize.SCORES['referrer_exact'],
  }
  return render(request, 'traffic/monitor.tmpl', context)
示例#6
0
def combine(request):
  params = QueryParams()
  params.add('version', type=int, choices=(1, 2, 3))
  params.parse(request.POST)
  error = None
  used_server_share = False
  secrets = {'lastpass_email':settings.PERSONAL_EMAIL, 'accounts_link':settings.ACCOUNTS_LINK}
  threshold = THRESHOLDS[params['version']]
  try:
    # Gather the shares.
    shares = gather_shares(params, threshold, WORD_LIST_PATH)
    if params['version'] == 1:
      secrets['lastpass'] = combine_shares(shares, threshold, hex=False)
    elif params['version'] == 2:
      if os.path.exists(WORD_LIST_PATH):
        words_hex = combine_shares(shares, threshold, hex=True)
        word_map = convert.read_word_list(WORD_LIST_PATH)
        try:
          words = convert.hex_to_words(words_hex, word_map, group_length=GROUP_LENGTH)
          secrets['lastpass'] = '******'.join(words)
        except ValueError:
          error = ('Combined horcruxes to get {!r}, but could not convert to the actual password.'
                   .format(words_hex))
      else:
        error = "Couldn't find word list file on the server."
      #TODO: Detect if the password is just numbers, which indicates the user entered version 1 codes.
    elif params['version'] == 3:
      # Read in the share stored on the server, if needed.
      if len(shares) < threshold:
        try:
          share1 = read_share(SHARE1_PATH)
          shares.append(share1)
          used_server_share = True
        except HorcruxError as exception:
          log.error(exception.message)
          if len(shares) < threshold:
            raise HorcruxError('too_few_shares_and_missing_share1',
                               'User entered {} shares, but missing share1 means {} are needed.'
                               .format(len(shares), threshold),
                               value=len(shares), value2=threshold)
      # Combine the shares and get the passwords from the vault.
      try:
        vault_password = combine_shares(shares, threshold, hex=True)
      except HorcruxError as exception:
        if exception.type == 'too_few_shares' and used_server_share:
          exception.value -= 1
          exception.value2 -= 1
        raise exception
      if os.path.exists(VAULT_PATH):
        plaintext = decrypt_vault(VAULT_PATH, vault_password)
        secrets.update(parse_vault(plaintext))
      else:
        error = ("Couldn't find encrypted vault file on the server, but successfully combined the "
                 "horcruxes to obtain its password: {!r}".format(vault_password))
    else:
      return HttpResponseRedirect(reverse('horcrux:main'))
  except HorcruxError as exception:
    log.error('HorcruxError {!r}: {}'.format(exception.type, exception.message))
    error = ERROR_MESSAGES.get(exception.type, DEFAULT_ERROR).format(**vars(exception))
    log.error(error)
  plural = params['version'] > 2
  context = {'version':params['version'], 'secrets':secrets, 'plural':plural, 'error':error}
  return render(request, 'horcrux/combine.tmpl', context)
示例#7
0
def view(request, page_name):
    params = QueryParams()
    params.add('note', type=int, default=None)
    params.add('version', type=int, default=None)
    params.add('format', default='html', choices=('html', 'plain'))
    params.add('admin', type=boolish, default=False, choices=(True, False))
    params.add('archived', type=boolish, default=False, choices=(True, False))
    params.add('deleted', type=boolish, default=False, choices=(True, False))
    params.add('select', default='none', choices=('all', 'none'))
    params.parse(request.GET)
    # If one of the parameters was invalid, redirect to a fixed url.
    # - QueryParams object will automatically set the parameter to a valid value.
    if params.invalid_value:
        return HttpResponseRedirect(
            reverse('notepad:view', args=(page_name, )) + str(params))
    # Only allow showing deleted notes to the admin over HTTPS.
    is_admin = is_admin_and_secure(request)
    if not is_admin and (params['admin'] or params['deleted']):
        query_str = str(params.but_with(admin=False, deleted=False))
        return HttpResponseRedirect(
            reverse('notepad:view', args=(page_name, )) + query_str)
    # Fetch the note(s).
    if params['version']:
        notes = lib.get_notes_from_ids([params['version']], page_name,
                                       params['archived'], params['deleted'])
    elif params['note']:
        note = lib.get_latest_version(params['note'], page_name,
                                      params['archived'], params['deleted'])
        notes = [note]
    else:
        notes = lib.get_notes(page_name, params['archived'], params['deleted'])
    # Bundle up the data and display the notes.
    if params['format'] == 'plain':
        contents = [note.content for note in notes]
        return HttpResponse('\n\n'.join(contents),
                            content_type=settings.PLAINTEXT)
    else:
        links = collections.OrderedDict()
        randomness = rand.randint(1, 1000000)
        links['☑ Select all'] = str(
            params.but_with(select='all', reload=randomness))
        links['□ Select none'] = str(
            params.but_with(select='none', reload=randomness))
        if is_admin:
            if params['admin']:
                links['Admin off'] = str(params.but_with(admin=False))
            else:
                links['Admin on'] = str(params.but_with(admin=True))
        if params['archived']:
            links['Hide archived'] = str(params.but_with(archived=False))
        else:
            links['Show archived'] = str(params.but_with(archived=True))
        if is_admin:
            if params['deleted']:
                links['Hide deleted'] = str(params.but_with(deleted=False))
            else:
                links['Show deleted'] = str(params.but_with(deleted=True))
        context = {
            'page': page_name,
            'notes': notes,
            'links': links,
            'admin_view': params['admin'],
            'select': params['select'],
        }
        return render(request, 'notepad/view.tmpl', context)
示例#8
0
def edititem(request, page):
    params = QueryParams()
    params.add('key')
    params.add('id', type=int)
    params.add('type', choices=('item', 'listitem'))
    params.add('content')
    params.add('title')
    params.add('body')
    params.add('attributes')
    params.parse(request.POST)
    log.info('Editing item: key {!r}, id {!r}'.format(params['key'],
                                                      params['id']))
    item_type = ITEM_TYPES.get(params['type'])
    if not item_type:
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    item = get_by_key_or_id(item_type, page, params['key'], params['id'])
    content = compose_content(params['title'], params['body'],
                              params['content'])
    if item:
        log.info('Editing existing item.')
        edit_item(item, content, params['attributes'], request.visit)
    elif params['type'] == 'item':
        # Won't work for ListItems, but they can't be created via edititem anyway.
        log.info('Creating new item.')
        create_item(item_type,
                    page,
                    content,
                    params['attributes'],
                    request.visit,
                    key=params['key'])
    else:
        log.error('Warning: Cannot edit nonexistent ListItem.')
    return HttpResponseRedirect(get_view_url(page))
示例#9
0
def edititemform(request, page):
    params = QueryParams()
    params.add('key')
    params.add('id', type=int)
    params.add('type', choices=('item', 'listitem'))
    params.add('display-type')
    params.parse(request.POST)
    log.info('Composing edit form for item: key {!r}, id {!r}'.format(
        params['key'], params['id']))
    item_type = ITEM_TYPES.get(params['type'])
    if not item_type:
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    item = get_by_key_or_id(item_type, page, params['key'], params['id'])
    if item is None:
        log.info('No item found. Using a dummy.')
        item = {
            'id': params['id'],
            'key': params['key'],
            'note': {
                'content': ''
            }
        }
    # Determine whether the item has a title, body, or neither.
    display_type = 'title-body'
    if params['display-type']:
        display_type = params['display-type']
    elif params['key']:
        display_type_key = params['key'] + '-display-type'
        if params.get(display_type_key) is not None:
            display_type = params[display_type_key]
    context = {
        'editing': True,
        'editing_text': True,
        'editing_item': True,
        'admin': True,
        'item': item,
        'display_type': display_type,
        'type': params['type']
    }
    return show_page(request, page, context)
示例#10
0
def moveitem(request, page):
    params = QueryParams()
    params.add('action', choices=('moveup', 'movedown'))
    params.add('type', choices=('item', 'listitem'))
    params.add('key')
    params.add('id', type=int)
    params.parse(request.POST)
    if params['type'] != 'listitem':
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    item_type = ITEM_TYPES.get(params['type'])
    item = get_by_key_or_id(item_type, page, params['key'], params['id'])
    if not item:
        log.error(
            f'No item found by key {params["key"]!r} or id {params["id"]}.')
        return HttpResponseRedirect(get_view_url(page))
    if item.parent:
        siblings = item.parent.sorted_items()
    else:
        log.info('Item has no parent. Using root lists.')
        siblings = get_root_lists(page)
    if params['action'] == 'movedown':
        siblings = reversed(siblings)
    last_item = None
    for this_item in siblings:
        if this_item == item and last_item is not None:
            log.debug(
                f'Swapping order of Items {this_item.id} ({this_item.display_order}) and {last_item.id} '
                f'({last_item.display_order}).')
            this_move = Move(
                type='position',
                item=this_item,
                old_display_order=this_item.display_order,
                new_display_order=last_item.display_order,
                visit=request.visit,
            )
            last_move = Move(
                type='position',
                item=last_item,
                old_display_order=last_item.display_order,
                new_display_order=this_item.display_order,
                visit=request.visit,
            )
            this_item.display_order = this_move.new_display_order
            last_item.display_order = last_move.new_display_order
            try:
                with transaction.atomic():
                    this_item.save()
                    this_move.save()
                    last_item.save()
                    last_move.save()
            except DatabaseError as dbe:
                log.error(f'Error on saving moves: {dbe}')
            break
        last_item = this_item
    return HttpResponseRedirect(get_view_url(page))
示例#11
0
def additem(request, page):
    params = QueryParams()
    params.add('type', choices=('item', 'listitem'))
    params.add('title')
    params.add('body')
    params.add('content')
    params.add('attributes')
    params.add('key')
    params.add('parent_key')
    params.add('parent_id', type=int)
    params.parse(request.POST)
    item_type = ITEM_TYPES.get(params['type'])
    if not item_type:
        log.error('Invalid type {!r}.'.format(request.POST.get('type')))
        return HttpResponseRedirect(get_view_url(page))
    content = compose_content(params['title'], params['body'],
                              params['content'])
    parent_list = get_by_key_or_id(item_type, page, params['parent_key'],
                                   params['parent_id'])
    create_item(item_type,
                page,
                content,
                params['attributes'],
                request.visit,
                key=params['key'],
                parent_list=parent_list)
    return HttpResponseRedirect(get_view_url(page))