// File: nilnilnil[P]autocomplete/deps/mongoose/mongoose.c
// Function: handle_directory_request
static void handle_directory_request(struct mg_connection *conn,
                                     const char *dir) {
  struct dirent *dp;
  DIR *dirp;
  struct de *entries = NULL;
  char path[PATH_MAX];
  int i, sort_direction, num_entries = 0, arr_size = 128;

  if ((dirp = opendir(dir)) == NULL) {
    send_http_error(conn, 500, "Cannot open directory",
        "Error: opendir(%s): %s", path, strerror(ERRNO));
    return;
  }

  (void) mg_printf(conn, "%s",
      "HTTP/1.1 200 OK\r\n"
      "Connection: close\r\n"
      "Content-Type: text/html; charset=utf-8\r\n\r\n");

  sort_direction = conn->request_info.query_string != NULL &&
    conn->request_info.query_string[1] == 'd' ? 'a' : 'd';

  while ((dp = readdir(dirp)) != NULL) {

    // Do not show current dir and passwords file
    if (!strcmp(dp->d_name, ".") ||
        !strcmp(dp->d_name, "..") ||
        !strcmp(dp->d_name, PASSWORDS_FILE_NAME))
      continue;

    if (entries == NULL || num_entries >= arr_size) {
      arr_size *= 2;
      entries = (struct de *) realloc(entries,
          arr_size * sizeof(entries[0]));
    }

    if (entries == NULL) {
      closedir(dirp);
      send_http_error(conn, 500, "Cannot open directory",
          "%s", "Error: cannot allocate memory");
      return;
    }

    mg_snprintf(conn, path, sizeof(path), "%s%c%s", dir, DIRSEP, dp->d_name);

    // If we don't memset stat structure to zero, mtime will have
    // garbage and strftime() will segfault later on in
    // print_dir_entry(). memset is required only if mg_stat()
    // fails. For more details, see
    // http://code.google.com/p/mongoose/issues/detail?id=79
    if (mg_stat(path, &entries[num_entries].st) != 0) {
      memset(&entries[num_entries].st, 0, sizeof(entries[num_entries].st));
    }

    entries[num_entries].conn = conn;
    entries[num_entries].file_name = mg_strdup(dp->d_name);
    num_entries++;
  }
  (void) closedir(dirp);

  conn->num_bytes_sent += mg_printf(conn,
      "<html><head><title>Index of %s</title>"
      "<style>th {text-align: left;}</style></head>"
      "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
      "<tr><th><a href=\"?n%c\">Name</a></th>"
      "<th><a href=\"?d%c\">Modified</a></th>"
      "<th><a href=\"?s%c\">Size</a></th></tr>"
      "<tr><td colspan=\"3\"><hr></td></tr>",
      conn->request_info.uri, conn->request_info.uri,
      sort_direction, sort_direction, sort_direction);

  // Print first entry - link to a parent directory
  conn->num_bytes_sent += mg_printf(conn,
      "<tr><td><a href=\"%s%s\">%s</a></td>"
      "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
      conn->request_info.uri, "..", "Parent directory", "-", "-");

  // Sort and print directory entries
  qsort(entries, (size_t)num_entries, sizeof(entries[0]), compare_dir_entries);
  for (i = 0; i < num_entries; i++) {
    print_dir_entry(&entries[i]);
    free(entries[i].file_name);
  }
  free(entries);

  conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
  conn->request_info.status_code = 200;
}

// Assembly:
subq $0x1058, %rsp           # imm = 0x1058
movq %rdi, 0x1050(%rsp)
movq %rsi, 0x1048(%rsp)
movq $0x0, 0x1030(%rsp)
movl $0x0, 0x24(%rsp)
movl $0x80, 0x20(%rsp)
movq 0x1048(%rsp), %rdi
callq 0x5900
movq %rax, 0x1038(%rsp)
cmpq $0x0, %rax
jne 0x1dfed
movq 0x1050(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0x30(%rsp), %rax
movq %rax, 0x18(%rsp)
callq 0x5060
movl (%rax), %edi
callq 0x5190
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %r8
movq %rax, %r9
movl $0x1f4, %esi            # imm = 0x1F4
leaq 0x52b4(%rip), %rdx      # 0x2328e
leaq 0x52c3(%rip), %rcx      # 0x232a4
movb $0x0, %al
callq 0x1bc40
jmp 0x1e3b1
movq 0x1050(%rsp), %rdi
leaq 0x577c(%rip), %rsi      # 0x23778
leaq 0x52b8(%rip), %rdx      # 0x232bb
movb $0x0, %al
callq 0x17030
movq 0x1050(%rsp), %rcx
xorl %eax, %eax
cmpq $0x0, 0x28(%rcx)
movb %al, 0xf(%rsp)
je 0x1e039
movq 0x1050(%rsp), %rax
movq 0x28(%rax), %rax
movsbl 0x1(%rax), %eax
cmpl $0x64, %eax
sete %al
movb %al, 0xf(%rsp)
movb 0xf(%rsp), %dl
movl $0x64, %eax
movl $0x61, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movl %eax, 0x28(%rsp)
movq 0x1038(%rsp), %rdi
callq 0x5920
movq %rax, 0x1040(%rsp)
cmpq $0x0, %rax
je 0x1e230
movq 0x1040(%rsp), %rdi
addq $0x13, %rdi
leaq 0x5288(%rip), %rsi      # 0x2330b
callq 0x5810
cmpl $0x0, %eax
je 0x1e0c7
movq 0x1040(%rsp), %rdi
addq $0x13, %rdi
leaq 0x526a(%rip), %rsi      # 0x2330a
callq 0x5810
cmpl $0x0, %eax
je 0x1e0c7
movq 0x1040(%rsp), %rdi
addq $0x13, %rdi
leaq 0x4ff0(%rip), %rsi      # 0x230ad
callq 0x5810
cmpl $0x0, %eax
jne 0x1e0c9
jmp 0x1e051
cmpq $0x0, 0x1030(%rsp)
je 0x1e0de
movl 0x24(%rsp), %eax
cmpl 0x20(%rsp), %eax
jl 0x1e106
movl 0x20(%rsp), %eax
shll %eax
movl %eax, 0x20(%rsp)
movq 0x1030(%rsp), %rdi
movslq 0x20(%rsp), %rax
imulq $0x28, %rax, %rsi
callq 0x59e0
movq %rax, 0x1030(%rsp)
cmpq $0x0, 0x1030(%rsp)
jne 0x1e14c
movq 0x1038(%rsp), %rdi
callq 0x59b0
movq 0x1050(%rsp), %rdi
movl $0x1f4, %esi            # imm = 0x1F4
leaq 0x515c(%rip), %rdx      # 0x2328e
leaq 0x563f(%rip), %rcx      # 0x23778
leaq 0x51cd(%rip), %r8       # 0x2330d
movb $0x0, %al
callq 0x1bc40
jmp 0x1e3b1
movq 0x1050(%rsp), %rdi
leaq 0x30(%rsp), %rsi
movq 0x1048(%rsp), %r8
movq 0x1040(%rsp), %rax
addq $0x13, %rax
movl $0x1000, %edx           # imm = 0x1000
leaq 0x501f(%rip), %rcx      # 0x23198
movl $0x2f, %r9d
movq %rax, (%rsp)
movb $0x0, %al
callq 0x1cc90
leaq 0x30(%rsp), %rdi
movq 0x1030(%rsp), %rsi
movslq 0x24(%rsp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
addq $0x10, %rsi
callq 0x1a8a0
cmpl $0x0, %eax
je 0x1e1d5
movq 0x1030(%rsp), %rdi
movslq 0x24(%rsp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
addq $0x10, %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x52a0
movq 0x1050(%rsp), %rcx
movq 0x1030(%rsp), %rax
movslq 0x24(%rsp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, (%rax)
movq 0x1040(%rsp), %rdi
addq $0x13, %rdi
callq 0x18770
movq %rax, %rcx
movq 0x1030(%rsp), %rax
movslq 0x24(%rsp), %rdx
imulq $0x28, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x8(%rax)
movl 0x24(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x24(%rsp)
jmp 0x1e051
movq 0x1038(%rsp), %rdi
callq 0x59b0
movq 0x1050(%rsp), %rdi
movq 0x1050(%rsp), %rax
movq 0x18(%rax), %rdx
movq 0x1050(%rsp), %rax
movq 0x18(%rax), %rcx
movl 0x28(%rsp), %r8d
movl 0x28(%rsp), %r9d
movl 0x28(%rsp), %eax
leaq 0x50b9(%rip), %rsi      # 0x2332b
movl %eax, (%rsp)
movb $0x0, %al
callq 0x17030
movslq %eax, %rcx
movq 0x1050(%rsp), %rax
addq 0x4b0(%rax), %rcx
movq %rcx, 0x4b0(%rax)
movq 0x1050(%rsp), %rdi
movq 0x1050(%rsp), %rax
movq 0x18(%rax), %rdx
leaq 0x5193(%rip), %rsi      # 0x23443
leaq 0x5053(%rip), %rcx      # 0x2330a
leaq 0x51d6(%rip), %r8       # 0x23494
leaq 0x4cc0(%rip), %rax      # 0x22f85
movq %rax, %r9
movq %rax, (%rsp)
movb $0x0, %al
callq 0x17030
movslq %eax, %rcx
movq 0x1050(%rsp), %rax
addq 0x4b0(%rax), %rcx
movq %rcx, 0x4b0(%rax)
movq 0x1030(%rsp), %rdi
movslq 0x24(%rsp), %rsi
movl $0x28, %edx
leaq 0x167b(%rip), %rcx      # 0x1f980
callq 0x5b20
movl $0x0, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cmpl 0x24(%rsp), %eax
jge 0x1e35f
movq 0x1030(%rsp), %rdi
movslq 0x2c(%rsp), %rax
imulq $0x28, %rax, %rax
addq %rax, %rdi
callq 0x1fb30
movq 0x1030(%rsp), %rax
movslq 0x2c(%rsp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rdi
callq 0x56c0
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x1e312
movq 0x1030(%rsp), %rdi
callq 0x56c0
movq 0x1050(%rsp), %rdi
leaq 0x53fd(%rip), %rsi      # 0x23778
leaq 0x5123(%rip), %rdx      # 0x234a5
movb $0x0, %al
callq 0x17030
movslq %eax, %rcx
movq 0x1050(%rsp), %rax
addq 0x4b0(%rax), %rcx
movq %rcx, 0x4b0(%rax)
movq 0x1050(%rsp), %rax
movl $0xc8, 0x4c(%rax)
addq $0x1058, %rsp           # imm = 0x1058
retq
nopl (%rax)