def get_basic_context(request, is_mobile = False): """ get the context with various standard stuff preinitialized """ ctx = {} ctx['REMOTE_ADDR'] = request.META['REMOTE_ADDR'] ctx['remote_owner_token'] = get_owner_token(request) ctx['DEV_MODE'] = True next_after_accept = request.REQUEST.get('next_after_accept', None) if next_after_accept and re.match(r"/thread/[0-9]+", next_after_accept): ctx['next_after_accept'] = next_after_accept ctx['in_thread_view'] = request.REQUEST.get('in_thread_view', None)=="1" ctx['requestpath'] = request.path loc = get_current_loc(request) ctx['loc'] = loc ctx['is_mobile'] = is_mobile ctx['radius_options'] = c.RADIUS_MENU ctx['more_available'] = False if loc: ctx['loc_fixed'] = "%0.5f,%0.5f" % (loc.latitude, loc.longitude) ctx['MAX_POST_LEN'] = MAX_POST_LEN ctx['SHOW_REPLY_COUNT'] = SHOW_REPLY_COUNT ctx['rounding_val'] = get_current_rounding(request) ctx['radius'] = get_current_radius(request) ctx['nice_radius'] = c.RADII_TEXT[c.RADII.index(ctx['radius'])] ctx['round_options'] = c.ROUND_OPTIONS ctx['THUMB_WIDTH'] = THUMB_WIDTH ctx['THUMB_HEIGHT'] = THUMB_HEIGHT ctx['SLIDE_WIDTH '] = SLIDE_WIDTH ctx['SLIDE_HEIGHT'] = SLIDE_HEIGHT ctx['sitename'] = settings.SITENAME ctx['tagline'] = 'Foursquare meets 4chan' ctx.update(csrf(request)) return ctx
def post_android(request): """ post from an android phone. thanks to some omissions on the platform (like an easy way to serialize up a MIME document)*, we do this a little differently: the params are HTTP headers and the image (if there is one) is the request body. * there probably is one; I didn't look too hard """ #ctx = get_basic_context(request, is_mobile = True) reply_to = default_int(request.META.get(REPLY_TO_HTTP_HEADER, None), -1) has_image = request.META.get(HAS_IMAGE_HTTP_HEADER, None) == YES raw_content = request.META.get(CONTENT_HTTP_HEADER, None) owner_token = request.META.get(OWNER_TOKEN_HTTP_HEADER, None) #assert owner_token # FIXME: don't require this ; some ppl have older clients content = urllib.unquote(raw_content.replace("+"," "))\ .decode('utf8', 'replace') if raw_content else None # FIXME: in the dev version of django, we can use a file-like # iface and skip the stringio imagedata = request.raw_post_data image = None if imagedata: image = save_image(StringIO.StringIO(imagedata)) assert image or not has_image reply_to_post = Post.objects.get(id=reply_to, censored=False) \ if reply_to != -1 else None newpost = make_real_post(request, owner_token, get_current_loc(request), content, get_current_rounding(request), reply_to_post, picture = image, source=ANDROID) return HttpResponse(content=str(newpost.id), status=200)
def post_ajax(request): """ actually make a post via ajax. note that this kind of post can't have an image unless it's uploaded separately. """ parsedpost = urlparse.parse_qs(str(request.POST['form'])) # FIXME: is the csrf stuff needed? csrftoken = request.COOKIES.get('csrftoken', None) if not csrftoken: return HttpResponse(json.dumps(['fail', 'csrf token missing'])) if csrftoken != parsedpost.get('csrfmiddlewaretoken', [None])[0]: return HttpResponse(json.dumps(\ ['fail', 'csrf token mismatch %s %s' \ % (csrftoken, parsedpost['csrfmiddlewaretoken'])])) owner_token = parsedpost.get('owner_token', [None])[0] if not owner_token: owner_token = get_owner_token(request, cookie_only=True) #if not owner_token: # fixme: shouldn not require this... # return HttpResponse(json.dumps(['fail', 'owner_token missing'])) #rounding = default_int(parsedpost.get('round', [None])[0], c.DEFAULT_ROUNDING) # FIXME: if rounding-editing is re-enabled, we should use the above not this rounding = get_current_rounding(request) loc = string_to_location(parsedpost.get('loc', [None])[0]) if not loc: return HttpResponse(json.dumps(['fail', 'location invalid'])) content = parsedpost.get('content', [None])[0] if not content: return HttpResponse(json.dumps(['fail', 'post was blank'])) if len(content) > MAX_POST_LEN: return HttpResponse(json.dumps(['fail', 'post must be under %d characters' % MAX_POST_LEN])) # content = raw_extract(content) content = content.decode('utf-8', 'ignore') antidupetoken = parsedpost.get('antidupetoken', None) if not antidupetoken: return HttpResponse(json.dumps(['fail', 'antidupetoken missing'])) if antidupetoken == request.session.get('antidupetoken',''): return HttpResponse(json.dumps(['fail', 'duplicate post ignored'])) reply_to = default_int(parsedpost.get('reply_to', [None])[0], -1) reply_to = reply_to if reply_to and reply_to != -1 else None if reply_to == None: return HttpResponse(json.dumps(['fail', 'All thread-creating posts' ' must contain an image.'])) else: found = Post.objects.filter(id=reply_to, censored=False) if len(found) == 1: reply_to = found[0] else: return HttpResponse(\ json.dumps(['fail', 'internal error: invalid reply_to id.'])) make_real_post(request, owner_token, loc, content, rounding, reply_to, source=MOBILE_WEB if use_mobile(request) else WEB) request.session['antidupetoken'] = antidupetoken return HttpResponse(json.dumps(['ok', '']))
def conventional_post(request): """ handle a conventional post (used to handle a file upload) -> take the post and redirect the user to the main page """ postform = forms.PostForm(request.POST, request.FILES) if not postform.is_valid(): # FIXME: this is incredibly user-unfriendly, but all errors # should be caught by the javascript before we get # here. anything that gets this far is a serious problem with # the site, not a user-input error. return HttpResponse(content="Error: %s. Please click the back" " button to correct it." % postform.errors) # this is also bad, but it's the consequence of the redirect to # /conventional-post. we could do a second redirect back to / and # save the form state so we could show the user an error message, # but, quite frankly, I think errors of this sort will be rare. if request.FILES['picture_file'].size > MAXFILESIZE: return HttpResponse(content=("Error: file too large (%d bytes)."\ " Maximum permitted is %d bytes. "\ "Please click the back button " "and submit a smaller file.")\ % (request.FILES['picture_file'].size, MAXFILESIZE)) picture = save_image(request.FILES['picture_file']) if not picture: return HttpResponse(content=("Error: could not save picture. " "It might be invalid. " " Please click the back button and" " submit a different image.")) owner_token = get_owner_token(request) # FIXME; we shouldn't _require_ this # if not owner_token: # return HttpResponse(content=("Post error: owner_token missing." # " Are cookies disabled? " # "Try enabling cookies, reloading the page," # " and reposting.")) reply_to = default_int(request.POST.get('reply_to', None), -1) reply_to = reply_to if reply_to and reply_to != -1 else None if reply_to != None: found = Post.objects.filter(id=reply_to, censored=False) if len(found) == 1: reply_to = found[0] else: # FIXME: log these return HttpResponse(content=("Internal error: invalid reply_to id." " Try pressing the back button," " reloading the page, and reposting.")) newpost = make_real_post(request, owner_token, get_current_loc(request), request.POST.get('content'), get_current_rounding(request), reply_to, picture = picture, source=MOBILE_WEB if use_mobile(request) else WEB) response = HttpResponse(content="Post successful! Redirecting...", status=303) # note that in_thread_view means *single* thread view. in_thread_view = request.REQUEST.get('in_thread_view', None)=="1" response["Location"] = ("/m/" if use_mobile(request) else "/") \ + (("thread/"+str(reply_to.id)) if in_thread_view else "") \ + "#postchildbox_" + str(newpost.id) return response