#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <X11/extensions/Print.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xauth.h>
#include <stdlib.h>
#include <X11/Xos.h>
#include "XpExtUtil.h"
#define ALT_PDM_SELECTION_ENV_VAR "XPDMSELECTION"
#define ALT_PMD_DISPLAY_ENV_VAR "XPDMDISPLAY"
#define PDM_XAUTHORITY_ENV_VAR "XPDMXAUTHORITY"
char *_xpstrdup(char * str)
{
int len;
char *newstr;
if (!str)
return( (char *) NULL );
len = strlen(str) + 1;
newstr = (char *) Xmalloc( len );
memcpy( newstr, str, len );
return( newstr );
}
static Display *
_XpGetSelectionServer (
Display *print_display,
Display *video_display,
Atom *sel_atom
)
{
char *tstr1, *tstr2, *tstr3, *tstrptr;
char *sel_displaystr;
Display *sel_display;
char *selectionstr;
if ( (sel_displaystr = getenv( ALT_PMD_DISPLAY_ENV_VAR )) != NULL ) {
if ( !strcmp(sel_displaystr, "print") ) {
sel_display = print_display;
}
else if ( !strcmp(sel_displaystr, "video") ) {
sel_display = video_display;
}
else {
tstr1 = _xpstrdup( sel_displaystr );
tstr2 = _xpstrdup( XDisplayString(print_display) );
tstr3 = _xpstrdup( XDisplayString(video_display) );
if (( tstrptr = strrchr( tstr1, ':' ) ))
if (( tstrptr = strchr( tstrptr, '.' ) ))
*tstrptr = '\0';
if (( tstrptr = strrchr( tstr2, ':' ) ))
if (( tstrptr = strchr( tstrptr, '.' ) ))
*tstrptr = '\0';
if (( tstrptr = strrchr( tstr3, ':' ) ))
if (( tstrptr = strchr( tstrptr, '.' ) ))
*tstrptr = '\0';
if ( !strcmp( tstr1, tstr2 ) ) {
sel_display = print_display;
}
else if ( !strcmp( tstr1, tstr3 ) ) {
sel_display = video_display;
}
else {
sel_display = XOpenDisplay(sel_displaystr);
}
XFree( tstr3 );
XFree( tstr2 );
XFree( tstr1 );
}
}
else {
sel_display = print_display;
}
if (sel_display) {
if ( (selectionstr = getenv( ALT_PDM_SELECTION_ENV_VAR )) == NULL )
selectionstr = "PDM_MANAGER";
*sel_atom = XInternAtom( sel_display, selectionstr, False );
}
return( sel_display );
}
Status
XpGetPdmStartParams (
Display *print_display,
Window print_window,
XPContext print_context,
Display *video_display,
Window video_window,
Display **selection_display,
Atom *selection,
Atom *type,
int *format,
unsigned char **data,
int *nelements
)
{
XTextProperty text_prop;
int status;
char str1[128], str2[128], str3[128];
char *list[6];
*selection_display = _XpGetSelectionServer( print_display, video_display,
selection );
if (*selection_display == NULL) {
return( (Status) NULL );
}
list[0] = XDisplayString( video_display );
sprintf( str1, "0x%lx", (long)video_window );
list[1] = str1;
list[2] = XDisplayString( print_display );
sprintf( str2, "0x%lx", (long)print_window );
list[3] = str2;
sprintf( str3, "0x%lx", (long)print_context );
list[4] = str3;
list[5] = XpGetLocaleNetString();
status = XSupportsLocale();
if ( ! status ) {
if ( (*selection_display != print_display) &&
(*selection_display != video_display) ) {
XCloseDisplay( *selection_display );
*selection_display = (Display *) NULL;
}
return( (Status) NULL );
}
status = XmbTextListToTextProperty( *selection_display, list, 6,
XStdICCTextStyle, &text_prop );
if ( status < 0 ) {
if ( (*selection_display != print_display) &&
(*selection_display != video_display) ) {
XCloseDisplay( *selection_display );
*selection_display = (Display *) NULL;
}
return( (Status) NULL );
}
*type = text_prop.encoding;
*format = text_prop.format;
*data = text_prop.value;
*nelements = text_prop.nitems;
XFree(list[5]);
return( (Status) 1 );
}
Status XpSendOneTicket(
Display *display,
Window window,
Xauth *ticket,
Bool more )
{
XClientMessageEvent ev;
int bigstrlen, left, gofor;
char *bigstr, *tptr;
Status status;
ev.type = ClientMessage;
ev.display = display;
ev.window = window;
ev.message_type = XInternAtom( display, "PDM_MAIL", False );
ev.format = 16;
if (!ticket) {
ev.data.s[0] = 0;
}
else {
if (more)
ev.data.s[0] = 2;
else
ev.data.s[0] = 1;
ev.data.s[1] = (short) ticket->address_length;
ev.data.s[2] = (short) ticket->number_length;
ev.data.s[3] = (short) ticket->name_length;
ev.data.s[4] = (short) ticket->data_length;
ev.data.s[5] = (short) ticket->family;
}
status = XSendEvent( display, window, False, 0L, (XEvent *) &ev );
if (!status)
return( (Status) 0 );
if (!ticket)
return( (Status) 1 );;
ev.format = 8;
bigstrlen = (int) ticket->address_length +
(int) ticket->number_length +
(int) ticket->name_length +
(int) ticket->data_length;
bigstr = Xmalloc( bigstrlen );
tptr = bigstr;
memcpy( tptr, ticket->address, ticket->address_length );
tptr += ticket->address_length;
memcpy( tptr, ticket->number, ticket->number_length );
tptr += ticket->number_length;
memcpy( tptr, ticket->name, ticket->name_length );
tptr += ticket->name_length;
memcpy( tptr, ticket->data, ticket->data_length );
left = bigstrlen;
tptr = bigstr;
while ( left ) {
if (left > 20)
gofor = 20;
else
gofor = left;
memcpy( ev.data.b, tptr, gofor );
tptr += gofor;
left -= gofor;
status = XSendEvent( display, window, False, 0L, (XEvent *) &ev );
if (!status) {
Xfree( bigstr );
return( (Status) 0 );
}
}
Xfree( bigstr );
return( (Status) 1 );
}
Status XpSendAuth( Display *display, Window window )
{
FILE *auth_file;
char *auth_name;
Xauth *entry;
if ( !(auth_name = getenv( PDM_XAUTHORITY_ENV_VAR )) ) {
return( (Status) 0 );
}
if (access (auth_name, R_OK) != 0)
return( (Status) 0 );
auth_file = fopen (auth_name, "r");
if (!auth_file)
return( (Status) 0 );
for (;;) {
entry = XauReadAuth (auth_file);
if (!entry)
break;
XpSendOneTicket( display, window, entry, True );
XauDisposeAuth (entry);
}
XpSendOneTicket( display, window, (Xauth *) NULL, False );
(void) fclose (auth_file);
return( (Status) 1 );
}
Status
XpGetAuthParams (
Display *print_display,
Display *video_display,
Display **sel_display,
Atom *sel_atom,
Atom *sel_target_atom
)
{
*sel_display = _XpGetSelectionServer( print_display, video_display,
sel_atom );
if (*sel_display == NULL) {
return (Status)0;
}
*sel_target_atom = XInternAtom( *sel_display, "PDM_MBOX", False );
return (Status)1;
}
typedef struct {
Window requestor;
Atom selection;
Atom target;
} Dosnrec;
typedef struct {
Window window;
Atom atom;
} Dopnrec, Docmrec;
static Bool digOutSelectionNotify(
Display *display,
XEvent *event,
char *arg
)
{
Dosnrec *t;
if (event->type == SelectionNotify) {
t = (Dosnrec *) arg;
if ( ( t->requestor == event->xselection.requestor ) &&
( t->selection == event->xselection.selection ) &&
( t->target == event->xselection.target ) ) {
return( True );
}
if ( ( t->requestor == event->xselection.requestor ) &&
( t->selection == event->xselection.selection ) &&
( None == event->xselection.property ) ) {
return( True );
}
}
return( False );
}
static Bool digOutPropertyNotify(
Display *display,
XEvent *event,
char *arg
)
{
Dopnrec *t;
if (event->type == PropertyNotify) {
t = (Dopnrec *) arg;
if ( ( t->window == event->xproperty.window ) &&
( t->atom == event->xproperty.atom ) ) {
return( True );
}
}
return( False );
}
#ifdef UNUSED
static Bool digOutClientMessage(
Display *display,
XEvent *event,
char *arg
)
{
Docmrec *t;
if (event->type == ClientMessage) {
t = (Docmrec *) arg;
if ( ( t->window == event->xclient.window ) &&
( t->atom == event->xclient.message_type ) ) {
return( True );
}
}
return( False );
}
#endif
static char *
XpCookieToPdm (
Display *print_display,
Display *video_display,
Window sel_window
)
{
Display *sel_display;
Atom prop_atom, sel_atom, pdm_mbox_atom, ttype;
Dosnrec dosnrec;
Dopnrec dopnrec;
XEvent tevent;
int tformat;
unsigned long nitems, bytes_after;
unsigned char *return_data;
char *sel_str;
char cdata[2048];
Window tmpw;
if ( !getenv(PDM_XAUTHORITY_ENV_VAR) ) {
return( (char *) NULL );
}
if (! XpGetAuthParams( print_display, video_display,
&sel_display, &sel_atom, &pdm_mbox_atom ) ) {
sprintf(cdata,
"XpCookieToPdm: XpGetAuthParams failed");
return( _xpstrdup( cdata ) );
}
prop_atom = XInternAtom( sel_display, "PDM_MBOX_PROP", False );
XConvertSelection( sel_display, sel_atom, pdm_mbox_atom,
prop_atom, sel_window, CurrentTime );
dosnrec.requestor = sel_window;
dosnrec.selection = sel_atom;
dosnrec.target = pdm_mbox_atom;
XIfEvent( sel_display, &tevent, digOutSelectionNotify, (char *) &dosnrec );
if ( tevent.xselection.property == None ) {
sel_str = XGetAtomName( sel_display, sel_atom );
sprintf(cdata,
"XpCookieToPdm: Unable to make selection on %s", sel_str);
XFree(sel_str);
XDeleteProperty( sel_display, sel_window, prop_atom );
if ((sel_display != print_display) && (sel_display != video_display))
XCloseDisplay( sel_display );
return( _xpstrdup( cdata ) );
}
XGetWindowProperty( sel_display, sel_window,
prop_atom, 0, 100000, True, AnyPropertyType,
&ttype, &tformat, &nitems, &bytes_after,
&return_data );
dopnrec.window = sel_window;
dopnrec.atom = prop_atom;
while ( XCheckIfEvent( sel_display, &tevent, digOutPropertyNotify,
(char *) &dopnrec ) );
if ((sel_display != print_display) && (sel_display != video_display))
XCloseDisplay( sel_display );
if ((ttype != XA_WINDOW) && (tformat != 32) && (nitems != 1)) {
sprintf(cdata,
"XpCookieToPdm: Unable to read SelectionNotify property" );
return( _xpstrdup( cdata ) );
}
tmpw = *((Window *) return_data);
Xfree( return_data );
XpSendAuth( sel_display, tmpw );
return( (char *) NULL );
}
char *
XpNotifyPdm (
Display *print_display,
Window print_window,
XPContext print_context,
Display *video_display,
Window video_window,
Bool auth_flag
)
{
enum { XA_PDM_CLIENT_PROP, XA_PDM_START, XA_PDM_START_OK,
XA_PDM_START_VXAUTH, XA_PDM_START_PXAUTH, XA_PDM_START_ERROR,
NUM_ATOMS };
static char *atom_names[] = {
"PDM_CLIENT_PROP", "PDM_START", "PDM_START_OK",
"PDM_START_VXAUTH", "PDM_START_PXAUTH", "PDM_START_ERROR" };
char cdata[2048];
char *tptr;
Dosnrec dosnrec;
Dopnrec dopnrec;
XEvent tevent;
Display *sel_display;
int sel_screen;
Atom sel_atom;
char *sel_str;
Window sel_window;
Atom prop_type;
int prop_format;
unsigned char *prop_data;
int prop_nelements;
Atom ttype;
int tformat;
unsigned long nitems, bytes_after;
unsigned char *return_data;
int tmpi;
Atom atoms[NUM_ATOMS];
if ( ! XpGetPdmStartParams( print_display, print_window, print_context,
video_display, video_window,
&sel_display,
&sel_atom,
&prop_type,
&prop_format,
&prop_data,
&prop_nelements ) ) {
sprintf(cdata, "XpNotifyPdm: XpGetPdmStartParams failed" );
return( _xpstrdup( cdata ) );
}
sel_screen = DefaultScreen( sel_display );
sel_window = XCreateSimpleWindow( sel_display,
DefaultRootWindow( sel_display ),
0, 0, 1, 1, 1,
BlackPixel(sel_display, sel_screen),
WhitePixel(sel_display, sel_screen) );
if (auth_flag) {
tptr = XpCookieToPdm ( print_display, video_display, sel_window );
if (tptr)
return( tptr );
}
XInternAtoms( sel_display, atom_names, NUM_ATOMS, False, atoms );
XChangeProperty( sel_display,
sel_window, atoms[XA_PDM_CLIENT_PROP],
prop_type,
prop_format,
PropModeReplace,
prop_data,
prop_nelements );
XFree( prop_data );
XConvertSelection( sel_display, sel_atom, atoms[XA_PDM_START],
atoms[XA_PDM_CLIENT_PROP], sel_window, CurrentTime );
dosnrec.requestor = sel_window;
dosnrec.selection = sel_atom;
dosnrec.target = atoms[XA_PDM_START];
XIfEvent( sel_display, &tevent, digOutSelectionNotify, (char *) &dosnrec );
if ( tevent.xselection.property == None ) {
sel_str = XGetAtomName( sel_display, sel_atom );
sprintf(cdata,
"XpNotifyPdm: Unable to make selection on %s", sel_str);
XFree(sel_str);
XDeleteProperty( sel_display, sel_window, atoms[XA_PDM_CLIENT_PROP] );
XDestroyWindow( sel_display, sel_window );
if ((sel_display != print_display) && (sel_display != video_display))
XCloseDisplay( sel_display );
return( _xpstrdup( cdata ) );
}
XGetWindowProperty( sel_display, sel_window,
atoms[XA_PDM_CLIENT_PROP],
0, 100000, True, AnyPropertyType,
&ttype, &tformat, &nitems, &bytes_after,
&return_data );
dopnrec.window = sel_window;
dopnrec.atom = atoms[XA_PDM_CLIENT_PROP];
while ( XCheckIfEvent( sel_display, &tevent, digOutPropertyNotify,
(char *) &dopnrec ) );
XDestroyWindow( sel_display, sel_window );
if ((sel_display != print_display) && (sel_display != video_display))
XCloseDisplay( sel_display );
if ((ttype != XA_ATOM) && (tformat != 32) && (nitems != 1)) {
sprintf(cdata,
"XpNotifyPdm: Unable to read SelectionNotify property" );
return( _xpstrdup( cdata ) );
}
tmpi = *((Atom *) return_data);
Xfree( return_data );
if ( tmpi == atoms[XA_PDM_START_OK] ) {
return( (char *) NULL );
}
else if ( tmpi == atoms[XA_PDM_START_VXAUTH] ) {
sprintf(cdata,
"XpNotifyPdm: PDM not authorized to connect to video display." );
return( _xpstrdup( cdata ) );
}
else if ( tmpi == atoms[XA_PDM_START_PXAUTH] ) {
sprintf(cdata,
"XpNotifyPdm: PDM not authorized to connect to print display." );
return( _xpstrdup( cdata ) );
}
else if ( tmpi == atoms[XA_PDM_START_ERROR] ) {
sprintf(cdata,
"XpNotifyPdm: PDM encountered an error. See PDM log file." );
return( _xpstrdup( cdata ) );
}
else {
sprintf(cdata,
"XpNotifyPdm: unknown PDM error." );
return( _xpstrdup( cdata ) );
}
}