├── CaptureTool
├── VMBuffer.h
└── main.cpp
├── ChunkedBuffer.cpp
├── ChunkedBuffer.h
├── DatabaseLocker.h
├── English.lproj
├── InfoPlist.strings
└── MainMenu.xib
├── HexFiend.framework
├── Headers
├── HexFiend
├── Resources
└── Versions
│ ├── A
│ ├── Headers
│ │ ├── HFBTreeByteArray.h
│ │ ├── HFByteArray.h
│ │ ├── HFByteSlice.h
│ │ ├── HFCancelButton.h
│ │ ├── HFController.h
│ │ ├── HFFileByteSlice.h
│ │ ├── HFFileReference.h
│ │ ├── HFFullMemoryByteArray.h
│ │ ├── HFFullMemoryByteSlice.h
│ │ ├── HFFunctions.h
│ │ ├── HFHexTextRepresenter.h
│ │ ├── HFLayoutRepresenter.h
│ │ ├── HFLineCountingRepresenter.h
│ │ ├── HFProgressTracker.h
│ │ ├── HFRepresenter.h
│ │ ├── HFSharedMemoryByteSlice.h
│ │ ├── HFStatusBarRepresenter.h
│ │ ├── HFStringEncodingTextRepresenter.h
│ │ ├── HFTextField.h
│ │ ├── HFTextRepresenter.h
│ │ ├── HFTextView.h
│ │ ├── HFTypes.h
│ │ ├── HFVerticalScrollerRepresenter.h
│ │ └── HexFiend.h
│ ├── HexFiend
│ └── Resources
│ │ ├── HFCancelOff.tiff
│ │ ├── HFCancelOn.tiff
│ │ ├── HFModalProgress.nib
│ │ └── Info.plist
│ └── Current
├── LICENSE
├── PrettyCell.h
├── PrettyCell.m
├── README.md
├── Sniffer-Info.plist
├── Sniffer.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
├── SnifferCapture.h
├── SnifferCapture.mm
├── SnifferDocument.h
├── SnifferDocument.mm
├── SnifferWindowController.h
├── SnifferWindowController.mm
├── SnifferWindowController.xib
├── Sniffer_Prefix.pch
├── SpinLock.h
├── Utils.cpp
├── Utils.h
├── main.m
└── schema.sql
/CaptureTool/VMBuffer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include
17 |
18 | /**
19 | * A buffer of memory requested from the kernel. This is guaranteed to be page
20 | * aligned, but cannot be shrunk.
21 | */
22 | template
23 | class VMBuffer {
24 | public:
25 | VMBuffer(size_t initialSize = PAGE_SIZE) {
26 | Grow(initialSize);
27 | }
28 |
29 | ~VMBuffer() {
30 | vm_deallocate(mach_task_self(), mData, mSize);
31 | }
32 |
33 | /**
34 | * Expands the buffer to contain at least `newSize` bytes.
35 | *
36 | * This function has several side effects and limitations:
37 | * - the existing data pointer will be invalidated
38 | * - the new buffer is not guaranteed to be zeroed
39 | * - data will not be copied from the old buffer
40 | *
41 | * @param newSize The number of bytes the buffer needs to hold.
42 | */
43 | void Grow(size_t newSize) {
44 | if (mSize >= newSize) return;
45 |
46 | if (mData)
47 | vm_deallocate(mach_task_self(), mData, mSize);
48 |
49 | // Make sure that the requested amount of memory is page aligned.
50 | newSize += newSize % PAGE_SIZE;
51 |
52 | if (vm_allocate(mach_task_self(), &mData, newSize, VM_FLAGS_ANYWHERE) == 0) {
53 | mSize = newSize;
54 | } else {
55 | assert(0);
56 | }
57 | }
58 |
59 | T& operator[] (off_t offset) {
60 | assert(offset * sizeof(T) < mSize);
61 | return reinterpret_cast(mData)[offset];
62 | }
63 |
64 | /**
65 | * The allocated size of the buffer. This may be larger than the size requested
66 | * by Grow().
67 | */
68 | size_t Size() const {
69 | return mSize;
70 | }
71 |
72 | /**
73 | * The underlying data pointer.
74 | */
75 | T * Data() {
76 | return reinterpret_cast(mData);
77 | }
78 |
79 | private:
80 | vm_size_t mSize;
81 | vm_address_t mData;
82 | };
83 |
84 |
--------------------------------------------------------------------------------
/CaptureTool/main.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include "VMBuffer.h"
23 | #include "Utils.h"
24 |
25 | #define INVALID_PID -1
26 |
27 | static CFMessagePortRef gMessagePort;
28 |
29 | /**
30 | * Determines which process has a socket with the given endpoints. This returns
31 | * the first process found, or INVALID_PID upon failure.
32 | *
33 | * CURRENTLY ONLY HANDLES TCP/IPv4 PACKETS!
34 | */
35 | pid_t PIDForEndpoints(in_addr_t sourceAddress, int sourcePort, in_addr_t destAddress, int destPort) {
36 | // We need to call proc_listpids once to get the size of the required buffer,
37 | // then again to get the actual list.
38 | static VMBuffer pidBuffer;
39 | pidBuffer.Grow(proc_listpids(PROC_ALL_PIDS, 0, NULL, 0));
40 | int pidCount = proc_listpids(PROC_ALL_PIDS, 0, pidBuffer.Data(), pidBuffer.Size()) / sizeof(pid_t);
41 |
42 | for(int i = 0; i < pidCount; i++) {
43 | pid_t pid = pidBuffer[i];
44 |
45 | // We need to call proc_pidinfo once to get the size of the required buffer,
46 | // then again to get the actual list.
47 | static VMBuffer fdBuffer;
48 | fdBuffer.Grow(proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0));
49 | int fdCount = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdBuffer.Data(), fdBuffer.Size()) / sizeof(struct proc_fdinfo);
50 |
51 | for(int j = 0; j < fdCount; j++) {
52 | // only interested in sockets
53 | if(fdBuffer[j].proc_fdtype != PROX_FDTYPE_SOCKET) continue;
54 |
55 | // get the socket's info
56 | socket_fdinfo finfo;
57 | proc_pidfdinfo(pid, fdBuffer[j].proc_fd, PROC_PIDFDSOCKETINFO, &finfo, sizeof(finfo));
58 |
59 | // figure out this file's endpoints (holy nesting!)
60 | int fdDestPort = finfo.psi.soi_proto.pri_in.insi_fport;
61 | in_addr_t fdDestAddress = finfo.psi.soi_proto.pri_in.insi_faddr.ina_46.i46a_addr4.s_addr;
62 | int fdSourcePort = finfo.psi.soi_proto.pri_in.insi_lport;
63 | in_addr_t fdSourceAddress = finfo.psi.soi_proto.pri_in.insi_laddr.ina_46.i46a_addr4.s_addr;
64 |
65 | // see if this is our guy
66 | if((sourceAddress == fdSourceAddress && sourcePort == fdSourcePort && destAddress == fdDestAddress && destPort == fdDestPort) ||
67 | (sourceAddress == fdDestAddress && sourcePort == fdDestPort && destAddress == fdSourceAddress && destPort == fdSourcePort)) {
68 | return pid;
69 | }
70 |
71 | }
72 | }
73 |
74 | return INVALID_PID;
75 | }
76 |
77 | /**
78 | * Sends information that has been gathered about a packet to the GUI tool on the
79 | * other end of our CFMesssagePort.
80 | *
81 | * The format is:
82 | * - pcap_pkthdr
83 | * - packet data
84 | * - application path
85 | */
86 | static void SendPacketData(const char *appPath, const struct pcap_pkthdr *packHead, const u_char *packData)
87 | {
88 | static SInt32 msgid;
89 | static VMBuffer messageBuffer;
90 | messageBuffer.Grow(sizeof(pcap_pkthdr) + packHead->caplen + strlen(appPath) + 1);
91 |
92 | UInt8 *pos = messageBuffer.Data();
93 | memcpy(pos, packHead, sizeof(pcap_pkthdr));
94 | pos += sizeof(pcap_pkthdr);
95 |
96 | memcpy(pos, packData, packHead->caplen);
97 | pos += packHead->caplen;
98 |
99 | memcpy(pos, appPath, strlen(appPath) + 1);
100 | pos += strlen(appPath) + 1;
101 |
102 | CFDataRef data = CFDataCreateWithBytesNoCopy(NULL, messageBuffer.Data(), pos - messageBuffer.Data(), kCFAllocatorNull);
103 | CFMessagePortSendRequest(gMessagePort, msgid++, data, -1, -1, NULL, NULL);
104 | CFRelease(data);
105 | }
106 |
107 | /**
108 | * The libpcap callback function. Invoked every time a packet is sent/received.
109 | */
110 | void Handler(u_char *one, const struct pcap_pkthdr *packHead, const u_char *packData) {
111 | const struct ether_header *etherHeader = (const struct ether_header *)packData;
112 | const struct ip *ipHeader = (const struct ip *)(etherHeader + 1);
113 |
114 | // we can only find endpoints for TCP sockets for now
115 | if(IPPROTO_TCP == ipHeader->ip_p) {
116 | const struct tcphdr *tcpHeader = (const struct tcphdr *)(ipHeader + 1);
117 |
118 | // try to find our pid
119 | pid_t owningProcess = PIDForEndpoints(ipHeader->ip_src.s_addr, tcpHeader->th_sport, ipHeader->ip_dst.s_addr, tcpHeader->th_dport);
120 |
121 | // did we find it?
122 | if(INVALID_PID != owningProcess) {
123 | // grab the path
124 | char processPath[MAXPATHLEN] = {};
125 | proc_pidpath(owningProcess, processPath, sizeof(processPath));
126 |
127 | SendPacketData(processPath, packHead, packData);
128 | return;
129 | } else {
130 | SendPacketData("(unknown TCP)", packHead, packData);
131 | return;
132 | }
133 | }
134 |
135 | SendPacketData("(unknown other)", packHead, packData);
136 | }
137 |
138 | bool SetupCapture(const char *interface) {
139 | pcap_t *handle = pcap_open_live(interface, BUFSIZ, 1, 2, NULL);
140 | if (handle == NULL) return false;
141 |
142 | // We can't run this on the main thread because it'll block, so we need to
143 | // set it up on a background thread. I tried quite a bit to get this running
144 | // under a CFRunloop using CFFileDescriptorRef, but it just wouldn't work.
145 | //
146 | // If I ran it under libdispach directly, it worked fine (I think), but then
147 | // I couldn't get notifications about the message port being invalidated.
148 | RunBlockThreaded(^(void) {
149 | pcap_loop(handle, -1, Handler, NULL);
150 | pcap_close(handle);
151 | });
152 |
153 | return true;
154 | }
155 |
156 | void MessagePortClosed(CFMessagePortRef ms, void *info) {
157 | // FIXME: we should think about how this process should gracefully shut down.
158 | // Currently this doesn't kill the capture thread we set up or allow pcap_close
159 | // to run.
160 | //
161 | // I doubt it matters though.
162 | CFRunLoopStop(CFRunLoopGetCurrent());
163 | }
164 |
165 | int main(int argc, char *argv[]) {
166 | // The name of the message port we're supposed to be connecting to will be the
167 | // first argument passed to the program. If it's invalid or not specified,
168 | // this is a critical error and we must abort the process.
169 | if (argc >= 2) {
170 | CFStringRef portName = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8);
171 | gMessagePort = CFMessagePortCreateRemote(NULL, portName);
172 | CFRelease(portName);
173 |
174 | if (!gMessagePort) return 1;
175 | }
176 |
177 | // FIXME: don't hardcode "en1". Instead we should probably have it passed
178 | // to us in argv.
179 | if (SetupCapture("en1")) {
180 | // We need to get notified when this message port gets invalidated because
181 | // this is our signal by the parent process that capturing needs to stop.
182 | //
183 | // Since we're in CF-land and not using Mach ports directly, we need a
184 | // CFRunLoop and not dispatch_main.
185 | CFMessagePortSetInvalidationCallBack(gMessagePort, MessagePortClosed);
186 | CFRunLoopRun();
187 | return 0;
188 | }
189 |
190 | return 1;
191 | }
192 |
--------------------------------------------------------------------------------
/ChunkedBuffer.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 |
17 | #include "ChunkedBuffer.h"
18 | #include
19 |
20 | ChunkedBuffer::ChunkedBuffer(size_t chunkSize) :
21 | mChunkSize(chunkSize),
22 | mCurrentOffset(0)
23 | {
24 | mChunks.push_back(CheckedAlloc(chunkSize));
25 | }
26 |
27 | ChunkedBuffer::~ChunkedBuffer()
28 | {
29 | for (int i = 0; i < mChunks.size(); i++) {
30 | free(mChunks[i]);
31 | }
32 | }
33 |
34 | void ChunkedBuffer::AppendBytes(const void *bytes, size_t length)
35 | {
36 | while (length > mChunkSize - mCurrentOffset) {
37 | // Copy what will fit into the current chunk
38 | size_t available = mChunkSize - mCurrentOffset;
39 | memcpy(mChunks.back(), bytes, available);
40 |
41 | // Advance past the bytes we just wrote
42 | bytes = (char *)bytes + available;
43 | length -= available;
44 |
45 | // And add a new chunk to our buffer to hold what's left of this data
46 | mChunks.push_back(CheckedAlloc(mChunkSize));
47 | mCurrentOffset = 0;
48 | }
49 |
50 | memcpy(mChunks.back() + mCurrentOffset, bytes, length);
51 | mCurrentOffset += length;
52 | }
53 |
54 | void ChunkedBuffer::CopyBytes(off_t offset, size_t length, void *outBuffer) const
55 | {
56 | char *resultPtr = (char *)outBuffer;
57 |
58 | while (length) {
59 | int chunk = offset / mChunkSize;
60 | int readOffset = offset % mChunkSize;
61 | int readSize = std::min(length, mChunkSize - readOffset);
62 |
63 | memcpy(resultPtr, mChunks[chunk] + readOffset, readSize);
64 |
65 | offset = 0;
66 | resultPtr += readSize;
67 | length -= readSize;
68 | }
69 | }
70 |
71 | size_t ChunkedBuffer::Length() const
72 | {
73 | return (mChunks.size() - 1) * mChunkSize + mCurrentOffset;
74 | }
75 |
76 | char * ChunkedBuffer::CheckedAlloc(size_t size)
77 | {
78 | char *result = (char *)malloc(size);
79 | assert(result);
80 | return result;
81 | }
82 |
--------------------------------------------------------------------------------
/ChunkedBuffer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include
17 | #include
18 |
19 | /**
20 | * A memory buffer that can grow to arbitrary sizes without paying the cost of
21 | * copying all of the data every time the buffer needs to grow. This is achieved
22 | * by spreading the data across various chunks of memory that are allocated on
23 | * demand.
24 | */
25 | class ChunkedBuffer {
26 | public:
27 | ChunkedBuffer(size_t chunkSize);
28 | ~ChunkedBuffer();
29 |
30 | /**
31 | * Appends a series of bytes to this memory buffer.
32 | *
33 | * @param bytes - the bytes to append
34 | * @param length - the number of bytes to append
35 | */
36 | void AppendBytes(const void *bytes, size_t length);
37 |
38 | /**
39 | * The number of bytes that have been added to the buffer.
40 | */
41 | size_t Length() const;
42 |
43 | /**
44 | * Copies bytes from this buffer into another buffer.
45 | *
46 | * @param offset - the offset into this buffer
47 | * @param length - the number of bytes to copy
48 | * @param outBuffer - the buffer to copy into
49 | */
50 | void CopyBytes(off_t offset, size_t length, void *outBuffer) const;
51 |
52 | private:
53 | ChunkedBuffer(const ChunkedBuffer &other);
54 | ChunkedBuffer& operator= (const ChunkedBuffer &other);
55 |
56 | static char * CheckedAlloc(size_t size);
57 |
58 | size_t mChunkSize;
59 | off_t mCurrentOffset;
60 | std::vector mChunks;
61 | };
62 |
--------------------------------------------------------------------------------
/DatabaseLocker.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #pragma once
17 | #import "SnifferDocument.h"
18 |
19 | class DatabaseLocker {
20 | public:
21 | DatabaseLocker(SnifferDocument *document) :
22 | mDocument([document retain])
23 | {
24 | mDatabase = [document acquireDatabase];
25 | }
26 |
27 | ~DatabaseLocker()
28 | {
29 | [mDocument releaseDatabase];
30 | [mDocument release];
31 | }
32 |
33 | sqlite3 * Database()
34 | {
35 | return mDatabase;
36 | }
37 |
38 | private:
39 | SnifferDocument *mDocument;
40 | sqlite3 *mDatabase;
41 | };
42 |
--------------------------------------------------------------------------------
/English.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/HexFiend.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/HexFiend.framework/HexFiend:
--------------------------------------------------------------------------------
1 | Versions/Current/HexFiend
--------------------------------------------------------------------------------
/HexFiend.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFBTreeByteArray.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFBTreeByteArray.h
3 | // HexFiend_2
4 | //
5 | // Created by peter on 4/28/09.
6 | // Copyright 2009 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HFBTree;
12 |
13 | /*! @class HFBTreeByteArray
14 | @brief The principal efficient implementation of HFByteArray.
15 |
16 | HFBTreeByteArray is an efficient subclass of HFByteArray that stores @link HFByteSlice HFByteSlices@endlink, using a 10-way B+ tree. This allows for insertion, deletion, and searching in approximately log-base-10 time.
17 |
18 | Create an HFBTreeByteArray via \c -init. It has no methods other than those on HFByteArray.
19 | */
20 |
21 | @interface HFBTreeByteArray : HFByteArray {
22 | @private
23 | HFBTree *btree;
24 | }
25 |
26 | /*! Designated initializer for HFBTreeByteArray.
27 | */
28 | - init;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFByteArray.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFByteArray.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/4/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HFByteSlice, HFProgressTracker, HFFileReference;
12 |
13 | /*! @class HFByteArray
14 | @brief The principal Model class for HexFiend's MVC architecture.
15 |
16 | HFByteArray implements the Model portion of HexFiend.framework. It is logically a mutable, resizable array of bytes, with a 64 bit length. It is somewhat analagous to a 64 bit version of NSMutableData, except that it is designed to enable efficient (faster than O(n)) implementations of insertion and deletion.
17 |
18 | HFByteArray, being an abstract class, will raise an exception if you attempt to instantiate it directly. For most uses, instantiate HFBTreeByteArray instead, with the usual [[class alloc] init].
19 |
20 | HFByteArray also exposes itself as an array of @link HFByteSlice HFByteSlices@endlink, which are logically immutable arrays of bytes. which is useful for operations such as file saving that need to access the underlying byte slices.
21 |
22 | HFByteArray contains a generation count, which is incremented whenever the HFByteArray changes (to allow caches to be implemented on top of it). It also includes the notion of locking: a locked HFByteArray will raise an exception if written to, but it may still be read.
23 |
24 | ByteArrays have the usual threading restrictions for non-concurrent data structures. It is safe to read an HFByteArray concurrently from multiple threads. It is not safe to read an HFByteArray while it is being modified from another thread, nor is it safe to modify one simultaneously from two threads.
25 |
26 | HFByteArray is an abstract class. It will raise an exception if you attempt to instantiate it directly. The principal concrete subclass is HFBTreeByteArray.
27 | */
28 |
29 | enum
30 | {
31 | HFHexDataStringType,
32 | HFASCIIDataStringType
33 | };
34 | typedef NSUInteger HFByteArrayDataStringType;
35 |
36 | @interface HFByteArray : NSObject {
37 | @private
38 | NSUInteger changeLockCounter;
39 | NSUInteger changeGenerationCount;
40 | }
41 |
42 | /*! @name Accessing raw data
43 | */
44 | //@{
45 |
46 | /*! Returns the length of the HFByteArray as a 64 bit unsigned long long. This is an abstract method that concrete subclasses must override. */
47 | - (unsigned long long)length;
48 |
49 | /*! Copies a range of bytes into a buffer. This is an abstract method that concrete subclasses must override. */
50 | - (void)copyBytes:(unsigned char *)dst range:(HFRange)range;
51 | //@}
52 |
53 | /*! @name Accessing byte slices
54 | Methods to access the byte slices underlying the HFByteArray.
55 | */
56 | //@{
57 | /*! Returns the contents of the receiver as an array of byte slices. This is an abstract method that concrete subclasses must override. */
58 | - (NSArray *)byteSlices;
59 |
60 | /*! Returns an NSEnumerator representing the byte slices of the receiver. This is implemented as enumerating over the result of -byteSlices, but subclasses can override this to be more efficient. */
61 | - (NSEnumerator *)byteSliceEnumerator;
62 | //@}
63 |
64 | /*! @name Modifying the byte array
65 | Methods to modify the given byte array.
66 | */
67 | //@{
68 | /*! Insert an HFByteSlice in the given range. The maximum value of the range must not exceed the length of the subarray. The length of the given slice is not required to be equal to length of the range - in other words, this method may change the length of the receiver. This is an abstract method that concrete subclasses must override. */
69 | - (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)lrange;
70 |
71 | /*! Insert an HFByteArray in the given range. This is implemented via calling insertByteSlice:inRange: with the byte slices from the given byte array. */
72 | - (void)insertByteArray:(HFByteArray *)array inRange:(HFRange)lrange;
73 |
74 | /*! Delete bytes in the given range. This is implemented on the base class by creating an empty byte array and inserting it in the range to be deleted, via insertByteSlice:inRange:. */
75 | - (void)deleteBytesInRange:(HFRange)range;
76 |
77 | /*! Returns a new HFByteArray containing the given range. This is an abstract class that concrete subclasses must override. */
78 | - (HFByteArray *)subarrayWithRange:(HFRange)range;
79 | //@}
80 |
81 | /*! @name Write locking and generation count
82 | Methods to lock and query the lock that prevents writes.
83 | */
84 | //@{
85 |
86 | /*! Increment the change lock. Until the change lock reaches 0, all modifications to the receiver will raise an exception. */
87 | - (void)incrementChangeLockCounter;
88 |
89 | /*! Decrement the change lock. If the change lock reaches 0, modifications will be allowed again. */
90 | - (void)decrementChangeLockCounter;
91 |
92 | /*! Query if the changes are locked. This method is KVO compliant. */
93 | - (BOOL)changesAreLocked;
94 | //@}
95 |
96 | /* @name Generation count
97 | Manipulate the generation count */
98 | // @{
99 | /*! Increments the generation count, unless the receiver is locked, in which case it raises an exception. All subclasses of HFByteArray should call this method at the beginning of any overridden method that may modify the receiver.
100 | @param sel The selector that would modify the receiver (e.g. deleteBytesInRange:). This is usually _cmd. */
101 | - (void)incrementGenerationOrRaiseIfLockedForSelector:(SEL)sel;
102 |
103 | /*! Return the change generation count. Every change to the ByteArray increments this by one or more. This can be used for caching layers on top of HFByteArray, to known when to expire their cache. */
104 | - (NSUInteger)changeGenerationCount;
105 |
106 | //@}
107 |
108 |
109 |
110 | /*! @name Searching
111 | */
112 | //@{
113 | /*! Searches the receiver for a byte array matching findBytes within the given range, and returns the index that it was found. This is a concrete method on HFByteArray.
114 | @param findBytes The HFByteArray containing the data to be found (the needle to the receiver's haystack).
115 | @param range The range of the receiver in which to search. The end of the range must not exceed the receiver's length.
116 | @param forwards If this is YES, then the first match within the range is returned. Otherwise the last is returned.
117 | @param progressTracker An HFProgressTracker to allow progress reporting and cancelleation for the search operation.
118 | @return The index in the receiver of bytes equal to findBytes, or ULLONG_MAX if the byte array was not found (or the operation was cancelled)
119 | */
120 | - (unsigned long long)indexOfBytesEqualToBytes:(HFByteArray *)findBytes inRange:(HFRange)range searchingForwards:(BOOL)forwards trackingProgress:(HFProgressTracker *)progressTracker;
121 | //@}
122 |
123 | @end
124 |
125 |
126 | /*! @category HFByteArray(HFFileWriting)
127 | @brief HFByteArray methods for writing to files, and preparing other HFByteArrays for potentially destructive file writes.
128 | */
129 | @interface HFByteArray (HFFileWriting)
130 | /* Attempts to write the receiver to a file. This is a concrete method on HFByteArray.
131 | @param targetURL A URL to the file to be written to. It is OK for the receiver to contain one or more instances of HFByteSlice that are sourced from the file.
132 | @param progressTracker An HFProgressTracker to allow progress reporting and cancelleation for the write operation.
133 | @param error An out NSError parameter.
134 | @return YES if the write succeeded, NO if it failed.
135 | */
136 | - (BOOL)writeToFile:(NSURL *)targetURL trackingProgress:(HFProgressTracker *)progressTracker error:(NSError **)error;
137 |
138 | /*! Returns the ranges of the file that would be modified, if the receiver were written to it. This is useful (for example) in determining if the clipboard can be preserved after a save operation. This is a concrete method on HFByteArray.
139 | @param reference An HFFileReference to the file to be modified
140 | @return An array of @link HFRangeWrapper HFRangeWrappers@endlink, representing the ranges of the file that would be affected. If no range would be affected, the result is an empty array.
141 | */
142 | - (NSArray *)rangesOfFileModifiedIfSavedToFile:(HFFileReference *)reference;
143 |
144 | /*! Attempts to modify the receiver so that it no longer depends on any of the HFRanges in the array within the given file. It is not necessary to perform this operation on the byte array that is being written to the file.
145 | @param ranges An array of HFRangeWrappers, representing ranges in the given file that the receiver should no longer depend on.
146 | @param reference The HFFileReference that the receiver should no longer depend on.
147 | @return A YES return indicates the operation was successful, and the receiver no longer contains byte slices that source data from any of the ranges of the given file (or never did). A NO return indicates that breaking the dependencies would require too much memory, and so the receiver still depends on some of those ranges.
148 | */
149 | - (BOOL)clearDependenciesOnRanges:(NSArray *)ranges inFile:(HFFileReference *)reference;
150 |
151 | @end
152 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFByteSlice.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFByteSlice.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/4/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HFFileReference;
12 |
13 | /*! @class HFByteSlice
14 | @brief A class representing a source of data for an HFByteArray.
15 |
16 | HFByteSlice is an abstract class encapsulating primitive data sources (files, memory buffers, etc.). Each source must support random access reads, and have a well defined length. All HFByteSlices are \b immutable.
17 |
18 | The two principal subclasses of HFByteSlice are HFSharedMemoryByteSlice and HFFileByteSlice, which respectively encapsulate data from memory and from a file.
19 | */
20 | @interface HFByteSlice : NSObject {
21 | NSUInteger retainCount;
22 | }
23 |
24 | /*! Return the length of the byte slice as a 64 bit value. This is an abstract method that concrete subclasses must override. */
25 | - (unsigned long long)length;
26 |
27 | /*! Copies a range of data from the byte slice into an in-memory buffer. This is an abstract method that concrete subclasses must override. */
28 | - (void)copyBytes:(unsigned char *)dst range:(HFRange)range;
29 |
30 | /*! Returns a new slice containing a subrange of the given slice. This is an abstract method that concrete subclasses must override. */
31 | - (HFByteSlice *)subsliceWithRange:(HFRange)range;
32 |
33 | /*! Attempts to create a new byte slice by appending one byte slice to another. This does not modify the receiver or the slice argument (after all, both are immutable). This is provided as an optimization, and is allowed to return nil if the appending cannot be done efficiently. The default implementation returns nil.
34 | */
35 | - (id)byteSliceByAppendingSlice:(HFByteSlice *)slice;
36 |
37 | /*! Returns YES if the receiver is sourced from a file. The default implementation returns NO. This is used to estimate cost when writing to a file.
38 | */
39 | - (BOOL)isSourcedFromFile;
40 |
41 | /*! For a given file reference, returns the range within the file that the receiver is sourced from. If the receiver is not sourced from this file, returns {ULLONG_MAX, ULLONG_MAX}. The default implementation returns {ULLONG_MAX, ULLONG_MAX}. This is used during file saving to to determine how to properly overwrite a given file.
42 | */
43 | - (HFRange)sourceRangeForFile:(HFFileReference *)reference;
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFCancelButton.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFCancelButton.h
3 | // HexFiend_2
4 | //
5 | // Created by peter on 6/11/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFCancelButton
12 | @brief A simple subclass of NSButton that has the correct appearance for cancelling. This is not a generally useful class. */
13 |
14 | @interface HFCancelButton : NSButton
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFController.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFController.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/3/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import
12 |
13 | /*! @header HFController
14 | @abstract The HFController.h header contains the HFController class, which is a central class in Hex Fiend.
15 | */
16 |
17 | @class HFRepresenter, HFByteArray, HFControllerCoalescedUndo;
18 |
19 | /*! @enum HFControllerPropertyBits
20 | The HFControllerPropertyBits bitmask is used to inform the HFRepresenters of a change in the current state that they may need to react to. A bitmask of the changed properties is passed to representerChangedProperties:. It is common for multiple properties to be included in such a bitmask.
21 | */
22 | enum
23 | {
24 | HFControllerContentValue = 1 << 0, /*!< Indicates that the contents of the ByteArray has changed within the document. There is no indication as to what the change is. If redisplaying everything is expensive, Representers should cache their displayed data and compute any changes manually. */
25 | HFControllerContentLength = 1 << 1, /*!< Indicates that the length of the ByteArray has changed. */
26 | HFControllerDisplayedLineRange = 1 << 2, /*!< Indicates that the displayedLineRange property of the document has changed (e.g. the user scrolled). */
27 | HFControllerSelectedRanges = 1 << 3, /*!< Indicates that the selectedContentsRanges property of the document has changed (e.g. the user selected some other range). */
28 | HFControllerSelectionPulseAmount = 1 << 4, /*!< Indicates that the amount of "pulse" to show in the Find pulse indicator has changed. */
29 | HFControllerBytesPerLine = 1 << 5, /*!< Indicates that the number of bytes to show per line has changed. */
30 | HFControllerBytesPerColumn = 1 << 6, /*!< Indicates that the number of bytes per column (byte grouping) has changed. */
31 | HFControllerEditable = 1 << 7, /*!< Indicates that the document has become (or is no longer) editable. */
32 | HFControllerFont = 1 << 8, /*!< Indicates that the font property has changed. */
33 | HFControllerAntialias = 1 << 9, /*!< Indicates that the shouldAntialias property has changed. */
34 | HFControllerLineHeight = 1 << 10, /*!< Indicates that the lineHeight property has changed. */
35 | HFControllerViewSizeRatios = 1 << 11 /*!< Indicates that the optimum size for each view may have changed; used by HFLayoutController after font changes. */
36 | };
37 | typedef NSUInteger HFControllerPropertyBits;
38 |
39 | /*! @enum HFControllerMovementDirection
40 |
41 | The HFControllerMovementDirection enum is used to specify a direction (either left or right) in various text editing APIs. HexFiend does not support left-to-right languages.
42 | */
43 | enum
44 | {
45 | HFControllerDirectionLeft,
46 | HFControllerDirectionRight
47 | };
48 | typedef NSInteger HFControllerMovementDirection;
49 |
50 | /*! @enum HFControllerSelectionTransformation
51 |
52 | The HFControllerSelectionTransformation enum is used to specify what happens to the selection in various APIs. This is mainly interesting for text-editing style Representers.
53 | */
54 | enum
55 | {
56 | HFControllerDiscardSelection, /*!< The selection should be discarded. */
57 | HFControllerShiftSelection, /*!< The selection should be moved, without changing its length. */
58 | HFControllerExtendSelection /*!< The selection should be extended, changing its length. */
59 | };
60 | typedef NSInteger HFControllerSelectionTransformation;
61 |
62 | /*! @enum HFControllerMovementGranularity
63 |
64 | The HFControllerMovementGranularity enum is used to specify the granularity of text movement in various APIs. This is mainly interesting for text-editing style Representers.
65 | */
66 | enum
67 | {
68 | HFControllerMovementByte, /*!< Move by individual bytes */
69 | HFControllerMovementLine, /*!< Move by lines */
70 | HFControllerMovementPage, /*!< Move by pages */
71 | HFControllerMovementDocument /*!< Move by the whole document */
72 | };
73 | typedef NSInteger HFControllerMovementGranularity;
74 |
75 | /*! @class HFController
76 | @brief A central class that acts as the controller layer for HexFiend.framework
77 |
78 | HFController acts as the controller layer in the MVC architecture of HexFiend. The HFController plays several significant central roles, including:
79 | - Mediating between the data itself (in the HFByteArray) and the views of the data (the @link HFRepresenter HFRepresenters@endlink).
80 | - Propagating changes to the views.
81 | - Storing properties common to all Representers, such as the currently diplayed range, the currently selected range(s), the font, etc.
82 | - Handling text editing actions, such as selection changes or insertions/deletions.
83 |
84 | An HFController is the top point of ownership for a HexFiend object graph. It retains both its ByteArray (model) and its array of Representers (views).
85 |
86 | You create an HFController via [[HFController alloc] init]. After that, give it an HFByteArray via setByteArray:, and some Representers via addRepresenter:. Then insert the Representers' views in a window, and you're done.
87 |
88 | */
89 | @interface HFController : NSObject {
90 | @private
91 | NSMutableArray *representers;
92 | HFByteArray *byteArray;
93 | NSMutableArray *selectedContentsRanges;
94 | HFRange displayedContentsRange;
95 | HFFPRange displayedLineRange;
96 | NSUInteger bytesPerLine;
97 | NSUInteger bytesPerColumn;
98 | NSFont *font;
99 | CGFloat lineHeight;
100 |
101 | NSUInteger currentPropertyChangeToken;
102 | NSMutableArray *additionalPendingTransactions;
103 | HFControllerPropertyBits propertiesToUpdateInCurrentTransaction;
104 |
105 | NSUndoManager *undoManager;
106 |
107 | unsigned long long selectionAnchor;
108 | HFRange selectionAnchorRange;
109 |
110 | HFControllerCoalescedUndo *undoCoalescer;
111 |
112 | CFAbsoluteTime pulseSelectionStartTime, pulseSelectionCurrentTime;
113 | NSTimer *pulseSelectionTimer;
114 |
115 | /* Basic cache support */
116 | HFRange cachedRange;
117 | NSData *cachedData;
118 | NSUInteger cachedGenerationIndex;
119 |
120 | struct {
121 | unsigned antialias:1;
122 | unsigned overwriteMode:1;
123 | unsigned editable:1;
124 | unsigned selectable:1;
125 | unsigned selectionInProgress:1;
126 | unsigned shiftExtendSelection:1;
127 | unsigned commandExtendSelection:1;
128 | unsigned reserved1:25;
129 | unsigned reserved2:32;
130 | } _hfflags;
131 | }
132 |
133 | /*! @name Representer handling.
134 | Methods for modifying the list of HFRepresenters attached to a controller. Attached representers receive the controllerDidChange: message when various properties of the controller change. A representer may only be attached to one controller at a time. Representers are retained by the controller.
135 | */
136 | //@{
137 | /*! Gets the current array of representers attached to this controller. */
138 | - (NSArray *)representers;
139 |
140 | /*! Adds a new representer to this controller. */
141 | - (void)addRepresenter:(HFRepresenter *)representer;
142 |
143 | /*! Removes an existing representer from this controller. The representer must be present in the array of representers. */
144 | - (void)removeRepresenter:(HFRepresenter *)representer;
145 |
146 | //@}
147 |
148 | /*! @name Property transactions
149 | Methods for temporarily delaying notifying representers of property changes. There is a property transaction stack, and all property changes are collected until the last token is popped off the stack, at which point all representers are notified of all collected changes via representerChangedProperties:. To use this, call beginPropertyChangeTransaction, and record the token that is returned. Pass it to endPropertyChangeTransaction: to notify representers of all changed properties in bulk.
150 |
151 | Tokens cannot be popped out of order - they are used only as a correctness check.
152 | */
153 | //@{
154 | /*! Begins delaying property change transactions. Returns a token that should be passed to endPropertyChangeTransactions:. */
155 | - (NSUInteger)beginPropertyChangeTransaction;
156 |
157 | /*! Pass a token returned from beginPropertyChangeTransaction to this method to pop the transaction off the stack and, if the stack is empty, to notify Representers of all collected changes. Tokens cannot be popped out of order - they are used strictly as a correctness check. */
158 | - (void)endPropertyChangeTransaction:(NSUInteger)token;
159 | //@}
160 |
161 | /*! @name Byte array
162 | Set and get the byte array. */
163 | //@{
164 | /*! Sets the byte array for the HFController. The byte array must be non-nil. */
165 | - (void)setByteArray:(HFByteArray *)val;
166 |
167 | /*! Returns the byte array for the HFController. In general, HFRepresenters should not use this to determine what bytes to display. Instead they should use copyBytes:range: or dataForRange: below. */
168 | - (HFByteArray *)byteArray;
169 |
170 | /*! Replaces the entire byte array with a new one, preserving as much of the selection as possible. Unlike setByteArray:, this method is undoable, and intended to be used from representers that make a global change (such as Replace All). */
171 | - (void)replaceByteArray:(HFByteArray *)newArray;
172 | //@}
173 |
174 | /*! @name Properties shared between all representers
175 | The following properties are considered global among all HFRepresenters attached to the receiver.
176 | */
177 | //@{
178 | /*! Returns the number of lines on which the cursor may be placed. This is always at least 1, and is equivalent to (unsigned long long)(HFRoundUpToNextMultiple(contentsLength, bytesPerLine) / bytesPerLine) */
179 | - (unsigned long long)totalLineCount;
180 |
181 | /*! Indicates the number of bytes per line, which is a global property among all the line-oriented representers. */
182 | - (NSUInteger)bytesPerLine;
183 |
184 | /*! Returns the height of a line, in points. This is generally determined by the font. Representers that wish to align things to lines should use this. */
185 | - (CGFloat)lineHeight;
186 |
187 | //@}
188 |
189 | /*! @name Selection pulsing
190 | Used to show the current selection after a change, similar to Find in Safari
191 | */
192 | //{@
193 |
194 | /*! Begins selection pulsing (e.g. following a successful Find operation). Representers will receive callbacks indicating that HFControllerSelectionPulseAmount has changed. */
195 | - (void)pulseSelection;
196 |
197 | /*! Return the amount that the "Find pulse indicator" should show. 0 means no pulse, 1 means maximum pulse. This is useful for Representers that support find and replace. */
198 | - (double)selectionPulseAmount;
199 | //@}
200 |
201 | /*! @name Selection handling
202 | Methods for manipulating the current selected ranges. Hex Fiend supports discontiguous selection.
203 | */
204 | //{@
205 |
206 | /*! Returns an array of HFRangeWrappers, representing the selected ranges. This method always contains at least one range. If there is no selection, then the result will contain a single range of length 0, with the location equal to the position of the cursor. */
207 | - (NSArray *)selectedContentsRanges;
208 |
209 | /*! Explicitly set the selected contents ranges. Pass an array of HFRangeWrappers that meets the following criteria:
210 | The array must not be NULL.
211 | There always must be at least one selected range.
212 | If any range has length 0, there must be exactly one selected range.
213 | No range may extend beyond the contentsLength, with the exception of a single zero-length range, which may be at the end.
214 | */
215 | - (void)setSelectedContentsRanges:(NSArray *)selectedRanges;
216 |
217 | /*! Selects the entire contents. */
218 | - (IBAction)selectAll:(id)sender;
219 |
220 | /*! Returns the smallest value in the selected contents ranges, or the insertion location if the selection is empty. */
221 | - (unsigned long long)minimumSelectionLocation;
222 |
223 | /*! Returns the largest HFMaxRange of the selected contents ranges, or the insertion location if the selection is empty. */
224 | - (unsigned long long)maximumSelectionLocation;
225 |
226 | /*! Convenience method for creating a byte array containing all of the selected bytes. If the selection has length 0, this returns an empty byte array. */
227 | - (HFByteArray *)byteArrayForSelectedContentsRanges;
228 | //@}
229 |
230 | /*! @name Bytes per column
231 | Set and get the number of bytes per column. */
232 | //@{
233 | /* Sets the number of bytes used in each column for a text-style representer. */
234 | - (void)setBytesPerColumn:(NSUInteger)val;
235 |
236 | /* Returns the number of bytes used in each column for a text-style representer. */
237 | - (NSUInteger)bytesPerColumn;
238 | //@}
239 |
240 | /*! @name Overwrite mode
241 | Determines whether text insertion overwrites subsequent text or not. */
242 | //@{
243 |
244 | /*! Determines whether this HFController is in overwrite mode or not. */
245 | - (BOOL)inOverwriteMode;
246 |
247 | /*! Sets whether we this HFController is in overwrite mode or not. */
248 | - (void)setInOverwriteMode:(BOOL)val;
249 |
250 | /*! Returns YES if we must be in overwrite mode (because our backing data cannot have its size changed) */
251 | - (BOOL)requiresOverwriteMode;
252 |
253 | //@}
254 |
255 | /*! @name Displayed line range
256 | Methods for setting and getting the current range of displayed lines.
257 | */
258 | //{@
259 | /*! Get the current displayed line range. The displayed line range is an HFFPRange (range of long doubles) containing the lines that are currently displayed.
260 |
261 | The values may be fractional. That is, if only the bottom half of line 4 through the top two thirds of line 8 is shown, then the displayedLineRange.location will be 4.5 and the displayedLineRange.length will be 3.17 ( = 7.67 - 4.5). Representers are expected to be able to handle such fractional values.
262 |
263 | */
264 | - (HFFPRange)displayedLineRange;
265 |
266 | /*! Sets the displayed line range. When setting the displayed line range, the given range must be nonnegative, and the maximum of the range must be no larger than the total line count. See the -displayedLineRange method for more information. */
267 | - (void)setDisplayedLineRange:(HFFPRange)range;
268 |
269 | /*! Modify the displayedLineRange as little as possible so that as much of the given range as can fit is visible. */
270 | - (void)maximizeVisibilityOfContentsRange:(HFRange)range;
271 |
272 | //@}
273 |
274 | /*! @name Font
275 | Get and set the current font.
276 | */
277 | //@{
278 | /*! Get the current font. */
279 | - (NSFont *)font;
280 |
281 | /*! Set the current font. */
282 | - (void)setFont:(NSFont *)font;
283 |
284 | /*! @name Undo management
285 | Get and set the undo manager. If no undo manager is set, then undo is not supported.
286 | */
287 | //@{
288 |
289 | /*! Set the undo manager for this HFController. By default the undo manager for an HFController is nil. If one is not set, undo does not occur. This retains the undo manager. */
290 | - (void)setUndoManager:(NSUndoManager *)manager;
291 |
292 | /*! Gets the undo manager for this HFController. By default the undo manager is nil. Undo will not be supported unless an undo manager is set. */
293 | - (NSUndoManager *)undoManager;
294 |
295 | //@}
296 |
297 | /*! @name Editability
298 | Set and get whether representers should allow editing the data.
299 | */
300 | //@{
301 | /*! Get the editable property, which determines whether the user can edit the document. */
302 | - (BOOL)editable;
303 |
304 | /*! Set the editable property, which determines whether the user can edit the document. */
305 | - (void)setEditable:(BOOL)flag;
306 | //@}
307 |
308 | /*! @name Antialiasing
309 | Set and get whether the text should be antialiased. Note that Mac OS X settings may prevent antialiasing text below a certain point size. */
310 | //@{
311 | /*! Returns whether text should be antialiased. */
312 | - (BOOL)shouldAntialias;
313 |
314 | /*! Sets whether text should be antialiased. */
315 | - (void)setShouldAntialias:(BOOL)antialias;
316 | //@}
317 |
318 | /*! Representer initiated property changes
319 | Called from a representer to indicate when some internal property of the representer has changed which requires that some properties be recalculated.
320 | */
321 | //@{
322 | /*! Callback for a representer-initiated change to some property. For example, if some property of a view changes that would cause the number of bytes per line to change, then the representer should call this method which will trigger the HFController to recompute the relevant properties. */
323 |
324 | - (void)representer:(HFRepresenter *)rep changedProperties:(HFControllerPropertyBits)properties;
325 | //@}
326 |
327 | /*! @name Mouse selection
328 | Methods to handle mouse selection. Representers that allow text selection should call beginSelectionWithEvent:forByteIndex: upon receiving a mouseDown event, and then continueSelectionWithEvent:forByteIndex: for mouseDragged events, terminating with endSelectionWithEvent:forByteIndex: upon receiving the mouse up. HFController will compute the correct selected ranges and propagate any changes via the HFControllerPropertyBits mechanism. */
329 | //@{
330 | /*! Begin a selection session, with a mouse down at the given byte index. */
331 | - (void)beginSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
332 |
333 | /*! Continue a selection session, whe the user drags over the given byte index. */
334 | - (void)continueSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
335 |
336 | /*! End a selection session, with a mouse up at the given byte index. */
337 | - (void)endSelectionWithEvent:(NSEvent *)event forByteIndex:(unsigned long long)byteIndex;
338 |
339 | /*! @name Scrollling
340 | Support for the mouse wheel and scroll bars. */
341 | //@{
342 | /*! Trigger scrolling appropriate for the given scroll event. */
343 | - (void)scrollWithScrollEvent:(NSEvent *)scrollEvent;
344 |
345 | /*! Trigger scrolling by the given number of lines. If lines is positive, then the document is scrolled down; otherwise it is scrolled up. */
346 | - (void)scrollByLines:(long double)lines;
347 |
348 | //@}
349 |
350 | /*! @name Keyboard navigation
351 | Support for chaging the selection via the keyboard
352 | */
353 |
354 | /*! General purpose navigation function. Modify the selection in the given direction by the given number of bytes. The selection is modifed according to the given transformation. If useAnchor is set, then anchored selection is used; otherwise any anchor is discarded.
355 |
356 | This has a few limitations:
357 | - Only HFControllerDirectionLeft and HFControllerDirectionRight movement directions are supported.
358 | - Anchored selection is not supported for HFControllerShiftSelection (useAnchor must be NO)
359 | */
360 | - (void)moveInDirection:(HFControllerMovementDirection)direction byByteCount:(unsigned long long)amountToMove withSelectionTransformation:(HFControllerSelectionTransformation)transformation usingAnchor:(BOOL)useAnchor;
361 |
362 | /*! Navigation designed for key events. */
363 | - (void)moveInDirection:(HFControllerMovementDirection)direction withGranularity:(HFControllerMovementGranularity)granularity andModifySelection:(BOOL)extendSelection;
364 | - (void)moveToLineBoundaryInDirection:(HFControllerMovementDirection)direction andModifySelection:(BOOL)extendSelection;
365 |
366 | /*! @name Text editing
367 | Methods to support common text editing operations */
368 | //@{
369 |
370 | /*! Replaces the selection with the given data. For something like a hex view representer, it takes two keypresses to create a whole byte; the way this is implemented, the first keypress goes into the data as a complete byte, and the second one (if any) replaces it. If previousByteCount > 0, then that many prior bytes are replaced, without breaking undo coalescing. For previousByteCount to be > 0, the following must be true: There is only one selected range, and it is of length 0, and its location >= previousByteCount
371 |
372 | These functions return YES if they succeed, and NO if they fail. Currently they may fail only in overwrite mode, if you attempt to insert data that would require lengthening the byte array.
373 |
374 | These methods are undoable.
375 | */
376 | - (BOOL)insertByteArray:(HFByteArray *)byteArray replacingPreviousBytes:(unsigned long long)previousByteCount allowUndoCoalescing:(BOOL)allowUndoCoalescing;
377 | - (BOOL)insertData:(NSData *)data replacingPreviousBytes:(unsigned long long)previousByteCount allowUndoCoalescing:(BOOL)allowUndoCoalescing;
378 |
379 | /*! Deletes the selection. This operation is undoable. */
380 | - (void)deleteSelection;
381 |
382 | /*! If the selection is empty, deletes one byte in a given direction, which must be HFControllerDirectionLeft or HFControllerDirectionRight; if the selection is not empty, deletes the selection. Undoable. */
383 | - (void)deleteDirection:(HFControllerMovementDirection)direction;
384 |
385 | //@}
386 |
387 | /*! @name Reading data
388 | Methods for reading data */
389 |
390 | /*! Returns an NSData representing the given HFRange. The length of the HFRange must be of a size that can reasonably be fit in memory. This method may cache the result. */
391 | - (NSData *)dataForRange:(HFRange)range;
392 |
393 | /*! Copies data within the given HFRange into an in-memory buffer. This is equivalent to [[controller byteArray] copyBytes:bytes range:range]. */
394 | - (void)copyBytes:(unsigned char *)bytes range:(HFRange)range;
395 |
396 | /*! Returns total number of bytes. This is equivalent to [[controller byteArray] length]. */
397 | - (unsigned long long)contentsLength;
398 |
399 | /*! @name File writing dependency handling
400 | */
401 | //@{
402 | /*! Attempts to clear all dependencies on the given file (clipboard, undo, etc.) that could not be preserved if the file were written. Returns YES if we successfully prepared, NO if someone objected. */
403 | + (BOOL)prepareForChangeInFile:(NSURL *)targetFile fromWritingByteArray:(HFByteArray *)array;
404 | //@}
405 |
406 | @end
407 |
408 | /*! A notification posted whenever any of the HFController's properties change. The object is the HFController. The userInfo contains one key, HFControllerChangedPropertiesKey, which contains an NSNumber with the changed properties as a HFControllerPropertyBits bitmask. This is useful for external objects to be notified of changes. HFRepresenters added to the HFController are notified via the controllerDidChange: message.
409 | */
410 | extern NSString * const HFControllerDidChangePropertiesNotification;
411 |
412 | /*! @name HFControllerDidChangePropertiesNotification keys
413 | */
414 | //@{
415 | extern NSString * const HFControllerChangedPropertiesKey; //!< A key in the HFControllerDidChangeProperties containing a bitmask of the changed properties, as a HFControllerPropertyBits
416 | //@}
417 |
418 | /*! A notification posted from prepareForChangeInFile:fromWritingByteArray: because we are about to write a ByteArray to a file. The object is the FileReference.
419 | Currently, HFControllers do not listen for this notification. This is because under GC there is no way of knowing whether the controller is live or not. However, pasteboard owners do listen for it, because as long as we own a pasteboard we are guaranteed to be live.
420 | */
421 | extern NSString * const HFPrepareForChangeInFileNotification;
422 |
423 | /*! @name HFPrepareForChangeInFileNotification keys
424 | */
425 | //@{
426 | extern NSString * const HFChangeInFileByteArrayKey; //!< A key in the HFPrepareForChangeInFileNotification specifying the byte array that will be written
427 | extern NSString * const HFChangeInFileModifiedRangesKey; //!< A key in the HFPrepareForChangeInFileNotification specifying the array of HFRangeWrappers indicating which parts of the file will be modified
428 | extern NSString * const HFChangeInFileShouldCancelKey; //!< A key in the HFPrepareForChangeInFileNotification specifying an NSValue containing a pointer to a BOOL. If set to YES, then someone was unable to prepare and the file should not be saved. It's a good idea to check if this value points to YES; if so your notification handler does not have to do anything.
429 | //@}
430 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFFileByteSlice.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFFileByteSlice.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 1/23/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HFFileReference;
12 |
13 | /*! @class HFFileByteSlice
14 | @brief A subclass of HFByteSlice for working data stored in files.
15 |
16 | HFFileByteSlice is a subclass of HFByteSlice that represents a portion of data from a file. The file is specified as an HFFileReference; since the HFFileReference encapsulates the file descriptor, multiple HFFileByteSlices may all reference the same file without risking overrunning the limit on open files.
17 | */
18 | @interface HFFileByteSlice : HFByteSlice {
19 | HFFileReference *fileReference;
20 | unsigned long long offset;
21 | unsigned long long length;
22 | }
23 |
24 | /*! Initialize an HFByteSlice from a file. The receiver represents the entire extent of the file. */
25 | - initWithFile:(HFFileReference *)file;
26 |
27 | /*! Initialize an HFByteSlice from a portion of a file, specified as an offset and length. The sum of the offset and length must not exceed the length of the file. This is the designated initializer. */
28 | - initWithFile:(HFFileReference *)file offset:(unsigned long long)offset length:(unsigned long long)length;
29 |
30 | @end
31 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFFileReference.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFFileReference.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 1/23/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFFileReference
12 | @brief A reference to an open file.
13 |
14 | HFFileReference encapsulates a reference to an open file. Multiple instances of HFFileByteSlice may share an HFFileReference, so that the file only needs to be opened once.
15 |
16 | All HFFileReferences use non-caching IO (F_NOCACHE is set).
17 | */
18 | @interface HFFileReference : NSObject {
19 | int fileDescriptor;
20 | dev_t device;
21 | unsigned long long fileLength;
22 | unsigned long long inode;
23 | BOOL isWritable;
24 | }
25 |
26 |
27 | /*! Open a file for reading and writing at the given path. The permissions mode of any newly created file is 0744. Returns nil if the file could not be opened, in which case the error parameter (if not nil) will be set. */
28 | - initWritableWithPath:(NSString *)path error:(NSError **)error;
29 |
30 | /*! Open a file for reading only at the given path. Returns nil if the file could not be opened, in which case the error parameter (if not nil) will be set. */
31 | - initWithPath:(NSString *)path error:(NSError **)error;
32 |
33 | /*! Closes the file. */
34 | - (void)close;
35 |
36 | /*! Reads from the file into a local memory buffer. The sum of the length and the offset must not exceed the length of the file.
37 | @param buff The buffer to read into.
38 | @param length The number of bytes to read.
39 | @param offset The offset in the file to read.
40 | */
41 | - (void)readBytes:(unsigned char *)buff length:(NSUInteger)length from:(unsigned long long)offset;
42 |
43 | /*! Writes data to the file, which must have been opened writable.
44 | @param buff The data to write.
45 | @param length The number of bytes to write.
46 | @param offset The offset in the file to write to.
47 | @return 0 on success, or an errno-style error code on failure
48 | */
49 | - (int)writeBytes:(const unsigned char *)buff length:(NSUInteger)length to:(unsigned long long)offset;
50 |
51 | /*! Returns the length of the file, as a 64 bit unsigned long long. */
52 | - (unsigned long long)length;
53 |
54 | /*! Changes the length of the file via \c ftruncate. Returns YES on success, NO on failure; on failure it optionally returns an NSError by reference. */
55 | - (BOOL)setLength:(unsigned long long)length error:(NSError **)error;
56 |
57 | /*! isEqual: returns whether two file references both reference the same file, as in have the same inode and device. */
58 | - (BOOL)isEqual:(id)val;
59 |
60 | @end
61 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFFullMemoryByteArray.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFFullMemoryByteArray.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/4/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*!
12 | @class HFFullMemoryByteArray
13 | @brief A naive subclass of HFByteArray suitable mainly for testing. Use HFBTreeByteArray instead.
14 |
15 | HFFullMemoryByteArray is a simple subclass of HFByteArray that does not store any byte slices. Because it stores all data in an NSMutableData, it is not efficient. It is mainly useful as a naive implementation for testing. Use HFBTreeByteArray instead.
16 | */
17 | @interface HFFullMemoryByteArray : HFByteArray {
18 | NSMutableData *data;
19 | }
20 |
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFFullMemoryByteSlice.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFFullMemoryByteSlice.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/4/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFFullMemoryByteSlice
12 |
13 | @brief A simple subclass of HFByteSlice that wraps an NSData. For most uses, prefer HFSharedMemoryByteSlice.
14 | */
15 | @interface HFFullMemoryByteSlice : HFByteSlice {
16 | NSData *data;
17 | }
18 |
19 | /*! Init with a given NSData, which is copied via the \c -copy message. */
20 | - initWithData:(NSData *)val;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFFunctions.h:
--------------------------------------------------------------------------------
1 | /* Functions and convenience methods for working with HFTypes */
2 |
3 | #import
4 | #import
5 |
6 | #define HFZeroRange (HFRange){0, 0}
7 |
8 | /*!
9 | Makes an HFRange. An HFRange is like an NSRange except it uses unsigned long longs.
10 | */
11 | static inline HFRange HFRangeMake(unsigned long long loc, unsigned long long len) {
12 | return (HFRange){loc, len};
13 | }
14 |
15 | /*!
16 | Returns true if a given location is within a given HFRange.
17 | */
18 | static inline BOOL HFLocationInRange(unsigned long long location, HFRange range) {
19 | return location >= range.location && location - range.location < range.length;
20 | }
21 |
22 | /*!
23 | Like NSRangeToString but for HFRanges
24 | */
25 | static inline NSString* HFRangeToString(HFRange range) {
26 | return [NSString stringWithFormat:@"{%llu, %llu}", range.location, range.length];
27 | }
28 |
29 | /*!
30 | Converts a given HFFPRange to a string.
31 | */
32 | static inline NSString* HFFPRangeToString(HFFPRange range) {
33 | return [NSString stringWithFormat:@"{%Lf, %Lf}", range.location, range.length];
34 | }
35 |
36 | /*!
37 | Returns true if two HFRanges are equal.
38 | */
39 | static inline BOOL HFRangeEqualsRange(HFRange a, HFRange b) {
40 | return a.location == b.location && a.length == b.length;
41 | }
42 |
43 | /*!
44 | Returns true if a + b does not overflow an unsigned long long.
45 | */
46 | static inline BOOL HFSumDoesNotOverflow(unsigned long long a, unsigned long long b) {
47 | return a + b >= a;
48 | }
49 |
50 | /*!
51 | Returns true if a * b does not overflow an unsigned long long.
52 | */
53 | static inline BOOL HFProductDoesNotOverflow(unsigned long long a, unsigned long long b) {
54 | if (b == 0) return YES;
55 | unsigned long long result = a * b;
56 | return result / b == a;
57 | }
58 |
59 | /*!
60 | Returns a * b as an NSUInteger. This asserts on overflow, unless NDEBUG is defined.
61 | */
62 | static inline NSUInteger HFProductInt(NSUInteger a, NSUInteger b) {
63 | NSUInteger result = a * b;
64 | assert(a == 0 || result / a == b); //detect overflow
65 | return result;
66 | }
67 |
68 | /*!
69 | Returns a + b as an NSUInteger. This asserts on overflow unless NDEBUG is defined.
70 | */
71 | static inline NSUInteger HFSumInt(NSUInteger a, NSUInteger b) {
72 | assert(a + b >= a);
73 | return a + b;
74 | }
75 |
76 | /*!
77 | Returns a * b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
78 | */
79 | static inline unsigned long long HFProductULL(unsigned long long a, unsigned long long b) {
80 | unsigned long long result = a * b;
81 | assert(HFProductDoesNotOverflow(a, b)); //detect overflow
82 | return result;
83 | }
84 |
85 | /*!
86 | Returns a + b as an unsigned long long. This asserts on overflow, unless NDEBUG is defined.
87 | */
88 | static inline unsigned long long HFSum(unsigned long long a, unsigned long long b) {
89 | assert(HFSumDoesNotOverflow(a, b));
90 | return a + b;
91 | }
92 |
93 | /*!
94 | Returns a - b as an unsigned long long. This asserts on underflow (if b > a), unless NDEBUG is defined.
95 | */
96 | static inline unsigned long long HFSubtract(unsigned long long a, unsigned long long b) {
97 | assert(a >= b);
98 | return a - b;
99 | }
100 |
101 | /*!
102 | Returns the smallest multiple of B strictly larger than A.
103 | */
104 | static inline unsigned long long HFRoundUpToNextMultiple(unsigned long long a, unsigned long long b) {
105 | assert(b > 0);
106 | return HFSum(a, b - a % b);
107 | }
108 |
109 | /*! Like NSMaxRange, but for an HFRange. */
110 | static inline unsigned long long HFMaxRange(HFRange a) {
111 | assert(HFSumDoesNotOverflow(a.location, a.length));
112 | return a.location + a.length;
113 | }
114 |
115 | /*! Returns YES if needle is fully contained within haystack. Equal ranges are always considered to be subranges of each other (even if they are empty). Furthermore, a zero length needle at the end of haystack is considered a subrange - for example, {6, 0} is a subrange of {3, 3}. */
116 | static inline BOOL HFRangeIsSubrangeOfRange(HFRange needle, HFRange haystack) {
117 | // handle the case where our needle starts before haystack, or is longer than haystack. These conditions are important to prevent overflow in future checks.
118 | if (needle.location < haystack.location || needle.length > haystack.length) return NO;
119 |
120 | // Equal ranges are considered to be subranges. This is an important check, because two equal ranges of zero length are considered to be subranges.
121 | if (HFRangeEqualsRange(needle, haystack)) return YES;
122 |
123 | // handle the case where needle is a zero-length range at the very end of haystack. We consider this a subrange - that is, (6, 0) is a subrange of (3, 3)
124 | // rearrange the expression needle.location > haystack.location + haystack.length in a way that cannot overflow
125 | if (needle.location - haystack.location > haystack.length) return NO;
126 |
127 | // rearrange expression: (needle.location + needle.length > haystack.location + haystack.length) in a way that cannot produce overflow
128 | if (needle.location - haystack.location > haystack.length - needle.length) return NO;
129 |
130 | return YES;
131 | }
132 |
133 | /*! Returns YES if the given ranges intersect. Two ranges are considered to intersect if they share at least one index in common. Thus, zero-length ranges do not intersect anything. */
134 | static inline BOOL HFIntersectsRange(HFRange a, HFRange b) {
135 | // Ranges are said to intersect if they share at least one value. Therefore, zero length ranges never intersect anything.
136 | if (a.length == 0 || b.length == 0) return NO;
137 |
138 | // rearrange (a.location < b.location + b.length && b.location < a.location + a.length) to not overflow
139 | // = ! (a.location >= b.location + b.length || b.location >= a.location + a.length)
140 | BOOL clause1 = (a.location >= b.location && a.location - b.location >= b.length);
141 | BOOL clause2 = (b.location >= a.location && b.location - a.location >= a.length);
142 | return ! (clause1 || clause2);
143 | }
144 |
145 | /*! Returns a range containing the union of the given ranges. These ranges must either intersect or be adjacent: there cannot be any "holes" between them. */
146 | static inline HFRange HFUnionRange(HFRange a, HFRange b) {
147 | assert(HFIntersectsRange(a, b) || HFMaxRange(a) == b.location || HFMaxRange(b) == a.location);
148 | HFRange result;
149 | result.location = MIN(a.location, b.location);
150 | assert(HFSumDoesNotOverflow(a.location, a.length));
151 | assert(HFSumDoesNotOverflow(b.location, b.length));
152 | result.length = MAX(a.location + a.length, b.location + b.length) - result.location;
153 | return result;
154 | }
155 |
156 |
157 | /*! Returns whether a+b > c+d, as if there were no overflow (so ULLONG_MAX + 1 > 10 + 20) */
158 | static inline BOOL HFSumIsLargerThanSum(unsigned long long a, unsigned long long b, unsigned long long c, unsigned long long d) {
159 | //theory: compare a/2 + b/2 to c/2 + d/2, and if they're equal, compare a%2 + b%2 to c%2 + d%2
160 | unsigned long long sum1 = a/2 + b/2;
161 | unsigned long long sum2 = c/2 + d/2;
162 | if (sum1 > sum2) return YES;
163 | else if (sum1 < sum2) return NO;
164 | else {
165 | // sum1 == sum2
166 | unsigned int sum3 = (unsigned int)(a%2) + (unsigned int)(b%2);
167 | unsigned int sum4 = (unsigned int)(c%2) + (unsigned int)(d%2);
168 | if (sum3 > sum4) return YES;
169 | else return NO;
170 | }
171 | }
172 |
173 | /*! Returns the absolute value of a - b. */
174 | static inline unsigned long long HFAbsoluteDifference(unsigned long long a, unsigned long long b) {
175 | if (a > b) return a - b;
176 | else return b - a;
177 | }
178 |
179 | /*! Returns true if the end of A is larger than the end of B. */
180 | static inline BOOL HFRangeExtendsPastRange(HFRange a, HFRange b) {
181 | return HFSumIsLargerThanSum(a.location, a.length, b.location, b.length);
182 | }
183 |
184 | /*! Returns a range containing all indexes in common betwen the two ranges. If there are no indexes in common, returns {0, 0}. */
185 | static inline HFRange HFIntersectionRange(HFRange range1, HFRange range2) {
186 | unsigned long long minend = HFRangeExtendsPastRange(range2, range1) ? range1.location + range1.length : range2.location + range2.length;
187 | if (range2.location <= range1.location && range1.location - range2.location < range2.length) {
188 | return HFRangeMake(range1.location, minend - range1.location);
189 | }
190 | else if (range1.location <= range2.location && range2.location - range1.location < range1.length) {
191 | return HFRangeMake(range2.location, minend - range2.location);
192 | }
193 | return HFRangeMake(0, 0);
194 | }
195 |
196 | /*! ceil() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
197 | static inline CGFloat HFCeil(CGFloat a) {
198 | if (sizeof(a) == sizeof(float)) return (CGFloat)ceilf((float)a);
199 | else return (CGFloat)ceil((double)a);
200 | }
201 |
202 | /*! floor() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
203 | static inline CGFloat HFFloor(CGFloat a) {
204 | if (sizeof(a) == sizeof(float)) return (CGFloat)floorf((float)a);
205 | else return (CGFloat)floor((double)a);
206 | }
207 |
208 | /*! round() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
209 | static inline CGFloat HFRound(CGFloat a) {
210 | if (sizeof(a) == sizeof(float)) return (CGFloat)roundf((float)a);
211 | else return (CGFloat)round((double)a);
212 | }
213 |
214 | /*! fmin() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
215 | static inline CGFloat HFMin(CGFloat a, CGFloat b) {
216 | if (sizeof(a) == sizeof(float)) return (CGFloat)fminf((float)a, (float)b);
217 | else return (CGFloat)fmin((double)a, (double)b);
218 | }
219 |
220 | /*! fmax() for a CGFloat, for compatibility with OSes that do not have the CG versions. */
221 | static inline CGFloat HFMax(CGFloat a, CGFloat b) {
222 | if (sizeof(a) == sizeof(float)) return (CGFloat)fmaxf((float)a, (float)b);
223 | else return (CGFloat)fmax((double)a, (double)b);
224 | }
225 |
226 | /*! Returns true if the given HFFPRanges are equal. */
227 | static inline BOOL HFFPRangeEqualsRange(HFFPRange a, HFFPRange b) {
228 | return a.location == b.location && a.length == b.length;
229 | }
230 |
231 | /*! copysign() for a CGFloat */
232 | static inline CGFloat HFCopysign(CGFloat a, CGFloat b) {
233 | #if __LP64__
234 | return copysign(a, b);
235 | #else
236 | return copysignf(a, b);
237 | #endif
238 | }
239 |
240 | /*! Atomically increments an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
241 | static inline NSUInteger HFAtomicIncrement(NSUInteger *ptr, BOOL barrier) {
242 | #if __LP64__
243 | return (barrier ? OSAtomicIncrement64Barrier : OSAtomicIncrement64)((volatile int64_t *)ptr);
244 | #else
245 | return (barrier ? OSAtomicIncrement32Barrier : OSAtomicIncrement32)((volatile int32_t *)ptr);
246 | #endif
247 | }
248 |
249 | /*! Atomically decrements an NSUInteger, returning the new value. Optionally invokes a memory barrier. */
250 | static inline NSUInteger HFAtomicDecrement(NSUInteger *ptr, BOOL barrier) {
251 | #if __LP64__
252 | return (barrier ? OSAtomicDecrement64Barrier : OSAtomicDecrement64)((volatile int64_t *)ptr);
253 | #else
254 | return (barrier ? OSAtomicDecrement32Barrier : OSAtomicDecrement32)((volatile int32_t *)ptr);
255 | #endif
256 | }
257 |
258 | /*! Converts a long double to unsigned long long. Assumes that val is already an integer - use floorl or ceill */
259 | static inline unsigned long long HFFPToUL(long double val) {
260 | assert(val >= 0);
261 | assert(val <= ULLONG_MAX);
262 | unsigned long long result = (unsigned long long)val;
263 | assert((long double)result == val);
264 | return result;
265 | }
266 |
267 | /*! Converts an unsigned long long to a long double. */
268 | static inline long double HFULToFP(unsigned long long val) {
269 | long double result = (long double)val;
270 | assert(HFFPToUL(result) == val);
271 | return result;
272 | }
273 |
274 | /*! Convenience to return information about a CGAffineTransform for logging. */
275 | static inline NSString *HFDescribeAffineTransform(CGAffineTransform t) {
276 | return [NSString stringWithFormat:@"%f %f 0\n%f %f 0\n%f %f 1", t.a, t.b, t.c, t.d, t.tx, t.ty];
277 | }
278 |
279 | /*! Returns 1 + floor(log base 10 of val). If val is 0, returns 1. */
280 | static inline NSUInteger HFCountDigitsBase10(unsigned long long val) {
281 | const unsigned long long kValues[] = {0ULL, 9ULL, 99ULL, 999ULL, 9999ULL, 99999ULL, 999999ULL, 9999999ULL, 99999999ULL, 999999999ULL, 9999999999ULL, 99999999999ULL, 999999999999ULL, 9999999999999ULL, 99999999999999ULL, 999999999999999ULL, 9999999999999999ULL, 99999999999999999ULL, 999999999999999999ULL, 9999999999999999999ULL};
282 | NSUInteger low = 0, high = sizeof kValues / sizeof *kValues;
283 | while (high > low) {
284 | NSUInteger mid = (low + high)/2; //low + high cannot overflow
285 | if (val > kValues[mid]) {
286 | low = mid + 1;
287 | }
288 | else {
289 | high = mid;
290 | }
291 | }
292 | return MAX(1, low);
293 | }
294 |
295 | /*! Returns 1 + floor(log base 16 of val). If val is 0, returns 1. This works by computing the log base 2 based on the number of leading zeros, and then dividing by 4. */
296 | static inline NSUInteger HFCountDigitsBase16(unsigned long long val) {
297 | /* __builtin_clzll doesn't like being passed 0 */
298 | if (val == 0) return 1;
299 |
300 | /* Compute the log base 2 */
301 | NSUInteger leadingZeros = (NSUInteger)__builtin_clzll(val);
302 | NSUInteger logBase2 = (CHAR_BIT * sizeof val) - leadingZeros - 1;
303 | return 1 + logBase2/4;
304 | }
305 |
306 | /*! Returns YES if the given string encoding is a superset of ASCII. */
307 | BOOL HFStringEncodingIsSupersetOfASCII(NSStringEncoding encoding);
308 |
309 | /*! Converts an unsigned long long to NSUInteger. The unsigned long long should be no more than ULLONG_MAX. */
310 | static inline unsigned long ll2l(unsigned long long val) { assert(val <= NSUIntegerMax); return (unsigned long)val; }
311 |
312 | /*! Returns an unsigned long long, which must be no more than ULLONG_MAX, as an unsigned long. */
313 | static inline CGFloat ld2f(long double val) {
314 | #if ! NDEBUG
315 | if (isfinite(val)) {
316 | assert(val <= CGFLOAT_MAX);
317 | assert(val >= -CGFLOAT_MAX);
318 | if ((val > 0 && val < CGFLOAT_MIN) || (val < 0 && val > -CGFLOAT_MIN)) {
319 | NSLog(@"Warning - conversion of long double %Lf to CGFloat will result in the non-normal CGFloat %f", val, (CGFloat)val);
320 | }
321 | }
322 | #endif
323 | return (CGFloat)val;
324 | }
325 |
326 | /*! Returns the quotient of a divided by b, rounding up, for unsigned long longs. Will not overflow. */
327 | static inline unsigned long long HFDivideULLRoundingUp(unsigned long long a, unsigned long long b) {
328 | if (a == 0) return 0;
329 | else return ((a - 1) / b) + 1;
330 | }
331 |
332 | /*! Returns the quotient of a divided by b, rounding up, for NSUIntegers. Will not overflow. */
333 | static inline NSUInteger HFDivideULRoundingUp(NSUInteger a, NSUInteger b) {
334 | if (a == 0) return 0;
335 | else return ((a - 1) / b) + 1;
336 | }
337 |
338 | /*! @brief An object wrapper for the HFRange type.
339 |
340 | A simple class responsible for holding an immutable HFRange as an object. Methods that logically work on multiple HFRanges usually take or return arrays of HFRangeWrappers. */
341 | @interface HFRangeWrapper : NSObject {
342 | @public
343 | HFRange range;
344 | }
345 |
346 | /*! Returns the HFRange for this HFRangeWrapper. */
347 | - (HFRange)HFRange;
348 |
349 | /*! Creates an autoreleased HFRangeWrapper for this HFRange. */
350 | + (HFRangeWrapper *)withRange:(HFRange)range;
351 |
352 | /*! Creates an NSArray of HFRangeWrappers for this HFRange. */
353 | + (NSArray *)withRanges:(const HFRange *)ranges count:(NSUInteger)count;
354 |
355 | /*! Given an NSArray of HFRangeWrappers, get all of the HFRanges into a C array. */
356 | + (void)getRanges:(HFRange *)ranges fromArray:(NSArray *)array;
357 |
358 | /*! Given an array of HFRangeWrappers, returns a "cleaned up" array of equivalent ranges. This new array represents the same indexes, but overlapping ranges will have been merged, and the ranges will be sorted in ascending order. */
359 | + (NSArray *)organizeAndMergeRanges:(NSArray *)inputRanges;
360 |
361 | @end
362 |
363 | #ifndef NDEBUG
364 | void HFStartTiming(const char *name);
365 | void HFStopTiming(void);
366 | #endif
367 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFHexTextRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFHexTextRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/3/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFHexTextRepresenter
12 |
13 | @brief HFHexTextRepresenter is an HFRepresenter responsible for showing data in hexadecimal form.
14 |
15 | HFHexTextRepresenter is an HFRepresenter responsible for showing data in hexadecimal form. It has no methods except those inherited from HFTextRepresenter.
16 | */
17 | @interface HFHexTextRepresenter : HFTextRepresenter {
18 | unsigned long long omittedNybbleLocation;
19 | unsigned char unpartneredLastNybble;
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFLayoutRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFLayoutRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 12/10/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFLayoutRepresenter
12 | @brief An HFRepresenter responsible for arranging the views of other HFRepresenters attached to the same HFController.
13 |
14 | HFLayoutRepresenter is an HFRepresenter that manages the views of other HFRepresenters. It arranges their views in its own view, mediating between them to determine their position and size, as well as global properties such as bytes per line.
15 |
16 | HFLayoutRepresenter has an array of representers attached to it. When you add an HFRepresenter to this array, HFLayoutRepresenter will add the view of the representer as a subview of its own view.
17 |
18 | \b Layout
19 |
20 | HFLayoutRepresenter is capable of arranging the views of other HFRepresenters to fit within the bounds of its view. The layout process depends on three things:
21 |
22 | -# The \c frame and \c autoresizingMask of the representers' views.
23 | -# The \c minimumViewWidthForBytesPerLine: method, which determines the largest number of bytes per line that the representer can display for a given view width.
24 | -# The representer's \c layoutPosition. This is an NSPoint, but it is not used geometrically. Instead, the relative values of the X and Y coordinates of the \c layoutPosition determine the relative positioning of the views, as described below.
25 |
26 | Thus, to have your subclass of HFRepresenter participate in the HFLayoutRepresenter system, override \c defaultLayoutPosition: to control its positioning, and possibly \\c minimumViewWidthForBytesPerLine: if your representer requires a certain width to display some bytes per line. Then ensure your view has its autoresizing mask set properly, and if its frame is fixed size, ensure that its frame is correct as well.
27 |
28 | The layout process, in detail, is:
29 |
30 | -# The views are sorted vertically by the Y component of their representers' \c layoutPosition into "slices." Smaller values appear towards the bottom of the layout view. There is no space between slices.
31 | -# Views with equal Y components are sorted horizontally by the X component of their representers' \c layoutPosition, with smaller values appearing on the left.
32 | -# The height of each slice is determined by the tallest view within it, excluding views that have \c NSViewHeightSizable set. If there is any leftover vertical space, it is distributed equally among all slices with at least one view with \c NSViewHeightSizable set.
33 | -# If the layout representer is not set to maximize the bytes per line (BPL), then the BPL from the HFController is used. Otherwise:
34 | -# Each representer is queried for its \c minimumViewWidthForBytesPerLine:
35 | -# The largest BPL allowing each row to fit within the layout width is determined via a binary search.
36 | -# The BPL is rounded down to a multiple of the bytes per column (if non-zero).
37 | -# The BPL is then set on the controller.
38 | -# For each row, each view is assigned its minimum view width for the BPL.
39 | -# If there is any horizontal space left over, it is divided evenly between all views in that slice that have \c NSViewWidthSizable set in their autoresizing mask.
40 |
41 | */
42 | @interface HFLayoutRepresenter : HFRepresenter {
43 | NSMutableArray *representers;
44 | BOOL maximizesBytesPerLine;
45 |
46 | }
47 |
48 | /*! @name Managed representers
49 | Managing the list of representers laid out by the receiver
50 | */
51 | //@{
52 | /*! Return the array of representers managed by the receiver. */
53 | - (NSArray *)representers;
54 |
55 | /*! Adds a new representer to the receiver, triggering relayout. */
56 | - (void)addRepresenter:(HFRepresenter *)representer;
57 |
58 | /*! Removes a representer to the receiver (which must be present in the receiver's array of representers), triggering relayout. */
59 | - (void)removeRepresenter:(HFRepresenter *)representer;
60 | //@}
61 |
62 | /*! @name Configuration
63 | */
64 | //@{
65 | /*! Sets whether the receiver will attempt to maximize the bytes per line so as to consume as much as possible of the bounds rect. If this is YES, then upon relayout, the receiver will recalculate the maximum number of bytes per line that can fit in its boundsRectForLayout. If this is NO, then the receiver will not change the bytes per line. */
66 | - (void)setMaximizesBytesPerLine:(BOOL)val;
67 |
68 | /*! Returns whether the receiver maximizes the bytes per line. */
69 | - (BOOL)maximizesBytesPerLine;
70 | //@}
71 |
72 | /*! @name Layout
73 | Methods to get information about layout, and to explicitly trigger it.
74 | */
75 | //@{
76 | /*! Returns the smallest width that produces the same layout (and, if maximizes bytesPerLine, the same bytes per line) as the proposed width. */
77 | - (CGFloat)minimumViewWidthForLayoutInProposedWidth:(CGFloat)proposedWidth;
78 |
79 | /*! Relayouts are triggered when representers are added and removed, or when the view is resized. You may call this explicitly to trigger a relayout. */
80 | - (void)performLayout;
81 | //@}
82 |
83 | @end
84 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFLineCountingRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFLineCountingRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/26/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @enum HFLineNumberFormat
12 | HFLineNumberFormat is a simple enum used to determine whether line numbers are in decimal or hexadecimal format.
13 | */
14 | enum
15 | {
16 | HFLineNumberFormatDecimal, //!< Decimal line numbers
17 | HFLineNumberFormatHexadecimal, //!< Hexadecimal line numbers
18 | HFLineNumberFormatMAXIMUM //!< One more than the maximum valid line number format, so that line number formats can be cycled through easily
19 | };
20 | typedef NSUInteger HFLineNumberFormat;
21 |
22 | /*! @class HFLineCountingRepresenter
23 | @brief The HFRepresenter used to show the "line number gutter."
24 |
25 | HFLineCountingRepresenter is the HFRepresenter used to show the "line number gutter." HFLineCountingRepresenter makes space for a certain number of digits.
26 | */
27 | @interface HFLineCountingRepresenter : HFRepresenter {
28 | CGFloat lineHeight;
29 | NSUInteger digitsToRepresentContentsLength;
30 | NSUInteger minimumDigitCount;
31 | HFLineNumberFormat lineNumberFormat;
32 | CGFloat preferredWidth;
33 | CGFloat digitAdvance;
34 | }
35 |
36 | /*! Sets the minimum digit count. The receiver will always ensure it is big enough to display at least the minimum digit count. The default is 2. */
37 | - (void)setMinimumDigitCount:(NSUInteger)count;
38 |
39 | /*! Gets the minimum digit count. */
40 | - (NSUInteger)minimumDigitCount;
41 |
42 | /*! Returns the number of digits we are making space for. */
43 | - (NSUInteger)digitCount;
44 |
45 | /*! Returns the current width that the HFRepresenter prefers to be laid out with. */
46 | - (CGFloat)preferredWidth;
47 |
48 | /*! Returns the current line number format. */
49 | - (HFLineNumberFormat)lineNumberFormat;
50 |
51 | /*! Sets the current line number format to a new format. */
52 | - (void)setLineNumberFormat:(HFLineNumberFormat)format;
53 |
54 | /*! Switches to the next line number format. This is called from the view. */
55 | - (void)cycleLineNumberFormat;
56 |
57 | @end
58 |
59 | /*! Notification posted when the HFLineCountingRepresenter's width has changed because the number of digits it wants to show has increased or decreased. The object is the HFLineCountingRepresenter; there is no user info.
60 | */
61 | extern NSString *const HFLineCountingRepresenterMinimumViewWidthChanged;
62 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFProgressTracker.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFProgressTracker.h
3 | // HexFiend_2
4 | //
5 | // Created by peter on 2/12/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*!
12 | @class HFProgressTracker
13 | @brief A class that helps handle progress indication and cancellation for long running threaded operations.
14 |
15 | HFProgressTracker is a class that helps handle progress indication and cancellation for long running threaded operations, while imposing minimal overhead. Operations such as Find/Replace or Save take an HFProgressTracker to provide cancellation and progress reporting.
16 |
17 | The thread is expected to write directly into the public currentProgress field (with atomic functions) as it makes progress. Once beginTrackingProgress is called, the HFProgressTracker will poll currentProgress until endTrackingProgress is called.
18 |
19 | The thread is also expected to read directly from cancelRequested, which is set by the requestCancel method. If requestCancel is set, it should end the operation.
20 |
21 | Lastly, the thread is expected to call noteFinished: when it is done, either through cancellation or completing normally.
22 |
23 | On the client side, you can set a delegate. progressTracker: didChangeProgressTo: is called on your delegate at regular intervals in the main thread, as the progress changes. Likewise, progressTrackerDidFinish: is called on the main thread after noteFinished: is called.
24 |
25 | There is also a progressIndicator property, which if set to an NSProgressIndicator will cause it to be updated regularly.
26 |
27 | To use HFProgressTracker as a client:
28 |
29 |
30 | */
31 |
32 | @interface HFProgressTracker : NSObject {
33 | @public
34 | volatile unsigned long long currentProgress;
35 | volatile int cancelRequested;
36 | @private
37 | unsigned long long maxProgress;
38 | NSProgressIndicator *progressIndicator;
39 | NSTimer *progressTimer;
40 | double lastSetValue;
41 | NSDictionary *userInfo;
42 | id delegate;
43 | }
44 |
45 | /*!
46 | HFProgressTracker determines the progress as an unsigned long long, but passes the progress to the delegate as a double, which is computed as the current progress divided by the max progress.
47 | */
48 | - (void)setMaxProgress:(unsigned long long)max;
49 | - (unsigned long long)maxProgress;
50 |
51 | /*!
52 | The userInfo property is a convenience to allow passing information to the thread. The property is not thread safe - the expectation is that the main thread will set it before the operation starts, and the background thread will read it once after the operation starts.
53 | */
54 | - (void)setUserInfo:(NSDictionary *)info;
55 | - (NSDictionary *)userInfo;
56 |
57 | /*!
58 | The progressIndicator property allows an NSProgressIndicator to be associated with the HFProgressTracker. The progress indicator should have values in the range 0 to 1, and it will be updated with the fraction currentProgress / maxProgress.
59 | */
60 | - (void)setProgressIndicator:(NSProgressIndicator *)indicator;
61 | - (NSProgressIndicator *)progressIndicator;
62 |
63 | /*!
64 | Called to indicate you want to begin tracking the progress, which means that the progress indicator will be updated, and the delegate callbacks may fire.
65 | */
66 | - (void)beginTrackingProgress;
67 |
68 | /*!
69 | Called to indicate you want to end tracking progress. The progress indicator will no longer be updated.
70 | */
71 | - (void)endTrackingProgress;
72 |
73 | /*!
74 | noteFinished: should be called by the thread when it is done. It is safe to call this from the background thread.
75 | */
76 | - (void)noteFinished:(id)sender;
77 |
78 | /*!
79 | requestCancel: may be called to mark the cancelRequested variable. The thread should poll this variable to determine if it needs to cancel.
80 | */
81 | - (void)requestCancel:(id)sender;
82 |
83 | /*!
84 | Set and get the delegate, which may implement the optional methods below.
85 | */
86 | - (void)setDelegate:(id)delegate;
87 | - (id)delegate;
88 |
89 | @end
90 |
91 |
92 | /*!
93 | @protocol HFProgressTrackerDelegate
94 | @brief The delegate methods for the HFProgressTracker class.
95 |
96 | The HFProgressTrackerDelegate methods are called on the the HFProgressTracker's delegate. These are always called on the main thread.
97 | */
98 | @protocol HFProgressTrackerDelegate
99 |
100 | /*!
101 | Once beginTrackingProgress is called, this is called on the delegate at regular intervals to report on the new progress.
102 | */
103 | - (void)progressTracker:(HFProgressTracker *)tracker didChangeProgressTo:(double)fraction;
104 |
105 | /*!
106 | Once the thread has called noteFinished:, this is called on the delegate in the main thread to report that the background thread is done.
107 | */
108 | - (void)progressTrackerDidFinish:(HFProgressTracker *)tracker;
109 |
110 | @end
111 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/3/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | /*! @class HFRepresenter
13 | @brief The principal view class of Hex Fiend's MVC architecture.
14 |
15 | HFRepresenter is a class that visually represents some property of the HFController, such as the data (in various formats), the scroll position, the line number, etc. An HFRepresenter is added to an HFController and then gets notified of changes to various properties, through the controllerDidChange: methods.
16 |
17 | HFRepresenters also have a view, accessible through the -view method. The HFRepresenter is expected to update its view to reflect the relevant properties of its HFController. If the user can interact with the view, then the HFRepresenter should pass any changes down to the HFController, which will subsequently notify all HFRepresenters of the change.
18 |
19 | HFRepresenter is an abstract class, with a different subclass for each possible view type. Because HFController interacts with HFRepresenters, rather than views directly, an HFRepresenter can use standard Cocoa views and controls.
20 |
21 | To add a new view type:
22 |
23 | -# Create a subclass of HFRepresenter
24 | -# Override \c -createView to return a view (note that this method should transfer ownership)
25 | -# Override \c -controllerDidChange:, checking the bitmask to see what properties have changed and updating your view as appropriate
26 | -# If you plan on using this view together with other views, override \c +defaultLayoutPosition to control how your view gets positioned in an HFLayoutRepresenter
27 | -# If your view's width depends on the properties of the controller, override some of the measurement methods, such as \c +maximumBytesPerLineForViewWidth:, so that your view gets sized correctly
28 |
29 | */
30 | @interface HFRepresenter : NSObject {
31 | @private
32 | id view;
33 | HFController *controller;
34 | NSPoint layoutPosition;
35 | }
36 |
37 | /*! @name View management
38 | Methods related to accessing and initializing the representer's view.
39 | */
40 | //@{
41 | /*! Returns the view for the receiver, creating it if necessary. The view for the HFRepresenter is initially nil. When the \c -view method is called, if the view is nil, \c -createView is called and then the result is stored. This method should not be overridden; however you may want to call it to access the view.
42 | */
43 | - (id)view;
44 |
45 | /*! Override point for creating the view displaying this representation. This is called on your behalf the first time the \c -view method is called, so you would not want to call this explicitly; however this method must be overridden. This follows the "create" rule, and so it should return a retained view.
46 | */
47 | - (NSView *)createView;
48 |
49 | /*! Override point for initialization of view, after the HFRepresenter has the view set as its -view property. The default implementation does nothing.
50 | */
51 | - (void)initializeView;
52 |
53 | //@}
54 |
55 | /*! @name Accessing the HFController
56 | */
57 | //@{
58 | /*! Returns the HFController for the receiver. This is set by the controller from the call to \c addRepresenter:. A representer can only be in one controller at a time. */
59 | - (HFController *)controller;
60 | //@}
61 |
62 | /*! @name Property change notifications
63 | */
64 | //@{
65 | /*! Indicates that the properties indicated by the given bits did change, and the view should be updated as to reflect the appropriate properties. This is the main mechanism by which representers are notified of changes to the controller.
66 | */
67 | - (void)controllerDidChange:(HFControllerPropertyBits)bits;
68 | //@}
69 |
70 | /*! @name HFController convenience methods
71 | Convenience covers for certain HFController methods
72 | */
73 | //@{
74 | /*! Equivalent to [[self controller] bytesPerLine] */
75 | - (NSUInteger)bytesPerLine;
76 |
77 | /*! Equivalent to [[self controller] bytesPerColumn] */
78 | - (NSUInteger)bytesPerColumn;
79 |
80 | /*! Equivalent to [[self controller] representer:self changedProperties:properties] . You may call this when some internal aspect of the receiver's view (such as its frame) has changed in a way that may globally change some property of the controller, and the controller should recalculate those properties. For example, the text representers call this with HFControllerDisplayedLineRange when the view grows vertically, because more data may be displayed.
81 | */
82 | - (void)representerChangedProperties:(HFControllerPropertyBits)properties;
83 | //@}
84 |
85 | /*! @name Measurement
86 | Methods related to measuring the HFRepresenter, so that it can be laid out properly by an HFLayoutController. All of these methods are candidates for overriding.
87 | */
88 | //@{
89 | /*! Returns the maximum number of bytes per line for the given view size. The default value is NSUIntegerMax, which means that the representer can display any number of lines for the given view size. */
90 | - (NSUInteger)maximumBytesPerLineForViewWidth:(CGFloat)viewWidth;
91 |
92 | /*! Returns the minimum view frame size for the given bytes per line. Default is to return 0, which means that the representer can display the given bytes per line in any view size. Fixed width views should return their fixed width. */
93 | - (CGFloat)minimumViewWidthForBytesPerLine:(NSUInteger)bytesPerLine;
94 |
95 | /*! Returns the maximum number of lines that could be displayed at once for a given view height. Default is to return DBL_MAX. */
96 | - (double)maximumAvailableLinesForViewHeight:(CGFloat)viewHeight;
97 | //@}
98 |
99 | /*! @name Auto-layout methods
100 | Methods for simple auto-layout by HFLayoutRepresenter. See the HFLayoutRepresenter class for discussion of how it lays out representer views.
101 | */
102 | //@{
103 |
104 | /*! Sets the receiver's layout position to the given value.
105 | */
106 | - (void)setLayoutPosition:(NSPoint)position;
107 |
108 | /*! Returns the layout position for the receiver.
109 | */
110 | - (NSPoint)layoutPosition;
111 |
112 | /*! Returns the default layout position for representers of this class. Within the -init method, the view's layout position is set to the default for this class. You may override this to control the default layout position. See HFLayoutRepresenter for a discussion of the significance of the layout postition.
113 | */
114 | + (NSPoint)defaultLayoutPosition;
115 |
116 | //@}
117 |
118 |
119 | @end
120 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFSharedMemoryByteSlice.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFSharedMemoryByteSlice.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 2/17/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFSharedMemoryByteSlice
12 | @brief A subclass of HFByteSlice for working with data stored in memory.
13 |
14 | HFSharedMemoryByteSlice is a subclass of HFByteSlice that represents a portion of data from memory, e.g. typed or pasted in by the user. The term "shared" refers to the ability for mutiple HFSharedMemoryByteSlices to reference the same NSData; it does not mean that the data is in shared memory or shared between processes.
15 |
16 | Instances of HFSharedMemoryByteSlice are immutable (like all instances of HFByteSlice). However, to support efficient typing, the backing data is an instance of NSMutableData that may be grown. A referenced range of the NSMutableData will never have its contents changed, but it may be allowed to grow larger, so that the data does not have to be copied merely to append a single byte. This is implemented by overriding the -byteSliceByAppendingSlice: method of HFByteSlice.
17 | */
18 | @interface HFSharedMemoryByteSlice : HFByteSlice {
19 | NSMutableData *data;
20 | NSUInteger offset;
21 | NSUInteger length;
22 | unsigned char inlineTailLength;
23 | unsigned char inlineTail[15]; //size chosen to exhaust padding of 32-byte allocator
24 | }
25 |
26 | // copies the data
27 | - (id)initWithUnsharedData:(NSData *)data;
28 |
29 | // retains, does not copy
30 | - (id)initWithData:(NSMutableData *)data;
31 | - (id)initWithData:(NSMutableData *)data offset:(NSUInteger)offset length:(NSUInteger)length;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFStatusBarRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFStatusBarRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 12/16/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @enum HFStatusBarMode
12 | The HFStatusBarMode enum is used to describe the format of the byte counts displayed by the status bar.
13 | */
14 | enum {
15 | HFStatusModeDecimal, ///< The status bar should display byte counts in decimal
16 | HFStatusModeHexadecimal, ///< The status bar should display byte counts in hexadecimal
17 | HFStatusModeApproximate, ///< The text should display byte counts approximately (e.g. "56.3 KB")
18 | HFSTATUSMODECOUNT ///< The number of modes, to allow easy cycling
19 | };
20 | typedef NSUInteger HFStatusBarMode;
21 |
22 | /*! @class HFStatusBarRepresenter
23 | @brief The HFRepresenter for the status bar.
24 |
25 | HFStatusBarRepresenter is a subclass of HFRepresenter responsible for showing the status bar, which displays information like the total length of the document, or the number of selected bytes.
26 | */
27 | @interface HFStatusBarRepresenter : HFRepresenter {
28 | HFStatusBarMode statusMode;
29 | }
30 |
31 | - (HFStatusBarMode)statusMode;
32 | - (void)setStatusMode:(HFStatusBarMode)mode;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFStringEncodingTextRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFASCIITextRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/11/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFStringEncodingTextRepresenter
12 |
13 | @brief An HFRepresenter responsible for showing data interpreted via an NSStringEncoding.
14 |
15 | HFHexTextRepresenter is an HFRepresenter responsible for showing and editing data interpreted via an NSStringEncoding. Currently only supersets of ASCII are supported.
16 | */
17 | @interface HFStringEncodingTextRepresenter : HFTextRepresenter {
18 | NSStringEncoding stringEncoding;
19 | }
20 |
21 | /*! Get the string encoding for this representer. The default encoding is [NSString defaultCStringEncoding]. */
22 | - (NSStringEncoding)encoding;
23 |
24 | /*! Set the string encoding for this representer. */
25 | - (void)setEncoding:(NSStringEncoding)encoding;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFTextField.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFTextField.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 2/2/08.
6 | // Copyright 2008 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class HFLayoutRepresenter, HFRepresenter, HFController, HFHexTextRepresenter, HFStringEncodingTextRepresenter;
12 |
13 | /*! @class HFTextField
14 | @brief A high-level view class that is analagous to NSTextField.
15 |
16 | HFTextField encapsulates a HFController and HFRepresenters into a single "do it all" NSControl analagous to NSTextField. Its objectValue is an HFByteArray. It sends its \c action to its \c target when the user hits return. It has no control.
17 |
18 | An HFTextField can be configured to show a hexadecimal view, an ASCII (really the \c defaultCStringEncoding) view, or both.
19 |
20 | This class is currently missing a fair amount of functionality, such as enabled or editable state.
21 | */
22 |
23 | @interface HFTextField : NSControl {
24 | HFController *dataController;
25 | HFLayoutRepresenter *layoutRepresenter;
26 | HFHexTextRepresenter *hexRepresenter;
27 | HFStringEncodingTextRepresenter *textRepresenter;
28 | IBOutlet id target;
29 | SEL action;
30 | }
31 |
32 | /*! Returns whether the hexadecimal view is shown. */
33 | - (BOOL)usesHexArea;
34 |
35 | /*! Sets whether the hexadecimal view is shown. */
36 | - (void)setUsesHexArea:(BOOL)val;
37 |
38 | /*! Returns whether the ASCII view is shown. */
39 | - (BOOL)usesTextArea;
40 |
41 | /*! Sets whether the ASCII view is shown. */
42 | - (void)setUsesTextArea:(BOOL)val;
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFTextRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFTextRepresenter.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/3/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | /*! @class HFTextRepresenter
13 | @brief An HFRepresenter that draws text (e.g. the hex or ASCII view).
14 |
15 | HFTextRepresenter is an abstract subclass of HFRepresenter that is responsible for displaying text. There are two concrete subclass, HFHexTextRepresenter and HFStringEncodingTextRepresenter.
16 |
17 | Most of the functionality of HFTextRepresenter is private, and there is not yet enough exposed to allow creating new representers based on it. However, there is a small amount of configurability.
18 | */
19 | @interface HFTextRepresenter : HFRepresenter {
20 | BOOL behavesAsTextField;
21 | NSArray *rowBackgroundColors;
22 | }
23 |
24 |
25 | /*! Returns the per-row background colors. The default is -[NSControl controlAlternatingRowBackgroundColors]. */
26 | - (NSArray *)rowBackgroundColors;
27 |
28 | /*! Sets the per-row background colors. Each row is drawn with the next color in turn, cycling back to the beginning when the array is exhausted. Any empty space is filled with the first color in the array. If the array is empty, then the background is drawn with \c clearColor. */
29 | - (void)setRowBackgroundColors:(NSArray *)colors;
30 |
31 | /*! Set whether the text view behaves like a text field (YES) or a text view (NO). Currently this determines whether it draws a focus ring when it is the first responder.
32 | */
33 | - (void)setBehavesAsTextField:(BOOL)val;
34 |
35 | /*! Returns whether the text view behaves like a text field (YES) or a text view (NO).
36 | */
37 | - (BOOL)behavesAsTextField;
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFTextView.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFTextView.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 6/28/09.
6 | // Copyright 2009 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @class HFLayoutRepresenter;
13 |
14 | /*! @class HFTextView
15 | @brief A high-level view class analagous to NSTextView.
16 |
17 | HFTextField encapsulates a HFController and HFRepresenters into a single "do it all" NSControl analagous to NSTextView.
18 | */
19 | @interface HFTextView : NSControl {
20 | HFController *dataController;
21 | HFLayoutRepresenter *layoutRepresenter;
22 | NSArray *backgroundColors;
23 | BOOL bordered;
24 | IBOutlet id delegate;
25 | NSData *cachedData;
26 | }
27 |
28 | /*! @name Accessing MVC components
29 | */
30 | //@{
31 | /*! Returns the HFLayoutRepresenter for the receiver. You may want to access this to add or remove HFRepresenters from the text view at runtime. */
32 | - (HFLayoutRepresenter *)layoutRepresenter;
33 |
34 | /*! Returns the HFController for the receiver. You may want to access this to add or remove HFRepresenters from the text view at runtime. */
35 | - (HFController *)controller;
36 |
37 | /*! Returns the HFByteArray for the receiver. This is equivalent to [[self controller] byteArray]. */
38 | - (HFByteArray *)byteArray;
39 |
40 | //@}
41 |
42 | /*! @name Display configuration
43 | */
44 | //@{
45 | /*! Sets the arry of background colors for the receiver. The background colors are used in sequence to draw each row. */
46 | - (void)setBackgroundColors:(NSArray *)colors;
47 |
48 | /*! Returns the array of background colors for the receiver. */
49 | - (NSArray *)backgroundColors;
50 |
51 | /*! Sets whether the receiver draws a border. */
52 | - (void)setBordered:(BOOL)val;
53 |
54 | /*! Returns whether the receiver draws a border. */
55 | - (BOOL)bordered;
56 | //@}
57 |
58 | /*! @name Delegate handling
59 | */
60 | //@{
61 | /*! Sets the delegate, which may implement the methods in HFTextViewDelegate */
62 | - (void)setDelegate:(id)delegate;
63 |
64 | /*! Returns the delegate, which is initially nil. */
65 | - (id)delegate;
66 | //@}
67 |
68 | /*! @name Accessing contents as NSData
69 | */
70 | //@{
71 | /*! Returns the contents of the HFTextView's HFByteArray as an NSData This NSData proxies an HFByteArray, and therefore it is usually more efficient than naively copying all of the bytes. However, access to the \c -byte method will necessitate copying, a potentially expensive operation. Furthermore, the NSData API is inherently 32 bit in a 32 bit process. Lastly, there is no protection if the backing file for the data disappears.
72 |
73 | For those reasons, this should only be used when its convenience outweighs the downside (e.g. some bindings scenarios). For most use cases, it is better to use the \c -byteArray method above.
74 | */
75 | - (NSData *)data;
76 |
77 | /*! Sets the contents of the HFTextView's HFByteArray to an \c NSData. Note that the data is copied via the \c -copy message, so prefer to pass an immutable \c NSData when possible.
78 | */
79 | - (void)setData:(NSData *)data;
80 | //@}
81 |
82 | @end
83 |
84 | /*! @protocol HFTextViewDelegate
85 | @brief Delegate methods for HFTextView
86 | */
87 | @protocol HFTextViewDelegate
88 |
89 | /*! Called on the delegate when the HFTextView's HFController changed some properties. See the documentation for the #HFControllerPropertyBits enum. */
90 | - (void)hexTextView:(HFTextView *)view didChangeProperties:(HFControllerPropertyBits)properties;
91 |
92 | @end
93 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFTypes.h:
--------------------------------------------------------------------------------
1 | /* Hide this compatibility junk from Doxygen */
2 | #ifndef DOXYGEN_ONLY
3 |
4 | #ifndef NSINTEGER_DEFINED
5 | #if __LP64__ || NS_BUILD_32_LIKE_64
6 | typedef long NSInteger;
7 | typedef unsigned long NSUInteger;
8 | #else
9 | typedef int NSInteger;
10 | typedef unsigned int NSUInteger;
11 | #endif
12 | #define NSIntegerMax LONG_MAX
13 | #define NSIntegerMin LONG_MIN
14 | #define NSUIntegerMax ULONG_MAX
15 | #define NSINTEGER_DEFINED 1
16 | #endif
17 |
18 | #ifndef CGFLOAT_DEFINED
19 | #if defined(__LP64__) && __LP64__
20 | typedef double CGFloat;
21 | #define CGFLOAT_MIN DBL_MIN
22 | #define CGFLOAT_MAX DBL_MAX
23 | #define CGFLOAT_IS_DOUBLE 1
24 | #else /* !defined(__LP64__) || !__LP64__ */
25 | typedef float CGFloat;
26 | #define CGFLOAT_MIN FLT_MIN
27 | #define CGFLOAT_MAX FLT_MAX
28 | #define CGFLOAT_IS_DOUBLE 0
29 | #endif /* !defined(__LP64__) || !__LP64__ */
30 | #define CGFLOAT_DEFINED 1
31 | #endif
32 |
33 | #endif
34 |
35 | /*! @brief HFRange is the 64 bit analog of NSRange, containing a 64 bit location and length. */
36 | typedef struct {
37 | unsigned long long location;
38 | unsigned long long length;
39 | } HFRange;
40 |
41 | /*! @brief HFFPRange is a struct used for representing floating point ranges, similar to NSRange. It contains two long doubles.
42 |
43 | This is useful for (for example) showing the range of visible lines. A double-precision value has 53 significant bits in the mantissa - so we would start to have precision problems at the high end of the range we can represent. Long double has a 64 bit mantissa on Intel, which means that we would start to run into trouble at the very very end of our range - barely acceptable. */
44 | typedef struct {
45 | long double location;
46 | long double length;
47 | } HFFPRange;
48 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HFVerticalScrollerRepresenter.h:
--------------------------------------------------------------------------------
1 | //
2 | // HFRepresenterVerticalScroller.h
3 | // HexFiend_2
4 | //
5 | // Created by Peter Ammon on 11/12/07.
6 | // Copyright 2007 ridiculous_fish. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /*! @class HFVerticalScrollerRepresenter
12 | @brief An HFRepresenter responsible for showing a vertical scroll bar.
13 |
14 | HFVerticalScrollerRepresenter is an HFRepresenter whose view is a vertical NSScroller, that represents the current position within an HFController "document." It has no methods beyond those of HFRepresenter.
15 |
16 | As HFVerticalScrollerRepresenter is an especially simple representer, it makes for good sample code.
17 | */
18 | @interface HFVerticalScrollerRepresenter : HFRepresenter {
19 |
20 | }
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Headers/HexFiend.h:
--------------------------------------------------------------------------------
1 | /*! @mainpage HexFiend.framework
2 | *
3 | * @section intro Introduction
4 | * HexFiend.framework (hereafter "Hex Fiend" when there is no risk of confusion with the app by the same name) is a framework designed to enable applications to support viewing and editing of binary data. The emphasis is on editing data in a natural way, following Mac OS X text editing conventions.
5 | *
6 | * Hex Fiend is designed to work efficiently with large amounts (64 bits worth) of data. As such, it can work with arbitrarily large files without reading the entire file into memory. This includes insertions, deletions, and in-place editing. Hex Fiend can also efficiently save such changes back to the file, without requiring any additional temporary disk space.
7 | *
8 | * Hex Fiend has a clean separation between the model, view, and controller layers. The model layer allows for efficient manipulation of raw data of mixed sources, making it useful for tools that need to work with large files.
9 | *
10 | * Both the framework and the app are open source under a BSD-style license. In summary, you may use Hex Fiend in any project as long as you include the copyright notice somewhere in the documentation.
11 | *
12 | * @section requirements Requirements
13 | * Hex Fiend is only available on Mac OS X, and supported on Tiger and later. It is compiled "hybrid" (works with both garbage collection and reference counting) and 4-way fat (64 bit and 32 bit, PowerPC and Intel). Support for 64 bits worth of data is available in both 32 bit and 64 bit - there is no functional difference between the 32 bit and 64 bit versions.
14 | *
15 | * @section getting_started Getting Started
16 | *
17 | * The Hex Fiend source code is available at http://ridiculousfish.com/hexfiend/
18 | *
19 | * The easiest way to get started is to use the Interface Builder plugin to drag a hex view into your project! Hex Fiend also comes with some sample code ("HexFiendling"), distributed as part of the project. And of course the Hex Fiend application itself is open source, acting as a more sophisticated sample code.
20 | */
21 |
22 |
23 | #import
24 | #import
25 | #import
26 | #import
27 | #import
28 | #import
29 | #import
30 | #import
31 | #import
32 | #import
33 | #import
34 | #import
35 | #import
36 | #import
37 | #import
38 | #import
39 | #import
40 | #import
41 | #import
42 | #import
43 |
44 |
45 | /* The following is all for Doxygen */
46 |
47 |
48 | /*! @defgroup model Model
49 | * Hex Fiend's model classes
50 | */
51 | ///@{
52 | ///@class HFByteArray
53 | ///@class HFBTreeByteArray
54 | ///@class HFFullMemoryByteArray
55 | ///@class HFByteSlice
56 | ///@class HFFileByteSlice
57 | ///@class HFSharedMemoryByteSlice
58 | ///@class HFFullMemoryByteSlice
59 |
60 | ///@}
61 |
62 |
63 | /*! @defgroup view View
64 | * Hex Fiend's view classes
65 | */
66 | ///@{
67 | ///@class HFRepresenter
68 | ///@class HFHexTextRepresenter
69 | ///@class HFStringEncodingTextRepresenter
70 | ///@class HFLayoutRepresenter
71 | ///@class HFLineCountingRepresenter
72 | ///@class HFStatusBarRepresenter
73 | ///@class HFVerticalScrollerRepresenter
74 | ///@class HFLineCountingRepresenter
75 |
76 | ///@}
77 |
78 | /*! @defgroup controller Controller
79 | * Hex Fiend's controller classes
80 | */
81 | ///@{
82 | ///@class HFController
83 |
84 | ///@}
85 |
86 | /*! @defgroup highlevel High Level
87 | * Hex Fiend's "do it all" classes
88 | */
89 | ///@{
90 | ///@class HFTextView
91 | ///@class HFTextField
92 |
93 | ///@}
94 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/HexFiend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirg3/Sniffer/206ea800427cd250fb13aad8ed5807fe389c4d22/HexFiend.framework/Versions/A/HexFiend
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Resources/HFCancelOff.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirg3/Sniffer/206ea800427cd250fb13aad8ed5807fe389c4d22/HexFiend.framework/Versions/A/Resources/HFCancelOff.tiff
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Resources/HFCancelOn.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirg3/Sniffer/206ea800427cd250fb13aad8ed5807fe389c4d22/HexFiend.framework/Versions/A/Resources/HFCancelOn.tiff
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Resources/HFModalProgress.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sirg3/Sniffer/206ea800427cd250fb13aad8ed5807fe389c4d22/HexFiend.framework/Versions/A/Resources/HFModalProgress.nib
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleExecutable
8 | HexFiend
9 | CFBundleIdentifier
10 | com.ridiculousfish.HexFiend_Framework
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | FMWK
15 | CFBundleShortVersionString
16 | 2.0.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 200
21 |
22 |
23 |
--------------------------------------------------------------------------------
/HexFiend.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Library General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License
307 | along with this program; if not, write to the Free Software
308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
309 |
310 |
311 | Also add information on how to contact you by electronic and paper mail.
312 |
313 | If the program is interactive, make it output a short notice like this
314 | when it starts in an interactive mode:
315 |
316 | Gnomovision version 69, Copyright (C) year name of author
317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
318 | This is free software, and you are welcome to redistribute it
319 | under certain conditions; type `show c' for details.
320 |
321 | The hypothetical commands `show w' and `show c' should show the appropriate
322 | parts of the General Public License. Of course, the commands you use may
323 | be called something other than `show w' and `show c'; they could even be
324 | mouse-clicks or menu items--whatever suits your program.
325 |
326 | You should also get your employer (if you work as a programmer) or your
327 | school, if any, to sign a "copyright disclaimer" for the program, if
328 | necessary. Here is a sample; alter the names:
329 |
330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
331 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
332 |
333 | , 1 April 1989
334 | Ty Coon, President of Vice
335 |
336 | This General Public License does not permit incorporating your program into
337 | proprietary programs. If your program is a subroutine library, you may
338 | consider it more useful to permit linking proprietary applications with the
339 | library. If this is what you want to do, use the GNU Library General
340 | Public License instead of this License.
341 |
--------------------------------------------------------------------------------
/PrettyCell.h:
--------------------------------------------------------------------------------
1 | /*
2 | IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
3 | consideration of your agreement to the following terms, and your use, installation,
4 | modification or redistribution of this Apple software constitutes acceptance of these
5 | terms. If you do not agree with these terms, please do not use, install, modify or
6 | redistribute this Apple software.
7 |
8 | In consideration of your agreement to abide by the following terms, and subject to these
9 | terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in
10 | this original Apple software (the "Apple Software"), to use, reproduce, modify and
11 | redistribute the Apple Software, with or without modifications, in source and/or binary
12 | forms; provided that if you redistribute the Apple Software in its entirety and without
13 | modifications, you must retain this notice and the following text and disclaimers in all
14 | such redistributions of the Apple Software. Neither the name, trademarks, service marks
15 | or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
16 | the Apple Software without specific prior written permission from Apple. Except as expressly
17 | stated in this notice, no other rights or licenses, express or implied, are granted by Apple
18 | herein, including but not limited to any patent rights that may be infringed by your
19 | derivative works or by other works in which the Apple Software may be incorporated.
20 |
21 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES,
22 | EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
23 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
24 | USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
25 |
26 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
29 | REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
30 | WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
31 | OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 |
34 | #import
35 |
36 |
37 | @interface PrettyCell : NSTextFieldCell {
38 | @private
39 | NSImage *image;
40 | }
41 |
42 | - (void)setImage:(NSImage *)anImage;
43 | - (NSImage *)image;
44 |
45 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView;
46 | - (NSSize)cellSize;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/PrettyCell.m:
--------------------------------------------------------------------------------
1 | /*
2 | IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
3 | consideration of your agreement to the following terms, and your use, installation,
4 | modification or redistribution of this Apple software constitutes acceptance of these
5 | terms. If you do not agree with these terms, please do not use, install, modify or
6 | redistribute this Apple software.
7 |
8 | In consideration of your agreement to abide by the following terms, and subject to these
9 | terms, Apple grants you a personal, non-exclusive license, under Apple’s copyrights in
10 | this original Apple software (the "Apple Software"), to use, reproduce, modify and
11 | redistribute the Apple Software, with or without modifications, in source and/or binary
12 | forms; provided that if you redistribute the Apple Software in its entirety and without
13 | modifications, you must retain this notice and the following text and disclaimers in all
14 | such redistributions of the Apple Software. Neither the name, trademarks, service marks
15 | or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
16 | the Apple Software without specific prior written permission from Apple. Except as expressly
17 | stated in this notice, no other rights or licenses, express or implied, are granted by Apple
18 | herein, including but not limited to any patent rights that may be infringed by your
19 | derivative works or by other works in which the Apple Software may be incorporated.
20 |
21 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO WARRANTIES,
22 | EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
23 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
24 | USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
25 |
26 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
29 | REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
30 | WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
31 | OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 | */
33 |
34 | #import "PrettyCell.h"
35 |
36 |
37 | @implementation PrettyCell
38 | - (id)init {
39 | if (self = [super init]) {
40 | [self setLineBreakMode:NSLineBreakByTruncatingTail];
41 | [self setSelectable:YES];
42 | }
43 | return self;
44 | }
45 |
46 | - (void)dealloc {
47 | [image release];
48 | [super dealloc];
49 | }
50 |
51 | - (id)copyWithZone:(NSZone *)zone {
52 | PrettyCell *cell = (PrettyCell *)[super copyWithZone:zone];
53 | // The image ivar will be directly copied; we need to retain or copy it.
54 | cell->image = [image retain];
55 | return cell;
56 | }
57 |
58 | - (void)setImage:(NSImage *)anImage {
59 | if (anImage != image) {
60 | [image release];
61 | image = [anImage retain];
62 | }
63 | }
64 |
65 | - (NSImage *)image {
66 | return image;
67 | }
68 |
69 | - (NSRect)imageRectForBounds:(NSRect)cellFrame {
70 | NSRect result;
71 | if (image != nil) {
72 | result.size = [image size];
73 | result.origin = cellFrame.origin;
74 | result.origin.x += 1;
75 | result.origin.y += ceil((cellFrame.size.height - result.size.height) / 2);
76 | } else {
77 | result = NSZeroRect;
78 | }
79 | return result;
80 | }
81 |
82 | // We could manually implement expansionFrameWithFrame:inView: and drawWithExpansionFrame:inView: or just properly implement titleRectForBounds to get expansion tooltips to automatically work for us
83 | - (NSRect)titleRectForBounds:(NSRect)cellFrame {
84 | NSRect result;
85 | if (image != nil) {
86 | CGFloat imageWidth = [image size].width;
87 | result = cellFrame;
88 | result.origin.x += (7 + imageWidth);
89 | result.size.width -= (7 + imageWidth);
90 | } else {
91 | result = NSZeroRect;
92 | }
93 | return result;
94 | }
95 |
96 |
97 | - (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent *)theEvent {
98 | NSRect textFrame, imageFrame;
99 | NSDivideRect (aRect, &imageFrame, &textFrame, 7 + [image size].width, NSMinXEdge);
100 | [super editWithFrame: textFrame inView: controlView editor:textObj delegate:anObject event: theEvent];
101 | }
102 |
103 | - (void)selectWithFrame:(NSRect)aRect inView:(NSView *)controlView editor:(NSText *)textObj delegate:(id)anObject start:(NSInteger)selStart length:(NSInteger)selLength {
104 | NSRect textFrame, imageFrame;
105 | NSDivideRect (aRect, &imageFrame, &textFrame, 7 + [image size].width, NSMinXEdge);
106 | [super selectWithFrame: textFrame inView: controlView editor:textObj delegate:anObject start:selStart length:selLength];
107 | }
108 |
109 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
110 | if (image != nil) {
111 | NSRect imageFrame;
112 | NSSize imageSize = [image size];
113 | NSDivideRect(cellFrame, &imageFrame, &cellFrame, 5 + imageSize.width, NSMinXEdge);
114 | if ([self drawsBackground]) {
115 | [[self backgroundColor] set];
116 | NSRectFill(imageFrame);
117 | }
118 | imageFrame.origin.x += 5;
119 | imageFrame.size = imageSize;
120 |
121 | if ([controlView isFlipped])
122 | imageFrame.origin.y += ceil((cellFrame.size.height + imageFrame.size.height) / 2);
123 | else
124 | imageFrame.origin.y += ceil((cellFrame.size.height - imageFrame.size.height) / 2);
125 |
126 | [image compositeToPoint:imageFrame.origin operation:NSCompositeSourceOver];
127 | }
128 | [super drawWithFrame:cellFrame inView:controlView];
129 | }
130 |
131 | - (NSSize)cellSize {
132 | NSSize cellSize = [super cellSize];
133 | cellSize.width += (image ? [image size].width : 0) + 1;
134 | return cellSize;
135 | }
136 |
137 | - (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView {
138 | NSPoint point = [controlView convertPoint:[event locationInWindow] fromView:nil];
139 | // If we have an image, we need to see if the user clicked on the image portion.
140 | if (image != nil) {
141 | // This code closely mimics drawWithFrame:inView:
142 | NSSize imageSize = [image size];
143 | NSRect imageFrame;
144 | NSDivideRect(cellFrame, &imageFrame, &cellFrame, 1 + imageSize.width, NSMinXEdge);
145 |
146 | imageFrame.origin.x += 1;
147 | imageFrame.size = imageSize;
148 | // If the point is in the image rect, then it is a content hit
149 | if (NSMouseInRect(point, imageFrame, [controlView isFlipped])) {
150 | // We consider this just a content area. It is not trackable, nor it it editable text. If it was, we would or in the additional items.
151 | // By returning the correct parts, we allow NSTableView to correctly begin an edit when the text portion is clicked on.
152 | return NSCellHitContentArea;
153 | }
154 | }
155 | // At this point, the cellFrame has been modified to exclude the portion for the image. Let the superclass handle the hit testing at this point.
156 | return [super hitTestForEvent:event inRect:cellFrame ofView:controlView];
157 | }
158 | @end
159 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Sniffer
2 | =======
3 |
4 | Sniffer is an unoriginally-named packet sniffer with the unique ability of determining which application a packet is coming from (or going to). At the moment it is little more than a prototype to prove that the idea works.
5 |
6 | Internals
7 | ---------
8 |
9 | Like many packet sniffers, Sniffer is split into two applications: the GUI and the capture tool. The GUI launches the capture tool as root when needed and communicates with it via a CFMessagePort.
10 |
11 | The capture tool uses `libpcap` to do the actual packet capturing. When `libpcap` tells the capture tool about a packet, it uses `libproc` to search through all of the running processes, trying to find a process with a socket that matches. Since multiple processes can have access to the file descriptor for a socket, we simply return the first one found. This may limit the usefulness of the tool for your needs, but works well in most cases.
12 |
13 | To Do
14 | -----
15 |
16 | * remove hardcoded use of "en1" from the capture tool
17 | * add more endpoint matching (TCP/IPv6, UDP, etc)
18 | * remove Hex Fiend binary from the repository
19 | * provide a decent user interface
20 | * export capture as pcap
21 |
22 | License
23 | -------
24 |
25 | Sniffer is released under the GPLv2 license.
26 |
27 | Redistribution
28 | --------------
29 |
30 | Even though it is perfectly legal under the license, I urge you not to distribute binaries of Sniffer. The problem is that `libproc` is not ABI-compatible across Mac OS X releases (or even architectures of the same release). Distributing binaries could result in versions of the application that simply crash when launched on any version of the OS other than the one you built for.
--------------------------------------------------------------------------------
/Sniffer-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | English
7 | CFBundleDocumentTypes
8 |
9 |
10 | CFBundleTypeExtensions
11 |
12 | snifferSession
13 |
14 | CFBundleTypeName
15 | Sniffer
16 | CFBundleTypeRole
17 | Editor
18 | LSItemContentTypes
19 |
20 | com.alacatia.Sniffer.Session
21 |
22 | LSTypeIsPackage
23 |
24 | NSDocumentClass
25 | SnifferDocument
26 |
27 |
28 | CFBundleExecutable
29 | ${EXECUTABLE_NAME}
30 | CFBundleIconFile
31 |
32 | CFBundleIdentifier
33 | com.alacatia.${PRODUCT_NAME:rfc1034identifier}
34 | CFBundleInfoDictionaryVersion
35 | 6.0
36 | CFBundleName
37 | ${PRODUCT_NAME}
38 | CFBundlePackageType
39 | APPL
40 | CFBundleShortVersionString
41 | 1.0
42 | CFBundleSignature
43 | ????
44 | CFBundleVersion
45 | 1
46 | LSMinimumSystemVersion
47 | ${MACOSX_DEPLOYMENT_TARGET}
48 | NSMainNibFile
49 | MainMenu
50 | NSPrincipalClass
51 | NSApplication
52 | UTExportedTypeDeclarations
53 |
54 |
55 | UTTypeConformsTo
56 |
57 | public.composite-content
58 | com.apple.package
59 | public.data
60 |
61 | UTTypeIdentifier
62 | com.alacatia.Sniffer.Session
63 | UTTypeTagSpecification
64 |
65 | public.filename-extension
66 | snifferSession
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Sniffer.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
11 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
12 | 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; };
13 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
14 | AC4A678A12D539ED0051B7B1 /* PrettyCell.m in Sources */ = {isa = PBXBuildFile; fileRef = AC4A678912D539ED0051B7B1 /* PrettyCell.m */; };
15 | ACA31FDA12D2CD9400DF2343 /* HexFiend.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ACA31FD912D2CD9400DF2343 /* HexFiend.framework */; };
16 | ACA3208312D5340E00DF2343 /* HexFiend.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = ACA31FD912D2CD9400DF2343 /* HexFiend.framework */; };
17 | D8A2272012C339AF0085FDDE /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8A2271F12C339AF0085FDDE /* Utils.cpp */; };
18 | D8A2275612C3BEA80085FDDE /* ChunkedBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8A2275512C3BEA80085FDDE /* ChunkedBuffer.cpp */; };
19 | D8A2284212C6D7990085FDDE /* SnifferDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = D8A2284112C6D7990085FDDE /* SnifferDocument.mm */; };
20 | D8A2285B12C6F0040085FDDE /* SnifferWindowController.mm in Sources */ = {isa = PBXBuildFile; fileRef = D8A2285A12C6F0040085FDDE /* SnifferWindowController.mm */; };
21 | D8A2286112C6F23D0085FDDE /* SnifferWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D8A2286012C6F23D0085FDDE /* SnifferWindowController.xib */; };
22 | D8A2292512C716F40085FDDE /* SnifferCapture.mm in Sources */ = {isa = PBXBuildFile; fileRef = D8A2292412C716F40085FDDE /* SnifferCapture.mm */; };
23 | D8B4B7EA12C1C018007BE282 /* schema.sql in Resources */ = {isa = PBXBuildFile; fileRef = D8B4B7E912C1C018007BE282 /* schema.sql */; };
24 | D8B4B7F412C1C21E007BE282 /* libsqlite3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D8B4B7F312C1C21E007BE282 /* libsqlite3.dylib */; };
25 | D8E9D0A612BC904000FF3450 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D8E9D0A512BC904000FF3450 /* main.cpp */; };
26 | D8E9D1D512BD59BC00FF3450 /* libpcap.A.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E9D1D412BD59BC00FF3450 /* libpcap.A.dylib */; };
27 | D8E9D1DE12BD5A1700FF3450 /* CaptureTool in CopyFiles */ = {isa = PBXBuildFile; fileRef = D8E9D09612BC900400FF3450 /* CaptureTool */; };
28 | D8E9D22912BD5D3200FF3450 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E9D22712BD5D2C00FF3450 /* CoreFoundation.framework */; };
29 | D8E9D22E12BD5D4100FF3450 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E9D22D12BD5D4100FF3450 /* Security.framework */; };
30 | /* End PBXBuildFile section */
31 |
32 | /* Begin PBXContainerItemProxy section */
33 | D8E9D1DA12BD59FB00FF3450 /* PBXContainerItemProxy */ = {
34 | isa = PBXContainerItemProxy;
35 | containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
36 | proxyType = 1;
37 | remoteGlobalIDString = D8E9D09512BC900400FF3450;
38 | remoteInfo = Sniffer;
39 | };
40 | /* End PBXContainerItemProxy section */
41 |
42 | /* Begin PBXCopyFilesBuildPhase section */
43 | ACA3200112D2D48200DF2343 /* CopyFiles */ = {
44 | isa = PBXCopyFilesBuildPhase;
45 | buildActionMask = 2147483647;
46 | dstPath = "Users/zfisher/XCode Projects/Sniffer/HexFiend.framework";
47 | dstSubfolderSpec = 10;
48 | files = (
49 | );
50 | runOnlyForDeploymentPostprocessing = 0;
51 | };
52 | ACA3202D12D2D4FA00DF2343 /* CopyFiles */ = {
53 | isa = PBXCopyFilesBuildPhase;
54 | buildActionMask = 2147483647;
55 | dstPath = HexFiend.framework;
56 | dstSubfolderSpec = 7;
57 | files = (
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | ACA3203812D2D77600DF2343 /* CopyFiles */ = {
62 | isa = PBXCopyFilesBuildPhase;
63 | buildActionMask = 2147483647;
64 | dstPath = "";
65 | dstSubfolderSpec = 10;
66 | files = (
67 | ACA3208312D5340E00DF2343 /* HexFiend.framework in CopyFiles */,
68 | );
69 | runOnlyForDeploymentPostprocessing = 0;
70 | };
71 | ACA3203B12D2DB2100DF2343 /* CopyFiles */ = {
72 | isa = PBXCopyFilesBuildPhase;
73 | buildActionMask = 2147483647;
74 | dstPath = "";
75 | dstSubfolderSpec = 10;
76 | files = (
77 | );
78 | runOnlyForDeploymentPostprocessing = 0;
79 | };
80 | ACA3208D12D5342D00DF2343 /* CopyFiles */ = {
81 | isa = PBXCopyFilesBuildPhase;
82 | buildActionMask = 2147483647;
83 | dstPath = "Users/zfisher/XCode Projects/Sniffer/HexFiend.framework";
84 | dstSubfolderSpec = 10;
85 | files = (
86 | );
87 | runOnlyForDeploymentPostprocessing = 0;
88 | };
89 | D8E9D1F612BD5A2B00FF3450 /* CopyFiles */ = {
90 | isa = PBXCopyFilesBuildPhase;
91 | buildActionMask = 2147483647;
92 | dstPath = "";
93 | dstSubfolderSpec = 6;
94 | files = (
95 | D8E9D1DE12BD5A1700FF3450 /* CaptureTool in CopyFiles */,
96 | );
97 | runOnlyForDeploymentPostprocessing = 0;
98 | };
99 | /* End PBXCopyFilesBuildPhase section */
100 |
101 | /* Begin PBXFileReference section */
102 | 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; };
103 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
104 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; };
105 | 1DDD58150DA1D0A300B32029 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenu.xib; sourceTree = ""; };
106 | 256AC3F00F4B6AF500CF3369 /* Sniffer_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Sniffer_Prefix.pch; sourceTree = ""; };
107 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
108 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
109 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
110 | 8D1107310486CEB800E47090 /* Sniffer-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Sniffer-Info.plist"; sourceTree = ""; };
111 | 8D1107320486CEB800E47090 /* Sniffer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sniffer.app; sourceTree = BUILT_PRODUCTS_DIR; };
112 | AC4A678812D539ED0051B7B1 /* PrettyCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PrettyCell.h; sourceTree = ""; };
113 | AC4A678912D539ED0051B7B1 /* PrettyCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PrettyCell.m; sourceTree = ""; };
114 | ACA31FD912D2CD9400DF2343 /* HexFiend.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = HexFiend.framework; sourceTree = ""; };
115 | D8A2271E12C339AF0085FDDE /* Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Utils.h; sourceTree = ""; };
116 | D8A2271F12C339AF0085FDDE /* Utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Utils.cpp; sourceTree = ""; };
117 | D8A2275412C3BEA80085FDDE /* ChunkedBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChunkedBuffer.h; sourceTree = ""; };
118 | D8A2275512C3BEA80085FDDE /* ChunkedBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ChunkedBuffer.cpp; sourceTree = ""; };
119 | D8A2284012C6D7990085FDDE /* SnifferDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnifferDocument.h; sourceTree = ""; };
120 | D8A2284112C6D7990085FDDE /* SnifferDocument.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SnifferDocument.mm; sourceTree = ""; };
121 | D8A2284412C6DC420085FDDE /* SpinLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpinLock.h; sourceTree = ""; };
122 | D8A2285912C6F0040085FDDE /* SnifferWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnifferWindowController.h; sourceTree = ""; };
123 | D8A2285A12C6F0040085FDDE /* SnifferWindowController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SnifferWindowController.mm; sourceTree = ""; };
124 | D8A2286012C6F23D0085FDDE /* SnifferWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SnifferWindowController.xib; sourceTree = ""; };
125 | D8A2290612C715D20085FDDE /* DatabaseLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseLocker.h; sourceTree = ""; };
126 | D8A2292312C716F40085FDDE /* SnifferCapture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnifferCapture.h; sourceTree = ""; };
127 | D8A2292412C716F40085FDDE /* SnifferCapture.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SnifferCapture.mm; sourceTree = ""; };
128 | D8B4B7E912C1C018007BE282 /* schema.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = schema.sql; sourceTree = ""; };
129 | D8B4B7F312C1C21E007BE282 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
130 | D8E9D09612BC900400FF3450 /* CaptureTool */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CaptureTool; sourceTree = BUILT_PRODUCTS_DIR; };
131 | D8E9D0A512BC904000FF3450 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = CaptureTool/main.cpp; sourceTree = ""; };
132 | D8E9D1D412BD59BC00FF3450 /* libpcap.A.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpcap.A.dylib; path = usr/lib/libpcap.A.dylib; sourceTree = SDKROOT; };
133 | D8E9D22712BD5D2C00FF3450 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
134 | D8E9D22D12BD5D4100FF3450 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
135 | D8FECD8512BE9A0700AF375F /* VMBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VMBuffer.h; path = CaptureTool/VMBuffer.h; sourceTree = ""; };
136 | /* End PBXFileReference section */
137 |
138 | /* Begin PBXFrameworksBuildPhase section */
139 | 8D11072E0486CEB800E47090 /* Frameworks */ = {
140 | isa = PBXFrameworksBuildPhase;
141 | buildActionMask = 2147483647;
142 | files = (
143 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */,
144 | D8E9D22E12BD5D4100FF3450 /* Security.framework in Frameworks */,
145 | D8B4B7F412C1C21E007BE282 /* libsqlite3.dylib in Frameworks */,
146 | ACA31FDA12D2CD9400DF2343 /* HexFiend.framework in Frameworks */,
147 | );
148 | runOnlyForDeploymentPostprocessing = 0;
149 | };
150 | D8E9D09412BC900400FF3450 /* Frameworks */ = {
151 | isa = PBXFrameworksBuildPhase;
152 | buildActionMask = 2147483647;
153 | files = (
154 | D8E9D1D512BD59BC00FF3450 /* libpcap.A.dylib in Frameworks */,
155 | D8E9D22912BD5D3200FF3450 /* CoreFoundation.framework in Frameworks */,
156 | );
157 | runOnlyForDeploymentPostprocessing = 0;
158 | };
159 | /* End PBXFrameworksBuildPhase section */
160 |
161 | /* Begin PBXGroup section */
162 | 080E96DDFE201D6D7F000001 /* Classes */ = {
163 | isa = PBXGroup;
164 | children = (
165 | D8A2275412C3BEA80085FDDE /* ChunkedBuffer.h */,
166 | D8A2275512C3BEA80085FDDE /* ChunkedBuffer.cpp */,
167 | D8A2284012C6D7990085FDDE /* SnifferDocument.h */,
168 | D8A2284112C6D7990085FDDE /* SnifferDocument.mm */,
169 | D8A2284412C6DC420085FDDE /* SpinLock.h */,
170 | D8A2285912C6F0040085FDDE /* SnifferWindowController.h */,
171 | D8A2285A12C6F0040085FDDE /* SnifferWindowController.mm */,
172 | D8A2290612C715D20085FDDE /* DatabaseLocker.h */,
173 | D8A2292312C716F40085FDDE /* SnifferCapture.h */,
174 | D8A2292412C716F40085FDDE /* SnifferCapture.mm */,
175 | AC4A678812D539ED0051B7B1 /* PrettyCell.h */,
176 | AC4A678912D539ED0051B7B1 /* PrettyCell.m */,
177 | );
178 | name = Classes;
179 | sourceTree = "";
180 | };
181 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
182 | isa = PBXGroup;
183 | children = (
184 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */,
185 | D8E9D1D412BD59BC00FF3450 /* libpcap.A.dylib */,
186 | D8E9D22712BD5D2C00FF3450 /* CoreFoundation.framework */,
187 | D8E9D22D12BD5D4100FF3450 /* Security.framework */,
188 | D8B4B7F312C1C21E007BE282 /* libsqlite3.dylib */,
189 | ACA31FD912D2CD9400DF2343 /* HexFiend.framework */,
190 | );
191 | name = "Linked Frameworks";
192 | sourceTree = "";
193 | };
194 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = {
195 | isa = PBXGroup;
196 | children = (
197 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */,
198 | 13E42FB307B3F0F600E4EEF1 /* CoreData.framework */,
199 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */,
200 | );
201 | name = "Other Frameworks";
202 | sourceTree = "";
203 | };
204 | 19C28FACFE9D520D11CA2CBB /* Products */ = {
205 | isa = PBXGroup;
206 | children = (
207 | 8D1107320486CEB800E47090 /* Sniffer.app */,
208 | D8E9D09612BC900400FF3450 /* CaptureTool */,
209 | );
210 | name = Products;
211 | sourceTree = "";
212 | };
213 | 29B97314FDCFA39411CA2CEA /* PacketMuncher */ = {
214 | isa = PBXGroup;
215 | children = (
216 | D8E9D0A012BC901600FF3450 /* CaptureTool */,
217 | D8E9D09C12BC900D00FF3450 /* GUI */,
218 | 29B97323FDCFA39411CA2CEA /* Frameworks */,
219 | 19C28FACFE9D520D11CA2CBB /* Products */,
220 | );
221 | name = PacketMuncher;
222 | sourceTree = "";
223 | };
224 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
225 | isa = PBXGroup;
226 | children = (
227 | D8B4B7E912C1C018007BE282 /* schema.sql */,
228 | 256AC3F00F4B6AF500CF3369 /* Sniffer_Prefix.pch */,
229 | 29B97316FDCFA39411CA2CEA /* main.m */,
230 | );
231 | name = "Other Sources";
232 | sourceTree = "";
233 | };
234 | 29B97317FDCFA39411CA2CEA /* Resources */ = {
235 | isa = PBXGroup;
236 | children = (
237 | 8D1107310486CEB800E47090 /* Sniffer-Info.plist */,
238 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */,
239 | 1DDD58140DA1D0A300B32029 /* MainMenu.xib */,
240 | D8A2286012C6F23D0085FDDE /* SnifferWindowController.xib */,
241 | );
242 | name = Resources;
243 | sourceTree = "";
244 | };
245 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
246 | isa = PBXGroup;
247 | children = (
248 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */,
249 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */,
250 | );
251 | name = Frameworks;
252 | sourceTree = "";
253 | };
254 | D8E9D09C12BC900D00FF3450 /* GUI */ = {
255 | isa = PBXGroup;
256 | children = (
257 | 080E96DDFE201D6D7F000001 /* Classes */,
258 | 29B97315FDCFA39411CA2CEA /* Other Sources */,
259 | 29B97317FDCFA39411CA2CEA /* Resources */,
260 | );
261 | name = GUI;
262 | sourceTree = "";
263 | };
264 | D8E9D0A012BC901600FF3450 /* CaptureTool */ = {
265 | isa = PBXGroup;
266 | children = (
267 | D8E9D0A512BC904000FF3450 /* main.cpp */,
268 | D8FECD8512BE9A0700AF375F /* VMBuffer.h */,
269 | D8A2271E12C339AF0085FDDE /* Utils.h */,
270 | D8A2271F12C339AF0085FDDE /* Utils.cpp */,
271 | );
272 | name = CaptureTool;
273 | sourceTree = "";
274 | };
275 | /* End PBXGroup section */
276 |
277 | /* Begin PBXNativeTarget section */
278 | 8D1107260486CEB800E47090 /* Sniffer */ = {
279 | isa = PBXNativeTarget;
280 | buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Sniffer" */;
281 | buildPhases = (
282 | 8D1107290486CEB800E47090 /* Resources */,
283 | ACA3208D12D5342D00DF2343 /* CopyFiles */,
284 | 8D11072C0486CEB800E47090 /* Sources */,
285 | 8D11072E0486CEB800E47090 /* Frameworks */,
286 | ACA3200112D2D48200DF2343 /* CopyFiles */,
287 | ACA3202D12D2D4FA00DF2343 /* CopyFiles */,
288 | ACA3203812D2D77600DF2343 /* CopyFiles */,
289 | D8E9D1F612BD5A2B00FF3450 /* CopyFiles */,
290 | ACA3203B12D2DB2100DF2343 /* CopyFiles */,
291 | );
292 | buildRules = (
293 | );
294 | dependencies = (
295 | D8E9D1DB12BD59FB00FF3450 /* PBXTargetDependency */,
296 | );
297 | name = Sniffer;
298 | productInstallPath = "$(HOME)/Applications";
299 | productName = PacketMuncher;
300 | productReference = 8D1107320486CEB800E47090 /* Sniffer.app */;
301 | productType = "com.apple.product-type.application";
302 | };
303 | D8E9D09512BC900400FF3450 /* CaptureTool */ = {
304 | isa = PBXNativeTarget;
305 | buildConfigurationList = D8E9D09D12BC900D00FF3450 /* Build configuration list for PBXNativeTarget "CaptureTool" */;
306 | buildPhases = (
307 | D8E9D09312BC900400FF3450 /* Sources */,
308 | D8E9D09412BC900400FF3450 /* Frameworks */,
309 | );
310 | buildRules = (
311 | );
312 | dependencies = (
313 | );
314 | name = CaptureTool;
315 | productName = Sniffer;
316 | productReference = D8E9D09612BC900400FF3450 /* CaptureTool */;
317 | productType = "com.apple.product-type.tool";
318 | };
319 | /* End PBXNativeTarget section */
320 |
321 | /* Begin PBXProject section */
322 | 29B97313FDCFA39411CA2CEA /* Project object */ = {
323 | isa = PBXProject;
324 | attributes = {
325 | LastUpgradeCheck = 0410;
326 | ORGANIZATIONNAME = "Alacatia Labs";
327 | };
328 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Sniffer" */;
329 | compatibilityVersion = "Xcode 3.2";
330 | developmentRegion = English;
331 | hasScannedForEncodings = 1;
332 | knownRegions = (
333 | English,
334 | Japanese,
335 | French,
336 | German,
337 | );
338 | mainGroup = 29B97314FDCFA39411CA2CEA /* PacketMuncher */;
339 | projectDirPath = "";
340 | projectRoot = "";
341 | targets = (
342 | 8D1107260486CEB800E47090 /* Sniffer */,
343 | D8E9D09512BC900400FF3450 /* CaptureTool */,
344 | );
345 | };
346 | /* End PBXProject section */
347 |
348 | /* Begin PBXResourcesBuildPhase section */
349 | 8D1107290486CEB800E47090 /* Resources */ = {
350 | isa = PBXResourcesBuildPhase;
351 | buildActionMask = 2147483647;
352 | files = (
353 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */,
354 | 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */,
355 | D8B4B7EA12C1C018007BE282 /* schema.sql in Resources */,
356 | D8A2286112C6F23D0085FDDE /* SnifferWindowController.xib in Resources */,
357 | );
358 | runOnlyForDeploymentPostprocessing = 0;
359 | };
360 | /* End PBXResourcesBuildPhase section */
361 |
362 | /* Begin PBXSourcesBuildPhase section */
363 | 8D11072C0486CEB800E47090 /* Sources */ = {
364 | isa = PBXSourcesBuildPhase;
365 | buildActionMask = 2147483647;
366 | files = (
367 | 8D11072D0486CEB800E47090 /* main.m in Sources */,
368 | D8A2275612C3BEA80085FDDE /* ChunkedBuffer.cpp in Sources */,
369 | D8A2284212C6D7990085FDDE /* SnifferDocument.mm in Sources */,
370 | D8A2285B12C6F0040085FDDE /* SnifferWindowController.mm in Sources */,
371 | D8A2292512C716F40085FDDE /* SnifferCapture.mm in Sources */,
372 | AC4A678A12D539ED0051B7B1 /* PrettyCell.m in Sources */,
373 | );
374 | runOnlyForDeploymentPostprocessing = 0;
375 | };
376 | D8E9D09312BC900400FF3450 /* Sources */ = {
377 | isa = PBXSourcesBuildPhase;
378 | buildActionMask = 2147483647;
379 | files = (
380 | D8E9D0A612BC904000FF3450 /* main.cpp in Sources */,
381 | D8A2272012C339AF0085FDDE /* Utils.cpp in Sources */,
382 | );
383 | runOnlyForDeploymentPostprocessing = 0;
384 | };
385 | /* End PBXSourcesBuildPhase section */
386 |
387 | /* Begin PBXTargetDependency section */
388 | D8E9D1DB12BD59FB00FF3450 /* PBXTargetDependency */ = {
389 | isa = PBXTargetDependency;
390 | target = D8E9D09512BC900400FF3450 /* CaptureTool */;
391 | targetProxy = D8E9D1DA12BD59FB00FF3450 /* PBXContainerItemProxy */;
392 | };
393 | /* End PBXTargetDependency section */
394 |
395 | /* Begin PBXVariantGroup section */
396 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = {
397 | isa = PBXVariantGroup;
398 | children = (
399 | 089C165DFE840E0CC02AAC07 /* English */,
400 | );
401 | name = InfoPlist.strings;
402 | sourceTree = "";
403 | };
404 | 1DDD58140DA1D0A300B32029 /* MainMenu.xib */ = {
405 | isa = PBXVariantGroup;
406 | children = (
407 | 1DDD58150DA1D0A300B32029 /* English */,
408 | );
409 | name = MainMenu.xib;
410 | sourceTree = "";
411 | };
412 | /* End PBXVariantGroup section */
413 |
414 | /* Begin XCBuildConfiguration section */
415 | C01FCF4B08A954540054247B /* Debug */ = {
416 | isa = XCBuildConfiguration;
417 | buildSettings = {
418 | ALWAYS_SEARCH_USER_PATHS = NO;
419 | COPY_PHASE_STRIP = NO;
420 | FRAMEWORK_SEARCH_PATHS = (
421 | "$(inherited)",
422 | "\"$(SRCROOT)\"",
423 | );
424 | GCC_DYNAMIC_NO_PIC = NO;
425 | GCC_MODEL_TUNING = G5;
426 | GCC_OPTIMIZATION_LEVEL = 0;
427 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
428 | GCC_PREFIX_HEADER = Sniffer_Prefix.pch;
429 | INFOPLIST_FILE = "Sniffer-Info.plist";
430 | INSTALL_PATH = "$(HOME)/Applications";
431 | PRODUCT_NAME = Sniffer;
432 | };
433 | name = Debug;
434 | };
435 | C01FCF4C08A954540054247B /* Release */ = {
436 | isa = XCBuildConfiguration;
437 | buildSettings = {
438 | ALWAYS_SEARCH_USER_PATHS = NO;
439 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
440 | FRAMEWORK_SEARCH_PATHS = (
441 | "$(inherited)",
442 | "\"$(SRCROOT)\"",
443 | );
444 | GCC_MODEL_TUNING = G5;
445 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
446 | GCC_PREFIX_HEADER = Sniffer_Prefix.pch;
447 | INFOPLIST_FILE = "Sniffer-Info.plist";
448 | INSTALL_PATH = "$(HOME)/Applications";
449 | PRODUCT_NAME = Sniffer;
450 | };
451 | name = Release;
452 | };
453 | C01FCF4F08A954540054247B /* Debug */ = {
454 | isa = XCBuildConfiguration;
455 | buildSettings = {
456 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
457 | GCC_C_LANGUAGE_STANDARD = gnu99;
458 | GCC_OPTIMIZATION_LEVEL = 0;
459 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
460 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
461 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
462 | GCC_WARN_UNUSED_VARIABLE = YES;
463 | ONLY_ACTIVE_ARCH = YES;
464 | SDKROOT = macosx;
465 | };
466 | name = Debug;
467 | };
468 | C01FCF5008A954540054247B /* Release */ = {
469 | isa = XCBuildConfiguration;
470 | buildSettings = {
471 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
472 | GCC_C_LANGUAGE_STANDARD = gnu99;
473 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
474 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
475 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
476 | GCC_WARN_UNUSED_VARIABLE = YES;
477 | SDKROOT = macosx;
478 | };
479 | name = Release;
480 | };
481 | D8E9D09812BC900400FF3450 /* Debug */ = {
482 | isa = XCBuildConfiguration;
483 | buildSettings = {
484 | ALWAYS_SEARCH_USER_PATHS = NO;
485 | COPY_PHASE_STRIP = NO;
486 | GCC_DYNAMIC_NO_PIC = NO;
487 | GCC_MODEL_TUNING = G5;
488 | GCC_OPTIMIZATION_LEVEL = 0;
489 | INSTALL_PATH = /usr/local/bin;
490 | PRODUCT_NAME = CaptureTool;
491 | };
492 | name = Debug;
493 | };
494 | D8E9D09912BC900400FF3450 /* Release */ = {
495 | isa = XCBuildConfiguration;
496 | buildSettings = {
497 | ALWAYS_SEARCH_USER_PATHS = NO;
498 | COPY_PHASE_STRIP = YES;
499 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
500 | GCC_MODEL_TUNING = G5;
501 | INSTALL_PATH = /usr/local/bin;
502 | PRODUCT_NAME = Sniffer;
503 | ZERO_LINK = NO;
504 | };
505 | name = Release;
506 | };
507 | /* End XCBuildConfiguration section */
508 |
509 | /* Begin XCConfigurationList section */
510 | C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "Sniffer" */ = {
511 | isa = XCConfigurationList;
512 | buildConfigurations = (
513 | C01FCF4B08A954540054247B /* Debug */,
514 | C01FCF4C08A954540054247B /* Release */,
515 | );
516 | defaultConfigurationIsVisible = 0;
517 | defaultConfigurationName = Release;
518 | };
519 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "Sniffer" */ = {
520 | isa = XCConfigurationList;
521 | buildConfigurations = (
522 | C01FCF4F08A954540054247B /* Debug */,
523 | C01FCF5008A954540054247B /* Release */,
524 | );
525 | defaultConfigurationIsVisible = 0;
526 | defaultConfigurationName = Release;
527 | };
528 | D8E9D09D12BC900D00FF3450 /* Build configuration list for PBXNativeTarget "CaptureTool" */ = {
529 | isa = XCConfigurationList;
530 | buildConfigurations = (
531 | D8E9D09812BC900400FF3450 /* Debug */,
532 | D8E9D09912BC900400FF3450 /* Release */,
533 | );
534 | defaultConfigurationIsVisible = 0;
535 | defaultConfigurationName = Release;
536 | };
537 | /* End XCConfigurationList section */
538 | };
539 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
540 | }
541 |
--------------------------------------------------------------------------------
/Sniffer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SnifferCapture.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import
17 | #import
18 | @class SnifferDocument;
19 |
20 | @interface SnifferCapture : NSObject {
21 | SnifferDocument *document;
22 | CFMessagePortRef messagePort;
23 | }
24 |
25 | - (id)initWithDocument:(SnifferDocument *)document;
26 |
27 | - (NSString *)captureToolPath;
28 | - (BOOL)beginCaptureWithAuthorization:(AuthorizationRef)authorizationRef;
29 | - (void)stopCapture;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/SnifferCapture.mm:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import "SnifferCapture.h"
17 | #import
18 | #import "SnifferDocument.h"
19 |
20 | @implementation SnifferCapture
21 |
22 | void DissectPacket(SnifferCapture *delegate, SInt32 msgid, NSData *rawData) {
23 | const char *bytes = (const char *)[rawData bytes];
24 | pcap_pkthdr *header = (pcap_pkthdr *)bytes;
25 | const char *dataStart = (const char *)(header + 1);
26 | const char *nameStart = dataStart + header->caplen;
27 |
28 | NSData *packetData = [NSData dataWithBytes:dataStart length:header->caplen];
29 | [delegate->document addPacket:packetData
30 | header:header
31 | identifier:msgid
32 | application:[NSString stringWithUTF8String:nameStart]
33 | metadata:nil];
34 | }
35 |
36 | CFDataRef PacketCallback(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info) {
37 | SnifferCapture *delegate = (SnifferCapture *)info;
38 | CFDataRef dataCopy = CFDataCreateCopy(NULL, data);
39 |
40 | dispatch_async(dispatch_get_global_queue(0, 0), ^(void) {
41 | DissectPacket(delegate, msgid, (NSData *)dataCopy);
42 | CFRelease(dataCopy);
43 | });
44 |
45 | return NULL;
46 | }
47 |
48 | - (id)initWithDocument:(SnifferDocument *)theDocument {
49 | if (self = [super init]) {
50 | document = [theDocument retain];
51 | }
52 |
53 | return self;
54 | }
55 |
56 | - (NSString *)captureToolPath {
57 | return [[NSBundle mainBundle] pathForAuxiliaryExecutable:@"CaptureTool"];
58 | }
59 |
60 | - (NSString *)makePortName {
61 | CFUUIDRef uuid = CFUUIDCreate(NULL);
62 | CFStringRef uuidString = CFUUIDCreateString(NULL, uuid);
63 | NSString *result = [NSString stringWithFormat:@"com.alacatia.Sniffer.%@", uuidString];
64 |
65 | CFRelease(uuidString);
66 | CFRelease(uuid);
67 | return result;
68 | }
69 |
70 | - (BOOL)beginCaptureWithAuthorization:(AuthorizationRef)authorizationRef {
71 | NSString *portName = [self makePortName];
72 |
73 | CFMessagePortContext context;
74 | context.version = 0;
75 | context.info = self;
76 | context.retain = CFRetain;
77 | context.release = CFRelease;
78 | context.copyDescription = CFCopyDescription;
79 |
80 | messagePort = CFMessagePortCreateLocal(NULL, (CFStringRef)portName, PacketCallback, &context, NULL);
81 | CFRunLoopSourceRef source = CFMessagePortCreateRunLoopSource(NULL, messagePort, 0);
82 | CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
83 | CFRelease(source);
84 |
85 | NSString *snifferPathString = [self captureToolPath];
86 | const char *snifferPath = [snifferPathString fileSystemRepresentation];
87 |
88 | const char *args[] = { [portName UTF8String], NULL };
89 | OSStatus err = AuthorizationExecuteWithPrivileges(authorizationRef, snifferPath, kAuthorizationFlagDefaults, (char * const *)args, NULL);
90 |
91 | return err == noErr;
92 | }
93 |
94 | - (void)stopCapture {
95 | CFMessagePortInvalidate(messagePort);
96 | CFRelease(messagePort);
97 | messagePort = NULL;
98 | }
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/SnifferDocument.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import
17 | #import
18 | #import
19 | #import
20 | #import "ChunkedBuffer.h"
21 | @class SnifferWindowController;
22 |
23 | @interface SnifferDocument : NSDocument {
24 | OSSpinLock databaseLock;
25 | sqlite3 *database;
26 |
27 | OSSpinLock bufferLock;
28 | ChunkedBuffer *packetBuffer;
29 |
30 | sqlite3_stmt *appSelectStmt;
31 | sqlite3_stmt *appInsertStmt;
32 | sqlite3_stmt *packetInsertStmt;
33 | sqlite3_stmt *metadataInsertStmt;
34 | sqlite3_stmt *packetDataSelectStmt;
35 |
36 | SnifferWindowController *windowController;
37 | BOOL isNewDocument;
38 | }
39 |
40 | - (BOOL)isNewDocument;
41 |
42 | - (sqlite3 *)acquireDatabase;
43 | - (void)releaseDatabase;
44 |
45 | - (void)addPacket:(NSData *)data header:(pcap_pkthdr *)header identifier:(NSUInteger)packetID application:(NSString *)application metadata:(NSDictionary *)metadata;
46 |
47 | - (NSData *)packetData:(NSUInteger)packetID;
48 |
49 | @end
50 |
51 |
52 |
--------------------------------------------------------------------------------
/SnifferDocument.mm:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import "SnifferDocument.h"
17 | #import "SpinLock.h"
18 | #import "SnifferWindowController.h"
19 |
20 | // See http://wiki.wireshark.org/Development/LibpcapFileFormat
21 | struct pcap_hdr_t {
22 | uint32_t magic_number; /* magic number */
23 | uint16_t version_major; /* major version number */
24 | uint16_t version_minor; /* minor version number */
25 | int32_t thiszone; /* GMT to local correction */
26 | uint32_t sigfigs; /* accuracy of timestamps */
27 | uint32_t snaplen; /* max length of captured packets, in octets */
28 | uint32_t network; /* data link type */
29 | };
30 |
31 | struct pcaprec_hdr_t {
32 | uint32_t ts_sec; /* timestamp seconds */
33 | uint32_t ts_usec; /* timestamp microseconds */
34 | uint32_t incl_len; /* number of octets of packet saved in file */
35 | uint32_t orig_len; /* actual length of packet */
36 | };
37 |
38 |
39 | @implementation SnifferDocument
40 |
41 | - (id)init {
42 | if (self = [super init]) {
43 | NSURL *initialSQLURL = [[NSBundle mainBundle] URLForResource:@"schema" withExtension:@"sql"];
44 | NSString *initialSQL = [NSString stringWithContentsOfURL:initialSQLURL encoding:NSUTF8StringEncoding error:NULL];
45 |
46 | sqlite3_open(":memory:", &database);
47 | sqlite3_exec(database, [initialSQL UTF8String], NULL, NULL, NULL);
48 | sqlite3_prepare_v2(database, "SELECT rowid FROM applications WHERE path = ?", -1, &appSelectStmt, NULL);
49 | sqlite3_prepare_v2(database, "INSERT INTO applications (name, path, bookmark) VALUES (?, ?, ?)", -1, &appInsertStmt, NULL);
50 | sqlite3_prepare_v2(database, "INSERT INTO packets (rowid, application_fk, data_offset, data_size) VALUES (?, ?, ?, ?)", -1, &packetInsertStmt, NULL);
51 | sqlite3_prepare_v2(database, "INSERT INTO metadata (packet_fk, name, data) VALUES (?, ?, ?)", -1, &metadataInsertStmt, NULL);
52 | sqlite3_prepare_v2(database, "SELECT data_offset, data_size FROM packets ORDER BY rowid LIMIT 1 OFFSET ?", -1, &packetDataSelectStmt, NULL);
53 |
54 | databaseLock = OS_SPINLOCK_INIT;
55 |
56 | // Create our packet buffer with an initial size of 64MB
57 | packetBuffer = new ChunkedBuffer(67108864);
58 |
59 | // Our in-memory buffer is just going to be a pcap file. The overhead for
60 | // this is pretty small and makes it pretty easy to export as pcap or load
61 | // from pcap files.
62 | pcap_hdr_t header;
63 | header.magic_number = 0xA1B2C3D4;
64 | header.version_major = 2;
65 | header.version_minor = 4;
66 | header.thiszone = 0;
67 | header.sigfigs = 0;
68 | header.snaplen = 65535;
69 | header.network = 1;
70 | packetBuffer->AppendBytes(&header, sizeof(header));
71 |
72 | bufferLock = OS_SPINLOCK_INIT;
73 |
74 | isNewDocument = YES;
75 | }
76 |
77 | return self;
78 | }
79 |
80 | - (void)makeWindowControllers {
81 | windowController = [[SnifferWindowController alloc] initWithWindowNibName:@"SnifferWindowController"];
82 | [self addWindowController:windowController];
83 | }
84 |
85 | #pragma mark -
86 |
87 | - (void)addPacket:(NSData *)data header:(pcap_pkthdr *)header identifier:(NSUInteger)packetID application:(NSString *)application metadata:(NSDictionary *)metadata {
88 | off_t packetOffset;
89 |
90 | // Only put code in here that needs the file lock
91 | {
92 | SpinLock lock(&bufferLock);
93 |
94 | pcaprec_hdr_t headerRec;
95 | headerRec.ts_sec = header->ts.tv_sec;
96 | headerRec.ts_usec = header->ts.tv_usec;
97 | headerRec.incl_len = header->caplen;
98 | headerRec.orig_len = header->len;
99 | packetBuffer->AppendBytes(&headerRec, sizeof(headerRec));
100 |
101 | packetOffset = packetBuffer->Length();
102 | packetBuffer->AppendBytes([data bytes], [data length]);
103 | }
104 |
105 | // Only put code in here that needs the database lock
106 | {
107 | SpinLock dbLock(&databaseLock);
108 |
109 | // First, see if we have already put this application into the applications
110 | // table. If not, insert it.
111 | sqlite3_int64 appRowID = -1;
112 | sqlite3_bind_text(appSelectStmt, 1, [application UTF8String], -1, NULL);
113 | if (SQLITE_ROW == sqlite3_step(appSelectStmt)) {
114 | appRowID = sqlite3_column_int64(appSelectStmt, 0);
115 | } else {
116 | // FIXME: we might want to bookmark icons too, once we have that bit
117 | // of UI working.
118 | NSData *bookmark = [[NSURL fileURLWithPath:application] bookmarkDataWithOptions:0
119 | includingResourceValuesForKeys:nil
120 | relativeToURL:nil
121 | error:NULL];
122 |
123 | sqlite3_bind_text(appInsertStmt, 1, [[application lastPathComponent] UTF8String], -1, NULL);
124 | sqlite3_bind_text(appInsertStmt, 2, [application UTF8String], -1, NULL);
125 | sqlite3_bind_blob(appInsertStmt, 3, [bookmark bytes], [bookmark length], NULL);
126 | sqlite3_step(appInsertStmt);
127 | sqlite3_reset(appInsertStmt);
128 |
129 | appRowID = sqlite3_last_insert_rowid(database);
130 | }
131 | sqlite3_reset(appSelectStmt);
132 |
133 | // Now that we have our application inserted, we can insert the packet
134 | sqlite3_bind_int64(packetInsertStmt, 1, packetID);
135 | sqlite3_bind_int64(packetInsertStmt, 2, appRowID);
136 | sqlite3_bind_int64(packetInsertStmt, 3, packetOffset);
137 | sqlite3_bind_int64(packetInsertStmt, 4, [data length]);
138 | sqlite3_step(packetInsertStmt);
139 | sqlite3_reset(packetInsertStmt);
140 |
141 | // Now whatever metadata we might have been given
142 | [metadata enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
143 | // FIXME: support more types
144 | assert([key isKindOfClass:[NSString class]]);
145 | assert([value isKindOfClass:[NSString class]]);
146 |
147 | sqlite3_bind_int64(metadataInsertStmt, 1, packetID);
148 | sqlite3_bind_text(metadataInsertStmt, 2, [key UTF8String], -1, NULL);
149 | sqlite3_bind_text(metadataInsertStmt, 3, [value UTF8String], -1, NULL);
150 | sqlite3_step(metadataInsertStmt);
151 | sqlite3_reset(metadataInsertStmt);
152 | }];
153 | }
154 |
155 | dispatch_async(dispatch_get_main_queue(), ^(void) {
156 | [windowController dataChanged];
157 | });
158 | }
159 |
160 | - (NSData *)packetData:(NSUInteger)packetID {
161 | NSUInteger dataOffset = 0;
162 | NSUInteger dataSize = 0;
163 | {
164 | SpinLock lock(&databaseLock);
165 | sqlite3_reset(packetDataSelectStmt);
166 | sqlite3_bind_int64(packetDataSelectStmt, 1, packetID);
167 | sqlite3_step(packetDataSelectStmt);
168 | dataOffset = sqlite3_column_int(packetDataSelectStmt, 0);
169 | dataSize = sqlite3_column_int(packetDataSelectStmt, 1);
170 | }
171 |
172 | NSMutableData *data = [NSMutableData dataWithLength:dataSize];
173 | {
174 | SpinLock lock(&bufferLock);
175 | packetBuffer->CopyBytes(dataOffset, dataSize, [data mutableBytes]);
176 | }
177 |
178 | return data;
179 | }
180 |
181 | - (sqlite3 *)acquireDatabase {
182 | OSSpinLockLock(&databaseLock);
183 | return database;
184 | }
185 |
186 | - (void)releaseDatabase {
187 | OSSpinLockUnlock(&databaseLock);
188 | }
189 |
190 | #pragma mark -
191 |
192 | - (NSString *)temporaryFolder {
193 | NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]];
194 | BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:path
195 | withIntermediateDirectories:YES
196 | attributes:nil
197 | error:NULL];
198 | if (success) {
199 | return path;
200 | } else {
201 | // Hrm, we failed for some reason. Let's just return the temporary directory
202 | // and hope for the best!
203 | return NSTemporaryDirectory();
204 | }
205 | }
206 |
207 | - (NSData *)databaseData {
208 | // Unfortunately SQLite has no way to serialize a database to bytes in memory.
209 | // Instead, it requires you to write to a file on disk.
210 | //
211 | // In the future we could optimize this with one of two strategies:
212 | // - use named pipes (mkfifo)
213 | // - implement an SQLite VFS (sqlite3_vfs_register)
214 | NSData *result = nil;
215 |
216 | NSString *backupPath = [[self temporaryFolder] stringByAppendingPathComponent:@"metadata.sqlite"];
217 | sqlite3 *diskDB;
218 | if (SQLITE_OK == sqlite3_open([backupPath fileSystemRepresentation], &diskDB)) {
219 | SpinLock lock(&databaseLock);
220 |
221 | sqlite3_backup *backup = sqlite3_backup_init(diskDB, "main", database, "main");
222 | if (backup) {
223 | sqlite3_backup_step(backup, -1);
224 | sqlite3_backup_finish(backup);
225 | }
226 | sqlite3_close(diskDB);
227 | }
228 |
229 | result = [NSData dataWithContentsOfFile:backupPath];
230 | [[NSFileManager defaultManager] removeFileAtPath:backupPath handler:nil];
231 |
232 | return result;
233 | }
234 |
235 | - (void)loadDatabaseFromData:(NSData *)data {
236 | // Unfortunately SQLite has no way to read a database from memory. Instead,
237 | // it requires you to read the file from disk.
238 | //
239 | // In the future we could optimize this with one of two strategies:
240 | // - use named pipes (mkfifo)
241 | // - implement an SQLite VFS (sqlite3_vfs_register)
242 |
243 | NSString *backupPath = [[self temporaryFolder] stringByAppendingPathComponent:@"metadata.sqlite"];
244 | [data writeToFile:backupPath atomically:NO];
245 |
246 | sqlite3 *diskDB;
247 | if (SQLITE_OK == sqlite3_open([backupPath fileSystemRepresentation], &diskDB)) {
248 | SpinLock lock(&databaseLock);
249 |
250 | sqlite3_backup *backup = sqlite3_backup_init(database, "main", diskDB, "main");
251 | if (backup) {
252 | sqlite3_backup_step(backup, -1);
253 | sqlite3_backup_finish(backup);
254 | }
255 | sqlite3_close(diskDB);
256 | }
257 |
258 | [[NSFileManager defaultManager] removeFileAtPath:backupPath handler:nil];
259 | }
260 |
261 | - (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError {
262 | NSFileWrapper *result = [[[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil] autorelease];
263 | [result addRegularFileWithContents:[self databaseData] preferredFilename:@"metadata.sqlite"];
264 |
265 | // Copy all the data out of our packet buffer
266 | NSMutableData *data;
267 | {
268 | SpinLock lock(&bufferLock);
269 | data = [NSMutableData dataWithLength:packetBuffer->Length()];
270 | packetBuffer->CopyBytes(0, packetBuffer->Length(), [data mutableBytes]);
271 | }
272 | [result addRegularFileWithContents:data preferredFilename:@"packets.pcap"];
273 |
274 | return result;
275 | }
276 |
277 | - (BOOL)readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError **)outError {
278 | NSDictionary *wrappers = [fileWrapper fileWrappers];
279 | NSData *data = [[wrappers objectForKey:@"packets.pcap"] regularFileContents];
280 |
281 | // FIXME: we should be doing endian swapping
282 | if (*(uint32_t *)[data bytes] != 0xA1B2C3D4) {
283 | return NO;
284 | }
285 |
286 | packetBuffer->AppendBytes([data bytes], [data length]);
287 |
288 | [self loadDatabaseFromData:[[wrappers objectForKey:@"metadata.sqlite"] regularFileContents]];
289 | isNewDocument = NO;
290 |
291 | return YES;
292 | }
293 |
294 | - (BOOL)isNewDocument {
295 | return isNewDocument;
296 | }
297 |
298 | @end
299 |
--------------------------------------------------------------------------------
/SnifferWindowController.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri & Zach Fisher.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import
17 | #import
18 | @class HFTextView;
19 | @class SnifferCapture;
20 |
21 | @interface SnifferWindowController : NSWindowController {
22 | SnifferCapture *capture;
23 | sqlite3_stmt *rowCountStmt;
24 | sqlite3_stmt *packetSelectStmt;
25 | sqlite3_stmt *appSelectStmt;
26 |
27 | IBOutlet HFTextView *dataView;
28 | IBOutlet NSTableView *packetsView;
29 | }
30 |
31 | - (void)dataChanged;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/SnifferWindowController.mm:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri & Zach Fisher.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import "SnifferWindowController.h"
17 | #import "SnifferDocument.h"
18 | #import "DatabaseLocker.h"
19 | #import "SnifferCapture.h"
20 | #import "PrettyCell.h"
21 | #import
22 |
23 | @interface SnifferWindowController ()
24 | - (void)setupDatabase;
25 | - (void)launchCaptureTool;
26 | @end
27 |
28 |
29 | @implementation SnifferWindowController
30 |
31 | - (void)windowDidLoad {
32 | [self setupDatabase];
33 | [packetsView setDelegate:self];
34 | [packetsView setDataSource:self];
35 | [[self window] setDelegate:self];
36 |
37 | if ([[self document] isNewDocument]) {
38 | [self launchCaptureTool];
39 | }
40 | }
41 |
42 | - (void)windowWillClose:(NSNotification *)notification {
43 | [capture stopCapture];
44 | [capture release];
45 | capture = nil;
46 |
47 | sqlite3_finalize(rowCountStmt);
48 | rowCountStmt = NULL;
49 |
50 | sqlite3_finalize(packetSelectStmt);
51 | packetSelectStmt = NULL;
52 |
53 | sqlite3_finalize(appSelectStmt);
54 | appSelectStmt = NULL;
55 | }
56 |
57 | - (void)setupDatabase {
58 | DatabaseLocker lock([self document]);
59 | sqlite3_prepare_v2(lock.Database(), "SELECT COUNT(*) FROM packets", -1, &rowCountStmt, NULL);
60 | sqlite3_prepare_v2(lock.Database(), "SELECT * FROM packets ORDER BY rowid LIMIT 1 OFFSET ?", -1, &packetSelectStmt, NULL);
61 | sqlite3_prepare_v2(lock.Database(), "SELECT path FROM applications WHERE rowid = ?", -1, &appSelectStmt, NULL);
62 | }
63 |
64 | - (void)launchCaptureTool {
65 | capture = [[SnifferCapture alloc] initWithDocument:[self document]];
66 |
67 | NSString *snifferPathString = [capture captureToolPath];
68 | const char *snifferPath = [snifferPathString fileSystemRepresentation];
69 |
70 | OSStatus status = noErr;
71 | AuthorizationItem item = {
72 | "com.alactia.Sniffer.CaptureTool",
73 | strlen(snifferPath), (void *)snifferPath,
74 | 0 /* flags -- must be zero */
75 | };
76 |
77 | AuthorizationItemSet itemSet = { 1, &item };
78 | AuthorizationRef authorizationRef = NULL;
79 | status = AuthorizationCreate(&itemSet, kAuthorizationEmptyEnvironment,
80 | kAuthorizationFlagDefaults |
81 | kAuthorizationFlagInteractionAllowed |
82 | kAuthorizationFlagExtendRights,
83 | &authorizationRef);
84 | [capture beginCaptureWithAuthorization:authorizationRef];
85 | AuthorizationFree(authorizationRef, kAuthorizationFlagDefaults);
86 | }
87 |
88 | #pragma mark -
89 |
90 | - (void)dataChanged {
91 | [packetsView reloadData];
92 | [[self document] updateChangeCount:NSChangeDone];
93 | }
94 |
95 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
96 | DatabaseLocker lock([self document]);
97 |
98 | sqlite3_reset(rowCountStmt);
99 | sqlite3_step(rowCountStmt);
100 |
101 | return sqlite3_column_int(rowCountStmt, 0);
102 | }
103 |
104 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
105 | DatabaseLocker lock([self document]);
106 | int appRowID;
107 | NSString *result;
108 |
109 | sqlite3_bind_int64(packetSelectStmt, 1, row);
110 | sqlite3_step(packetSelectStmt);
111 | appRowID = sqlite3_column_int64(packetSelectStmt, 0);
112 | sqlite3_reset(packetSelectStmt);
113 |
114 | sqlite3_bind_int64(appSelectStmt, 1, appRowID);
115 | sqlite3_step(appSelectStmt);
116 | result = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(appSelectStmt, 0)];
117 | sqlite3_reset(appSelectStmt);
118 |
119 | return result;
120 | }
121 |
122 | - (void)tableViewSelectionDidChange:(NSNotification *)notification {
123 | NSInteger row = [[notification object] selectedRow];
124 |
125 | NSData *data = [[self document] packetData:row];
126 | //[dataView setString:[data description]];
127 | [dataView setData: data];
128 | }
129 |
130 | - (void)tableView:(NSTableView *)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
131 | {
132 | NSString *appPath = [cell stringValue];
133 |
134 | //strip off the XXX.app/Contents/MacOS/XXX part of the appPath. FIXME?
135 | appPath = [appPath stringByDeletingLastPathComponent];
136 | appPath = [appPath stringByDeletingLastPathComponent];
137 | appPath = [appPath stringByDeletingLastPathComponent];
138 | if (![appPath length]) return;
139 |
140 | NSImage *appIcon = [[NSWorkspace sharedWorkspace] iconForFile:appPath];
141 | NSImage *smallIcon = [[[NSImage alloc] initWithSize:NSMakeSize(16.0f, 16.0f)] autorelease];
142 | [smallIcon addRepresentation:[appIcon bestRepresentationForRect:NSMakeRect(0, 0, 16.0f, 16.0f) context:nil hints:nil]];
143 |
144 | PrettyCell *prettyCell = (PrettyCell *)cell;
145 | [prettyCell setImage: smallIcon];
146 | }
147 |
148 |
149 | @end
150 |
--------------------------------------------------------------------------------
/Sniffer_Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'Sniffer' target in the 'Sniffer' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/SpinLock.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include
17 |
18 | /**
19 | * A simple RAII wrapper for an OSSpinLock.
20 | */
21 | class SpinLock {
22 | public:
23 | SpinLock(OSSpinLock *lock) :
24 | mLock(lock)
25 | {
26 | OSSpinLockLock(mLock);
27 | }
28 |
29 | ~SpinLock()
30 | {
31 | OSSpinLockUnlock(mLock);
32 | }
33 |
34 | private:
35 | SpinLock(const SpinLock &other);
36 | SpinLock& operator= (const SpinLock& other);
37 |
38 | OSSpinLock *mLock;
39 | };
40 |
--------------------------------------------------------------------------------
/Utils.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include "Utils.h"
17 | #include
18 | #include
19 |
20 | static void * ThreadEntrypoint(void *info) {
21 | dispatch_block_t block = (dispatch_block_t)info;
22 | block();
23 |
24 | // We had to create a copy of the block to pass it into pthread_create, so
25 | // be sure to release it here.
26 | Block_release(block);
27 | return NULL;
28 | }
29 |
30 | void RunBlockThreaded(dispatch_block_t block) {
31 | pthread_t result;
32 | pthread_attr_t attr;
33 | pthread_attr_init( &attr );
34 | pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
35 | pthread_create( &result, &attr, ThreadEntrypoint, Block_copy(block));
36 | pthread_attr_destroy( &attr );
37 | }
38 |
--------------------------------------------------------------------------------
/Utils.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #include
17 |
18 | /**
19 | * Runs a block in its own pthread.
20 | */
21 | void RunBlockThreaded(dispatch_block_t block);
22 |
--------------------------------------------------------------------------------
/main.m:
--------------------------------------------------------------------------------
1 | // Copyright 2011 Joe Ranieri.
2 | //
3 | // Sniffer is free software: you can redistribute it and/or modify it under the
4 | // terms of the GNU General Public License as published by the Free Software
5 | // Foundation, either version 2 of the License, or (at your option) any later
6 | // version.
7 | //
8 | // Sniffer is distributed in the hope that it will be useful, but WITHOUT ANY
9 | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 | // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11 | // details.
12 | //
13 | // You should have received a copy of the GNU General Public License along with
14 | // Sniffer. If not, see .
15 |
16 | #import
17 |
18 | int main(int argc, char *argv[])
19 | {
20 | return NSApplicationMain(argc, (const char **) argv);
21 | }
22 |
--------------------------------------------------------------------------------
/schema.sql:
--------------------------------------------------------------------------------
1 | PRAGMA foreign_keys = ON;
2 |
3 | CREATE TABLE applications (
4 | name TEXT,
5 | path TEXT,
6 | bookmark BLOB
7 | );
8 |
9 | CREATE TABLE packets (
10 | application_fk INTEGER,
11 | data_offset INTEGER,
12 | data_size INTEGER
13 | );
14 |
15 | CREATE TABLE metadata (
16 | packet_fk INTEGER,
17 | name TEXT,
18 | data TEXT
19 | );
20 |
--------------------------------------------------------------------------------