예제 #1
0
bool status( LSHandle *handle, LSMessage *msg, void *ctx)
{
	if(rec_status())
	{
		LSMessageRespond( msg, "{\"returnValue\": true, \"Status\": true}", NULL);
		return true;
	}
	else 
		LSMessageRespond( msg, "{\"rerurnValue\": true, \"Status\": false}", NULL);
	return true;
}
예제 #2
0
bool getFilecacheType_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  if (access_denied(message)) return true;

  char filename[MAXLINLEN];

  // Extract the id argument from the message
  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *type = json_find_first_label(object, "type");               
  if (!type || (type->child->type != JSON_STRING) || (strspn(type->child->text, ALLOWED_CHARS) != strlen(type->child->text))) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing type\"}",
			&lserror)) goto error;
    return true;
  }

  sprintf(filename, "/etc/palm/filecache_types/%s", type->child->text);

  return read_file(message, filename, true);

 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #3
0
//
// Handler for the getStats service.
//
bool getStats_handler(LSHandle* lshandle, LSMessage *reply, void *ctx) {
  bool retVal;
  LSError lserror;
  LSErrorInit(&lserror);
  LSMessage* message = (LSMessage*)ctx;
  retVal = LSMessageRespond(message, LSMessageGetPayload(reply), &lserror);
  if (!retVal) {
    LSErrorPrint(&lserror, stderr);
    LSErrorFree(&lserror);
  }
  return retVal;
}
예제 #4
0
//
// Encrypt text
//
bool encrypt_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  // Local buffer to store the update command
  char command[MAXLINLEN];

  char *document;

  // Extract the userdata argument from the message
  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *userdata = json_find_first_label(object, "userdata");               

  if (!userdata || (userdata->child->type != JSON_OBJECT)) {
    if (!LSMessageRespond(message,
			  "{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing userdata\"}",
			  &lserror)) goto error;
    return true;
  }

  if (json_tree_to_string(userdata->child, &document) != JSON_OK) {
    if (!LSMessageRespond(message,
			  "{\"errorText\": \"Unable to parse userdata\", \"returnValue\": false, \"errorCode\": -1 }",
			   &lserror)) goto error;
    return true;
  }

  // Store the command, so it can be used in the error report if necessary
  sprintf(command, "echo '%s' | openssl rsautl -encrypt -certin -inkey /media/cryptofs/apps/usr/palm/applications/com.apptuckerbox.register/certs/com.apptuckerbox.crt | openssl enc -e -a 2>&1", document);
  
  return simple_command(message, command);

 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #5
0
static bool access_denied(LSMessage *message) {
  LSError lserror;
  LSErrorInit(&lserror);

  const char *appId = LSMessageGetApplicationID(message);
  if (!appId || strncmp(appId, "org.webosinternals.impostah", 27) || ((strlen(appId) > 27) && (*(appId+27) != ' '))) {
    if (!LSMessageRespond(message, "{\"returnValue\": false, \"errorText\": \"Unauthorised access\"}", &lserror)) {
      LSErrorPrint(&lserror, stderr);
      LSErrorFree(&lserror);
    }
    return true;
  }

  return false;
}
예제 #6
0
//
// Return the current API version of the service.
// Called directly from webOS, and returns directly to webOS.
//
bool version_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  if (access_denied(message)) return true;

  if (!LSMessageRespond(message, "{\"returnValue\": true, \"version\": \"" VERSION "\", \"apiVersion\": \"" API_VERSION "\"}", &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #7
0
//
// A dummy method, useful for unimplemented functions or as a status function.
// Called directly from webOS, and returns directly to webOS.
//
bool dummy_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  if (access_denied(message)) return true;

  if (!LSMessageRespond(message, "{\"returnValue\": true}", &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #8
0
//
// Handler for the impersonate service.
//
bool impersonate_handler(LSHandle* lshandle, LSMessage *reply, void *ctx) {
  bool retVal;
  LSError lserror;
  LSErrorInit(&lserror);
  LSMessage* message = (LSMessage*)ctx;
  retVal = LSMessageRespond(message, LSMessageGetPayload(reply), &lserror);
  if (!LSMessageIsSubscription(message)) {
    LSMessageUnref(message);
  }
  if (!retVal) {
    LSErrorPrint(&lserror, stderr);
    LSErrorFree(&lserror);
  }
  return retVal;
}
예제 #9
0
static bool access_denied(LSMessage *message) {
  LSError lserror;
  LSErrorInit(&lserror);

  const char *appId = LSMessageGetApplicationID(message);
  if (!appId || strncmp(appId, "com.apptuckerbox.register", 25) || ((strlen(appId) > 25) && (*(appId+25) != ' '))) {
    if (!LSMessageRespond(message, "{\"returnValue\": false, \"errorText\": \"Unauthorised access\"}", &lserror)) {
      LSErrorPrint(&lserror, stderr);
      LSErrorFree(&lserror);
    }
    return true;
  }

  return false;
}
예제 #10
0
//
// Send a standard format command failure message back to webOS.
// The command will be escaped.  The output argument should be a JSON array and is not escaped.
// The additional text  will not be escaped.
// The return value is from the LSMessageRespond call, not related to the command execution.
//
static bool report_command_failure(LSMessage *message, char *command, char *stdErrText, char *additional) {
  LSError lserror;
  LSErrorInit(&lserror);

  char buffer[MAXBUFLEN];
  char esc_buffer[MAXBUFLEN];

  // Include the command that was executed, in escaped form.
  snprintf(buffer, MAXBUFLEN,
	   "{\"errorText\": \"Unable to run command: %s\"",
	   json_escape_str(command, esc_buffer));

  // Include any stderr fields from the command.
  if (stdErrText) {
    strcat(buffer, ", \"stdErr\": ");
    strcat(buffer, stdErrText);
  }

  // Report that an error occurred.
  strcat(buffer, ", \"returnValue\": false, \"errorCode\": -1");

  // Add any additional JSON fields.
  if (additional) {
    strcat(buffer, ", ");
    strcat(buffer, additional);
  }

  // Terminate the JSON reply message ...
  strcat(buffer, "}");

  // fprintf(stderr, "Message is %s\n", buffer);

  // and send it.
  if (!LSMessageRespond(message, buffer, &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #11
0
//
// Run a simple shell command, and return the output to webOS.
//
static bool simple_command(LSMessage *message, char *command) {
  LSError lserror;
  LSErrorInit(&lserror);

  char run_command_buffer[MAXBUFLEN];

  // Initialise the output buffer
  strcpy(run_command_buffer, "{\"stdOut\": [");

  // Run the command
  if (run_command(command, true, run_command_buffer)) {

    // Finalise the message ...
    strcat(run_command_buffer, "], \"returnValue\": true}");

    // fprintf(stderr, "Message is %s\n", run_command_buffer);

    // and send it to webOS.
    if (!LSMessageRespond(message, run_command_buffer, &lserror)) goto error;
  }
  else {

    // Finalise the command output ...
    strcat(run_command_buffer, "]");

    // and use it in a failure report message.
    if (!report_command_failure(message, command, run_command_buffer+11, NULL)) goto end;
  }

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #12
0
bool importUsWords(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("importUsWords");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #13
0
bool phraseGetInfoList(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("phraseGetInfoList");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #14
0
bool loadPhrase(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("loadPhrase");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #15
0
bool getListCandList(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("getListCandList");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #16
0
bool put_file_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  char buffer[MAXBUFLEN];

  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *id;

  // Extract the url argument from the message
  id = json_find_first_label(object, "filename");
  if (!id || (id->child->type != JSON_STRING) ||
      (strlen(id->child->text) >= MAXLINLEN) ||
      (strlen(id->child->text) < 8) ||
      strncmp(id->child->text, "file://", 7)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, "
			"\"errorText\": \"Invalid or missing filename parameter\"}",
			&lserror)) goto error;
    return true;
  }
  char filename[MAXLINLEN];
  strcpy(filename, id->child->text+7);

  // Extract the object argument from the message
  id = json_find_first_label(object, "object");
  if (!id || (id->child->type != JSON_OBJECT)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, "
			"\"errorText\": \"Invalid or missing object parameter\"}",
			&lserror)) goto error;
    return true;
  }

  char *contents = NULL;

  if (json_tree_to_string(id->child, &contents) != JSON_OK) {
    sprintf(buffer,
	    "{\"errorText\": \"Unable to parse object\", \"returnValue\": false, \"errorCode\": -1 }");
    if (!LSMessageRespond(message, buffer, &lserror)) goto error;
    return true;
  }

  FILE *fp = fopen(filename, "w");
  if (!fp) {
    sprintf(buffer,
	    "{\"errorText\": \"Unable to open %s\", \"returnValue\": false, \"errorCode\": -1 }",
	    filename);
    if (!LSMessageRespond(message, buffer, &lserror)) goto error;
    return true;
  }

  if (fputs(contents, fp) == EOF) {
    (void)fclose(fp);
    (void)unlink(filename);
    sprintf(buffer,
	    "{\"errorText\": \"Unable to write to %s\", \"returnValue\": false, \"errorCode\": -1 }",
	    filename);
    if (!LSMessageRespond(message, buffer, &lserror)) goto error;
    return true;
  }
  
  if (fclose(fp)) {
    sprintf(buffer,
	    "{\"errorText\": \"Unable to close %s\", \"returnValue\": false, \"errorCode\": -1 }",
	    filename);
    if (!LSMessageRespond(message, buffer, &lserror)) goto error;
    return true;
  }

  if (!LSMessageRespond(message, "{\"returnValue\": true}", &lserror)) goto error;
  return true;

 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #17
0
static bool read_file(LSMessage *message, char *filename, bool subscribed) {
  LSError lserror;
  LSErrorInit(&lserror);

  FILE * file = fopen(filename, "r");
  if (!file) {
    sprintf(file_buffer,
	    "{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Cannot open %s\"}",
	    filename);
    
    if (!LSMessageRespond(message, file_buffer, &lserror)) goto error;
    return true;
  }
  
  char chunk[CHUNKSIZE];
  int chunksize = CHUNKSIZE;

  syslog(LOG_DEBUG, "Reading file %s\n", filename);

  fseek(file, 0, SEEK_END);
  int filesize = ftell(file);
  fseek(file, 0, SEEK_SET);

  if (subscribed) {
    if (sprintf(file_buffer,
		"{\"returnValue\": true, \"filesize\": %d, \"chunksize\": %d, \"stage\": \"start\"}",
		filesize, chunksize)) {

      if (!LSMessageRespond(message, file_buffer, &lserror)) goto error;

    }
  }
  else if (filesize < chunksize) {
    chunksize = filesize;
  }

  int size;
  int datasize = 0;
  while ((size = fread(chunk, 1, chunksize, file)) > 0) {
    datasize += size;
    chunk[size] = '\0';
    sprintf(file_buffer, "{\"returnValue\": true, \"size\": %d, \"contents\": \"", size);
    strcat(file_buffer, json_escape_str(chunk, file_esc_buffer));
    strcat(file_buffer, "\"");
    if (subscribed) {
      strcat(file_buffer, ", \"stage\": \"middle\"");
    }
    strcat(file_buffer, "}");

    if (!LSMessageRespond(message, file_buffer, &lserror)) goto error;

  }

  if (!fclose(file)) {
    if (subscribed) {
      sprintf(file_buffer, "{\"returnValue\": true, \"datasize\": %d, \"stage\": \"end\"}", datasize);

      if (!LSMessageRespond(message, file_buffer, &lserror)) goto error;

    }
  }
  else {
    sprintf(file_buffer, "{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Cannot close file\"}");

    if (!LSMessageRespond(message, file_buffer, &lserror)) goto error;

  }

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #18
0
bool setShuangpin(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("setShuangpin");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #19
0
bool findLian(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("findLian");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #20
0
bool cellInstall(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("cellInstall");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #21
0
//
// Dump the contents of an sqlite3 database table
//
static bool dump_sqlite(LSMessage *message, char *database, char *table) {
  LSError lserror;
  LSErrorInit(&lserror);

  char buffer[MAXBUFLEN];
  char esc_buffer[MAXBUFLEN];

  char line[MAXLINLEN];

  // Local buffer to store the command
  char command[MAXLINLEN];

  sprintf(command, "sqlite3 %s .dump 2>&1", database);

  // Is this the first line of output?
  bool first = true;

  // Was there an error in accessing any of the files?
  bool error = false;

  // Length of buffer before the last command
  int lastlen = 0;

  // Start execution of the command to list the config files.
  FILE *fp = popen(command, "r");

  // If the command cannot be started
  if (!fp) {

    // then report the error to webOS.
    if (!report_command_failure(message, command, NULL, NULL)) goto end;

    // The error report has been sent, so return to webOS.
    return true;
  }

  if (!LSMessageRespond(message, "{\"stage\": \"start\", \"returnValue\": true}", &lserror)) goto error;

  // Initialise the output message.
  strcpy(buffer, "{");
  lastlen = strlen(buffer);

  // Loop through the list of files in the scripts directory.
  while (fgets( line, sizeof line, fp)) {

    // Chomp the newline
    char *nl = strchr(line,'\n'); if (nl) *nl = 0;

    if ((strlen(line) <= 13+strlen(table)+9) ||
	strncmp(line, "INSERT INTO \"", 13) ||
	strncmp(line+13, table, strlen(table)) ||
	strncmp(line+13+strlen(table), "\" VALUES(", 9) ||
	strncmp(line+strlen(line)-2, ");", 2)) {
      continue;
    }

    *(line+strlen(line)-2) = 0;

    // Push out a partial chunk
    if (strlen(buffer) >= CHUNKSIZE) {

      // Terminate the JSON array
      if (!first) {
	strcat(buffer, "], ");
      }

      strcat(buffer, "\"stage\": \"middle\", ");

      // Check the error status, and return the current error status
      if (error) {
	strcat(buffer, "\"returnValue\": false}");
      }
      else {
	strcat(buffer, "\"returnValue\": true}");
      }
      
      // fprintf(stderr, "Message is %s\n", buffer);

      // Return the results to webOS.
      if (!LSMessageRespond(message, buffer, &lserror)) goto error;

      // This is now the first line of output
      first = true;

      // Initialise the output message.
      strcpy(buffer, "{");
      lastlen = strlen(buffer);
    }

    // Start or continue the JSON array
    if (first) {
      strcat(buffer, "\"results\": [");
      lastlen = strlen(buffer);
      first = false;
    }
    else if (strlen(buffer) > lastlen) {
      strcat(buffer, ", ");
      lastlen = strlen(buffer);
    }

    // Store the command output
    strcat(buffer, "\"");
    strcat(buffer, json_escape_str(line+13+strlen(table)+9, esc_buffer));
    strcat(buffer, "\"");
  }

  // Terminate the JSON array
  if (!first) {
    strcat(buffer, "], ");
  }

  strcat(buffer, "\"stage\": \"end\", ");

  // Check the close status of the process, and return the combined error status
  if (pclose(fp) || error) {
    strcat(buffer, "\"returnValue\": false}");
  }
  else {
    strcat(buffer, "\"returnValue\": true}");
  }

  // fprintf(stderr, "Message is %s\n", buffer);

  // Return the results to webOS.
  if (!LSMessageRespond(message, buffer, &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #22
0
bool getSysLibVer(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("getSysLibVer");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #23
0
//
// Impersonate a call to the requested service and return the output to webOS.
//
bool impersonate_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  bool retVal;
  LSError lserror;
  LSErrorInit(&lserror);
  LSMessageRef(message);

  if (access_denied(message)) return true;

  // Extract the method argument from the message
  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *id = json_find_first_label(object, "id");               
  if (!id || (id->child->type != JSON_STRING)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing id\"}",
			&lserror)) goto error;
    return true;
  }

  // Extract the service argument from the message
  object = json_parse_document(LSMessageGetPayload(message));
  json_t *service = json_find_first_label(object, "service");               
  if (!service || (service->child->type != JSON_STRING)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing service\"}",
			&lserror)) goto error;
    return true;
  }

  // Extract the method argument from the message
  object = json_parse_document(LSMessageGetPayload(message));
  json_t *method = json_find_first_label(object, "method");               
  if (!method || (method->child->type != JSON_STRING)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing method\"}",
			&lserror)) goto error;
    return true;
  }

  // Extract the params argument from the message
  object = json_parse_document(LSMessageGetPayload(message));
  json_t *params = json_find_first_label(object, "params");               
  if (!params || (params->child->type != JSON_OBJECT)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing params\"}",
			&lserror)) goto error;
    return true;
  }

  char uri[MAXLINLEN];
  sprintf(uri, "palm://%s/%s", service->child->text, method->child->text);

  char *paramstring = NULL;
  json_tree_to_string (params->child, &paramstring);
  if (!LSCallFromApplication(priv_serviceHandle, uri, paramstring, id->child->text,
			     impersonate_handler, message, NULL, &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #24
0
bool getMatchInfo(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("getMatchInfo");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #25
0
//
// Get the listing of a directory, and return it's contents.
//
bool get_dir_listing_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  char buffer[MAXBUFLEN];
  char esc_buffer[MAXBUFLEN];

  struct dirent *ep;

  // Local buffer to hold each line of output from ls
  char line[MAXLINLEN];

  // Is this the first line of output?
  bool first = true;

  // Was there an error in accessing any of the files?
  bool error = false;

  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *id = json_find_first_label(object, "directory");

  if (!id || (id->child->type != JSON_STRING) || (strspn(id->child->text, ALLOWED_CHARS"/") != strlen(id->child->text))) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Invalid or missing directory\"}",
			&lserror)) goto error;
  }

  // Start execution of the command to list the directory contents
  DIR *dp = opendir(id->child->text);

  // If the command cannot be started
  if (!dp) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, \"errorText\": \"Unable to open directory\"}",
			&lserror)) goto error;

    // The error report has been sent, so return to webOS.
    return true;
  }

  // Initialise the output message.
  strcpy(buffer, "{");

  // Loop through the list of directory entries.
  while (ep = readdir(dp)) {

    // Start or continue the JSON array
    if (first) {
      strcat(buffer, "\"contents\": [");
      first = false;
    }
    else {
      strcat(buffer, ", ");
    }

    strcat(buffer, "{\"name\":\"");
    strcat(buffer, json_escape_str(ep->d_name, esc_buffer));
    strcat(buffer, "\", ");

    strcat(buffer, "\"type\":\"");
    if (ep->d_type == DT_DIR) {
      strcat(buffer, "directory");
    }
    else if (ep->d_type == DT_REG) {
      strcat(buffer, "file");
    }
    else if (ep->d_type == DT_LNK) {
      strcat(buffer, "symlink");
    }
    else {
      strcat(buffer, "other");
    }
    strcat(buffer, "\"}");
  }

  // Terminate the JSON array
  if (!first) {
    strcat(buffer, "], ");
  }

  // Check the close status of the process, and return the combined error status
  if (closedir(dp) || error) {
    strcat(buffer, "\"returnValue\": false}");
  }
  else {
    strcat(buffer, "\"returnValue\": true}");
  }

  // Return the results to webOS.
  if (!LSMessageRespond(message, buffer, &lserror)) goto error;

  return true;
 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}
예제 #26
0
bool hsEnd(LSHandle *handle, LSMessage *msg, void *ctx)
{
	puts("hsEnd");
	LSMessageRespond(msg, "{\"returnValue\": true}", NULL);
	return true;
}
예제 #27
0
bool get_file_method(LSHandle* lshandle, LSMessage *message, void *ctx) {
  LSError lserror;
  LSErrorInit(&lserror);

  char run_command_buffer[MAXBUFLEN];
  char command[MAXLINLEN];

  json_t *object = json_parse_document(LSMessageGetPayload(message));
  json_t *id;

  // Extract the filename argument from the message
  id = json_find_first_label(object, "filename");
  if (!id || (id->child->type != JSON_STRING) ||
      (strlen(id->child->text) >= MAXNAMLEN) ||
      (strspn(id->child->text, ALLOWED_CHARS) != strlen(id->child->text))) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, "
			"\"errorText\": \"Invalid or missing filename parameter\", "
			"\"stage\": \"failed\"}",
			&lserror)) goto error;
    return true;
  }
  char filename[MAXNAMLEN];
  sprintf(filename, "/media/internal/.temp/%s", id->child->text);

  // Extract the url argument from the message
  id = json_find_first_label(object, "url");               
  if (!id || (id->child->type != JSON_STRING) ||
      (strlen(id->child->text) >= MAXLINLEN)) {
    if (!LSMessageRespond(message,
			"{\"returnValue\": false, \"errorCode\": -1, "
			"\"errorText\": \"Invalid or missing url parameter\", "
			"\"stage\": \"failed\"}",
			&lserror)) goto error;
    return true;
  }
  char url[MAXLINLEN];
  strcpy(url, id->child->text);

  if (!strncmp(url, "file://", 7)) {
    strcpy(filename, url+7);
  }
  else {

    /* Download the package */

    snprintf(command, MAXLINLEN,
	     "/usr/bin/curl --create-dirs --insecure --location --fail --show-error --output %s %s 2>&1", filename, url);

    strcpy(run_command_buffer, "{\"stdOut\": [");
    if (run_command(command, true, run_command_buffer)) {
      strcat(run_command_buffer, "], \"returnValue\": true, \"stage\": \"download\"}");
      if (!LSMessageRespond(message, run_command_buffer, &lserror)) goto error;
    }
    else {
      strcat(run_command_buffer, "]");
      if (!report_command_failure(message, command, run_command_buffer+11, "\"stage\": \"failed\"")) goto end;
      return true;
    }
  }

  return read_file(message, filename, true);

 error:
  LSErrorPrint(&lserror, stderr);
  LSErrorFree(&lserror);
 end:
  return false;
}