diff --git a/iOS/FlipperKit/FlipperClient.mm b/iOS/FlipperKit/FlipperClient.mm index 415cedb72..df9bcd00c 100644 --- a/iOS/FlipperKit/FlipperClient.mm +++ b/iOS/FlipperKit/FlipperClient.mm @@ -18,7 +18,7 @@ #import "FlipperClient+Testing.h" #if !TARGET_OS_SIMULATOR -//#import +#import #endif using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin; @@ -28,7 +28,8 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin; folly::ScopedEventBaseThread sonarThread; folly::ScopedEventBaseThread connectionThread; #if !TARGET_OS_SIMULATOR - // FKPortForwardingServer *_server; + FKPortForwardingServer *_secureServer; + FKPortForwardingServer *_insecureServer; #endif } @@ -119,9 +120,12 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin; - (void)start; { #if !TARGET_OS_SIMULATOR - // _server = [FKPortForwardingServer new]; - // [_server forwardConnectionsFromPort:8088]; - // [_server listenForMultiplexingChannelOnPort:8078]; + _secureServer = [FKPortForwardingServer new]; + [_secureServer forwardConnectionsFromPort:8088]; + [_secureServer listenForMultiplexingChannelOnPort:8078]; + _insecureServer = [FKPortForwardingServer new]; + [_insecureServer forwardConnectionsFromPort:8089]; + [_insecureServer listenForMultiplexingChannelOnPort:8079]; #endif _cppClient->start(); } @@ -131,8 +135,10 @@ using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin; { _cppClient->stop(); #if !TARGET_OS_SIMULATOR - // [_server close]; - // _server = nil; + [_secureServer close]; + _secureServer = nil; + [_insecureServer close]; + _insecureServer = nil; #endif } diff --git a/src/devices/IOSDevice.js b/src/devices/IOSDevice.js index 7e52adac1..0d013ddec 100644 --- a/src/devices/IOSDevice.js +++ b/src/devices/IOSDevice.js @@ -55,6 +55,9 @@ export default class IOSDevice extends BaseDevice { } startLogListener(retries: number = 3) { + if (this.deviceType === 'physical') { + return; + } if (retries === 0) { console.error('Attaching iOS log listener continuously failed.'); return; diff --git a/src/dispatcher/iOSDevice.js b/src/dispatcher/iOSDevice.js index 5aebb97f7..6eb390510 100644 --- a/src/dispatcher/iOSDevice.js +++ b/src/dispatcher/iOSDevice.js @@ -5,13 +5,18 @@ * @format */ +import type {ChildProcess} from 'child_process'; import type {Store} from '../reducers/index.js'; import type Logger from '../fb-stubs/Logger.js'; +import type {DeviceType} from '../devices/BaseDevice'; import {promisify} from 'util'; +import path from 'path'; import child_process from 'child_process'; -const execFile = promisify(child_process.execFile); +const execFile = child_process.execFile; import IOSDevice from '../devices/IOSDevice'; +import iosUtil from '../fb-stubs/iOSContainerUtility'; +import isProduction from '../utils/isProduction.js'; type iOSSimulatorDevice = {| state: 'Booted' | 'Shutdown' | 'Shutting Down', @@ -21,66 +26,106 @@ type iOSSimulatorDevice = {| udid: string, |}; -type IOSDeviceMap = {[id: string]: Array}; +type IOSDeviceParams = {udid: string, type: DeviceType, name: string}; -function querySimulatorDevices(store: Store): Promise { +const portforwardingClient = isProduction() + ? path.resolve( + __dirname, + 'PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp', + ) + : 'PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp'; + +function forwardPort(port: number, multiplexChannelPort: number) { + return execFile(portforwardingClient, [ + `-portForward=${port}`, + `-multiplexChannelPort=${multiplexChannelPort}`, + ]); +} +// start port forwarding server for real device connections +const portForwarders: Array = [ + forwardPort(8089, 8079), + forwardPort(8088, 8078), +]; +window.addEventListener('beforeunload', () => { + portForwarders.forEach(process => process.kill()); +}); + +function queryDevices(store: Store): Promise { const {connections} = store.getState(); + const currentDeviceIDs: Set = new Set( + connections.devices + .filter(device => device instanceof IOSDevice) + .map(device => device.serial), + ); + return Promise.all([getActiveSimulators(), getActiveDevices()]) + .then(([a, b]) => a.concat(b)) + .then(activeDevices => { + for (const {udid, type, name} of activeDevices) { + if (currentDeviceIDs.has(udid)) { + currentDeviceIDs.delete(udid); + } else { + store.dispatch({ + type: 'REGISTER_DEVICE', + payload: new IOSDevice(udid, type, name), + }); + } + } - return execFile('xcrun', ['simctl', 'list', 'devices', '--json'], { + if (currentDeviceIDs.size > 0) { + store.dispatch({ + type: 'UNREGISTER_DEVICES', + payload: currentDeviceIDs, + }); + } + }); +} + +function getActiveSimulators(): Promise> { + return promisify(execFile)('xcrun', ['simctl', 'list', 'devices', '--json'], { encoding: 'utf8', }) .then(({stdout}) => JSON.parse(stdout).devices) - .then((simulatorDevices: IOSDeviceMap) => { + .then(simulatorDevices => { const simulators: Array = Object.values( simulatorDevices, // $FlowFixMe ).reduce((acc, cv) => acc.concat(cv), []); - const currentDeviceIDs: Set = new Set( - connections.devices - .filter(device => device instanceof IOSDevice) - .map(device => device.serial), - ); - - const deviceIDsToRemove = new Set(); - simulators.forEach((simulator: iOSSimulatorDevice) => { - const isRunning = - simulator.state === 'Booted' && - // For some users "availability" is set, for others it's "isAvailable" - // It's not clear which key is set, so we are checking both. - (simulator.availability === '(available)' || - simulator.isAvailable === 'YES'); - - if (isRunning && !currentDeviceIDs.has(simulator.udid)) { - // create device - store.dispatch({ - type: 'REGISTER_DEVICE', - payload: new IOSDevice(simulator.udid, 'emulator', simulator.name), - }); - } else if (!isRunning && currentDeviceIDs.has(simulator.udid)) { - deviceIDsToRemove.add(simulator.udid); - // delete device - } - }); - - if (deviceIDsToRemove.size > 0) { - store.dispatch({ - type: 'UNREGISTER_DEVICES', - payload: deviceIDsToRemove, + return simulators + .filter( + simulator => + simulator.state === 'Booted' && + // For some users "availability" is set, for others it's "isAvailable" + // It's not clear which key is set, so we are checking both. + (simulator.availability === '(available)' || + simulator.isAvailable === 'YES'), + ) + .map(simulator => { + return { + udid: simulator.udid, + type: 'emulator', + name: simulator.name, + }; }); - } }); } +function getActiveDevices(): Promise> { + return iosUtil.targets().catch(e => { + console.warn(e); + return []; + }); +} + export default (store: Store, logger: Logger) => { // monitoring iOS devices only available on MacOS. if (process.platform !== 'darwin') { return; } - querySimulatorDevices(store) + queryDevices(store) .then(() => { const simulatorUpdateInterval = setInterval(() => { - querySimulatorDevices(store).catch(err => { + queryDevices(store).catch(err => { console.error(err); clearInterval(simulatorUpdateInterval); }); diff --git a/src/fb-stubs/iOSContainerUtility.js b/src/fb-stubs/iOSContainerUtility.js new file mode 100644 index 000000000..da78d4ffe --- /dev/null +++ b/src/fb-stubs/iOSContainerUtility.js @@ -0,0 +1,47 @@ +/** + * Copyright 2018-present Facebook. + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * @format + */ + +const errorMessage = 'Physical iOS devices not yet supported'; + +export type DeviceTarget = { + udid: string, + type: 'physical' | 'emulator', + name: string, +}; + +function isAvailable(): boolean { + return false; +} + +function targets(): Promise> { + return Promise.reject(errorMessage); +} + +function push( + udid: string, + src: string, + bundleId: string, + dst: string, +): Promise { + return Promise.reject(errorMessage); +} + +function pull( + udid: string, + src: string, + bundleId: string, + dst: string, +): Promise { + return Promise.reject(errorMessage); +} + +export default { + isAvailable: isAvailable, + targets: targets, + push: push, + pull: pull, +}; diff --git a/src/reducers/connections.js b/src/reducers/connections.js index 199590660..0ddb1b6ad 100644 --- a/src/reducers/connections.js +++ b/src/reducers/connections.js @@ -301,8 +301,10 @@ export default function reducer( case 'CLIENT_SETUP_ERROR': { const {payload} = action; + const errorMessage = + payload.error instanceof Error ? payload.error.message : payload.error; console.error( - new RecurringError(`Client setup error: ${payload.error.message}`), + new RecurringError(`Client setup error: ${errorMessage}`), `${payload.client.os}:${payload.client.deviceName}:${ payload.client.appName }`, @@ -313,10 +315,11 @@ export default function reducer( .map( c => isEqual(c.client, payload.client) - ? {...c, error: payload.error.message} + ? {...c, error: errorMessage} : c, ) .sort((a, b) => a.client.appName.localeCompare(b.client.appName)), + error: `Client setup error: ${errorMessage}`, }; } default: diff --git a/src/server.js b/src/server.js index 46176e4ad..db17a24f8 100644 --- a/src/server.js +++ b/src/server.js @@ -148,22 +148,6 @@ export default class Server extends EventEmitter { }; this.emit('start-client-setup', client); - if ( - clientData.os === 'iOS' && - !clientData.device.toLowerCase().includes('simulator') - ) { - this.emit( - 'error', - new Error( - "Flipper doesn't currently support physical iOS devices. You can still use it to view logs, but for now to use the majority of the Flipper plugins you'll have to use the Simulator.", - ), - ); - console.warn( - 'Physical iOS device detected. This is not currently supported by Flipper.', - 'server', - ); - } - return { requestResponse: (payload: {data: string}) => { if (typeof payload.data !== 'string') { diff --git a/src/utils/CertificateProvider.js b/src/utils/CertificateProvider.js index 709a4e91d..45ec3eb69 100644 --- a/src/utils/CertificateProvider.js +++ b/src/utils/CertificateProvider.js @@ -8,6 +8,8 @@ import LogManager from '../fb-stubs/Logger'; import {RecurringError} from './errors'; import {promisify} from 'util'; +import child_process from 'child_process'; +const exec = promisify(child_process.exec); const fs = require('fs'); const adb = require('adbkit-fb'); import { @@ -15,7 +17,10 @@ import { isInstalled as opensslInstalled, } from './openssl-wrapper-with-promises'; const path = require('path'); -const tmpFile = promisify(require('tmp').file); +const tmp = require('tmp'); +const tmpFile = promisify(tmp.file); +const tmpDir = promisify(tmp.dir); +import iosUtil from '../fb-stubs/iOSContainerUtility'; // Desktop file paths const os = require('os'); @@ -121,15 +126,7 @@ export default class CertificateProvider { if (os === 'Android') { return this.getTargetAndroidDeviceId(appName, appDirectory, csr); } else if (os === 'iOS') { - const matches = /\/Devices\/([^/]+)\//.exec(appDirectory); - if (matches === null || matches.length < 2) { - return Promise.reject( - new Error( - `iOS simulator directory doesn't match expected format: ${appDirectory}`, - ), - ); - } - return Promise.resolve(matches[1]); + return this.getTargetiOSDeviceId(appName, appDirectory, csr); } return Promise.resolve('unknown'); } @@ -169,6 +166,14 @@ export default class CertificateProvider { }); } + getRelativePathInAppContainer(absolutePath: string) { + const matches = /Application\/[^/]+\/(.*)/.exec(absolutePath); + if (matches && matches.length === 2) { + return matches[1]; + } + throw new Error("Path didn't match expected pattern: " + absolutePath); + } + deployFileToMobileApp( destination: string, filename: string, @@ -176,8 +181,9 @@ export default class CertificateProvider { csr: string, os: string, ): Promise { + const appNamePromise = this.extractAppNameFromCSR(csr); + if (os === 'Android') { - const appNamePromise = this.extractAppNameFromCSR(csr); const deviceIdPromise = appNamePromise.then(app => this.getTargetAndroidDeviceId(app, destination, csr), ); @@ -192,22 +198,54 @@ export default class CertificateProvider { ); } if (os === 'iOS' || os === 'windows') { - return new Promise((resolve, reject) => { - fs.writeFile(destination + filename, contents, err => { - if (err) { - reject( - `Invalid appDirectory recieved from ${os} device: ${destination}: ` + - err.toString(), + return promisify(fs.writeFile)(destination + filename, contents).catch( + err => { + if (os === 'iOS') { + // Writing directly to FS failed. It's probably a physical device. + const relativePathInsideApp = this.getRelativePathInAppContainer( + destination, ); - } else { - resolve(); + return appNamePromise + .then(appName => + this.getTargetiOSDeviceId(appName, destination, csr), + ) + .then(udid => { + return appNamePromise.then(appName => + this.pushFileToiOSDevice( + udid, + appName, + relativePathInsideApp, + filename, + contents, + ), + ); + }); } - }); - }); + throw new Error( + `Invalid appDirectory recieved from ${os} device: ${destination}: ` + + err.toString(), + ); + }, + ); } return Promise.reject(new RecurringError(`Unsupported device os: ${os}`)); } + pushFileToiOSDevice( + udid: string, + bundleId: string, + destination: string, + filename: string, + contents: string, + ): Promise { + return tmpDir({unsafeCleanup: true}).then(dir => { + const filePath = path.resolve(dir, filename); + promisify(fs.writeFile)(filePath, contents).then(() => + iosUtil.push(udid, filePath, bundleId, destination), + ); + }); + } + getTargetAndroidDeviceId( appName: string, deviceCsrFilePath: string, @@ -215,10 +253,6 @@ export default class CertificateProvider { ): Promise { return this.adb.listDevices().then((devices: Array<{id: string}>) => { const deviceMatchList = devices.map(device => - // To find out which device requested the cert, search them - // all for a matching csr file. - // It's not important to keep these secret from other apps. - // Just need to make sure each app can find its own one. this.androidDeviceHasMatchingCSR( deviceCsrFilePath, device.id, @@ -248,6 +282,39 @@ export default class CertificateProvider { }); } + getTargetiOSDeviceId( + appName: string, + deviceCsrFilePath: string, + csr: string, + ): Promise { + const matches = /\/Devices\/([^/]+)\//.exec(deviceCsrFilePath); + if (matches && matches.length == 2) { + // It's a simulator, the deviceId is in the filepath. + return Promise.resolve(matches[1]); + } + return iosUtil.targets().then(targets => { + const deviceMatchList = targets.map(target => + this.iOSDeviceHasMatchingCSR( + deviceCsrFilePath, + target.udid, + appName, + csr, + ).then(isMatch => { + return {id: target.udid, isMatch}; + }), + ); + return Promise.all(deviceMatchList).then(devices => { + const matchingIds = devices.filter(m => m.isMatch).map(m => m.id); + if (matchingIds.length == 0) { + throw new RecurringError( + `No matching device found for app: ${appName}`, + ); + } + return matchingIds[0]; + }); + }); + } + androidDeviceHasMatchingCSR( directory: string, deviceId: string, @@ -273,6 +340,42 @@ export default class CertificateProvider { }); } + iOSDeviceHasMatchingCSR( + directory: string, + deviceId: string, + bundleId: string, + csr: string, + ): Promise { + const originalFile = this.getRelativePathInAppContainer( + path.resolve(directory, csrFileName), + ); + return tmpDir({unsafeCleanup: true}) + .then(dir => { + return iosUtil + .pull(deviceId, originalFile, bundleId, dir) + .then(() => dir); + }) + .then(dir => { + return promisify(fs.readdir)(dir) + .then(items => { + if (items.length !== 1) { + throw new Error('Conflict in temp dir'); + } + return items[0]; + }) + .then(fileName => { + const copiedFile = path.resolve(dir, fileName); + return promisify(fs.readFile)(copiedFile).then(data => + data + .toString() + .replace(/\r/g, '') + .trim(), + ); + }); + }) + .then(csrFromDevice => csrFromDevice === csr.replace(/\r/g, '').trim()); + } + pushFileToAndroidDevice( deviceId: string, app: string, diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/CocoaAsyncSocketMac b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/CocoaAsyncSocketMac new file mode 100755 index 000000000..8917be44d Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/CocoaAsyncSocketMac differ diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Resources/Info.plist new file mode 100644 index 000000000..9e893f549 --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + English + CFBundleExecutable + CocoaAsyncSocketMac + CFBundleIdentifier + com.robbiehanson.CocoaAsyncSocketMac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + CocoaAsyncSocketMac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/CocoaAsyncSocketMac b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/CocoaAsyncSocketMac new file mode 100755 index 000000000..8917be44d Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/CocoaAsyncSocketMac differ diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..9e893f549 --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/CocoaAsyncSocketMac.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,44 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + English + CFBundleExecutable + CocoaAsyncSocketMac + CFBundleIdentifier + com.robbiehanson.CocoaAsyncSocketMac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + CocoaAsyncSocketMac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/FBPortForwarding-Mac b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/FBPortForwarding-Mac new file mode 100755 index 000000000..901b31192 Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/FBPortForwarding-Mac differ diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Resources/Info.plist new file mode 100644 index 000000000..a0e8d7ec9 --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Resources/Info.plist @@ -0,0 +1,46 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + en + CFBundleExecutable + FBPortForwarding-Mac + CFBundleIdentifier + com.facebook.FBPortForwarding-Mac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + FBPortForwarding-Mac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/FBPortForwarding-Mac b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/FBPortForwarding-Mac new file mode 100755 index 000000000..901b31192 Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/FBPortForwarding-Mac differ diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..a0e8d7ec9 --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/FBPortForwarding-Mac.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,46 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + en + CFBundleExecutable + FBPortForwarding-Mac + CFBundleIdentifier + com.facebook.FBPortForwarding-Mac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + FBPortForwarding-Mac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Resources/Info.plist new file mode 100644 index 000000000..f66988b1e --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Resources/Info.plist @@ -0,0 +1,46 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + en + CFBundleExecutable + peertalkMac + CFBundleIdentifier + com.facebook.peertalkMac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + peertalkMac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/Resources/Info.plist b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..f66988b1e --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,46 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + en + CFBundleExecutable + peertalkMac + CFBundleIdentifier + com.facebook.peertalkMac + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + peertalkMac + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + NSHumanReadableCopyright + Copyright © 2014 Facebook. All rights reserved. + + diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/peertalkMac b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/peertalkMac new file mode 100755 index 000000000..291ebf9aa Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/Versions/A/peertalkMac differ diff --git a/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/peertalkMac b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/peertalkMac new file mode 100755 index 000000000..291ebf9aa Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/Frameworks/peertalkMac.framework/peertalkMac differ diff --git a/static/PortForwardingMacApp.app/Contents/Info.plist b/static/PortForwardingMacApp.app/Contents/Info.plist new file mode 100644 index 000000000..5a3dc25fd --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/Info.plist @@ -0,0 +1,50 @@ + + + + + BuildMachineOSBuild + 16G29 + CFBundleDevelopmentRegion + en + CFBundleExecutable + PortForwardingMacApp + CFBundleIdentifier + com.facebook.PortForwardingMacApp + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + PortForwardingMacApp + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 9A235 + DTPlatformVersion + GM + DTSDKBuild + 17A360 + DTSDKName + macosx10.13 + DTXcode + 0900 + DTXcodeBuild + 9A235 + LSMinimumSystemVersion + 10.10 + NSHumanReadableCopyright + Copyright © 2013-present Facebook. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/static/PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp b/static/PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp new file mode 100755 index 000000000..8b1ee87b2 Binary files /dev/null and b/static/PortForwardingMacApp.app/Contents/MacOS/PortForwardingMacApp differ diff --git a/static/PortForwardingMacApp.app/Contents/PkgInfo b/static/PortForwardingMacApp.app/Contents/PkgInfo new file mode 100644 index 000000000..bd04210fb --- /dev/null +++ b/static/PortForwardingMacApp.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPL???? \ No newline at end of file