#import #include #include // cdropPasteboardChangeCount returns the general pasteboard's monotonic change // counter. Polling it is the cheap way to detect a copy without a callback API. long cdropPasteboardChangeCount(void) { return (long)[[NSPasteboard generalPasteboard] changeCount]; } // cdropPasteboardReadText returns a malloc'd UTF-8 copy of the pasteboard's // plain-text payload (caller frees), or NULL when there is no text (image / // file only). It sets *sensitive to 1 when a privacy marker type is present — // org.nspasteboard.{Concealed,Transient,AutoGenerated}Type — so the upload // policy can skip it. (Most password managers set no marker; this is a // best-effort secondary guard behind the server's short TTL.) char *cdropPasteboardReadText(int *sensitive) { NSPasteboard *pb = [NSPasteboard generalPasteboard]; *sensitive = 0; for (NSString *type in pb.types) { if ([type isEqualToString:@"org.nspasteboard.ConcealedType"] || [type isEqualToString:@"org.nspasteboard.TransientType"] || [type isEqualToString:@"org.nspasteboard.AutoGeneratedType"]) { *sensitive = 1; break; } } NSString *s = [pb stringForType:NSPasteboardTypeString]; if (s == nil) { return NULL; } const char *utf8 = [s UTF8String]; if (utf8 == NULL) { return NULL; } return strdup(utf8); } // cdropPasteboardWriteText replaces the pasteboard's contents with plain text. void cdropPasteboardWriteText(const char *text) { NSString *s = [NSString stringWithUTF8String:text]; if (s == nil) { return; } NSPasteboard *pb = [NSPasteboard generalPasteboard]; [pb clearContents]; [pb setString:s forType:NSPasteboardTypeString]; }