Example #1
0
static void handle_propfind(struct mg_connection *conn, const char *path,
                            struct file *filep) {
  const char *depth = mg_get_header(conn, "Depth");

  conn->must_close = 1;
  conn->status_code = 207;
  mg_printf(conn, "HTTP/1.1 207 Multi-Status\r\n"
            "Connection: close\r\n"
            "Content-Type: text/xml; charset=utf-8\r\n\r\n");

  conn->num_bytes_sent += mg_printf(conn,
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
      "<d:multistatus xmlns:d='DAV:'>\n");

  // Print properties for the requested resource itself
  print_props(conn, conn->request_info.uri, filep);

  // If it is a directory, print directory entries too if Depth is not 0
  if (filep->is_directory &&
      !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes") &&
      (depth == NULL || strcmp(depth, "0") != 0)) {
    scan_directory(conn, path, conn, &print_dav_dir_entry);
  }

  conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
}
Example #2
0
// Check the user's password, return 1 if OK
static int check_password(const char *method, const char *ha1, const char *uri,
                          const char *nonce, const char *nc, const char *cnonce,
                          const char *qop, const char *response) {
  char ha2[32 + 1], expected_response[32 + 1];

  // Some of the parameters may be NULL
  if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL ||
      qop == NULL || response == NULL) {
    return 0;
  }

  // NOTE(lsm): due to a bug in MSIE, we do not compare the URI
  // TODO(lsm): check for authentication timeout
  if (// strcmp(dig->uri, c->ouri) != 0 ||
      strlen(response) != 32
      // || now - strtoul(dig->nonce, NULL, 10) > 3600
      ) {
    return 0;
  }

  mg_md5(ha2, method, ":", uri, NULL);
  mg_md5(expected_response, ha1, ":", nonce, ":", nc,
      ":", cnonce, ":", qop, ":", ha2, NULL);

  return mg_strcasecmp(response, expected_response) == 0;
}
Example #3
0
// Return HTTP header value, or NULL if not found.
static const char *get_header(const struct mg_request_info *ri,
                              const char *name) {
  int i;

  for (i = 0; i < ri->num_headers; i++)
    if (!mg_strcasecmp(name, ri->http_headers[i].name))
      return ri->http_headers[i].value;

  return NULL;
}
Example #4
0
static void test_mg_fetch(void) {
  static const char *options[] = {
    "document_root", ".",
    "listening_ports", UNUSED_PORT,
    NULL,
  };
  char buf[2000], buf2[2000];
  int n, length;
  struct mg_context *ctx;
  struct mg_request_info ri;
  const char *tmp_file = "temporary_file_name_for_unit_test.txt";
  struct file file;
  FILE *fp;

  ASSERT((ctx = mg_start(event_handler, NULL, options)) != NULL);

  // Failed fetch, pass invalid URL
  ASSERT(mg_fetch(ctx, "localhost", tmp_file, buf, sizeof(buf), &ri) == NULL);
  ASSERT(mg_fetch(ctx, "localhost:" UNUSED_PORT, tmp_file,
                  buf, sizeof(buf), &ri) == NULL);
  ASSERT(mg_fetch(ctx, "http://$$$.$$$", tmp_file,
                  buf, sizeof(buf), &ri) == NULL);

  // Failed fetch, pass invalid file name
  ASSERT(mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/data",
                  "/this/file/must/not/exist/ever",
                  buf, sizeof(buf), &ri) == NULL);

  // Successful fetch
  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/data",
                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
  ASSERT(ri.num_headers == 2);
  ASSERT(!strcmp(ri.request_method, "HTTP/1.1"));
  ASSERT(!strcmp(ri.uri, "200"));
  ASSERT(!strcmp(ri.http_version, "OK"));
  ASSERT((length = ftell(fp)) == (int) strlen(fetch_data));
  fseek(fp, 0, SEEK_SET);
  ASSERT(fread(buf2, 1, length, fp) == (size_t) length);
  ASSERT(memcmp(buf2, fetch_data, length) == 0);
  fclose(fp);

  // Fetch big file, mongoose.c
  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/mongoose.c",
                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
  ASSERT(mg_stat(fc(ctx), "mongoose.c", &file));
  ASSERT(file.size == ftell(fp));
  ASSERT(!strcmp(ri.request_method, "HTTP/1.1"));

  // Fetch nonexistent file, /blah
  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/boo",
                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
  ASSERT(!mg_strcasecmp(ri.uri, "404"));
  fclose(fp);

  // Fetch existing inmemory file
  ASSERT((fp = mg_fetch(ctx, "http://localhost:" UNUSED_PORT "/blah",
                        tmp_file, buf, sizeof(buf), &ri)) != NULL);
  ASSERT(!mg_strcasecmp(ri.uri, "200"));
  n = ftell(fp);
  fseek(fp, 0, SEEK_SET);
  printf("%s %d %d [%.*s]\n", __func__, n, (int) feof(fp), n, buf2);
  n = fread(buf2, 1, n, fp);
  printf("%s %d %d [%.*s]\n", __func__, n, (int) feof(fp), n, buf2);
  ASSERT((size_t) ftell(fp) == (size_t) strlen(inmemory_file_data));
  ASSERT(!memcmp(inmemory_file_data, buf2, ftell(fp)));
  fclose(fp);

  remove(tmp_file);
  mg_stop(ctx);
}