1. Changed license year
[apps/home/mobileprint.git] / mobileprint / previewgen / lib / pdfgen.c
1 /*
2 *  Mobileprint
3 *
4 * Copyright 2012  Samsung Electronics Co., Ltd
5
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9
10 * http://floralicense.org/license/
11
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "pgen_debug.h"
24 #include "previewgen.h"
25 #include "preview_util.h"
26
27 #include "pdfgen.h"
28
29
30 #define CUPS_OPTION_PORTRAIT    "orientation-requested=3"
31 #define CUPS_OPTION_LANDSCAPE   "orientation-requested=4"
32
33 #define CUPS_FILTER_DIR         "/usr/lib/cups/filter"
34
35 #define PPI_MAX_VAL             10000
36 #define PPI_STR_MAX_LEN         sizeof("10000")
37
38 #define PDFGEN_CMDSTR_MAXLEN    1024
39
40 #define PDFUNITE_PATH           "/usr/bin/pdfunite"
41
42 /**
43  * @brief      This function securely executes cmd line request with popen
44  * @param[in]  cmd_str        command line to execute
45  * @return     0       success
46  *             -1      error
47  */
48 int call_cmd(const char *cmd_str)
49 {
50         PGEN_TRACE_BEGIN;
51
52         //NOTICE : Use popen or fork/execv function instead of system() which has security hole.
53
54         FILE *cmd_output = popen(cmd_str, "r");
55         if (cmd_output == NULL) {
56                 PGEN_DEBUG("popen error (%s)", cmd_str);
57                 PGEN_TRACE_END;
58                 return -1;
59         }
60
61         char *str_buf = NULL;
62         size_t len = 0;
63         ssize_t read_len = 0;
64
65         do {
66                 read_len = getline(&str_buf, &len, cmd_output);
67         } while (read_len != -1);
68
69         PGEN_IF_FREE_MEM(str_buf);
70         pclose(cmd_output);
71
72         PGEN_TRACE_END;
73         return 0;
74 }
75
76 /**
77  * @brief      This function forms and executes cmd line request to CUPS
78  *             pdftopdf filter to convert PDF file
79  * @param[in]  path            path to destination PDF file
80  * @param[in]  outfile         destination file name
81  * @param[in]  settings        several settings of generating PDF
82  * @return     0       success
83  *             -1      error
84  */
85 int call_pdftopdf(const char *infile, const char *outfile,
86                                   const struct pdfgen_settings *settings)
87 {
88         PGEN_TRACE_BEGIN;
89
90         PGEN_RETV_IF(infile == NULL || outfile == NULL || settings == NULL || settings->ppd_filename == NULL,
91                                 -1, "Invalid argument");
92
93         int err_code = 0;
94         char cmd_str[1024];
95
96         /* placing n_up number of pages on the specified media */
97         snprintf(cmd_str, 1024, "PPD=%s " CUPS_FILTER_DIR "/pdftopdf job user title 1 \"%s number-up=%d PageSize=%s fit-to-page=True pdftopdfAutoRotate=false\" \"%s\""
98                          " >%s 2> " PREVIEW_TEMP_DIR "/errlog",
99                          settings->ppd_filename,
100                          PAGE_ORIENTATION_PORTRAIT == settings->orientation ? CUPS_OPTION_PORTRAIT :
101                          PAGE_ORIENTATION_LANDSCAPE == settings->orientation ? CUPS_OPTION_LANDSCAPE : "",
102                          settings->n_up,
103                          settings->paper_name, infile, outfile);
104
105         PGEN_DEBUG("call_pdftopdf(): %s", cmd_str);
106         err_code = call_cmd(cmd_str);
107         PGEN_RETV_IF(err_code, -1, "call_pdftopdf returned non-zero error code");
108
109         PGEN_TRACE_END;
110         return err_code;
111 }
112
113
114 int strcat_img_scale_option(char *res, const char *img_path,
115                 const struct page_scale *scale)
116 {
117         PGEN_TRACE_BEGIN;
118         PGEN_RETV_IF(res == NULL , -1 , "res is NULL");
119         PGEN_RETV_IF(img_path == NULL , -1 , "img_path is NULL");
120         PGEN_RETV_IF(scale == NULL , -1 , "scale is NULL");
121         //PGEN_RETV_IF(scale->w == 0 , -1 , "scale->w is 0");
122
123         int imgw;
124         int imgh;
125         int ppi;
126         char ppi_str[PPI_STR_MAX_LEN + 1];
127         int result;
128
129         switch (scale->type) {
130         case SCALE_FIT_TO_PAPER:
131                 strcat(res, "fit-to-page=true");
132                 return 0;
133         case SCALE_ORIGINAL:
134                 strcat(res, "scaling=100");
135                 return 0;
136         case SCALE_CUSTOM:
137                 break;
138         }
139
140         result = get_image_resolution(img_path, &imgw, &imgh);
141         PGEN_RETV_IF(result < 0, -1 , "Can't get resolution");
142
143         ppi = (double)imgw / scale->w;
144         PGEN_RETV_IF(ppi >= PPI_MAX_VAL, -1 , "Resolution is too big");
145
146         snprintf(ppi_str, PPI_STR_MAX_LEN, "%d", ppi);
147         ppi_str[PPI_STR_MAX_LEN] = '\0';
148         strcat(res, "PPI=");
149         strcat(res, ppi_str);
150
151         return 0;
152 }
153
154
155 /**
156  * @brief      This function forms and executes cmd line request to CUPS
157  *             imagetopdf filter to convert image to PDF file
158  * @param[in]  path            path to destination PDF file
159  * @param[in]  outfile         destination file name
160  * @param[in]  settings        several settings of generating PDF
161  * @return     0       success
162  *             -1      error
163  */
164 int call_imagetopdf(const char *infile, const char *outfile,
165                                         const struct pdfgen_settings *settings)
166 {
167         PGEN_TRACE_BEGIN;
168         PGEN_RETV_IF(infile== NULL || outfile == NULL || settings == NULL || settings->ppd_filename == NULL,
169                                 -1 , "Invalid argument");
170
171         int err_code = 0;
172         char cmd_str[1024];
173         char scale_str[256];
174
175         scale_str[0] = '\0';
176         strcat_img_scale_option(scale_str, infile,  &(settings->scale));
177
178         /* placing n_up number of pages on the specified media */
179         snprintf(cmd_str, 1024, "PPD=%s " CUPS_FILTER_DIR
180                         "/imagetopdf job user title 1 \"%s"
181                         " number-up=%d PageSize=%s"
182                         /*fit-to-page=%s*/
183                         " %s"
184                         " \" \"%s\""
185                         " >%s 2> /tmp/mobileprint/errlog",
186                         settings->ppd_filename,
187                         PAGE_ORIENTATION_PORTRAIT == settings->orientation
188                                 ? CUPS_OPTION_PORTRAIT " "
189                         : PAGE_ORIENTATION_LANDSCAPE == settings->orientation
190                                 ? CUPS_OPTION_LANDSCAPE " "
191                         : "",
192                         settings->n_up,
193                         settings->paper_name,
194                         /*SCALE_FIT_TO_PAPER == settings->scale.type
195                                 ? "True" : "False",*/
196                         scale_str,
197                         infile, outfile);
198
199         PGEN_DEBUG("call_imagetopdf(): %s", cmd_str);
200         err_code = call_cmd(cmd_str);
201         PGEN_RETV_IF(err_code, -1, "call_pdftopdf returned non-zero error code");
202
203         PGEN_TRACE_END;
204         return 0;
205 }
206
207
208 int call_pdfunite(char **const infiles_z, const char *outfile)
209 {
210         int err_code = 0;
211         char cmd_str[PDFGEN_CMDSTR_MAXLEN + 1];
212         int i;
213
214         PGEN_TRACE_BEGIN;
215         PGEN_RETV_IF(NULL == infiles_z || NULL == infiles_z[0]
216                         || NULL == outfile, -1, "Argument error");
217
218         cmd_str[0] = '\0';
219         strncat(cmd_str, PDFUNITE_PATH, PDFGEN_CMDSTR_MAXLEN);
220
221         i = 0;
222         while (infiles_z[i] != NULL) {
223                 strncat(cmd_str, " ", PDFGEN_CMDSTR_MAXLEN);
224                 strncat(cmd_str, infiles_z[i], PDFGEN_CMDSTR_MAXLEN);
225                 ++i;
226         }
227
228         strncat(cmd_str, " ", PDFGEN_CMDSTR_MAXLEN);
229         strncat(cmd_str, outfile, PDFGEN_CMDSTR_MAXLEN);
230         cmd_str[PDFGEN_CMDSTR_MAXLEN] = '\0';
231
232         err_code = call_cmd(cmd_str);
233
234         PGEN_TRACE_END;
235         return 0;
236 }
237