/** * Get a parameter at |index| as an int. * @param[in] params The parameter array. * @param[in] index The index in |params| to get. * @param[out] out_file The output int32_t. * @param[out] out_error An error message, if this operation failed. * @return int 0 if successful, otherwise 1. */ static int GetParamInt(struct PP_Var params, uint32_t index, int32_t* out_int, const char** out_error) { struct PP_Var value = g_ppb_var_array->Get(params, index); if (value.type != PP_VARTYPE_INT32) { *out_error = PrintfToNewString("Expected param at index %d to be an int32", index); return 1; } *out_int = value.value.as_int; return 0; }
/** * Handle a call to closedir() made by JavaScript. * * closedir expects 1 parameter: * 0: The index of the directory (which is mapped to a DIR*) * on success, closedir returns a result in |output|: * 0: "closedir" * 1: the name of the directory * on failure, closedir returns an error string in |out_error|. */ int HandleClosedir(struct PP_Var params, struct PP_Var* output, const char** out_error) { #if defined(WIN32) *out_error = PrintfToNewString("Win32 does not support closedir"); return 1; #else CHECK_PARAM_COUNT(closedir, 1); PARAM_DIR(0, dir); int result = closedir(dir); if (result) { *out_error = PrintfToNewString("closedir returned error %d", result); return 1; } RemoveDirFromMap(dir_index); CREATE_RESPONSE(closedir); RESPONSE_INT(dir_index); return 0; #endif }
/** * Get a parameter at |index| as a string. * @param[in] params The parameter array. * @param[in] index The index in |params| to get. * @param[out] out_string The output string. * @param[out] out_string_len The length of the output string. * @param[out] out_error An error message, if this operation failed. * @return int 0 if successful, otherwise 1. */ static int GetParamString(struct PP_Var params, uint32_t index, char** out_string, uint32_t* out_string_len, const char** out_error) { if (index >= MAX_PARAMS) { *out_error = PrintfToNewString("Param index %u >= MAX_PARAMS (%d)", index, MAX_PARAMS); return 1; } struct PP_Var value = g_ppb_var_array->Get(params, index); if (value.type != PP_VARTYPE_STRING) { *out_error = PrintfToNewString("Expected param at index %d to be a string not.%d", index,value.type); return 1; } uint32_t length; const char* var_str = g_ppb_var->VarToUtf8(value, &length); char* string = (char*)malloc(length + 1); memcpy(string, var_str, length); string[length] = 0; /* Put the allocated string in g_ParamStrings. This keeps us from leaking * each parameter string, without having to do manual cleanup in every * Handle* function below. */ free(g_ParamStrings[index]); g_ParamStrings[index] = string; *out_string = string; *out_string_len = length; return 0; }
/** * Handle a call to connect() made by JavaScript. * * connect expects 2 parameters: * 0: The hostname to connect to. * 1: The port number to connect to. * on success, connect returns a result in |output|: * 0: "connect" * 1: The socket file descriptor. * on failure, connect returns an error string in |out_error|. */ int HandleConnect(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(connect, 2); PARAM_STRING(0, hostname); PARAM_INT(1, port); // Lookup host struct hostent* hostent = gethostbyname(hostname); if (hostent == NULL) { *out_error = PrintfToNewString("gethostbyname() returned error: %d", errno); return 1; } struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); addr.sin_family = AF_INET; addr.sin_port = htons(port); memcpy(&addr.sin_addr.s_addr, hostent->h_addr_list[0], hostent->h_length); int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { *out_error = PrintfToNewString("socket() failed: %s", strerror(errno)); return 1; } int result = connect(sock, (struct sockaddr*)&addr, addrlen); if (result != 0) { *out_error = PrintfToNewString("connect() failed: %s", strerror(errno)); close(sock); return 1; } CREATE_RESPONSE(connect); RESPONSE_INT(sock); return 0; }
/** * Handle a call to fread() made by JavaScript. * * fread expects 2 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: The number of bytes to read from the file. * on success, fread returns a result in |output| separated by \1: * 0: "fread" * 1: the file index * 2: the data read from the file * on failure, fread returns an error string in |output|. * * @param[in] num_params The number of params in |params|. * @param[in] params An array of strings, parameters to this function. * @param[out] output A string to write informational function output to. * @return An errorcode; 0 means success, anything else is a failure. */ int HandleFread(int num_params, char** params, char** output) { FILE* file; const char* file_index_string; char* buffer; size_t data_len; size_t bytes_read; if (num_params != 2) { *output = PrintfToNewString("Error: fread takes 2 parameters."); return 1; } file_index_string = params[0]; file = GetFileFromIndexString(file_index_string, NULL); data_len = strtol(params[1], NULL, 10); if (!file) { *output = PrintfToNewString("Error: Unknown file handle %s.", file_index_string); return 2; } buffer = (char*)malloc(data_len + 1); bytes_read = fread(buffer, 1, data_len, file); buffer[bytes_read] = 0; if (ferror(file)) { *output = PrintfToNewString( "Error: Read %d bytes, but ferror() returns true.", bytes_read); return 3; } *output = PrintfToNewString("fread\1%s\1%s", file_index_string, buffer); free(buffer); return 0; }
/** * Append a PP_Var to the response dictionary. * @param[in,out] response_var The response PP_var. * @param[in] value The value to add to the response args. * @param[out] out_error An error message, if this call failed. */ static void AppendResponseVar(struct PP_Var* response_var, struct PP_Var value, const char** out_error) { struct PP_Var args_value = GetDictVar(*response_var, "args"); uint32_t args_length = g_ppb_var_array->GetLength(args_value); PP_Bool result = g_ppb_var_array->Set(args_value, args_length, value); if (!result) { // Release the dictionary that was there before. g_ppb_var->Release(*response_var); // Return an error message instead. *response_var = PP_MakeUndefined(); *out_error = PrintfToNewString("Unable to append value to result"); return; } }
/** * Handle a call to getcwd() made by JavaScript. * * getcwd expects 0 parameters. * on success, getcwd returns a result in |output|: * 0: "getcwd" * 1: the current working directory * on failure, getcwd returns an error string in |out_error|. */ int HandleGetcwd(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(getcwd, 0); char cwd[PATH_MAX]; char* result = getcwd(cwd, PATH_MAX); if (result == NULL) { *out_error = PrintfToNewString("getcwd returned error: %d", errno); return 1; } CREATE_RESPONSE(getcwd); RESPONSE_STRING(cwd); return 0; }
/** * Handle a call to close() made by JavaScript. * * close expects 1 parameters: * 0: The socket file descriptor to close. * on success, close returns a result in |output|: * 0: "close" * 1: The socket file descriptor closed. * on failure, close returns an error string in |out_error|. */ int HandleClose(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(close, 1); PARAM_INT(0, sock); int result = close(sock); if (result != 0) { *out_error = PrintfToNewString("close returned error: %d", errno); return 1; } CREATE_RESPONSE(close); RESPONSE_INT(sock); return 0; }
/** * Handle a call to chdir() made by JavaScript. * * chdir expects 1 parameter: * 0: The name of the directory * on success, chdir returns a result in |output|: * 0: "chdir" * 1: the name of the directory * on failure, chdir returns an error string in |out_error|. */ int HandleChdir(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(chdir, 1); PARAM_STRING(0, dirname); int result = chdir(dirname); if (result != 0) { *out_error = PrintfToNewString("chdir returned error: %d", errno); return 1; } CREATE_RESPONSE(chdir); RESPONSE_STRING(dirname); return 0; }
/** * Handle a call to send() made by JavaScript. * * send expects 2 parameters: * 0: The socket file descriptor to send using. * 1: The NULL terminated string to send. * on success, send returns a result in |output|: * 0: "send" * 1: The number of bytes sent. * on failure, send returns an error string in |out_error|. */ int HandleSend(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(send, 2); PARAM_INT(0, sock); PARAM_STRING(1, buffer); int result = (int32_t)send(sock, buffer, strlen(buffer), 0); if (result <= 0) { *out_error = PrintfToNewString("send failed: %s", strerror(errno)); return 1; } CREATE_RESPONSE(send); RESPONSE_INT(result); return 0; }
/** * Handle a call to fclose() made by JavaScript. * * fclose expects 1 parameter: * 0: The index of the file (which is mapped to a FILE*) * on success, fclose returns a result in |output|: * 0: "fclose" * 1: the file index * on failure, fclose returns an error string in |out_error|. */ int HandleFclose(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(fclose, 1); PARAM_FILE(0, file); int result = fclose(file); if (result) { *out_error = PrintfToNewString("fclose returned error %d", result); return 1; } RemoveFileFromMap(file_index); CREATE_RESPONSE(fclose); RESPONSE_INT(file_index); return 0; }
/** * Handle a call to fwrite() made by JavaScript. * * fwrite expects 2 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: A string to write to the file * on success, fwrite returns a result in |output|: * 0: "fwrite" * 1: the file index * 2: the number of bytes written * on failure, fwrite returns an error string in |out_error|. */ int HandleFwrite(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(fwrite, 2); PARAM_FILE(0, file); PARAM_STRING(1, data); size_t bytes_written = fwrite(data, 1, data_len, file); if (ferror(file)) { *out_error = PrintfToNewString( "Wrote %" PRIuS " bytes, but ferror() returns true", bytes_written); return 1; } CREATE_RESPONSE(fwrite); RESPONSE_INT(file_index); RESPONSE_INT((int32_t)bytes_written); return 0; }
/** * Handle a call to stat() made by JavaScript. * * stat expects 1 parameter: * 0: The name of the file * on success, stat returns a result in |output|: * 0: "stat" * 1: the file name * 2: the size of the file * on failure, stat returns an error string in |out_error|. */ int HandleStat(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(stat, 1); PARAM_STRING(0, filename); struct stat buf; memset(&buf, 0, sizeof(buf)); int result = stat(filename, &buf); if (result == -1) { *out_error = PrintfToNewString("stat returned error %d", errno); return 1; } CREATE_RESPONSE(stat); RESPONSE_STRING(filename); RESPONSE_INT((int32_t)buf.st_size); return 0; }
/** * Handle a call to readdir() made by JavaScript. * * readdir expects 1 parameter: * 0: The index of the directory (which is mapped to a DIR*) * on success, opendir returns a result in |output|: * 0: "readdir" * 1: the inode number of the entry * 2: the name of the entry * if there are no more entries, |output| contains: * 0: "readdir" * on failure, readdir returns an error string in |out_error|. */ int HandleReaddir(struct PP_Var params, struct PP_Var* output, const char** out_error) { #if defined(WIN32) *out_error = PrintfToNewString("Win32 does not support readdir"); return 1; #else CHECK_PARAM_COUNT(readdir, 1); PARAM_DIR(0, dir); struct dirent* entry = readdir(dir); CREATE_RESPONSE(readdir); RESPONSE_INT(dir_index); if (entry != NULL) { RESPONSE_INT((int32_t)entry->d_ino); RESPONSE_STRING(entry->d_name); } return 0; #endif }
/** * Handle a call to fread() made by JavaScript. * * fread expects 2 parameters: * 0: The index of the file (which is mapped to a FILE*) * 1: The number of bytes to read from the file. * on success, fread returns a result in |output|: * 0: "fread" * 1: the file index * 2: the data read from the file * on failure, fread returns an error string in |out_error|. */ int HandleFread(struct PP_Var params, struct PP_Var* output, const char** out_error) { CHECK_PARAM_COUNT(fread, 2); PARAM_FILE(0, file); PARAM_INT(1, data_len); char* buffer = (char*)malloc(data_len + 1); size_t bytes_read = fread(buffer, 1, data_len, file); buffer[bytes_read] = 0; if (ferror(file)) { *out_error = PrintfToNewString( "Read %" PRIuS " bytes, but ferror() returns true", bytes_read); free(buffer); return 1; } CREATE_RESPONSE(fread); RESPONSE_INT(file_index); RESPONSE_STRING(buffer); free(buffer); return 0; }