1

So I'm using Chrome, with Django version 1.9.6, python 2.7.13.

I'm trying to send raw data (audio file) from html/js over to django server to convert from .mp3 to .wav format.

However, it doesn't even reach views.py with CSRF cookie not set. error.

I've tried almost everything I could find online.

I have following views.py and index.html.

index.html

<!DOCTYPE html>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://www.w3schools.com/lib/w3.css">
    <title title="Audio Editor">Audio Editor</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<main>
  <h1><img src="http://blog.blogtalkradio.com/wp-content/uploads/2011/10/Audio_Icon.jpg" alt="http://blog.blogtalkradio.com/wp-content/uploads/2011/10/Audio_Icon.jpg" style="float:left;width:30px;height:width;"><img src="https://image.freepik.com/free-icon/question-mark_318-52837.jpg" alt="https://image.freepik.com/free-icon/question-mark_318-52837.jpg" style="float:left;width:30px;height:width;"> Obfuscate your audio</h1>
  <br>
  <br>
  <body>
  <h3>1. Upload your audio:</h3>
  <input type="file" id="audio-file" onchange="fileAdded()"/>
  <p id="message"></p>
  <br>
  <h3>2. Obfuscate and download:</h3>
  <button id="obfuscate-button" onclick="obfuscate()">Obfuscate!</button>
  </body>
  <br>
  <br>
  <hr>
  <a href="https://github.com/mgjo5899/web_audio">Check out the github page!</a>
</main>

<script>
var file = undefined;
var audio_formats = ["mp3", "wav"];

// using jQuery
function getCookie(name) {
  var cookieValue = null;

  if (document.cookie && document.cookie !== '') {
    var cookies = document.cookie.split(';');
    for (var i = 0; i < cookies.length; i++) {
      var cookie = jQuery.trim(cookies[i]);
      // Does this cookie string begin with the name we want?
      if (cookie.substring(0, name.length + 1) === (name + '=')) {
        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
        break;
      }
    }
  }

  return cookieValue;
}

function fileAdded() {
  var x = document.getElementById("audio-file");
  file = x.files[0];
  var msg = document.getElementById("message");

  if (file != undefined) {
    x = file.name.split(".");
    var ext = x[x.length - 1];

    if (audio_formats.indexOf(ext) == -1) {
      msg.innerHTML = ext + " is not an audio file!";
    } else {
      msg.innerHTML = file.name + " has been successfully added!";
    }
  } else {
    msg.innerHTML = "Please select an audio file to obfuscate!";
  }
}

function obfuscate() {
  if (file == undefined)
    alert("Choose an audio file!");
  else {
    var obfuscateButton = document.getElementById("obfuscate-button");
    obfuscateButton.innerHTML = "Proccessing...";
    var xhr = new XMLHttpRequest();
    var url = "http://127.0.0.1:8000/obfuscator/obfuscate/";
    var method = 'POST';
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4 && xhr.status === 200) {
       obfuscateButton.innerHTML = "Done!"
      }
    }
    xhr.open(method, url, true);

 xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

    var formData = new FormData();
    formData.append("audio_file", file);
    formData.append("file_name", file.name)
    xhr.send(formData);
  }
}
</script>
</html>

view.py

from django.http import HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import ensure_csrf_cookie
from subprocess import call
from django.core.files import File
from .forms import UploadFileForm
from django.views.decorators.csrf import csrf_exempt
import subprocess

def index(request):
 return render(request, 'obfuscator/index.html')

#@csrf_exempt
def obfuscate(request):
 print("HI")
 if request.method == 'GET':
  return HttpResponse("Hi")

 if request.method == 'POST':
  print("files: " + str(request.FILES))
  print("posts: " + str(request.POST))

  if len(request.POST) > 0:
   handle_uploaded_file(request.FILES['audio_file'])

 return HttpResponse("The form was valid!")

def handle_uploaded_file(f):
 with open('temp.mp3', 'wb+') as destination:
  for chunk in f.chunks():
   destination.write(chunk)

 subprocess.check_call("ffmpeg -y -i temp.mp3 temp.wav", shell=True)

I really don't know why this is not working on my computer (mac OS X). Every time it gives me (CSRF cookie not sets) error, not the (CSRF token missing or incorrect.) error.

I can use this with csrf_exempt but I would like to use it with csrf protection.

Please help!

Thank you.

Joseph
  • 73
  • 10

1 Answers1

1

Indeed, your CSRF error occurs because you aren't setting the csrf cookie in your template

You need to set the csrf_token in your templat as follow:

<form action="#" method="POST">
    {% csrf_token %}
    <h3>1. Upload your audio:</h3>
    <input type="file" id="audio-file" onchange="fileAdded()"/>
    <p id="message"></p>
    <br>
    <h3>2. Obfuscate and download:</h3>
    <button id="obfuscate-button" onclick="obfuscate()">Obfuscate!   </button>
</form>

In other hand, maybe you could try using the @ensure_csrf_cookie decorator in the view that renders the template

@ensure_csrf_cookie
def index(request):
    return render(request, 'obfuscator/index.html')
Angel F
  • 479
  • 3
  • 13
  • I thought I was adding csrf_token manually in the javascript part by doing setRequestHeader("...") after open, right before send for ajax sends. Can you confirm? – Joseph May 09 '17 at 03:25
  • Your approach to get and set set the cookie to request heder is okk, but you need yo create the cookie, and with django you can do it with csrf_token tag or wirh the decorator – Angel F May 09 '17 at 03:40
  • Yeah but isn't that only when you are using html code directly to send HTTP request? Like using an input type or something like that – Joseph May 09 '17 at 03:43
  • Try with @ensure_csrf_cookie in the View that renders your template – Angel F May 09 '17 at 03:44
  • Nope... Doesn't work. So previously, I remember trying it out like your suggested code on HTML side (form post) and have javascript doing another ajax post again. I first thought it was working. Then realized it was giving error for the JS AJAX post request that was overwritten by the effect of that form POST request on HTML. So two different post request were sent, and the JS part didn't work, the one that I want to make happening. – Joseph May 09 '17 at 03:48
  • Maybe this post could help you http://stackoverflow.com/q/17716624/4396011 – Angel F May 09 '17 at 03:54
  • I've already gone through that page before and checked my setting that its CSRF_COOKIE_SECURE is false. Funny thing is I thought this option CSRF_COOKIE_SECURE is telling Django to check/ don't check CSRF verification. But somehow, even in the original setting with that being false, it checks... – Joseph May 09 '17 at 03:58