in notifier/rss.c [55:393]
static int save_rss(cups_array_t *rss, const char *filename,
const char *baseurl);
static char *xml_escape(const char *s);
/*
* 'main()' - Main entry for the test notifier.
*/
int /* O - Exit status */
main(int argc, /* I - Number of command-line arguments */
char *argv[]) /* I - Command-line arguments */
{
int i; /* Looping var */
ipp_t *event; /* Event from scheduler */
ipp_state_t state; /* IPP event state */
char scheme[32], /* URI scheme ("rss") */
username[256], /* Username for remote RSS */
host[1024], /* Hostname for remote RSS */
resource[1024], /* RSS file */
*options; /* Options */
int port, /* Port number for remote RSS */
max_events; /* Maximum number of events */
http_t *http; /* Connection to remote server */
http_status_t status; /* HTTP GET/PUT status code */
char filename[1024], /* Local filename */
newname[1024]; /* filename.N */
cups_lang_t *language; /* Language information */
ipp_attribute_t *printer_up_time, /* Timestamp on event */
*notify_sequence_number,/* Sequence number */
*notify_printer_uri; /* Printer URI */
char *subject, /* Subject for notification message */
*text, /* Text for notification message */
link_url[1024], /* Link to printer */
link_scheme[32], /* Scheme for link */
link_username[256], /* Username for link */
link_host[1024], /* Host for link */
link_resource[1024]; /* Resource for link */
int link_port; /* Link port */
cups_array_t *rss; /* RSS message array */
_cups_rss_t *msg; /* RSS message */
char baseurl[1024]; /* Base URL */
fd_set input; /* Input set for select() */
struct timeval timeout; /* Timeout for select() */
int changed; /* Has the RSS data changed? */
int exit_status; /* Exit status */
fprintf(stderr, "DEBUG: argc=%d\n", argc);
for (i = 0; i < argc; i ++)
fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]);
/*
* See whether we are publishing this RSS feed locally or remotely...
*/
if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme),
username, sizeof(username), host, sizeof(host), &port,
resource, sizeof(resource)) < HTTP_URI_OK)
{
fprintf(stderr, "ERROR: Bad RSS URI \"%s\"!\n", argv[1]);
return (1);
}
max_events = 20;
if ((options = strchr(resource, '?')) != NULL)
{
*options++ = '\0';
if (!strncmp(options, "max_events=", 11))
{
max_events = atoi(options + 11);
if (max_events <= 0)
max_events = 20;
}
}
rss = cupsArrayNew((cups_array_func_t)compare_rss, NULL);
if (host[0])
{
/*
* Remote feed, see if we can get the current file...
*/
int fd; /* Temporary file */
if ((rss_password = strchr(username, ':')) != NULL)
*rss_password++ = '\0';
cupsSetPasswordCB(password_cb);
cupsSetUser(username);
if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
{
fprintf(stderr, "ERROR: Unable to create temporary file: %s\n",
strerror(errno));
return (1);
}
if ((http = httpConnect(host, port)) == NULL)
{
fprintf(stderr, "ERROR: Unable to connect to %s on port %d: %s\n",
host, port, strerror(errno));
close(fd);
unlink(filename);
return (1);
}
status = cupsGetFd(http, resource, fd);
close(fd);
if (status != HTTP_OK && status != HTTP_NOT_FOUND)
{
fprintf(stderr, "ERROR: Unable to GET %s from %s on port %d: %d %s\n",
resource, host, port, status, httpStatus(status));
httpClose(http);
unlink(filename);
return (1);
}
strlcpy(newname, filename, sizeof(newname));
httpAssembleURI(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http",
NULL, host, port, resource);
}
else
{
const char *cachedir, /* CUPS_CACHEDIR */
*server_name, /* SERVER_NAME */
*server_port; /* SERVER_PORT */
http = NULL;
if ((cachedir = getenv("CUPS_CACHEDIR")) == NULL)
cachedir = CUPS_CACHEDIR;
if ((server_name = getenv("SERVER_NAME")) == NULL)
server_name = "localhost";
if ((server_port = getenv("SERVER_PORT")) == NULL)
server_port = "631";
snprintf(filename, sizeof(filename), "%s/rss%s", cachedir, resource);
snprintf(newname, sizeof(newname), "%s.N", filename);
httpAssembleURIf(HTTP_URI_CODING_ALL, baseurl, sizeof(baseurl), "http",
NULL, server_name, atoi(server_port), "/rss%s", resource);
}
/*
* Load the previous RSS file, if any...
*/
load_rss(rss, filename);
changed = cupsArrayCount(rss) == 0;
/*
* Localize for the user's chosen language...
*/
language = cupsLangDefault();
/*
* Read events and update the RSS file until we are out of events.
*/
for (exit_status = 0, event = NULL;;)
{
if (changed)
{
/*
* Save the messages to the file again, uploading as needed...
*/
if (save_rss(rss, newname, baseurl))
{
if (http)
{
/*
* Upload the RSS file...
*/
if ((status = cupsPutFile(http, resource, filename)) != HTTP_CREATED)
fprintf(stderr, "ERROR: Unable to PUT %s from %s on port %d: %d %s\n",
resource, host, port, status, httpStatus(status));
}
else
{
/*
* Move the new RSS file over top the old one...
*/
if (rename(newname, filename))
fprintf(stderr, "ERROR: Unable to rename %s to %s: %s\n",
newname, filename, strerror(errno));
}
changed = 0;
}
}
/*
* Wait up to 30 seconds for an event...
*/
timeout.tv_sec = 30;
timeout.tv_usec = 0;
FD_ZERO(&input);
FD_SET(0, &input);
if (select(1, &input, NULL, NULL, &timeout) < 0)
continue;
else if (!FD_ISSET(0, &input))
{
fprintf(stderr, "DEBUG: %s is bored, exiting...\n", argv[1]);
break;
}
/*
* Read the next event...
*/
event = ippNew();
while ((state = ippReadFile(0, event)) != IPP_DATA)
{
if (state <= IPP_IDLE)
break;
}
if (state == IPP_ERROR)
fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr);
if (state <= IPP_IDLE)
break;
/*
* Collect the info from the event...
*/
printer_up_time = ippFindAttribute(event, "printer-up-time",
IPP_TAG_INTEGER);
notify_sequence_number = ippFindAttribute(event, "notify-sequence-number",
IPP_TAG_INTEGER);
notify_printer_uri = ippFindAttribute(event, "notify-printer-uri",
IPP_TAG_URI);
subject = cupsNotifySubject(language, event);
text = cupsNotifyText(language, event);
if (printer_up_time && notify_sequence_number && subject && text)
{
/*
* Create a new RSS message...
*/
if (notify_printer_uri)
{
httpSeparateURI(HTTP_URI_CODING_ALL,
notify_printer_uri->values[0].string.text,
link_scheme, sizeof(link_scheme),
link_username, sizeof(link_username),
link_host, sizeof(link_host), &link_port,
link_resource, sizeof(link_resource));
httpAssembleURI(HTTP_URI_CODING_ALL, link_url, sizeof(link_url),
"http", link_username, link_host, link_port,
link_resource);
}
msg = new_message(notify_sequence_number->values[0].integer,
xml_escape(subject), xml_escape(text),
notify_printer_uri ? xml_escape(link_url) : NULL,
printer_up_time->values[0].integer);
if (!msg)
{
fprintf(stderr, "ERROR: Unable to create message: %s\n",
strerror(errno));
exit_status = 1;
break;
}
/*
* Add it to the array...
*/
cupsArrayAdd(rss, msg);
changed = 1;
/*
* Trim the array as needed...
*/
while (cupsArrayCount(rss) > max_events)
{
msg = cupsArrayFirst(rss);
cupsArrayRemove(rss, msg);
delete_message(msg);
}
}
if (subject)
free(subject);
if (text)
free(text);
ippDelete(event);
event = NULL;
}
/*
* We only get here when idle or error...
*/
ippDelete(event);
if (http)
{
unlink(filename);
httpClose(http);
}
return (exit_status);
}