From 5b4622f661c00e55c8f0b33180f18382e21d7ca3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 22 May 2015 22:36:50 -0400 Subject: [PATCH] initial commit --- .gitignore | 1 + Makefile | 23 +++ images/icon-128x128.png | Bin 0 -> 8780 bytes images/icon-48x48.png | Bin 0 -> 2930 bytes images/icon.svg | 174 +++++++++++++++++++ images/tile-small.png | Bin 0 -> 29403 bytes js/common.js | 6 + js/launcher.js | 6 + js/main.js | 243 +++++++++++++++++++++++++++ js/net_error_list.js | 361 ++++++++++++++++++++++++++++++++++++++++ main.html | 118 +++++++++++++ makedist.sh | 52 ++++++ manifest.files | 7 + manifest.json | 26 +++ 14 files changed, 1017 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 images/icon-128x128.png create mode 100644 images/icon-48x48.png create mode 100644 images/icon.svg create mode 100644 images/tile-small.png create mode 100644 js/common.js create mode 100644 js/launcher.js create mode 100644 js/main.js create mode 100644 js/net_error_list.js create mode 100644 main.html create mode 100755 makedist.sh create mode 100644 manifest.files create mode 100644 manifest.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4c4ffc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5e88047 --- /dev/null +++ b/Makefile @@ -0,0 +1,23 @@ +CLOSURE = closure-compiler --language_in ECMASCRIPT5 +YUICOMPRESSOR = yuicompressor + +all: + +%.js.min: %.js + $(CLOSURE) $< > $@ + +JS_FILES = $(shell grep '[.]js$$' manifest.files) +js-min: $(JS_FILES:=.min) + +%.css.min: %.css + $(YUICOMPRESSOR) $< > $@ + +CSS_FILES = $(shell grep '[.]css$$' manifest.files) +css-min: $(CSS_FILES:=.min) + +check: css-min js-min + +dist: + ./makedist.sh + +.PHONY: all clean check css-min dist js-min diff --git a/images/icon-128x128.png b/images/icon-128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..c1bf91bf7133ba3ea6fc0e07f1ccbd23a57ee49f GIT binary patch literal 8780 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 + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/tile-small.png b/images/tile-small.png new file mode 100644 index 0000000000000000000000000000000000000000..833d8c999318b37cc0325450cac3e4ba89ade2d7 GIT binary patch literal 29403 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. +// Released into the public domain. + +function $(s) { return document.querySelectorAll(s); } +function $$(s) { return document.querySelector(s); } +function nullcb() {} diff --git a/js/launcher.js b/js/launcher.js new file mode 100644 index 0000000..3dbd4ac --- /dev/null +++ b/js/launcher.js @@ -0,0 +1,6 @@ +// Written by Mike Frysinger . +// Released into the public domain. + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('main.html') +}); diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..b6ce2a9 --- /dev/null +++ b/js/main.js @@ -0,0 +1,243 @@ +// Written by Mike Frysinger . +// Released into the public domain. + +function status(msg) { + $$('[name=status]').innerText = msg; +} + +// Create a packet following the spec: +// https://en.wikipedia.org/wiki/Wake-on-LAN#Magic_packet +function magicpacket(mac, pass) { + var data = new ArrayBuffer(6 + 16 * 6 + 6 + 6); + var bytes = new Uint8Array(data); + var i, j, base = 0; + + // First 6 bytes should be all 0xFF. + for (i = 0; i < 6; ++i) + bytes[base + i] = 0xff; + base += 6; + + // Then the MAC address is repeated 16 times. + for (i = 0; i < 6; ++i) + for (j = 0; j < 16 * 6; j += 6) + bytes[base + j + i] = mac[i]; + base += 16 * 6; + + // Then 6 bytes before the pass should be 0xFF. + for (i = 0; i < 6; ++i) + bytes[base + i] = 0xff; + base += 6; + + // Finally the 6 bytes of the password. + for (i = 0; i < 6; ++i) + bytes[base + i] = pass[i]; + + return data; +} + +function split_data(v) { + var data = Array(6); + var i, idata; + + window['sync_' + v](); + + for (i = 0; i < 6; ++i) { + idata = $$('input[name=' + v + i + ']'); + if (!/^[0-9a-fA-F]?[0-9a-fA-F]$/.test(idata.value.replace(' ', ''))) { + status(v + ' byte ' + i + ' is invalid; must be 2 hex characters'); + idata.focus(); + idata.setSelectionRange(0, idata.value.length); + return false; + } + data[i] = parseInt(idata.value, 16); + } + + return data; +} + +function send() { + status('initializing'); + + var form = $$('form[name=settings]'); + var shost = '0.0.0.0'; + var dhost = form.host.value; + var port = parseInt(form.port.value); + + // Get the MAC address & password to convert to packet data. + var mac = split_data('mac'); + var pass = split_data('pass'); + var data = magicpacket(mac, pass); + console.log('packet', new Uint8Array(data)); + + var checkresult = function(s, step, result) { + if (result < 0) { + status('error in ' + step + ': ' + net_error_list[result]); + chrome.sockets.udp.close(s, nullcb); + return false; + } + return true; + }; + + // Create the socket ... + chrome.sockets.udp.create({}, function(createInfo) { + var s = createInfo.socketId; + + console.log('[create] socketInfo', createInfo); + status('binding ' + shost); + + // Bind it locally ... + chrome.sockets.udp.bind(s, shost, 0, function(result) { + console.log('[bind] result', result); + + if (!checkresult(s, 'bind', result)) + return false; + + status('enabling broadcast'); + + // Turn on broadcast support ... + chrome.sockets.udp.setBroadcast(s, true, function(result) { + console.log('[setBroadcast] result', result); + + if (!checkresult(s, 'broadcast', result)) + return false; + + status('sending to ' + dhost + ':' + port); + + // Send the backet ... + chrome.sockets.udp.send(s, data, dhost, port, function(sendInfo) { + console.log('[send] sendInfo', sendInfo); + + if (!checkresult(s, 'send', sendInfo.resultCode)) + return false; + + status('closing'); + + // Shut it down ... + chrome.sockets.udp.close(s, function() { + status('sent to ' + dhost + ':' + port); + store_settings(); + }); + }); + }); + }); + }); + + // Keep the form from submitting. + return false; +} + +function sync_it(v) { + var smany = $$('span[name=' + v + '-many]'); + var sone = $$('span[name=' + v + '-one]'); + + // Sync the two sets of fields. + var i; + if (smany.hidden) { + var idata = $$('input[name=' + v + ']'); + var data = idata.value.split(':'); + + if (data.length != 6) { + data = idata.value.replace(/[ :]/g, ''); + if (data.length != 6 * 2) { + status('invalid ' + v + '; please fix'); + return false; + } + data = data.match(/../g); + } else { + for (i = 0; i < 6; ++i) + if (data[i].length > 2) { + status('invalid ' + v + ' please fix'); + return false; + } + } + + for (i = 0; i < 6; ++i) + $$('input[name=' + v + i + ']').value = data[i]; + } else { + var data = ''; + + for (i = 0; i < 6; ++i) { + data += $$('input[name=' + v + i + ']').value; + if (i < 5) + data += ':'; + } + + $$('input[name=' + v + ']').value = data; + } +} +function sync_mac() { return sync_it('mac'); } +function sync_pass() { return sync_it('pass'); } + + +function paste_mac() { + sync_mac(); + + var smany = $$('span[name=mac-many]'); + var sone = $$('span[name=mac-one]'); + smany.hidden = !smany.hidden; + sone.hidden = !sone.hidden; + + return false; +} + +function paste_pass() { + sync_pass(); + + var smany = $$('span[name=pass-many]'); + var sone = $$('span[name=pass-one]'); + smany.hidden = !smany.hidden; + sone.hidden = !sone.hidden; + + return false; +} + +/* + * Storage logic. + */ +var settings_keys = [ + 'host', + 'mac', + 'pass', + 'port', +]; + +function load_settings() { + var storage = chrome.storage.local; + + chrome.storage.local.get(settings_keys, function(settings) { + var form = $$('form[name=settings]'); + form.host.value = settings['host'] || '192.168.0.255'; + form.port.value = settings['port'] || '40000'; + // We assume we only get called during init. + paste_mac(); + form.mac.value = settings['mac'] || '20:00:00:00:00:00'; + paste_mac(); + paste_pass(); + form.pass.value = settings['pass'] || '00:00:00:00:00:00'; + paste_pass(); + }); +} + +function store_settings() { + var form = $$('form[name=settings]'); + sync_mac(); + sync_pass(); + var settings = { + 'host': form.host.value, + 'mac': form.mac.value, + 'pass': form.pass.value, + 'port': form.port.value, + }; + chrome.storage.local.set(settings); +} + +/* + * Startup. + */ +window.onload = function() { + $$('form[name=settings]').onsubmit = send; + $$('a[name=mac-paste]').onclick = paste_mac; + $$('a[name=pass-paste]').onclick = paste_pass; + + load_settings(); +}; diff --git a/js/net_error_list.js b/js/net_error_list.js new file mode 100644 index 0000000..7a13d9f --- /dev/null +++ b/js/net_error_list.js @@ -0,0 +1,361 @@ +/* Auto-generated from chromium/src/net/base/net_error_list.h; do not edit. */ + +var net_error_list = { + "-1": "IO_PENDING", + "-2": "FAILED", + "-3": "ABORTED", + "-4": "INVALID_ARGUMENT", + "-5": "INVALID_HANDLE", + "-6": "FILE_NOT_FOUND", + "-7": "TIMED_OUT", + "-8": "FILE_TOO_BIG", + "-9": "UNEXPECTED", + "-10": "ACCESS_DENIED", + "-11": "NOT_IMPLEMENTED", + "-12": "INSUFFICIENT_RESOURCES", + "-13": "OUT_OF_MEMORY", + "-14": "UPLOAD_FILE_CHANGED", + "-15": "SOCKET_NOT_CONNECTED", + "-16": "FILE_EXISTS", + "-17": "FILE_PATH_TOO_LONG", + "-18": "FILE_NO_SPACE", + "-19": "FILE_VIRUS_INFECTED", + "-20": "BLOCKED_BY_CLIENT", + "-21": "NETWORK_CHANGED", + "-22": "BLOCKED_BY_ADMINISTRATOR", + "-23": "SOCKET_IS_CONNECTED", + "-100": "CONNECTION_CLOSED", + "-101": "CONNECTION_RESET", + "-102": "CONNECTION_REFUSED", + "-103": "CONNECTION_ABORTED", + "-104": "CONNECTION_FAILED", + "-105": "NAME_NOT_RESOLVED", + "-106": "INTERNET_DISCONNECTED", + "-107": "SSL_PROTOCOL_ERROR", + "-108": "ADDRESS_INVALID", + "-109": "ADDRESS_UNREACHABLE", + "-110": "SSL_CLIENT_AUTH_CERT_NEEDED", + "-111": "TUNNEL_CONNECTION_FAILED", + "-112": "NO_SSL_VERSIONS_ENABLED", + "-113": "SSL_VERSION_OR_CIPHER_MISMATCH", + "-114": "SSL_RENEGOTIATION_REQUESTED", + "-115": "PROXY_AUTH_UNSUPPORTED", + "-116": "CERT_ERROR_IN_SSL_RENEGOTIATION", + "-117": "BAD_SSL_CLIENT_AUTH_CERT", + "-118": "CONNECTION_TIMED_OUT", + "-119": "HOST_RESOLVER_QUEUE_TOO_LARGE", + "-120": "SOCKS_CONNECTION_FAILED", + "-121": "SOCKS_CONNECTION_HOST_UNREACHABLE", + "-122": "NPN_NEGOTIATION_FAILED", + "-123": "SSL_NO_RENEGOTIATION", + "-124": "WINSOCK_UNEXPECTED_WRITTEN_BYTES", + "-125": "SSL_DECOMPRESSION_FAILURE_ALERT", + "-126": "SSL_BAD_RECORD_MAC_ALERT", + "-127": "PROXY_AUTH_REQUESTED", + "-128": "SSL_UNSAFE_NEGOTIATION", + "-129": "SSL_WEAK_SERVER_EPHEMERAL_DH_KEY", + "-130": "PROXY_CONNECTION_FAILED", + "-131": "MANDATORY_PROXY_CONFIGURATION_FAILED", + "-133": "PRECONNECT_MAX_SOCKET_LIMIT", + "-134": "SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED", + "-135": "SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY", + "-136": "PROXY_CERTIFICATE_INVALID", + "-137": "NAME_RESOLUTION_FAILED", + "-138": "NETWORK_ACCESS_DENIED", + "-139": "TEMPORARILY_THROTTLED", + "-140": "HTTPS_PROXY_TUNNEL_RESPONSE", + "-141": "SSL_CLIENT_AUTH_SIGNATURE_FAILED", + "-142": "MSG_TOO_BIG", + "-143": "SPDY_SESSION_ALREADY_EXISTS", + "-145": "WS_PROTOCOL_ERROR", + "-146": "PROTOCOL_SWITCHED", + "-147": "ADDRESS_IN_USE", + "-148": "SSL_HANDSHAKE_NOT_COMPLETED", + "-149": "SSL_BAD_PEER_PUBLIC_KEY", + "-150": "SSL_PINNED_KEY_NOT_IN_CERT_CHAIN", + "-151": "CLIENT_AUTH_CERT_TYPE_UNSUPPORTED", + "-152": "ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH", + "-153": "SSL_DECRYPT_ERROR_ALERT", + "-154": "WS_THROTTLE_QUEUE_TOO_LARGE", + "-155": "TOO_MANY_SOCKET_STREAMS", + "-156": "SSL_SERVER_CERT_CHANGED", + "-157": "SSL_INAPPROPRIATE_FALLBACK", + "-158": "CT_NO_SCTS_VERIFIED_OK", + "-200": "CERT_COMMON_NAME_INVALID", + "-201": "CERT_DATE_INVALID", + "-202": "CERT_AUTHORITY_INVALID", + "-203": "CERT_CONTAINS_ERRORS", + "-204": "CERT_NO_REVOCATION_MECHANISM", + "-205": "CERT_UNABLE_TO_CHECK_REVOCATION", + "-206": "CERT_REVOKED", + "-207": "CERT_INVALID", + "-208": "CERT_WEAK_SIGNATURE_ALGORITHM", + "-210": "CERT_NON_UNIQUE_NAME", + "-211": "CERT_WEAK_KEY", + "-212": "CERT_NAME_CONSTRAINT_VIOLATION", + "-213": "CERT_END", + "-300": "INVALID_URL", + "-301": "DISALLOWED_URL_SCHEME", + "-302": "UNKNOWN_URL_SCHEME", + "-310": "TOO_MANY_REDIRECTS", + "-311": "UNSAFE_REDIRECT", + "-312": "UNSAFE_PORT", + "-320": "INVALID_RESPONSE", + "-321": "INVALID_CHUNKED_ENCODING", + "-322": "METHOD_NOT_SUPPORTED", + "-323": "UNEXPECTED_PROXY_AUTH", + "-324": "EMPTY_RESPONSE", + "-325": "RESPONSE_HEADERS_TOO_BIG", + "-326": "PAC_STATUS_NOT_OK", + "-327": "PAC_SCRIPT_FAILED", + "-328": "REQUEST_RANGE_NOT_SATISFIABLE", + "-329": "MALFORMED_IDENTITY", + "-330": "CONTENT_DECODING_FAILED", + "-331": "NETWORK_IO_SUSPENDED", + "-332": "SYN_REPLY_NOT_RECEIVED", + "-333": "ENCODING_CONVERSION_FAILED", + "-334": "UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT", + "-335": "INVALID_SPDY_STREAM", + "-336": "NO_SUPPORTED_PROXIES", + "-337": "SPDY_PROTOCOL_ERROR", + "-338": "INVALID_AUTH_CREDENTIALS", + "-339": "UNSUPPORTED_AUTH_SCHEME", + "-340": "ENCODING_DETECTION_FAILED", + "-341": "MISSING_AUTH_CREDENTIALS", + "-342": "UNEXPECTED_SECURITY_LIBRARY_STATUS", + "-343": "MISCONFIGURED_AUTH_ENVIRONMENT", + "-344": "UNDOCUMENTED_SECURITY_LIBRARY_STATUS", + "-345": "RESPONSE_BODY_TOO_BIG_TO_DRAIN", + "-346": "RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH", + "-347": "INCOMPLETE_SPDY_HEADERS", + "-348": "PAC_NOT_IN_DHCP", + "-349": "RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION", + "-350": "RESPONSE_HEADERS_MULTIPLE_LOCATION", + "-351": "SPDY_SERVER_REFUSED_STREAM", + "-352": "SPDY_PING_FAILED", + "-353": "PIPELINE_EVICTION", + "-354": "CONTENT_LENGTH_MISMATCH", + "-355": "INCOMPLETE_CHUNKED_ENCODING", + "-356": "QUIC_PROTOCOL_ERROR", + "-357": "RESPONSE_HEADERS_TRUNCATED", + "-358": "QUIC_HANDSHAKE_FAILED", + "-400": "CACHE_MISS", + "-401": "CACHE_READ_FAILURE", + "-402": "CACHE_WRITE_FAILURE", + "-403": "CACHE_OPERATION_NOT_SUPPORTED", + "-404": "CACHE_OPEN_FAILURE", + "-405": "CACHE_CREATE_FAILURE", + "-406": "CACHE_RACE", + "-407": "CACHE_CHECKSUM_READ_FAILURE", + "-408": "CACHE_CHECKSUM_MISMATCH", + "-501": "INSECURE_RESPONSE", + "-502": "NO_PRIVATE_KEY_FOR_CERT", + "-503": "ADD_USER_CERT_FAILED", + "-601": "FTP_FAILED", + "-602": "FTP_SERVICE_UNAVAILABLE", + "-603": "FTP_TRANSFER_ABORTED", + "-604": "FTP_FILE_BUSY", + "-605": "FTP_SYNTAX_ERROR", + "-606": "FTP_COMMAND_NOT_SUPPORTED", + "-607": "FTP_BAD_COMMAND_SEQUENCE", + "-701": "PKCS12_IMPORT_BAD_PASSWORD", + "-702": "PKCS12_IMPORT_FAILED", + "-703": "IMPORT_CA_CERT_NOT_CA", + "-704": "IMPORT_CERT_ALREADY_EXISTS", + "-705": "IMPORT_CA_CERT_FAILED", + "-706": "IMPORT_SERVER_CERT_FAILED", + "-707": "PKCS12_IMPORT_INVALID_MAC", + "-708": "PKCS12_IMPORT_INVALID_FILE", + "-709": "PKCS12_IMPORT_UNSUPPORTED", + "-710": "KEY_GENERATION_FAILED", + "-711": "ORIGIN_BOUND_CERT_GENERATION_FAILED", + "-712": "PRIVATE_KEY_EXPORT_FAILED", + "-713": "SELF_SIGNED_CERT_GENERATION_FAILED", + "-714": "CERT_DATABASE_CHANGED", + "-800": "DNS_MALFORMED_RESPONSE", + "-801": "DNS_SERVER_REQUIRES_TCP", + "-802": "DNS_SERVER_FAILED", + "-803": "DNS_TIMED_OUT", + "-804": "DNS_CACHE_MISS", + "-805": "DNS_SEARCH_EMPTY", + "-806": "DNS_SORT_ERROR", +}; + +var NET_ERR_IO_PENDING = -1; +var NET_ERR_FAILED = -2; +var NET_ERR_ABORTED = -3; +var NET_ERR_INVALID_ARGUMENT = -4; +var NET_ERR_INVALID_HANDLE = -5; +var NET_ERR_FILE_NOT_FOUND = -6; +var NET_ERR_TIMED_OUT = -7; +var NET_ERR_FILE_TOO_BIG = -8; +var NET_ERR_UNEXPECTED = -9; +var NET_ERR_ACCESS_DENIED = -10; +var NET_ERR_NOT_IMPLEMENTED = -11; +var NET_ERR_INSUFFICIENT_RESOURCES = -12; +var NET_ERR_OUT_OF_MEMORY = -13; +var NET_ERR_UPLOAD_FILE_CHANGED = -14; +var NET_ERR_SOCKET_NOT_CONNECTED = -15; +var NET_ERR_FILE_EXISTS = -16; +var NET_ERR_FILE_PATH_TOO_LONG = -17; +var NET_ERR_FILE_NO_SPACE = -18; +var NET_ERR_FILE_VIRUS_INFECTED = -19; +var NET_ERR_BLOCKED_BY_CLIENT = -20; +var NET_ERR_NETWORK_CHANGED = -21; +var NET_ERR_BLOCKED_BY_ADMINISTRATOR = -22; +var NET_ERR_SOCKET_IS_CONNECTED = -23; +var NET_ERR_CONNECTION_CLOSED = -100; +var NET_ERR_CONNECTION_RESET = -101; +var NET_ERR_CONNECTION_REFUSED = -102; +var NET_ERR_CONNECTION_ABORTED = -103; +var NET_ERR_CONNECTION_FAILED = -104; +var NET_ERR_NAME_NOT_RESOLVED = -105; +var NET_ERR_INTERNET_DISCONNECTED = -106; +var NET_ERR_SSL_PROTOCOL_ERROR = -107; +var NET_ERR_ADDRESS_INVALID = -108; +var NET_ERR_ADDRESS_UNREACHABLE = -109; +var NET_ERR_SSL_CLIENT_AUTH_CERT_NEEDED = -110; +var NET_ERR_TUNNEL_CONNECTION_FAILED = -111; +var NET_ERR_NO_SSL_VERSIONS_ENABLED = -112; +var NET_ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113; +var NET_ERR_SSL_RENEGOTIATION_REQUESTED = -114; +var NET_ERR_PROXY_AUTH_UNSUPPORTED = -115; +var NET_ERR_CERT_ERROR_IN_SSL_RENEGOTIATION = -116; +var NET_ERR_BAD_SSL_CLIENT_AUTH_CERT = -117; +var NET_ERR_CONNECTION_TIMED_OUT = -118; +var NET_ERR_HOST_RESOLVER_QUEUE_TOO_LARGE = -119; +var NET_ERR_SOCKS_CONNECTION_FAILED = -120; +var NET_ERR_SOCKS_CONNECTION_HOST_UNREACHABLE = -121; +var NET_ERR_NPN_NEGOTIATION_FAILED = -122; +var NET_ERR_SSL_NO_RENEGOTIATION = -123; +var NET_ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES = -124; +var NET_ERR_SSL_DECOMPRESSION_FAILURE_ALERT = -125; +var NET_ERR_SSL_BAD_RECORD_MAC_ALERT = -126; +var NET_ERR_PROXY_AUTH_REQUESTED = -127; +var NET_ERR_SSL_UNSAFE_NEGOTIATION = -128; +var NET_ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY = -129; +var NET_ERR_PROXY_CONNECTION_FAILED = -130; +var NET_ERR_MANDATORY_PROXY_CONFIGURATION_FAILED = -131; +var NET_ERR_PRECONNECT_MAX_SOCKET_LIMIT = -133; +var NET_ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED = -134; +var NET_ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY = -135; +var NET_ERR_PROXY_CERTIFICATE_INVALID = -136; +var NET_ERR_NAME_RESOLUTION_FAILED = -137; +var NET_ERR_NETWORK_ACCESS_DENIED = -138; +var NET_ERR_TEMPORARILY_THROTTLED = -139; +var NET_ERR_HTTPS_PROXY_TUNNEL_RESPONSE = -140; +var NET_ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED = -141; +var NET_ERR_MSG_TOO_BIG = -142; +var NET_ERR_SPDY_SESSION_ALREADY_EXISTS = -143; +var NET_ERR_WS_PROTOCOL_ERROR = -145; +var NET_ERR_PROTOCOL_SWITCHED = -146; +var NET_ERR_ADDRESS_IN_USE = -147; +var NET_ERR_SSL_HANDSHAKE_NOT_COMPLETED = -148; +var NET_ERR_SSL_BAD_PEER_PUBLIC_KEY = -149; +var NET_ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN = -150; +var NET_ERR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED = -151; +var NET_ERR_ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH = -152; +var NET_ERR_SSL_DECRYPT_ERROR_ALERT = -153; +var NET_ERR_WS_THROTTLE_QUEUE_TOO_LARGE = -154; +var NET_ERR_TOO_MANY_SOCKET_STREAMS = -155; +var NET_ERR_SSL_SERVER_CERT_CHANGED = -156; +var NET_ERR_SSL_INAPPROPRIATE_FALLBACK = -157; +var NET_ERR_CT_NO_SCTS_VERIFIED_OK = -158; +var NET_ERR_CERT_COMMON_NAME_INVALID = -200; +var NET_ERR_CERT_DATE_INVALID = -201; +var NET_ERR_CERT_AUTHORITY_INVALID = -202; +var NET_ERR_CERT_CONTAINS_ERRORS = -203; +var NET_ERR_CERT_NO_REVOCATION_MECHANISM = -204; +var NET_ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205; +var NET_ERR_CERT_REVOKED = -206; +var NET_ERR_CERT_INVALID = -207; +var NET_ERR_CERT_WEAK_SIGNATURE_ALGORITHM = -208; +var NET_ERR_CERT_NON_UNIQUE_NAME = -210; +var NET_ERR_CERT_WEAK_KEY = -211; +var NET_ERR_CERT_NAME_CONSTRAINT_VIOLATION = -212; +var NET_ERR_CERT_END = -213; +var NET_ERR_INVALID_URL = -300; +var NET_ERR_DISALLOWED_URL_SCHEME = -301; +var NET_ERR_UNKNOWN_URL_SCHEME = -302; +var NET_ERR_TOO_MANY_REDIRECTS = -310; +var NET_ERR_UNSAFE_REDIRECT = -311; +var NET_ERR_UNSAFE_PORT = -312; +var NET_ERR_INVALID_RESPONSE = -320; +var NET_ERR_INVALID_CHUNKED_ENCODING = -321; +var NET_ERR_METHOD_NOT_SUPPORTED = -322; +var NET_ERR_UNEXPECTED_PROXY_AUTH = -323; +var NET_ERR_EMPTY_RESPONSE = -324; +var NET_ERR_RESPONSE_HEADERS_TOO_BIG = -325; +var NET_ERR_PAC_STATUS_NOT_OK = -326; +var NET_ERR_PAC_SCRIPT_FAILED = -327; +var NET_ERR_REQUEST_RANGE_NOT_SATISFIABLE = -328; +var NET_ERR_MALFORMED_IDENTITY = -329; +var NET_ERR_CONTENT_DECODING_FAILED = -330; +var NET_ERR_NETWORK_IO_SUSPENDED = -331; +var NET_ERR_SYN_REPLY_NOT_RECEIVED = -332; +var NET_ERR_ENCODING_CONVERSION_FAILED = -333; +var NET_ERR_UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT = -334; +var NET_ERR_INVALID_SPDY_STREAM = -335; +var NET_ERR_NO_SUPPORTED_PROXIES = -336; +var NET_ERR_SPDY_PROTOCOL_ERROR = -337; +var NET_ERR_INVALID_AUTH_CREDENTIALS = -338; +var NET_ERR_UNSUPPORTED_AUTH_SCHEME = -339; +var NET_ERR_ENCODING_DETECTION_FAILED = -340; +var NET_ERR_MISSING_AUTH_CREDENTIALS = -341; +var NET_ERR_UNEXPECTED_SECURITY_LIBRARY_STATUS = -342; +var NET_ERR_MISCONFIGURED_AUTH_ENVIRONMENT = -343; +var NET_ERR_UNDOCUMENTED_SECURITY_LIBRARY_STATUS = -344; +var NET_ERR_RESPONSE_BODY_TOO_BIG_TO_DRAIN = -345; +var NET_ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH = -346; +var NET_ERR_INCOMPLETE_SPDY_HEADERS = -347; +var NET_ERR_PAC_NOT_IN_DHCP = -348; +var NET_ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION = -349; +var NET_ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION = -350; +var NET_ERR_SPDY_SERVER_REFUSED_STREAM = -351; +var NET_ERR_SPDY_PING_FAILED = -352; +var NET_ERR_PIPELINE_EVICTION = -353; +var NET_ERR_CONTENT_LENGTH_MISMATCH = -354; +var NET_ERR_INCOMPLETE_CHUNKED_ENCODING = -355; +var NET_ERR_QUIC_PROTOCOL_ERROR = -356; +var NET_ERR_RESPONSE_HEADERS_TRUNCATED = -357; +var NET_ERR_QUIC_HANDSHAKE_FAILED = -358; +var NET_ERR_CACHE_MISS = -400; +var NET_ERR_CACHE_READ_FAILURE = -401; +var NET_ERR_CACHE_WRITE_FAILURE = -402; +var NET_ERR_CACHE_OPERATION_NOT_SUPPORTED = -403; +var NET_ERR_CACHE_OPEN_FAILURE = -404; +var NET_ERR_CACHE_CREATE_FAILURE = -405; +var NET_ERR_CACHE_RACE = -406; +var NET_ERR_CACHE_CHECKSUM_READ_FAILURE = -407; +var NET_ERR_CACHE_CHECKSUM_MISMATCH = -408; +var NET_ERR_INSECURE_RESPONSE = -501; +var NET_ERR_NO_PRIVATE_KEY_FOR_CERT = -502; +var NET_ERR_ADD_USER_CERT_FAILED = -503; +var NET_ERR_FTP_FAILED = -601; +var NET_ERR_FTP_SERVICE_UNAVAILABLE = -602; +var NET_ERR_FTP_TRANSFER_ABORTED = -603; +var NET_ERR_FTP_FILE_BUSY = -604; +var NET_ERR_FTP_SYNTAX_ERROR = -605; +var NET_ERR_FTP_COMMAND_NOT_SUPPORTED = -606; +var NET_ERR_FTP_BAD_COMMAND_SEQUENCE = -607; +var NET_ERR_PKCS12_IMPORT_BAD_PASSWORD = -701; +var NET_ERR_PKCS12_IMPORT_FAILED = -702; +var NET_ERR_IMPORT_CA_CERT_NOT_CA = -703; +var NET_ERR_IMPORT_CERT_ALREADY_EXISTS = -704; +var NET_ERR_IMPORT_CA_CERT_FAILED = -705; +var NET_ERR_IMPORT_SERVER_CERT_FAILED = -706; +var NET_ERR_PKCS12_IMPORT_INVALID_MAC = -707; +var NET_ERR_PKCS12_IMPORT_INVALID_FILE = -708; +var NET_ERR_PKCS12_IMPORT_UNSUPPORTED = -709; +var NET_ERR_KEY_GENERATION_FAILED = -710; +var NET_ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED = -711; +var NET_ERR_PRIVATE_KEY_EXPORT_FAILED = -712; +var NET_ERR_SELF_SIGNED_CERT_GENERATION_FAILED = -713; +var NET_ERR_CERT_DATABASE_CHANGED = -714; +var NET_ERR_DNS_MALFORMED_RESPONSE = -800; +var NET_ERR_DNS_SERVER_REQUIRES_TCP = -801; +var NET_ERR_DNS_SERVER_FAILED = -802; +var NET_ERR_DNS_TIMED_OUT = -803; +var NET_ERR_DNS_CACHE_MISS = -804; +var NET_ERR_DNS_SEARCH_EMPTY = -805; +var NET_ERR_DNS_SORT_ERROR = -806; diff --git a/main.html b/main.html new file mode 100644 index 0000000..e694264 --- /dev/null +++ b/main.html @@ -0,0 +1,118 @@ + + + + + +Wake-On-Lan (WOL) + + + + + + + + +

+ + Wake-On-Lan (WOL) Magic Packet Generator + +

+ +
+
+ + + + + + + + + + + + + + + + + + + + +
+ IP + / + Hostname: +
MAC address: + + + + + + + + + + Paste +
Port:
SecureOn: + + + + + + + + + + Paste +
+ +
+
+
+ +

Status: idle

+ +
+ +

+Problems? Try +troubleshooting.
+
+Random tips (applies to all WOL and is not specific to this app):
+

    +
  • You have to be on the same local network as the target
  • +
  • i.e. You cannot wake up computers over the internet
  • +
  • WiFi computers often cannot be woken up remotely
  • +
  • WOL support has to be turned on in the BIOS/OS
  • +
  • Make sure the MAC address matches the computer
  • +
  • The SecureOn (password) is not supported by many devices;
    feel free to leave the default value
  • +
+

+ + + diff --git a/makedist.sh b/makedist.sh new file mode 100755 index 0000000..2c21c87 --- /dev/null +++ b/makedist.sh @@ -0,0 +1,52 @@ +#!/bin/bash -e +# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +case $1 in +-h|--help) + echo "Usage: $0 [rev]" + exit 0 + ;; +esac + +json_value() { + local key=$1 + sed -n -r \ + -e '/^[[:space:]]*"'"${key}"'"/s|.*:[[:space:]]*"([^"]*)",?$|\1|p' \ + manifest.json +} + +PN=$(json_value name | sed 's:[[:space:]/]:_:g' | tr '[:upper:]' '[:lower:]') +if [[ ${PN} == "__msg_name__" ]] ; then + PN=$(basename "$(pwd)") +fi +PV=$(json_value version) +rev=${1:-0} +PVR="${PV}.${rev}" +P="${PN}-${PVR}" + +rm -rf "${P}" +mkdir "${P}" + +while read line ; do + [[ ${line} == */* ]] && mkdir -p "${P}/${line%/*}" + ln "${line}" "${P}/${line}" +done < <(sed 's:#.*::' manifest.files) +cp Makefile manifest.files manifest.json "${P}/" + +make -C "${P}" -j {css,js}-min +while read line ; do + mv "${line}.min" "${line}" +done < <(find "${P}" -name '*.js' -o -name '*.css') +rm "${P}"/{manifest.files,Makefile} + +sed -i \ + -e '/"version"/s:"[^"]*",:"'${PVR}'",:' \ + "${P}/manifest.json" + +zip="${P}.zip" +rm -f "${zip}" +zip -r "${zip}" "${P}" +rm -rf "${P}" +du -b "${zip}" diff --git a/manifest.files b/manifest.files new file mode 100644 index 0000000..9deef5c --- /dev/null +++ b/manifest.files @@ -0,0 +1,7 @@ +images/icon-48x48.png +images/icon-128x128.png +js/common.js +js/launcher.js +js/main.js +js/net_error_list.js +main.html diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..90d1af0 --- /dev/null +++ b/manifest.json @@ -0,0 +1,26 @@ +{ + "manifest_version": 2, + "minimum_chrome_version": "44", + "name": "Wake-On-Lan (WOL)", + "version": "0.1", + "description": "Wake up other computers with WOL magic packets", + "icons": { + "48": "images/icon-48x48.png", + "128": "images/icon-128x128.png" + }, + "app": { + "background": { + "scripts": ["js/launcher.js"] + } + }, + "offline_enabled": true, + "permissions": [ + "storage" + ], + "sockets": { + "udp": { + "send": ["*"], + "bind": ["*"] + } + } +} -- 2.39.2