summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AFC.c106
-rw-r--r--src/AFC.h40
-rw-r--r--src/Makefile.am4
-rw-r--r--src/NotificationProxy.c263
-rw-r--r--src/NotificationProxy.h31
-rw-r--r--src/usbmux.c7
6 files changed, 432 insertions, 19 deletions
diff --git a/src/AFC.c b/src/AFC.c
index 67d37f3..dfe8af7 100644
--- a/src/AFC.c
+++ b/src/AFC.c
@@ -178,7 +178,7 @@ static int dispatch_AFC_packet(iphone_afc_client_t client, const char *data, int
log_debug_msg("dispatch_AFC_packet: sent the first now go with the second\n");
log_debug_msg("Length: %i\n", length - offset);
log_debug_msg("Buffer: \n");
- log_debug_msg(data + offset);
+ log_debug_buffer(data + offset, length - offset);
iphone_mux_send(client->connection, data + offset, length - offset, &bytes);
return bytes;
@@ -916,6 +916,63 @@ iphone_error_t iphone_afc_close_file(iphone_afc_client_t client, iphone_afc_file
return IPHONE_E_SUCCESS;
}
+/** Locks or unlocks a file on the phone.
+ *
+ * makes use of flock, see
+ * http://developer.apple.com/documentation/Darwin/Reference/ManPages/man2/flock.2.html
+ *
+ * operation (same as in sys/file.h on linux):
+ *
+ * LOCK_SH 1 // shared lock
+ * LOCK_EX 2 // exclusive lock
+ * LOCK_NB 4 // don't block when locking
+ * LOCK_UN 8 // unlock
+ *
+ * @param client The client to close the file with.
+ * @param file A pointer to an AFCFile struct containing the file handle of the
+ * file to close.
+ * @operation the lock or unlock operation to perform.
+ */
+iphone_error_t iphone_afc_lock_file(iphone_afc_client_t client, iphone_afc_file_t file, int operation)
+{
+ if (!client || !file)
+ return IPHONE_E_INVALID_ARG;
+ char *buffer = malloc(16);
+ uint32_t zero = 0;
+ int bytes = 0;
+ uint64_t op = operation;
+
+ afc_lock(client);
+
+ log_debug_msg("afc_lock_file: File handle %i\n", file->filehandle);
+
+ // Send command
+ memcpy(buffer, &file->filehandle, sizeof(uint32_t));
+ memcpy(buffer + sizeof(uint32_t), &zero, sizeof(zero));
+ memcpy(buffer + 8, &op, 8);
+
+ client->afc_packet->operation = AFC_FILE_LOCK;
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ bytes = dispatch_AFC_packet(client, buffer, 15);
+ free(buffer);
+ buffer = NULL;
+
+ if (bytes <= 0) {
+ afc_unlock(client);
+ log_debug_msg("fuck\n");
+ return IPHONE_E_UNKNOWN_ERROR;
+ }
+ // Receive the response
+ bytes = receive_AFC_data(client, &buffer);
+ log_debug_msg("%s: receiving response (%d bytes)\n", __func__, bytes);
+ if (buffer) {
+ log_debug_buffer(buffer, bytes);
+ free(buffer);
+ }
+ afc_unlock(client);
+ return IPHONE_E_SUCCESS;
+}
+
/** Seeks to a given position of a pre-opened file on the phone.
*
* @param client The client to use to seek to the position.
@@ -1016,6 +1073,53 @@ iphone_error_t iphone_afc_truncate_file(iphone_afc_client_t client, iphone_afc_f
}
}
+/** Sets the size of a file on the phone without prior opening it.
+ *
+ * @param client The client to use to set the file size.
+ * @param path The path of the file to be truncated.
+ * @param newsize The size to set the file to.
+ *
+ * @return IPHONE_E_SUCCESS if everything went well, IPHONE_E_INVALID_ARG
+ * if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
+ */
+iphone_error_t iphone_afc_truncate(iphone_afc_client_t client, const char *path, off_t newsize)
+{
+ char *response = NULL;
+ char *send = (char *) malloc(sizeof(char) * (strlen(path) + 1 + 8));
+ int bytes = 0;
+ uint64_t size_requested = newsize;
+
+ if (!client || !path || !client->afc_packet || !client->connection)
+ return IPHONE_E_INVALID_ARG;
+
+ afc_lock(client);
+
+ // Send command
+ memcpy(send, &size_requested, 8);
+ memcpy(send + 8, path, strlen(path) + 1);
+ client->afc_packet->entire_length = client->afc_packet->this_length = 0;
+ client->afc_packet->operation = AFC_TRUNCATE;
+ bytes = dispatch_AFC_packet(client, send, 8 + strlen(path));
+ free(send);
+ if (bytes <= 0) {
+ afc_unlock(client);
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ }
+ // Receive response
+ bytes = receive_AFC_data(client, &response);
+ if (response)
+ free(response);
+
+ afc_unlock(client);
+
+ if (bytes < 0) {
+ return IPHONE_E_NOT_ENOUGH_DATA;
+ } else {
+ return IPHONE_E_SUCCESS;
+ }
+}
+
+
uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file)
{
return file->filehandle;
diff --git a/src/AFC.h b/src/AFC.h
index 5e4d17c..90b406a 100644
--- a/src/AFC.h
+++ b/src/AFC.h
@@ -58,20 +58,34 @@ struct iphone_afc_file_int {
enum {
AFC_ERROR = 0x00000001,
- AFC_GET_INFO = 0x0000000a,
- AFC_GET_DEVINFO = 0x0000000b,
- AFC_LIST_DIR = 0x00000003,
- AFC_MAKE_DIR = 0x00000009,
- AFC_DELETE = 0x00000008,
- AFC_RENAME = 0x00000018,
AFC_SUCCESS_RESPONSE = 0x00000002,
- AFC_FILE_OPEN = 0x0000000d,
- AFC_FILE_CLOSE = 0x00000014,
- AFC_FILE_SEEK = 0x00000011,
- AFC_FILE_TRUNCATE = 0x00000015,
- AFC_FILE_HANDLE = 0x0000000e,
- AFC_READ = 0x0000000f,
- AFC_WRITE = 0x00000010
+ AFC_LIST_DIR = 0x00000003, // ReadDir
+ // 0x00000004 // ReadFile
+ // 0x00000005 // WriteFile
+ // 0x00000006 // WritePart
+ AFC_TRUNCATE = 0x00000007, // Truncate
+ AFC_DELETE = 0x00000008, // RemovePath
+ AFC_MAKE_DIR = 0x00000009, // MakeDir
+ AFC_GET_INFO = 0x0000000a, // GetFileInfo
+ AFC_GET_DEVINFO = 0x0000000b, // GetDeviceInfo
+ // 0x0000000c // same as 5, but writes to temp file, then renames it.
+ AFC_FILE_OPEN = 0x0000000d, // FileRefOpen
+ AFC_FILE_HANDLE = 0x0000000e, // _unknownPacket
+ AFC_READ = 0x0000000f, // FileRefRead
+ AFC_WRITE = 0x00000010, // FileRefWrite
+ AFC_FILE_SEEK = 0x00000011, // FileRefSeek
+ AFC_FILE_TELL = 0x00000012, // FileRefTell
+ // 0x00000013 // _unknownPacket
+ AFC_FILE_CLOSE = 0x00000014, // FileRefClose
+ AFC_FILE_TRUNCATE = 0x00000015, // FileRefSetFileSize (ftruncate)
+ // 0x00000016 // SetFatalError
+ // 0x00000017 // SetConnectionOptions
+ AFC_RENAME = 0x00000018, // RenamePath
+ // 0x00000019 // SetFSBlockSize (0x800000)
+ // 0x0000001A // SetBlockSize (0x800000)
+ AFC_FILE_LOCK = 0x0000001B, // FileRefLock
+ AFC_MAKE_LINK = 0x0000001C // MakeLink
};
+
uint32_t iphone_afc_get_file_handle(iphone_afc_file_t file);
diff --git a/src/Makefile.am b/src/Makefile.am
index 039632f..71667ae 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
INCLUDES = -I$(top_srcdir)/include
-AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) -g
+AM_CFLAGS = $(GLOBAL_CFLAGS) $(libusb_CFLAGS) $(libglib2_CFLAGS) $(libgnutls_CFLAGS) $(libtasn1_CFLAGS) $(libgthread2_CFLAGS) $(libplist_CFLAGS) $(LFS_CFLAGS)
AM_LDFLAGS = $(libusb_LIBS) $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_LIBS) $(libplist_LIBS)
bin_PROGRAMS = libiphone-initconf
@@ -12,4 +12,4 @@ libiphone_initconf_LDFLAGS = $(libgthread2_LIBS) $(AM_LDFLAGS)
lib_LTLIBRARIES = libiphone.la
-libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c userpref.c utils.c MobileSync.c
+libiphone_la_SOURCES = usbmux.c iphone.c lockdown.c AFC.c NotificationProxy.c userpref.c utils.c MobileSync.c
diff --git a/src/NotificationProxy.c b/src/NotificationProxy.c
new file mode 100644
index 0000000..eec7857
--- /dev/null
+++ b/src/NotificationProxy.c
@@ -0,0 +1,263 @@
+/*
+ * NotificationProxy.c
+ * Notification Proxy implementation.
+ *
+ * Copyright (c) 2009 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <plist/plist.h>
+#include "NotificationProxy.h"
+#include "utils.h"
+
+/** Locks an NP client, done for thread safety stuff.
+ *
+ * @param client The NP
+ */
+static void np_lock(iphone_np_client_t client)
+{
+ log_debug_msg("NP: Locked\n");
+ g_mutex_lock(client->mutex);
+}
+
+/** Unlocks an NP client, done for thread safety stuff.
+ *
+ * @param client The NP
+ */
+static void np_unlock(iphone_np_client_t client)
+{
+ log_debug_msg("NP: Unlocked\n");
+ g_mutex_unlock(client->mutex);
+}
+
+/** Makes a connection to the NP service on the phone.
+ *
+ * @param phone The iPhone to connect on.
+ * @param s_port The source port.
+ * @param d_port The destination port.
+ *
+ * @return A handle to the newly-connected client or NULL upon error.
+ */
+iphone_error_t iphone_np_new_client ( iphone_device_t device, int src_port, int dst_port, iphone_np_client_t *client )
+{
+ int ret = IPHONE_E_SUCCESS;
+
+ //makes sure thread environment is available
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ iphone_np_client_t client_loc = (iphone_np_client_t) malloc(sizeof(struct iphone_np_client_int));
+
+ if (!device)
+ return IPHONE_E_INVALID_ARG;
+
+ // Attempt connection
+ client_loc->connection = NULL;
+ ret = iphone_mux_new_client(device, src_port, dst_port, &client_loc->connection);
+ if (IPHONE_E_SUCCESS != ret || !client_loc->connection) {
+ free(client_loc);
+ return ret;
+ }
+
+ client_loc->mutex = g_mutex_new();
+
+ *client = client_loc;
+ return IPHONE_E_SUCCESS;
+}
+
+/** Disconnects an NP client from the phone.
+ *
+ * @param client The client to disconnect.
+ */
+iphone_error_t iphone_np_free_client ( iphone_np_client_t client )
+{
+ if (!client || !client->connection )
+ return IPHONE_E_INVALID_ARG;
+
+ iphone_mux_free_client(client->connection);
+ free(client);
+ return IPHONE_E_SUCCESS;
+}
+
+/** Sends a notification to the NP client.
+ *
+ * notification messages seen so far:
+ * com.apple.itunes-mobdev.syncWillStart
+ * com.apple.itunes-mobdev.syncDidStart
+ *
+ * @param client The client to send to
+ * @param notification The notification Message
+ */
+iphone_error_t iphone_np_post_notification( iphone_np_client_t client, const char *notification )
+{
+ char *XML_content = NULL;
+ uint32_t length = 0;
+ int bytes = 0;
+ iphone_error_t ret;
+ unsigned char sndbuf[4096];
+ int sndlen = 0;
+ int nlen = 0;
+ plist_t dict = NULL;
+
+ if (!client || !notification) {
+ return IPHONE_E_INVALID_ARG;
+ }
+ np_lock(client);
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "PostNotification");
+ plist_add_sub_key_el(dict, "Name");
+ plist_add_sub_string_el(dict, notification);
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen += 4;
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen += length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "Shutdown");
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen+=4;
+
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen+=length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ log_debug_buffer(sndbuf, sndlen);
+
+ iphone_mux_send(client->connection, sndbuf, sndlen, &bytes);
+ if (bytes <= 0) {
+ np_unlock(client);
+ return bytes;
+ }
+
+ np_unlock(client);
+ return bytes;
+}
+
+/** Notifies the iphone to send a notification on certain events.
+ *
+ * observation messages seen so far:
+ * com.apple.itunes-client.syncCancelRequest
+ * com.apple.itunes-client.syncSuspendRequest
+ * com.apple.itunes-client.syncResumeRequest
+ * com.apple.mobile.lockdown.phone_number_changed
+ * com.apple.mobile.lockdown.device_name_changed
+ * com.apple.springboard.attemptactivation
+ * com.apple.mobile.data_sync.domain_changed
+ * com.apple.mobile.application_installed
+ * com.apple.mobile.application_uninstalled
+ *
+ * @param client The client to send to
+ */
+iphone_error_t iphone_np_observe_notification( iphone_np_client_t client )
+{
+ plist_t dict = NULL;
+ char *XML_content = NULL;
+ uint32_t length = 0;
+ int bytes = 0;
+ iphone_error_t ret;
+ unsigned char sndbuf[4096];
+ int sndlen = 0;
+ int nlen = 0;
+ int i=0;
+ const char *notifications[10] = {
+ "com.apple.itunes-client.syncCancelRequest",
+ "com.apple.itunes-client.syncSuspendRequest",
+ "com.apple.itunes-client.syncResumeRequest",
+ "com.apple.mobile.lockdown.phone_number_changed",
+ "com.apple.mobile.lockdown.device_name_changed",
+ "com.apple.springboard.attemptactivation",
+ "com.apple.mobile.data_sync.domain_changed",
+ "com.apple.mobile.application_installed",
+ "com.apple.mobile.application_uninstalled",
+ NULL};
+
+ sndlen = 0;
+
+ if (!client) {
+ return IPHONE_E_INVALID_ARG;
+ }
+ np_lock(client);
+
+ while (notifications[i]) {
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "ObserveNotification");
+ plist_add_sub_key_el(dict, "Name");
+ plist_add_sub_string_el(dict, notifications[i++]);
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen += 4;
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen += length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+ }
+
+ dict = plist_new_dict();
+ plist_add_sub_key_el(dict, "Command");
+ plist_add_sub_string_el(dict, "Shutdown");
+ plist_to_xml(dict, &XML_content, &length);
+
+ nlen = htonl(length);
+
+ memcpy(sndbuf+sndlen, &nlen, 4);
+ sndlen+=4;
+
+ memcpy(sndbuf+sndlen, XML_content, length);
+ sndlen+=length;
+
+ plist_free(dict);
+ dict = NULL;
+ free(XML_content);
+ XML_content = NULL;
+
+ log_debug_buffer(sndbuf, sndlen);
+
+ iphone_mux_send(client->connection, sndbuf, sndlen, &bytes);
+ if (bytes <= 0) {
+ np_unlock(client);
+ return bytes;
+ }
+
+ np_unlock(client);
+ return bytes;
+}
diff --git a/src/NotificationProxy.h b/src/NotificationProxy.h
new file mode 100644
index 0000000..57ad751
--- /dev/null
+++ b/src/NotificationProxy.h
@@ -0,0 +1,31 @@
+/*
+ * NotificationProxy.h
+ * Notification Proxy header file.
+ *
+ * Copyright (c) 2009 Nikias Bassen, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "libiphone/libiphone.h"
+#include "usbmux.h"
+#include "iphone.h"
+
+#include <glib.h>
+
+struct iphone_np_client_int {
+ iphone_umux_client_t connection;
+ GMutex *mutex;
+};
+
diff --git a/src/usbmux.c b/src/usbmux.c
index 5eaa1d1..22ce588 100644
--- a/src/usbmux.c
+++ b/src/usbmux.c
@@ -309,7 +309,8 @@ iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t
}
// Since we were able to fill the data straight from our buffer, we can just return datalen. See 2a above.
- return datalen;
+ *recv_bytes = datalen;
+ return IPHONE_E_SUCCESS;
} else {
memcpy(data, client->recv_buffer, client->r_len);
free(client->recv_buffer); // don't need to deal with anymore, but...
@@ -362,10 +363,10 @@ iphone_error_t iphone_mux_recv(iphone_umux_client_t client, char *data, uint32_t
if ((bytes - 28) > datalen) {
// Copy what we need into the data, buffer the rest because we can.
memcpy(data + offset, buffer + 28, datalen); // data+offset: see #2b, above
- complex = client->r_len + (bytes - 28) - datalen;
+ complex = client->r_len + ((bytes - 28) - datalen);
client->recv_buffer = (char *) realloc(client->recv_buffer, (sizeof(char) * complex));
client->r_len = complex;
- complex = client->r_len - (bytes - 28) - datalen;
+ complex = client->r_len - ((bytes - 28) - datalen);
memcpy(client->recv_buffer + complex, buffer + 28 + datalen, (bytes - 28) - datalen);
free(buffer);
client->header->ocnt += bytes - 28;