Blame channels/printer/client/printer_cups.c

Packit Service fa4841
/**
Packit Service fa4841
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit Service fa4841
 * Print Virtual Channel - CUPS driver
Packit Service fa4841
 *
Packit Service fa4841
 * Copyright 2010-2011 Vic Lee
Packit Service fa4841
 * Copyright 2015 Thincast Technologies GmbH
Packit Service fa4841
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
Packit Service fa4841
 * Copyright 2016 Armin Novak <armin.novak@gmail.com>
Packit Service fa4841
 *
Packit Service fa4841
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit Service fa4841
 * you may not use this file except in compliance with the License.
Packit Service fa4841
 * You may obtain a copy of the License at
Packit Service fa4841
 *
Packit Service fa4841
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit Service fa4841
 *
Packit Service fa4841
 * Unless required by applicable law or agreed to in writing, software
Packit Service fa4841
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit Service fa4841
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit Service fa4841
 * See the License for the specific language governing permissions and
Packit Service fa4841
 * limitations under the License.
Packit Service fa4841
 */
Packit Service fa4841
Packit Service fa4841
#ifdef HAVE_CONFIG_H
Packit Service fa4841
#include "config.h"
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
#include <stdio.h>
Packit Service fa4841
#include <stdlib.h>
Packit Service fa4841
#include <string.h>
Packit Service fa4841
#include <pthread.h>
Packit Service fa4841
Packit Service fa4841
#include <time.h>
Packit Service fa4841
#include <cups/cups.h>
Packit Service fa4841
Packit Service fa4841
#include <winpr/crt.h>
Packit Service fa4841
#include <winpr/string.h>
Packit Service fa4841
Packit Service fa4841
#include <freerdp/channels/rdpdr.h>
Packit Service fa4841
Packit Service bb5c11
#include "printer_main.h"
Packit Service bb5c11
Packit Service bb5c11
#include "printer_cups.h"
Packit Service fa4841
Packit Service fa4841
typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver;
Packit Service fa4841
typedef struct rdp_cups_printer rdpCupsPrinter;
Packit Service fa4841
typedef struct rdp_cups_print_job rdpCupsPrintJob;
Packit Service fa4841
Packit Service fa4841
struct rdp_cups_printer_driver
Packit Service fa4841
{
Packit Service fa4841
	rdpPrinterDriver driver;
Packit Service fa4841
Packit Service fa4841
	int id_sequence;
Packit Service fa4841
};
Packit Service fa4841
Packit Service fa4841
struct rdp_cups_printer
Packit Service fa4841
{
Packit Service fa4841
	rdpPrinter printer;
Packit Service fa4841
Packit Service fa4841
	rdpCupsPrintJob* printjob;
Packit Service fa4841
};
Packit Service fa4841
Packit Service fa4841
struct rdp_cups_print_job
Packit Service fa4841
{
Packit Service fa4841
	rdpPrintJob printjob;
Packit Service fa4841
Packit Service fa4841
	void* printjob_object;
Packit Service fa4841
	int printjob_id;
Packit Service fa4841
};
Packit Service fa4841
Packit Service bb5c11
static void printer_cups_get_printjob_name(char* buf, int size)
Packit Service fa4841
{
Packit Service fa4841
	time_t tt;
Packit Service fa4841
	struct tm* t;
Packit Service fa4841
Packit Service fa4841
	tt = time(NULL);
Packit Service bb5c11
	t = localtime(&tt;;
Packit Service bb5c11
	sprintf_s(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
Packit Service bb5c11
		t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
Packit Service bb5c11
		t->tm_hour, t->tm_min, t->tm_sec);
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
/**
Packit Service fa4841
 * Function description
Packit Service fa4841
 *
Packit Service fa4841
 * @return 0 on success, otherwise a Win32 error code
Packit Service fa4841
 */
Packit Service bb5c11
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
Packit Service fa4841
{
Packit Service bb5c11
	rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
Packit Service fa4841
Packit Service fa4841
#ifndef _CUPS_API_1_4
Packit Service fa4841
Packit Service fa4841
	{
Packit Service fa4841
		FILE* fp;
Packit Service fa4841
Packit Service bb5c11
		fp = fopen((const char*) cups_printjob->printjob_object, "a+b");
Packit Service fa4841
Packit Service fa4841
		if (!fp)
Packit Service fa4841
			return ERROR_INTERNAL_ERROR;
Packit Service fa4841
Packit Service fa4841
		if (fwrite(data, 1, size, fp) < size)
Packit Service fa4841
		{
Packit Service fa4841
			fclose(fp);
Packit Service fa4841
			return ERROR_INTERNAL_ERROR;
Packit Service fa4841
			// FIXME once this function doesn't return void anymore!
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		fclose(fp);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#else
Packit Service fa4841
Packit Service bb5c11
	cupsWriteRequestData((http_t*) cups_printjob->printjob_object, (const char*) data, size);
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
	return CHANNEL_RC_OK;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void printer_cups_close_printjob(rdpPrintJob* printjob)
Packit Service fa4841
{
Packit Service bb5c11
	rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;
Packit Service fa4841
Packit Service fa4841
#ifndef _CUPS_API_1_4
Packit Service fa4841
Packit Service fa4841
	{
Packit Service fa4841
		char buf[100];
Packit Service fa4841
Packit Service bb5c11
		printer_cups_get_printjob_name(buf, sizeof(buf));
Packit Service fa4841
Packit Service bb5c11
		if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0)
Packit Service fa4841
		{
Packit Service bb5c11
Packit Service fa4841
		}
Packit Service fa4841
Packit Service fa4841
		unlink(cups_printjob->printjob_object);
Packit Service fa4841
		free(cups_printjob->printjob_object);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#else
Packit Service fa4841
Packit Service bb5c11
	cupsFinishDocument((http_t*) cups_printjob->printjob_object, printjob->printer->name);
Packit Service fa4841
	cups_printjob->printjob_id = 0;
Packit Service bb5c11
	httpClose((http_t*) cups_printjob->printjob_object);
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service bb5c11
	((rdpCupsPrinter*) printjob->printer)->printjob = NULL;
Packit Service bb5c11
	free(cups_printjob) ;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
Packit Service fa4841
{
Packit Service bb5c11
	rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
Packit Service fa4841
	rdpCupsPrintJob* cups_printjob;
Packit Service fa4841
Packit Service fa4841
	if (cups_printer->printjob != NULL)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service bb5c11
	cups_printjob = (rdpCupsPrintJob*) calloc(1, sizeof(rdpCupsPrintJob));
Packit Service fa4841
	if (!cups_printjob)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	cups_printjob->printjob.id = id;
Packit Service fa4841
	cups_printjob->printjob.printer = printer;
Packit Service fa4841
Packit Service fa4841
	cups_printjob->printjob.Write = printer_cups_write_printjob;
Packit Service fa4841
	cups_printjob->printjob.Close = printer_cups_close_printjob;
Packit Service fa4841
Packit Service fa4841
#ifndef _CUPS_API_1_4
Packit Service fa4841
Packit Service fa4841
	cups_printjob->printjob_object = _strdup(tmpnam(NULL));
Packit Service fa4841
	if (!cups_printjob->printjob_object)
Packit Service fa4841
	{
Packit Service fa4841
		free(cups_printjob);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#else
Packit Service fa4841
	{
Packit Service fa4841
		char buf[100];
Packit Service fa4841
Packit Service bb5c11
		cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
Packit Service bb5c11
Packit Service fa4841
		if (!cups_printjob->printjob_object)
Packit Service fa4841
		{
Packit Service fa4841
			free(cups_printjob);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service bb5c11
		printer_cups_get_printjob_name(buf, sizeof(buf));
Packit Service fa4841
Packit Service bb5c11
		cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
Packit Service bb5c11
			printer->name, buf, 0, NULL);
Packit Service fa4841
Packit Service fa4841
		if (!cups_printjob->printjob_id)
Packit Service fa4841
		{
Packit Service bb5c11
			httpClose((http_t*) cups_printjob->printjob_object);
Packit Service fa4841
			free(cups_printjob);
Packit Service fa4841
			return NULL;
Packit Service fa4841
		}
Packit Service fa4841
Packit Service bb5c11
		cupsStartDocument((http_t*) cups_printjob->printjob_object,
Packit Service bb5c11
			printer->name, cups_printjob->printjob_id, buf, CUPS_FORMAT_AUTO, 1);
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
#endif
Packit Service fa4841
Packit Service fa4841
	cups_printer->printjob = cups_printjob;
Packit Service bb5c11
	
Packit Service fa4841
	return (rdpPrintJob*)cups_printjob;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, UINT32 id)
Packit Service fa4841
{
Packit Service fa4841
	rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
Packit Service fa4841
Packit Service fa4841
	if (cups_printer->printjob == NULL)
Packit Service fa4841
		return NULL;
Packit Service fa4841
	if (cups_printer->printjob->printjob.id != id)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	return (rdpPrintJob*)cups_printer->printjob;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static void printer_cups_free_printer(rdpPrinter* printer)
Packit Service fa4841
{
Packit Service bb5c11
	rdpCupsPrinter* cups_printer = (rdpCupsPrinter*) printer;
Packit Service fa4841
Packit Service fa4841
	if (cups_printer->printjob)
Packit Service bb5c11
		cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob);
Packit Service fa4841
Packit Service fa4841
	free(printer->name);
Packit Service fa4841
	free(printer->driver);
Packit Service fa4841
	free(printer);
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
Packit Service bb5c11
	const char* name, const char* driverName, BOOL is_default)
Packit Service fa4841
{
Packit Service fa4841
	rdpCupsPrinter* cups_printer;
Packit Service fa4841
Packit Service bb5c11
	cups_printer = (rdpCupsPrinter*) calloc(1, sizeof(rdpCupsPrinter));
Packit Service fa4841
	if (!cups_printer)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	cups_printer->printer.id = cups_driver->id_sequence++;
Packit Service fa4841
	cups_printer->printer.name = _strdup(name);
Packit Service fa4841
	if (!cups_printer->printer.name)
Packit Service fa4841
	{
Packit Service fa4841
		free(cups_printer);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service fa4841
	if (driverName)
Packit Service fa4841
		cups_printer->printer.driver = _strdup(driverName);
Packit Service fa4841
	else
Packit Service fa4841
		cups_printer->printer.driver = _strdup("MS Publisher Imagesetter");
Packit Service fa4841
	if (!cups_printer->printer.driver)
Packit Service fa4841
	{
Packit Service fa4841
		free(cups_printer->printer.name);
Packit Service fa4841
		free(cups_printer);
Packit Service fa4841
		return NULL;
Packit Service fa4841
	}
Packit Service fa4841
	cups_printer->printer.is_default = is_default;
Packit Service fa4841
Packit Service fa4841
	cups_printer->printer.CreatePrintJob = printer_cups_create_printjob;
Packit Service fa4841
	cups_printer->printer.FindPrintJob = printer_cups_find_printjob;
Packit Service bb5c11
	cups_printer->printer.Free = printer_cups_free_printer;
Packit Service fa4841
Packit Service bb5c11
	return (rdpPrinter*) cups_printer;
Packit Service fa4841
}
Packit Service fa4841
Packit Service fa4841
static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
Packit Service fa4841
{
Packit Service fa4841
	rdpPrinter** printers;
Packit Service fa4841
	int num_printers;
Packit Service bb5c11
	cups_dest_t *dests;
Packit Service bb5c11
	cups_dest_t *dest;
Packit Service fa4841
	int num_dests;
Packit Service fa4841
	int i;
Packit Service fa4841
Packit Service fa4841
	num_dests = cupsGetDests(&dests);
Packit Service bb5c11
	printers = (rdpPrinter**) calloc(num_dests + 1, sizeof(rdpPrinter*));
Packit Service fa4841
	if (!printers)
Packit Service fa4841
		return NULL;
Packit Service fa4841
Packit Service fa4841
	num_printers = 0;
Packit Service fa4841
Packit Service fa4841
	for (i = 0, dest = dests; i < num_dests; i++, dest++)
Packit Service fa4841
	{
Packit Service fa4841
		if (dest->instance == NULL)
Packit Service fa4841
		{
Packit Service bb5c11
			printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
Packit Service bb5c11
				dest->name, NULL, dest->is_default);
Packit Service fa4841
		}
Packit Service fa4841
	}
Packit Service fa4841
	cupsFreeDests(num_dests, dests);
Packit Service fa4841
Packit Service fa4841
	return printers;
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver,
Packit Service bb5c11
        const char* name, const char* driverName)
Packit Service fa4841
{
Packit Service bb5c11
	rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
Packit Service fa4841
Packit Service fa4841
	return printer_cups_new_printer(cups_driver, name, driverName,
Packit Service bb5c11
            cups_driver->id_sequence == 1 ? TRUE : FALSE);
Packit Service fa4841
}
Packit Service fa4841
Packit Service bb5c11
static rdpCupsPrinterDriver* cups_driver = NULL;
Packit Service fa4841
Packit Service bb5c11
rdpPrinterDriver* printer_cups_get_driver(void)
Packit Service fa4841
{
Packit Service bb5c11
	if (cups_driver == NULL)
Packit Service fa4841
	{
Packit Service bb5c11
		cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver));
Packit Service fa4841
Packit Service bb5c11
		if (!cups_driver)
Packit Service fa4841
			return NULL;
Packit Service fa4841
Packit Service bb5c11
		cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
Packit Service bb5c11
		cups_driver->driver.GetPrinter = printer_cups_get_printer;
Packit Service fa4841
Packit Service bb5c11
		cups_driver->id_sequence = 1;
Packit Service fa4841
	}
Packit Service fa4841
Packit Service bb5c11
	return (rdpPrinterDriver*) cups_driver;
Packit Service fa4841
}
Packit Service bb5c11