def geolocate(request): """Return the country code provided by our CDN https://support.cloudflare.com/hc/en-us/articles/200168236-What-does-CloudFlare-IP-Geolocation-do- Mimics the responses from the Mozilla Location Service: https://mozilla.github.io/ichnaea/api/region.html """ country_code = get_geo_from_request(request) if country_code is None: return HttpResponseJSON( { "error": { "errors": [{ "domain": "geolocation", "reason": "notFound", "message": "Not found", }], "code": 404, "message": "Not found", } }, status=404) return HttpResponseJSON({ 'country_code': country_code, })
def geolocate(request): """Return the country code provided by our CDN https://support.cloudflare.com/hc/en-us/articles/200168236-What-does-CloudFlare-IP-Geolocation-do- Mimics the responses from the Mozilla Location Service: https://mozilla.github.io/ichnaea/api/region.html """ if settings.DEV: country_code = settings.DEV_GEO_COUNTRY_CODE else: country_code = request.META.get('HTTP_CF_IPCOUNTRY', 'XX') if country_code == 'XX' or len(country_code) != 2: return HttpResponseJSON( { "error": { "errors": [{ "domain": "geolocation", "reason": "notFound", "message": "Not found", }], "code": 404, "message": "Not found", } }, status=404) return HttpResponseJSON({ 'country_code': country_code, })
def stub_attribution_code(request): """Return a JSON response containing the HMAC signed stub attribution value""" if not request.is_ajax(): return HttpResponseJSON({'error': 'Resource only available via XHR'}, status=400) response = None rate = settings.STUB_ATTRIBUTION_RATE key = settings.STUB_ATTRIBUTION_HMAC_KEY if not rate: # return as though it was rate limited, since it was response = HttpResponseJSON({'error': 'rate limited'}, status=429) elif not key: response = HttpResponseJSON({'error': 'service not configured'}, status=403) if response: patch_response_headers(response, 300) # 5 min return response data = request.GET codes = OrderedDict() has_value = False for name, default_value in STUB_VALUE_NAMES: val = data.get(name, '') # remove utm_ name = name[4:] if val and STUB_VALUE_RE.match(val): codes[name] = val has_value = True else: codes[name] = default_value if codes['source'] == '(not set)' and 'referrer' in data: try: domain = urlparse(data['referrer']).netloc if domain and STUB_VALUE_RE.match(domain): codes['source'] = domain codes['medium'] = 'referral' has_value = True except Exception: # any problems and we should just ignore it pass if not has_value: codes['source'] = 'www.mozilla.org' codes['medium'] = '(none)' codes['timestamp'] = str(int(time())) code = '&'.join('='.join(attr) for attr in codes.items()) code = querystringsafe_base64.encode(code) sig = hmac.new(key, code, hashlib.sha256).hexdigest() response = HttpResponseJSON({ 'attribution_code': code, 'attribution_sig': sig, }) patch_response_headers(response, 300) # 5 min return response
def stub_attribution_code(request): """Return a JSON response containing the HMAC signed stub attribution value""" if not request.is_ajax(): return HttpResponseJSON({'error': 'Resource only available via XHR'}, status=400) response = None if not settings.STUB_ATTRIBUTION_RATE: # return as though it was rate limited, since it was response = HttpResponseJSON({'error': 'rate limited'}, status=429) elif not settings.STUB_ATTRIBUTION_HMAC_KEY: response = HttpResponseJSON({'error': 'service not configured'}, status=403) if response: patch_response_headers(response, 300) # 5 min return response data = request.GET codes = OrderedDict() has_value = False for name, default_value in STUB_VALUE_NAMES: val = data.get(name, '') # remove utm_ name = name[4:] if val and STUB_VALUE_RE.match(val): codes[name] = val has_value = True else: codes[name] = default_value if codes['source'] == '(not set)' and 'referrer' in data: try: domain = urlparse(data['referrer']).netloc if domain and STUB_VALUE_RE.match(domain): codes['source'] = domain codes['medium'] = 'referral' has_value = True except Exception: # any problems and we should just ignore it pass if not has_value: codes['source'] = 'www.mozilla.org' codes['medium'] = '(none)' code_data = sign_attribution_codes(codes) if code_data: response = HttpResponseJSON(code_data) else: response = HttpResponseJSON({'error': 'Invalid code'}, status=400) patch_response_headers(response, 300) # 5 min return response
def newsletter_subscribe(request): if request.method == 'POST': newsletters = request.POST.get('newsletters', None) form = NewsletterFooterForm(newsletters, l10n_utils.get_locale(request), request.POST) errors = [] if form.is_valid(): data = form.cleaned_data kwargs = {'format': data['fmt']} # add optional data kwargs.update(dict((k, data[k]) for k in ['country', 'lang', 'source_url', 'first_name', 'last_name', ] if data[k])) try: basket.subscribe(data['email'], data['newsletters'], **kwargs) except basket.BasketException as e: if e.code == basket.errors.BASKET_INVALID_EMAIL: errors.append(unicode(invalid_email_address)) else: log.exception("Error subscribing %s to newsletter %s" % (data['email'], data['newsletters'])) errors.append(unicode(general_error)) else: if 'email' in form.errors: errors.append(_('Please enter a valid email address')) if 'privacy' in form.errors: errors.append(_('You must agree to the privacy notice')) for fieldname in ('fmt', 'lang', 'country'): if fieldname in form.errors: errors.extend(form.errors[fieldname]) # form error messages may contain unsanitized user input errors = map(escape, errors) if request.is_ajax(): # return JSON if errors: resp = { 'success': False, 'errors': errors, } else: resp = {'success': True} return HttpResponseJSON(resp) else: ctx = {'newsletter_form': form} if not errors: ctx['success'] = True return l10n_utils.render(request, 'newsletter/mozilla-and-you.html', ctx) return l10n_utils.render(request, 'newsletter/mozilla-and-you.html')
def mozid_data_view(request, source_name): try: qs = ContributorActivity.objects.group_by_date_and_source(source_name) except ContributorActivity.DoesNotExist: # not a valid source_name raise Http404 data = [{'wkcommencing': activity['date'].isoformat(), 'totalactive': activity['total__sum'], 'new': activity['new__sum']} for activity in qs] return HttpResponseJSON(data, cors=True)
def send_to_device_ajax(request): locale = l10n_utils.get_locale(request) phone_or_email = request.POST.get('phone-or-email') if not phone_or_email: return HttpResponseJSON({'success': False, 'errors': ['phone-or-email']}) data = { 'platform': request.POST.get('platform'), } data_type = 'email' if '@' in phone_or_email else 'number' data[data_type] = phone_or_email form = SendToDeviceWidgetForm(data) if form.is_valid(): phone_or_email = form.cleaned_data.get(data_type) platform = form.cleaned_data.get('platform') # check for android & valid send to device test value # update email/sms message if conditions match send_to_device_test = request.POST.get('android-send-to-device-test') if (platform == 'android' and send_to_device_test in ['android-test-modal', 'android-test-embed']): platform = send_to_device_test if data_type == 'number': if platform in SMS_MESSAGES: try: basket.send_sms(phone_or_email, SMS_MESSAGES[platform]) except basket.BasketException: return HttpResponseJSON({'success': False, 'errors': ['system']}, status=400) else: # TODO define all platforms in SMS_MESSAGES return HttpResponseJSON({'success': False, 'errors': ['platform']}) else: # email if platform in EMAIL_MESSAGES: try: basket.subscribe(phone_or_email, EMAIL_MESSAGES[platform], source_url=request.POST.get('source-url'), lang=locale) except basket.BasketException: return HttpResponseJSON({'success': False, 'errors': ['system']}, status=400) else: # TODO define all platforms in EMAIL_MESSAGES return HttpResponseJSON({'success': False, 'errors': ['platform']}) resp_data = {'success': True} else: resp_data = { 'success': False, 'errors': form.errors.keys(), } return HttpResponseJSON(resp_data)
def sms_send(request): form = SMSSendForm(request.POST or None) if request.method == 'POST': error_msg = _( 'An error occurred in our system. Please try again later.') error = None if form.is_valid(): try: basket.send_sms(form.cleaned_data['number'], SMS_MESSAGES['android'], form.cleaned_data['optin']) except basket.BasketException: error = error_msg else: number_errors = form.errors.get('number') if number_errors: # form error messages may contain unsanitized user input error = escape(number_errors[0]) else: error = error_msg if request.is_ajax(): # return JSON if error: resp = { 'success': False, 'error': error, } else: resp = {'success': True} return HttpResponseJSON(resp) else: if error: form.errors['__all__'] = form.error_class([error]) else: return HttpResponseRedirect( reverse('firefox.android.sms-thankyou')) return l10n_utils.render(request, 'firefox/android/sms-send.html', {'sms_form': form})
def send_to_device_ajax(request): locale = l10n_utils.get_locale(request) phone_or_email = request.POST.get('phone-or-email') if not phone_or_email: return HttpResponseJSON({'success': False, 'errors': ['phone-or-email']}) data = { 'platform': request.POST.get('platform'), } data_type = 'email' if '@' in phone_or_email else 'number' data[data_type] = phone_or_email form = SendToDeviceWidgetForm(data) if form.is_valid(): phone_or_email = form.cleaned_data.get(data_type) platform = form.cleaned_data.get('platform') if data_type == 'number': if platform in SMS_MESSAGES: try: basket.send_sms(phone_or_email, SMS_MESSAGES[platform]) except basket.BasketException: return HttpResponseJSON({'success': False, 'errors': ['system']}, status=400) else: # TODO define all platforms in SMS_MESSAGES return HttpResponseJSON({'success': False, 'errors': ['platform']}) else: # email if platform in EMAIL_MESSAGES: try: basket.subscribe(phone_or_email, EMAIL_MESSAGES[platform], source_url=request.POST.get('source-url'), lang=locale) except basket.BasketException: return HttpResponseJSON({'success': False, 'errors': ['system']}, status=400) else: # TODO define all platforms in EMAIL_MESSAGES return HttpResponseJSON({'success': False, 'errors': ['platform']}) resp_data = {'success': True} else: resp_data = { 'success': False, 'errors': form.errors.keys(), } return HttpResponseJSON(resp_data)
def process_partnership_form(request, template, success_url_name, template_vars=None, form_kwargs=None): template_vars = template_vars or {} form_kwargs = form_kwargs or {} if request.method == 'POST': form = WebToLeadForm(data=request.POST, **form_kwargs) msg = 'Form invalid' stat = 400 success = False if form.is_valid(): data = form.cleaned_data.copy() honeypot = data.pop('office_fax') if honeypot: msg = 'ok' stat = 200 else: # form testing address if not data['email'] == '*****@*****.**': data['lead_source'] = form_kwargs.get( 'lead_source', 'www.mozilla.org/about/partnerships/') subject = PARTNERSHIPS_EMAIL_SUBJECT sender = PARTNERSHIPS_EMAIL_FROM to = PARTNERSHIPS_EMAIL_TO body = render_to_string('mozorg/emails/partnerships.txt', data, request=request) email = EmailMessage(subject, body, sender, to) email.send() msg = 'ok' stat = 200 success = True if request.is_ajax(): form_errors = { fn: [escape(msg) for msg in msgs] for fn, msgs in form.errors.iteritems() } return HttpResponseJSON({ 'msg': msg, 'errors': form_errors }, status=stat) # non-AJAX POST else: # if form is not valid, render template to retain form data/error messages if not success: template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = success return l10n_utils.render(request, template, template_vars) # if form is valid, redirect to avoid refresh double post possibility else: return HttpResponseRedirect("%s?success" % (reverse(success_url_name))) # no form POST - build form, add CSRF, & render template else: # without auto_id set, all id's get prefixed with 'id_' form = WebToLeadForm(auto_id='%s', **form_kwargs) template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = True if ('success' in request.GET) else False return l10n_utils.render(request, template, template_vars)
def send_to_device_ajax(request): locale = l10n_utils.get_locale(request) phone_or_email = request.POST.get('phone-or-email') # ensure a value was entered in phone or email field if not phone_or_email: return HttpResponseJSON({ 'success': False, 'errors': ['phone-or-email'] }) # pull message set from POST (not part of form, so wont be in cleaned_data) message_set = request.POST.get('message-set', 'default') # begin collecting data to pass to form constructor data = { 'platform': request.POST.get('platform'), } # determine if email or phone number was submitted data_type = 'email' if '@' in phone_or_email else 'number' # populate data type in form data dict data[data_type] = phone_or_email # instantiate the form with processed POST data form = SendToDeviceWidgetForm(data) if form.is_valid(): phone_or_email = form.cleaned_data.get(data_type) platform = form.cleaned_data.get('platform') # if no platform specified, default to 'all' if not platform: platform = 'all' # ensure we have a valid message set. if not, fall back to default if message_set not in SEND_TO_DEVICE_MESSAGE_SETS: MESSAGES = SEND_TO_DEVICE_MESSAGE_SETS['default'] else: MESSAGES = SEND_TO_DEVICE_MESSAGE_SETS[message_set] if data_type == 'number': if platform in MESSAGES['sms']: data = { 'mobile_number': phone_or_email, 'msg_name': MESSAGES['sms'][platform], 'lang': locale, } country = request.POST.get('country') if country and re.match(r'^[a-z]{2}$', country, flags=re.I): data['country'] = country try: basket.request('post', 'subscribe_sms', data=data) except basket.BasketException as e: if e.desc == 'mobile_number is invalid': return HttpResponseJSON({ 'success': False, 'errors': ['number'] }) else: return HttpResponseJSON( { 'success': False, 'errors': ['system'] }, status=400) else: return HttpResponseJSON({ 'success': False, 'errors': ['platform'] }) else: # email if platform in MESSAGES['email']: try: basket.subscribe(phone_or_email, MESSAGES['email'][platform], source_url=request.POST.get('source-url'), lang=locale) except basket.BasketException: return HttpResponseJSON( { 'success': False, 'errors': ['system'] }, status=400) else: return HttpResponseJSON({ 'success': False, 'errors': ['platform'] }) resp_data = {'success': True} else: resp_data = { 'success': False, 'errors': form.errors.keys(), } return HttpResponseJSON(resp_data)
def process_partnership_form(request, template, success_url_name, template_vars=None, form_kwargs=None): template_vars = template_vars or {} form_kwargs = form_kwargs or {} if request.method == 'POST': form = WebToLeadForm(data=request.POST, **form_kwargs) msg = 'Form invalid' stat = 400 success = False if form.is_valid(): data = form.cleaned_data.copy() honeypot = data.pop('office_fax') if honeypot: msg = 'Visitor invalid' stat = 400 else: interest = data.pop('interest') data['00NU0000002pDJr'] = interest data['oid'] = '00DU0000000IrgO' data['lead_source'] = form_kwargs.get( 'lead_source', 'www.mozilla.org/about/partnerships/') # As we're doing the Salesforce POST in the background here, # `retURL` is never visited/seen by the user. I believe it # is required by Salesforce though, so it should hang around # as a placeholder (with a valid URL, just in case). data['retURL'] = ('http://www.mozilla.org/en-US/about/' 'partnerships?success=1') r = requests.post( 'https://www.salesforce.com/servlet/' 'servlet.WebToLead?encoding=UTF-8', data) msg = requests.status_codes._codes.get(r.status_code, ['error'])[0] stat = r.status_code success = True if request.is_ajax(): return HttpResponseJSON({ 'msg': msg, 'errors': form.errors }, status=stat) # non-AJAX POST else: # if form is not valid, render template to retain form data/error messages if not success: template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = success return l10n_utils.render(request, template, template_vars) # if form is valid, redirect to avoid refresh double post possibility else: return HttpResponseRedirect("%s?success" % (reverse(success_url_name))) # no form POST - build form, add CSRF, & render template else: # without auto_id set, all id's get prefixed with 'id_' form = WebToLeadForm(auto_id='%s', **form_kwargs) template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = True if ('success' in request.GET) else False return l10n_utils.render(request, template, template_vars)
def process_content_services_form(request, template, success_url_name, template_vars=None, form_kwargs=None): template_vars = template_vars or {} form_kwargs = form_kwargs or {} if request.method == 'POST': form = ContentServicesForm(data=request.POST, **form_kwargs) msg = 'Form invalid' stat = 400 success = False if form.is_valid(): data = form.cleaned_data.copy() honeypot = data.pop('office_fax') if honeypot: # don't let on there was a problem msg = 'ok' stat = 200 else: # rename custom Salesforce fields to their real GUID name data['00NU00000053D4G'] = data.pop('interested_countries') data['00NU00000053D4L'] = data.pop('interested_languages') data['00NU00000053D4a'] = data.pop('campaign_type') data['00NU0000004ELEK'] = data.pop('mobile') data['oid'] = '00DU0000000IrgO' if data['country'] != 'us': data['state'] = data.pop('province') data['lead_source'] = form_kwargs.get( 'lead_source', 'www.mozilla.org/about/partnerships/contentservices/') # As we're doing the Salesforce POST in the background here, # `retURL` is never visited/seen by the user. I believe it # is required by Salesforce though, so it should hang around # as a placeholder (with a valid URL, just in case). data['retURL'] = ('http://www.mozilla.org/en-US/' 'about/partnerships/' 'contentservices/start?success=1') r = requests.post('https://www.salesforce.com/servlet/' 'servlet.WebToLead?encoding=UTF-8', data) msg = requests.status_codes._codes.get(r.status_code, ['error'])[0] stat = r.status_code success = True if request.is_ajax(): # ensure no unescaped values sent back. form_errors = {fn: [escape(msg) for msg in msgs] for fn, msgs in form.errors.iteritems()} return HttpResponseJSON({'msg': msg, 'errors': form_errors}, status=stat) # non-AJAX POST else: # if form is not valid, render template to retain form data/error messages if not success: template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = success return l10n_utils.render(request, template, template_vars) # if form is valid, redirect to avoid refresh double post possibility else: return HttpResponseRedirect("%s?success" % (reverse(success_url_name))) # no form POST - build form, add CSRF, & render template else: # without auto_id set, all id's get prefixed with 'id_' form = ContentServicesForm(auto_id='%s', **form_kwargs) template_vars.update(csrf(request)) template_vars['form'] = form template_vars['form_success'] = True if ('success' in request.GET) else False return l10n_utils.render(request, template, template_vars)
def newsletter_subscribe(request): if request.method == 'POST': newsletters = request.POST.get('newsletters', None) form = NewsletterFooterForm(newsletters, l10n_utils.get_locale(request), request.POST) errors = [] if form.is_valid(): data = form.cleaned_data kwargs = {} # add optional data kwargs.update( dict((k, data[k]) for k in [ 'country', 'lang', 'source_url', 'first_name', 'last_name', ] if data[k])) # NOTE this is not a typo; Referrer is misspelled in the HTTP spec # https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.36 if not kwargs.get('source_url') and request.META.get( 'HTTP_REFERER'): kwargs['source_url'] = request.META['HTTP_REFERER'] try: basket.subscribe(data['email'], data['newsletters'], **kwargs) except basket.BasketException as e: if e.code == basket.errors.BASKET_INVALID_EMAIL: errors.append(unicode(invalid_email_address)) else: log.exception("Error subscribing %s to newsletter %s" % (data['email'], data['newsletters'])) errors.append(unicode(general_error)) else: if 'email' in form.errors: errors.append(_('Please enter a valid email address')) if 'privacy' in form.errors: errors.append(_('You must agree to the privacy notice')) for fieldname in ('lang', 'country'): if fieldname in form.errors: errors.extend(form.errors[fieldname]) # form error messages may contain unsanitized user input errors = map(escape, errors) if request.is_ajax(): # return JSON if errors: resp = { 'success': False, 'errors': errors, } else: resp = {'success': True} return HttpResponseJSON(resp) else: ctx = {'newsletter_form': form} if not errors: ctx['success'] = True return l10n_utils.render(request, 'newsletter/index.html', ctx) return l10n_utils.render(request, 'newsletter/index.html')