├── doc ├── HACKING ├── Makefile.am └── api-ref.org ├── ChangeLog ├── .gitignore ├── src ├── geteuroxref ├── form.h ├── cred.h ├── tlssupport.h ├── dbutil.h ├── account.h ├── protocol-io.h ├── stripe.h ├── preorder.h ├── mbox-util.h ├── paypal.h ├── currency.h ├── encrypt.h ├── commands.h ├── journal.h ├── session.h ├── t-preorder.c ├── t-common.h ├── dbutil.c ├── strlist.h ├── payprocd.h ├── membuf.h ├── form.c ├── tlssupport.c ├── cred.c ├── libjnlib-config.h ├── jrnl-fields.h ├── t-encrypt.c ├── logging.h ├── tls-ca.pem ├── Makefile.am ├── strlist.c ├── membuf.c ├── paypal-ipn.c ├── t-util.c ├── ppipnhd.c ├── http.h ├── percent.c ├── t-http.c ├── util.h ├── cJSON.h ├── mbox-util.c ├── argparse.h ├── currency.c ├── ppsepaqr.c ├── protocol-io.c └── cJSON.readme ├── tests └── Makefile.am ├── m4 ├── Makefile.am ├── npth.m4 ├── gpg-error.m4 └── libgcrypt.m4 ├── NEWS ├── Makefile.am ├── README ├── AUTHORS └── autogen.sh /doc/HACKING: -------------------------------------------------------------------------------- 1 | # Payproc blurbs -*- org -*- 2 | 3 | * Design goals 4 | 5 | 6 | * Architecture 7 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | No ChangeLog files in Git! 2 | ========================== 3 | 4 | Do create any ChangeLog files in the Git repository. A top-level 5 | ChangeLog file wil be build from git logs at "make dist" time. As 6 | such, there are strict requirements on the form of the commit log 7 | messages. See doc/HACKING for details. 8 | 9 | 10 | Local Variables: 11 | buffer-read-only: t 12 | mode: text 13 | End: 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /autom4te.cache/ 2 | /aclocal.m4 3 | /config.h 4 | /config.h.in 5 | /config.log 6 | /config.status 7 | /configure 8 | /Makefile 9 | /Makefile.in 10 | /doc/Makefile 11 | /doc/Makefile.in 12 | /m4/Makefile 13 | /m4/Makefile.in 14 | /src/Makefile 15 | /src/Makefile.in 16 | /stamp-h1 17 | /tests/Makefile 18 | /tests/Makefile.in 19 | .deps/ 20 | *.o 21 | /src/payprocd 22 | /src/t-http 23 | /src/ca.pem 24 | /src/dh_param.pem 25 | /src/x1 26 | /src/x2 27 | /src/x3 28 | /src/y1 29 | /src/y2 30 | /src/y3 31 | /src/stripe.livekey 32 | /src/stripe.testkey 33 | /src/t-commands 34 | /src/out2 35 | /payproc-*.tar.bz2 36 | /src/payproc-jrnl 37 | /src/libcommon.a 38 | /src/libcommonpth.a 39 | /src/ppipnhd 40 | /src/payproc-stat 41 | /src/t-preorder 42 | /src/payproc-post 43 | /src/t-util 44 | -------------------------------------------------------------------------------- /src/geteuroxref: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | name=euroxref.dat 4 | dir=/var/lib/payproc 5 | file="$dir/$name" 6 | tfile="$dir/.#$name" 7 | 8 | if [ ! -d "$dir" ]; then 9 | echo "geteuroxref: directory '$dir' does not exist" >&2 10 | exit 1 11 | fi 12 | 13 | wget -qO- https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml \ 14 | | awk ' 15 | /$tfile 19 | 20 | if ! grep -q '^# eof' $tfile; then 21 | echo "geteuroxref: error retrieving data (check $tfile)" >&2 22 | exit 1 23 | fi 24 | if ! mv $tfile $file ; then 25 | echo "geteuroxref: error storing data" >&2 26 | exit 1 27 | fi 28 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | # tests/Makefile.am 2 | # Copyright (C) 2013 g10 Code GmbH 3 | # 4 | # This file is part of Payproc. 5 | # 6 | # Payproc is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Payproc is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, see . 18 | 19 | 20 | EXTRA_DIST = 21 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | # doc/Makefile.am 2 | # Copyright (C) 2014 g10 Code GmbH 3 | # 4 | # This file is part of Payproc. 5 | # 6 | # Payproc is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Payproc is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, see . 18 | 19 | 20 | EXTRA_DIST = HACKING api-ref.org 21 | -------------------------------------------------------------------------------- /m4/Makefile.am: -------------------------------------------------------------------------------- 1 | # m4/Makefile.am 2 | # Copyright (C) 2014 g10 Code GmbH 3 | # 4 | # This file is part of Payproc. 5 | # 6 | # Payproc is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Payproc is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, see . 18 | 19 | 20 | EXTRA_DIST = \ 21 | gpg-error.m4 npth.m4 libgcrypt.m4 22 | -------------------------------------------------------------------------------- /src/form.h: -------------------------------------------------------------------------------- 1 | /* form.h - Form handling functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef FORM_H 21 | #define FORM_H 22 | 23 | gpg_error_t encode_formdata (keyvalue_t form, char **r_encoded); 24 | 25 | #endif /*FORM_H*/ 26 | -------------------------------------------------------------------------------- /src/cred.h: -------------------------------------------------------------------------------- 1 | /* cred.h - Definitions pertaining to credentials. 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef CRED_H 21 | #define CRED_H 22 | 23 | int credentials_from_socket (int fd, pid_t *r_pid, uid_t *r_uid, gid_t *r_gid); 24 | 25 | 26 | #endif /*CRED_H*/ 27 | -------------------------------------------------------------------------------- /src/tlssupport.h: -------------------------------------------------------------------------------- 1 | /* tlssupport.h - TLS supporting functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef TLSSUPPORT_H 21 | #define TLSSUPPORT_H 22 | 23 | void init_tls_subsystem (void); 24 | void deinit_tls_subsystem (void); 25 | 26 | 27 | #endif /*TLSSUPPORT_H*/ 28 | -------------------------------------------------------------------------------- /src/dbutil.h: -------------------------------------------------------------------------------- 1 | /* dbutil.h - Definition for database utility functions 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef DBUTIL_H 21 | #define DBUTIL_H 22 | 23 | #define DB_DATETIME_SIZE 20 /* "1970-01-01 12:00:00" */ 24 | 25 | char *db_datetime_now (char *buffer); 26 | 27 | 28 | #endif /*DBUTIL_H*/ 29 | -------------------------------------------------------------------------------- /src/account.h: -------------------------------------------------------------------------------- 1 | /* account.h - Definition for account database related functions 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef ACCOUNT_H 21 | #define ACCOUNT_H 22 | 23 | gpg_error_t account_new_record (char **r_account_id); 24 | gpg_error_t account_update_record (keyvalue_t dict); 25 | 26 | 27 | #endif /*ACCOUNT_H*/ 28 | -------------------------------------------------------------------------------- /src/protocol-io.h: -------------------------------------------------------------------------------- 1 | /* protocol-io.h - Server protocol helper helper functions. 2 | * Copyright (C) 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef PROTOCOL_IO_H 21 | #define PROTOCOL_IO_H 22 | 23 | gpg_error_t protocol_read_request (estream_t stream, 24 | char **r_command, keyvalue_t *dataitems); 25 | gpg_error_t protocol_read_response (estream_t stream, keyvalue_t *dataitems); 26 | 27 | #endif /*PROTOCOL_IO_H*/ 28 | -------------------------------------------------------------------------------- /src/stripe.h: -------------------------------------------------------------------------------- 1 | /* stripe.h - Definitions to access the stripe.com service 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef STRIPE_H 21 | #define STRIPE_H 22 | 23 | gpg_error_t stripe_create_card_token (keyvalue_t *dict); 24 | gpg_error_t stripe_charge_card (keyvalue_t *dict); 25 | gpg_error_t stripe_find_create_plan (keyvalue_t *dict); 26 | gpg_error_t stripe_create_subscription (keyvalue_t *dict); 27 | 28 | 29 | #endif /*STRIPE_H*/ 30 | -------------------------------------------------------------------------------- /src/preorder.h: -------------------------------------------------------------------------------- 1 | /* preorder.h - Definition for preorder related functions 2 | * Copyright (C) 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef PREORDER_H 21 | #define PREORDER_H 22 | 23 | gpg_error_t preorder_store_record (keyvalue_t *dictp); 24 | gpg_error_t preorder_update_record (keyvalue_t *dict); 25 | gpg_error_t preorder_get_record (keyvalue_t *dictp); 26 | gpg_error_t preorder_list_records (keyvalue_t *dictp, unsigned int *r_count); 27 | 28 | 29 | #endif /*PREORDER_H*/ 30 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Payproc - The Payment Processor 2 | 3 | Noteworthy changes in version 0.4.0 (unreleased) 4 | ------------------------------------------------ 5 | 6 | * Support for an explicit test mode so that a second daemon can be 7 | run in test mode. 8 | 9 | 10 | Noteworthy changes in version 0.3.0 (2015-10-15) 11 | ------------------------------------------------ 12 | 13 | * Support for SEPA payments 14 | 15 | * New tool payproc-post. 16 | 17 | * Implement access restrictions via user ids. 18 | 19 | 20 | Noteworthy changes in version 0.2.1 (2014-09-09) 21 | ------------------------------------------------ 22 | 23 | * Support exchange rates. 24 | 25 | 26 | Noteworthy changes in version 0.2.0 (2014-05-23) 27 | ------------------------------------------------ 28 | 29 | * Add session mangement. 30 | 31 | 32 | Noteworthy changes in version 0.1.0 (2014-04-17) 33 | ------------------------------------------------ 34 | 35 | * Allow writing a journal 36 | 37 | * Return proper error messages. 38 | 39 | * Other cleanups. 40 | 41 | 42 | Noteworthy changes in version 0.0.0 (2014-04-03) 43 | ------------------------------------------------ 44 | 45 | * Initial release with some basic functions. 46 | -------------------------------------------------------------------------------- /src/mbox-util.h: -------------------------------------------------------------------------------- 1 | /* mbox-util.h - Defs for mail address helper functions 2 | * Copyright (C) 2015 Werner Koch 3 | * 4 | * This file is part of GnuPG. 5 | * 6 | * This file is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as 8 | * published by the Free Software Foundation; either version 2.1 of 9 | * the License, or (at your option) any later version. 10 | * 11 | * This file is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this program; if not, see . 18 | */ 19 | #ifndef GNUPG_COMMON_MBOX_UTIL_H 20 | #define GNUPG_COMMON_MBOX_UTIL_H 21 | 22 | int has_invalid_email_chars (const void *buffer, size_t length); 23 | int is_valid_mailbox (const char *name); 24 | int is_valid_mailbox_mem (const void *buffer, size_t length); 25 | /* char *mailbox_from_userid (const char *userid); */ 26 | /* int is_valid_user_id (const char *uid); */ 27 | 28 | 29 | #endif /*GNUPG_COMMON_MBOX_UTIL_H*/ 30 | -------------------------------------------------------------------------------- /src/paypal.h: -------------------------------------------------------------------------------- 1 | /* paypal.h - Definitions to access the paypal.com service 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef PAYPAL_H 21 | #define PAYPAL_H 22 | 23 | /*-- paypal.c --*/ 24 | gpg_error_t paypal_find_create_plan (keyvalue_t *dict); 25 | gpg_error_t paypal_create_subscription (keyvalue_t *dict); 26 | gpg_error_t paypal_checkout_prepare (keyvalue_t *dict); 27 | gpg_error_t paypal_checkout_execute (keyvalue_t *dict); 28 | 29 | 30 | /*-- paypal-ipn.c --*/ 31 | void paypal_proc_ipn (keyvalue_t *dict); 32 | 33 | 34 | #endif /*PAYPAL_H*/ 35 | -------------------------------------------------------------------------------- /src/currency.h: -------------------------------------------------------------------------------- 1 | /* currency.h - Definitions for currency management functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef CURRENCY_H 21 | #define CURRENCY_H 22 | 23 | void read_exchange_rates (void); 24 | 25 | int valid_currency_p (const char *string, int *r_decdigits); 26 | const char *get_currency_info (int seq, char const **r_desc, double *r_rate); 27 | char *convert_currency (char *buffer, size_t bufsize, 28 | const char *currency, const char *amount); 29 | 30 | int valid_recur_p (const char *string, int *r_recur); 31 | 32 | 33 | #endif /*CURRENCY_H*/ 34 | -------------------------------------------------------------------------------- /src/encrypt.h: -------------------------------------------------------------------------------- 1 | /* encrypt.h - Definition to encrypt data items etc. 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef ENCRYPT_H 21 | #define ENCRYPT_H 22 | 23 | /* Bit flags to specify which encrytpion key to use. */ 24 | #define ENCRYPT_TO_DATABASE 1 /* Encrypt to the database. */ 25 | #define ENCRYPT_TO_BACKOFFICE 2 /* Encrypt to the backoffice. */ 26 | 27 | gpg_error_t encrypt_setup_keys (void); 28 | void encrypt_release_keys (void); 29 | void encrypt_show_keys (void); 30 | gpg_error_t encrypt_string (char **result, const char *string, int encrypt_to); 31 | 32 | 33 | #endif /*ENCRYPT_H*/ 34 | -------------------------------------------------------------------------------- /src/commands.h: -------------------------------------------------------------------------------- 1 | /* commands.h - Definitions pertaining to a connection. 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef COMMANDS_H 21 | #define COMMANDS_H 22 | 23 | #include 24 | 25 | struct conn_s; 26 | typedef struct conn_s *conn_t; 27 | 28 | 29 | /*-- commands.c --*/ 30 | conn_t new_connection_obj (void); 31 | void init_connection_obj (conn_t conn, int fd); 32 | void release_connection_obj (conn_t conn); 33 | unsigned int id_from_connection_obj (conn_t conn); 34 | int fd_from_connection_obj (conn_t conn); 35 | 36 | void connection_handler (conn_t conn, uid_t uid); 37 | 38 | 39 | #endif /*COMMANDS_H*/ 40 | -------------------------------------------------------------------------------- /src/journal.h: -------------------------------------------------------------------------------- 1 | /* journal.h - Definition for journal related functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef JOURNAL_H 21 | #define JOURNAL_H 22 | 23 | #define PAYMENT_SERVICE_NONE 0 24 | #define PAYMENT_SERVICE_STRIPE 1 25 | #define PAYMENT_SERVICE_PAYPAL 2 26 | #define PAYMENT_SERVICE_SEPA 3 27 | #define PAYMENT_SERVICE_USER 255 28 | 29 | 30 | void jrnl_set_file (const char *fname); 31 | void jrnl_store_sys_record (const char *text); 32 | void jrnl_store_exchange_rate_record (const char *currency, double rate); 33 | void jrnl_store_charge_record (keyvalue_t *dictp, int service, int recur); 34 | 35 | 36 | #endif /*JOURNAL_H*/ 37 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Makefile.am 2 | # Copyright (C) 2014 g10 Code GmbH 3 | # 4 | # This file is part of Payproc. 5 | # 6 | # Payproc is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Payproc is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, see . 18 | 19 | ACLOCAL_AMFLAGS = -I m4 20 | 21 | GITLOG_TO_CHANGELOG=gitlog-to-changelog 22 | 23 | 24 | SUBDIRS = m4 src doc tests 25 | 26 | 27 | dist-hook: gen-ChangeLog 28 | echo "$(VERSION)" > $(distdir)/VERSION 29 | 30 | 31 | .PHONY: gen-ChangeLog 32 | gen-ChangeLog: 33 | set -e; \ 34 | if test -d $(top_srcdir)/.git; then \ 35 | (cd $(top_srcdir) && \ 36 | $(GITLOG_TO_CHANGELOG) --append-dot --tear-off \ 37 | --amend=build-aux/git-log-fix ) > $(distdir)/cl-t; \ 38 | cat $(top_srcdir)/build-aux/git-log-footer >>$(distdir)/cl-t; \ 39 | rm -f $(distdir)/ChangeLog; \ 40 | mv $(distdir)/cl-t $(distdir)/ChangeLog; \ 41 | fi 42 | -------------------------------------------------------------------------------- /src/session.h: -------------------------------------------------------------------------------- 1 | /* session.h - Definition for session management 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef SESSION_H 21 | #define SESSION_H 22 | 23 | struct session_s; 24 | typedef struct session_s *session_t; 25 | 26 | void session_housekeeping (void); 27 | 28 | gpg_error_t session_create (int ttl, keyvalue_t data, char **r_sessid); 29 | gpg_error_t session_destroy (const char *sessid); 30 | gpg_error_t session_put (const char *sessid, keyvalue_t dict); 31 | gpg_error_t session_get (const char *sessid, keyvalue_t *dictp); 32 | gpg_error_t session_create_alias (const char *sessid, char **r_aliasid); 33 | gpg_error_t session_destroy_alias (const char *aliasid); 34 | gpg_error_t session_get_sessid (const char *aliasid, char **r_sessid); 35 | 36 | 37 | #endif /*SESSION_H*/ 38 | -------------------------------------------------------------------------------- /src/t-preorder.c: -------------------------------------------------------------------------------- 1 | /* t-preorder.c - Regression test for parts of preorder.c 2 | * Copyright (C) 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | # include 22 | #endif 23 | #include 24 | #include 25 | 26 | #include "t-common.h" 27 | 28 | #include "preorder.c" /* The module under test. */ 29 | 30 | 31 | static void 32 | test_make_sepa_ref (void) 33 | { 34 | char buffer[9]; 35 | int i; 36 | 37 | for (i=0; i < 500; i++) 38 | { 39 | make_sepa_ref (buffer, sizeof buffer); 40 | if (verbose) 41 | printf ("%s\n", buffer); 42 | } 43 | } 44 | 45 | 46 | int 47 | main (int argc, char **argv) 48 | { 49 | if (argc > 1 && !strcmp (argv[1], "--verbose")) 50 | verbose = 1; 51 | 52 | test_make_sepa_ref (); 53 | 54 | return !!errorcount; 55 | } 56 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Payproc - A local payment processor 2 | ------------------------------------- 3 | 4 | To run the daemon: 5 | 6 | payprocd --stripe-key /etc/payproc/stripe.testkey \ 7 | --verbose --log-file /var/log/payproc/payprocd.log \ 8 | --journal /var/log/payproc/journal --live 9 | 10 | Payprocd creates the socket /var/run/payproc/daemon and expect the CA 11 | root certificate in /etc/payproc/tls-ca.pem . The given journal file 12 | name will be suffixed with the current date and ".log". The time 13 | stamp in the journal is given in UTC. 14 | 15 | You should also add a cron job for the payproc user to run 16 | /usr/lib/payproc/geteuroxref each day at about 16:00 CET. 17 | 18 | To add access restrictions to certain user ids in addition to the file 19 | permissions of the communication socket, the options --allow-uids/-U 20 | and --admin-uid may be used. They take an UID or a username as 21 | argument. Setting an --admin-uid implicitly uses the uid for 22 | --allow-uid. If any UID has been specified payprocd checks all 23 | connection attempts against this uids. To use the admin-required commands 24 | --admin-uid must have been given. Thus a common list of options is 25 | "-U www-data --admin-uid OPERATOR" to allow OPERATOR to make use of 26 | all features. 27 | 28 | To run payproc in a test environment replace the keys with the test 29 | keys and use the option --test instead of --live. In test mode 30 | payprocd creates a socket /var/run/payproc-test/daemon 31 | 32 | See doc/api-ref.org for a description of supported commands. 33 | -------------------------------------------------------------------------------- /src/t-common.h: -------------------------------------------------------------------------------- 1 | /* t-common.h - Common stuff for regression tests 2 | * Copyright (C) 2013 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef T_COMMON_H 21 | #define T_COMMON_H 22 | 23 | #include 24 | 25 | /* Commonly used global variables. */ 26 | static int verbose; 27 | static int errorcount; 28 | 29 | /* Macros to print the result of a test. */ 30 | #define pass() do { ; } while(0) 31 | #define fail(a) do { \ 32 | fprintf (stderr, "%s:%d: test %d failed\n", \ 33 | __FILE__,__LINE__, (a)); \ 34 | errorcount++;; \ 35 | } while(0) 36 | 37 | 38 | /* Other common macros. */ 39 | #ifndef DIM 40 | # define DIM(v) (sizeof(v)/sizeof((v)[0])) 41 | #endif 42 | #ifndef DIMof 43 | # define DIMof(type,member) DIM(((type *)0)->member) 44 | #endif 45 | 46 | #endif /* T_COMMON */ 47 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Program: PayProc 2 | Homepage: 3 | Maintainer: Werner Koch 4 | Bug reports: 5 | Security related bug reports: 6 | License: GPLv3+ 7 | 8 | 9 | Copyright 10 | ========= 11 | 12 | PayProc is distributed under the GNU General Public License, version 3 13 | or later. 14 | 15 | Copyright (C) 2014-2015 g10 Code GmbH 16 | 17 | Parts of the code are taken from other FSF software (mainly GnuPG) and 18 | are either under the GPLv3 or LGPLv2+/GPLv2+. 19 | 20 | Copyright (C) 1998--2012 Free Software Foundation, Inc. 21 | 22 | For the text of the GPLv3 see the file COPYING. 23 | 24 | The cJSON code is 25 | 26 | Copyright (c) 2009 Dave Gamble 27 | 28 | Permission is hereby granted, free of charge, to any person obtaining a copy 29 | of this software and associated documentation files (the "Software"), to deal 30 | in the Software without restriction, including without limitation the rights 31 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 32 | copies of the Software, and to permit persons to whom the Software is 33 | furnished to do so, subject to the following conditions: 34 | 35 | The above copyright notice and this permission notice shall be included in 36 | all copies or substantial portions of the Software. 37 | 38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 39 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 40 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 41 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 42 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 43 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 44 | THE SOFTWARE. 45 | -------------------------------------------------------------------------------- /src/dbutil.c: -------------------------------------------------------------------------------- 1 | /* dbutil.c - Databse utility functions 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "util.h" 29 | #include "logging.h" 30 | #include "payprocd.h" 31 | #include "membuf.h" 32 | #include "dbutil.h" 33 | 34 | 35 | /* Given a buffer of size DB_DATETIME_SIZE put the current time into it. */ 36 | char * 37 | db_datetime_now (char *buffer) 38 | { 39 | #if DB_DATETIME_SIZE != TIMESTAMP_SIZE + 4 40 | # error mismatching timestamp sizes 41 | #endif 42 | get_current_time (buffer); 43 | /* "19700101T120000" to 44 | "1970-01-01 12:00:00" */ 45 | buffer[19] = 0; 46 | buffer[18] = buffer[14]; 47 | buffer[17] = buffer[13]; 48 | buffer[16] = ':'; 49 | buffer[15] = buffer[12]; 50 | buffer[14] = buffer[11]; 51 | buffer[13] = ':'; 52 | buffer[12] = buffer[10]; 53 | buffer[11] = buffer[9]; 54 | buffer[10] = ' '; 55 | buffer[9] = buffer[7]; 56 | buffer[8] = buffer[6]; 57 | buffer[7] = '-'; 58 | buffer[6] = buffer[5]; 59 | buffer[5] = buffer[4]; 60 | buffer[4] = '-'; 61 | 62 | return buffer; 63 | } 64 | -------------------------------------------------------------------------------- /src/strlist.h: -------------------------------------------------------------------------------- 1 | /* strlist.h 2 | * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. 3 | * 4 | * This file is part of JNLIB, which is a subsystem of GnuPG. 5 | * 6 | * JNLIB is free software; you can redistribute it and/or modify it 7 | * under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * JNLIB is distributed in the hope that it will be useful, but 22 | * WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | * General Public License for more details. 25 | * 26 | * You should have received a copies of the GNU General Public License 27 | * and the GNU Lesser General Public License along with this program; 28 | * if not, see . 29 | */ 30 | 31 | #ifndef LIBJNLIB_STRLIST_H 32 | #define LIBJNLIB_STRLIST_H 33 | 34 | struct string_list 35 | { 36 | struct string_list *next; 37 | unsigned int flags; 38 | char d[1]; 39 | }; 40 | typedef struct string_list *strlist_t; 41 | 42 | void free_strlist (strlist_t sl); 43 | strlist_t add_to_strlist (strlist_t *list, const char *string); 44 | strlist_t add_to_strlist_try (strlist_t *list, const char *string); 45 | 46 | strlist_t add_to_strlist2( strlist_t *list, const char *string, int is_utf8); 47 | 48 | strlist_t append_to_strlist (strlist_t *list, const char *string); 49 | strlist_t append_to_strlist2 (strlist_t *list, const char *string, 50 | int is_utf8); 51 | 52 | strlist_t strlist_copy (strlist_t list); 53 | 54 | strlist_t strlist_prev (strlist_t head, strlist_t node); 55 | strlist_t strlist_last (strlist_t node); 56 | char * strlist_pop (strlist_t *list); 57 | 58 | #define FREE_STRLIST(a) do { free_strlist((a)); (a) = NULL ; } while(0) 59 | 60 | 61 | #endif /*LIBJNLIB_STRLIST_H*/ 62 | -------------------------------------------------------------------------------- /src/payprocd.h: -------------------------------------------------------------------------------- 1 | /* payprocd.h - Declarations for payprocd 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef PAYPROCD_H 21 | #define PAYPROCD_H 22 | 23 | #include 24 | 25 | 26 | /* The global options. */ 27 | struct 28 | { 29 | int verbose; /* Verbose logging. */ 30 | int nodetach; /* Do not detach from the console. */ 31 | int debug_client; /* Debug communication with the client. */ 32 | int debug_stripe; /* Debug Stripe REST interaction. */ 33 | int debug_paypal; /* Debug PayPal REST interaction. */ 34 | 35 | int livemode; /* Expect to be in live mode. Default is test mode. */ 36 | char *stripe_secret_key; /* The secret key for stripe.com */ 37 | char *paypal_secret_key; /* The secret key for PayPal */ 38 | 39 | /* The fingerprint of the OpenPGP key used to encrypt items in the 40 | * database. A secret and a public key is required. */ 41 | char *database_key_fpr; 42 | /* The fingerprint of the OpenPGP key used to encrypt data for use 43 | * by the backoffice. Only the public key is required. */ 44 | char *backoffice_key_fpr; 45 | 46 | /* The count and the list of clients allowed to use the service. */ 47 | int n_allowed_uids; 48 | uid_t allowed_uids[20]; 49 | 50 | /* The count and the list of clients allowed to use admin services. */ 51 | int n_allowed_admin_uids; 52 | uid_t allowed_admin_uids[20]; 53 | 54 | } opt; 55 | 56 | 57 | const char *server_socket_name (void); 58 | 59 | void shutdown_server (void); 60 | 61 | 62 | #endif /*PAYPROCD_H*/ 63 | -------------------------------------------------------------------------------- /src/membuf.h: -------------------------------------------------------------------------------- 1 | /* membuf.h - A simple implementation of a dynamic buffer 2 | * Copyright (C) 2001, 2003 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GnuPG. 5 | * 6 | * This file is free software; you can redistribute it and/or modify 7 | * it under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * This file is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with this program; if not, see . 28 | */ 29 | 30 | #ifndef MEMBUF_H 31 | #define MEMBUF_H 32 | 33 | #include "util.h" 34 | 35 | /* The definition of the structure is private, we only need it here, 36 | so it can be allocated on the stack. */ 37 | struct private_membuf_s 38 | { 39 | size_t len; 40 | size_t size; 41 | char *buf; 42 | int out_of_core; 43 | }; 44 | 45 | typedef struct private_membuf_s membuf_t; 46 | 47 | /* Return the current length of the membuf. */ 48 | #define get_membuf_len(a) ((a)->len) 49 | #define is_membuf_ready(a) ((a)->buf || (a)->out_of_core) 50 | #define MEMBUF_ZERO { 0, 0, NULL, 0} 51 | 52 | void init_membuf (membuf_t *mb, int initiallen); 53 | void clear_membuf (membuf_t *mb, size_t amount); 54 | void put_membuf (membuf_t *mb, const void *buf, size_t len); 55 | void put_membuf_chr (membuf_t *mb, int c); 56 | void put_membuf_str (membuf_t *mb, const char *string); 57 | void put_membuf_printf (membuf_t *mb, const char *format, 58 | ...) JNLIB_GCC_A_PRINTF(2,3); 59 | void *get_membuf (membuf_t *mb, size_t *len); 60 | void *get_membuf_shrink (membuf_t *mb, size_t *len); 61 | const void *peek_membuf (membuf_t *mb, size_t *len); 62 | 63 | #endif /*MEMBUF_H*/ 64 | -------------------------------------------------------------------------------- /src/form.c: -------------------------------------------------------------------------------- 1 | /* form.c - Form handling functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "util.h" 27 | #include "membuf.h" 28 | #include "http.h" 29 | #include "form.h" 30 | 31 | 32 | /* Encode the data in FORM for use with POST. */ 33 | gpg_error_t 34 | encode_formdata (keyvalue_t form, char **r_encoded) 35 | { 36 | gpg_error_t err; 37 | membuf_t mb; 38 | keyvalue_t kv; 39 | char *escaped; 40 | 41 | *r_encoded = NULL; 42 | 43 | init_membuf (&mb, 0); 44 | for (kv = form; kv; kv = kv->next) 45 | { 46 | if (kv != form) 47 | put_membuf_str (&mb, "&"); 48 | if (!kv->value) 49 | continue; /* Deleted item. */ 50 | escaped = http_escape_string (kv->name, NULL/*form-encoding*/); 51 | if (!escaped) 52 | { 53 | err = gpg_error_from_syserror (); 54 | xfree (get_membuf (&mb, NULL)); 55 | return err; 56 | } 57 | put_membuf_str (&mb, escaped); 58 | xfree (escaped); 59 | put_membuf_str (&mb, "="); 60 | escaped = http_escape_string (kv->value, NULL/*form-encoding*/); 61 | if (!escaped) 62 | { 63 | err = gpg_error_from_syserror (); 64 | xfree (get_membuf (&mb, NULL)); 65 | return err; 66 | } 67 | put_membuf_str (&mb, escaped); 68 | xfree (escaped); 69 | } 70 | 71 | put_membuf (&mb, "", 1); 72 | *r_encoded = get_membuf (&mb, NULL); 73 | if (!*r_encoded) 74 | return gpg_error_from_syserror (); 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /src/tlssupport.c: -------------------------------------------------------------------------------- 1 | /* tlssupport.c - TLS supporting functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | #include "util.h" 32 | #include "logging.h" 33 | #include "http.h" 34 | #include "tlssupport.h" 35 | 36 | /* static void */ 37 | /* my_gnutls_log (int level, const char *text) */ 38 | /* { */ 39 | /* size_t n; */ 40 | 41 | /* n = strlen (text); */ 42 | /* if (n && text[n-1] == '\n') */ 43 | /* n--; */ 44 | /* log_debug ("gnutls:L%d: %.*s\n", level, (int)n, text); */ 45 | /* } */ 46 | 47 | 48 | /* This is called by the HTTP module to authenticate a connection. */ 49 | static gpg_error_t 50 | verify_callback (http_t hd, http_session_t session, int reserved) 51 | { 52 | (void)hd; 53 | (void)reserved; 54 | return http_verify_server_credentials (session); 55 | } 56 | 57 | 58 | /* Initialize the TLS subsystem. */ 59 | void 60 | init_tls_subsystem (void) 61 | { 62 | int rc; 63 | 64 | rc = gnutls_global_init (); 65 | if (rc) 66 | log_fatal ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); 67 | 68 | /* gnutls_global_set_log_function (my_gnutls_log); */ 69 | /* gnutls_global_set_log_level (10); */ 70 | 71 | http_register_tls_callback (verify_callback); 72 | http_register_tls_ca ("/etc/payproc/tls-ca.pem"); 73 | } 74 | 75 | /* Deinitialize the TLS subsystem. Thisis intended to be run from an 76 | atexit handler. */ 77 | void 78 | deinit_tls_subsystem (void) 79 | { 80 | gnutls_global_deinit (); 81 | } 82 | -------------------------------------------------------------------------------- /src/cred.c: -------------------------------------------------------------------------------- 1 | /* cred.c - Credentials support 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #ifdef HAVE_UCRED_H 30 | # include 31 | #endif 32 | 33 | 34 | #include "util.h" 35 | #include "cred.h" 36 | 37 | 38 | /* Retrieve the credentials from the peer using the connect file 39 | descriptor FD. Returns 0 on success or -1 on error. */ 40 | int 41 | credentials_from_socket (int fd, pid_t *r_pid, uid_t *r_uid, gid_t *r_gid) 42 | { 43 | int rc = -1; 44 | 45 | #ifdef HAVE_SO_PEERCRED 46 | { 47 | struct ucred cr; 48 | socklen_t cl = sizeof cr; 49 | 50 | if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl)) 51 | { 52 | *r_pid = cr.pid; 53 | *r_uid = cr.uid; 54 | *r_gid = cr.gid; 55 | rc = 0; 56 | } 57 | } 58 | #elif defined (HAVE_GETPEERUCRED) 59 | { 60 | ucred_t *ucred = NULL; 61 | 62 | if (getpeerucred (fd, &ucred) != -1) 63 | { 64 | *r_pid = ucred_getpid (ucred); 65 | *r_uid = ucred_geteuid (ucred); 66 | *r_gid = ucred_getegid (ucred); 67 | rc = 0; 68 | ucred_free (ucred); 69 | } 70 | } 71 | #elif defined (HAVE_LOCAL_PEEREID) 72 | { 73 | struct unpcbid unp; 74 | socklen_t unpl = sizeof unp; 75 | 76 | if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1) 77 | { 78 | *r_pid = unp.unp_pid; 79 | *r_uid = unp.unp_euid; 80 | *r_gid = unp.unp_egid; 81 | rc = 0; 82 | } 83 | } 84 | #elif defined(HAVE_GETPEEREID) 85 | { 86 | if (getpeereid (fd, r_uid, r_gid) != -1) 87 | { 88 | r_pid = (pid_t)(-1); 89 | rc = 0; 90 | } 91 | } 92 | #endif 93 | 94 | return rc; 95 | } 96 | -------------------------------------------------------------------------------- /src/libjnlib-config.h: -------------------------------------------------------------------------------- 1 | /* libjnlib-config.h - local configuration of the jnlib functions 2 | * Copyright (C) 2000, 2001, 2006 Free Software Foundation, Inc. 3 | * 4 | * This file is part of JNLIB, which is a subsystem of GnuPG. 5 | * 6 | * JNLIB is free software; you can redistribute it and/or modify it 7 | * under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * JNLIB is distributed in the hope that it will be useful, but 22 | * WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | * General Public License for more details. 25 | * 26 | * You should have received a copies of the GNU General Public License 27 | * and the GNU Lesser General Public License along with this program; 28 | * if not, see . 29 | */ 30 | 31 | /**************** 32 | * This header is to be included only by the files in this directory 33 | * it should not be used by other modules. 34 | */ 35 | 36 | #ifndef LIBJNLIB_CONFIG_H 37 | #define LIBJNLIB_CONFIG_H 38 | 39 | #include "logging.h" 40 | 41 | /* Gettext stubs. */ 42 | #define _(a) (a) 43 | #define N_(a) (a) 44 | 45 | /* Malloc functions to be used by jnlib. */ 46 | #define jnlib_malloc(a) xtrymalloc ((a)) 47 | #define jnlib_calloc(a,b) xtrycalloc ((a), (b)) 48 | #define jnlib_realloc(a,b) xtryrealloc((a), (b)) 49 | #define jnlib_strdup(a) xtrystrdup ((a)) 50 | #define jnlib_xmalloc(a) xmalloc ((a)) 51 | #define jnlib_xcalloc(a,b) xcalloc ((a), (b)) 52 | #define jnlib_xrealloc(a,n) xrealloc ((a), (n)) 53 | #define jnlib_xstrdup(a) xstrdup ((a)) 54 | #define jnlib_free(a) xfree ((a)) 55 | 56 | /* Logging functions to be used by jnlib. */ 57 | #define jnlib_log_debug log_debug 58 | #define jnlib_log_info log_info 59 | #define jnlib_log_error log_error 60 | #define jnlib_log_fatal log_fatal 61 | #define jnlib_log_bug log_bug 62 | 63 | /* Wrapper to set ERRNO. */ 64 | #define jnlib_set_errno(e) do { errno = (e); } while (0) 65 | 66 | /* Dummy replacement for getenv. */ 67 | #ifndef HAVE_GETENV 68 | #define getenv(a) (NULL) 69 | #endif 70 | 71 | #endif /*LIBJNUTIL_CONFIG_H*/ 72 | -------------------------------------------------------------------------------- /src/jrnl-fields.h: -------------------------------------------------------------------------------- 1 | /* jrnl-fields.h - Definitions of journal fields. 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef JRNL_FIELDS_H 21 | #define JRNL_FIELDS_H 22 | 23 | enum jrnl_fields 24 | { 25 | JRNL_FIELD_DATE = 0, /* UTC the record was created. */ 26 | JRNL_FIELD_TYPE = 1, /* Record type. */ 27 | JRNL_FIELD_LIVE = 2, /* 1 if this is not a test account. */ 28 | JRNL_FIELD_CURRENCY = 3, /* 3 letter ISO code for the currency. */ 29 | JRNL_FIELD_AMOUNT = 4, /* Amount with decimal point. */ 30 | JRNL_FIELD_DESC = 5, /* Description for this transaction. */ 31 | JRNL_FIELD_MAIL = 6, /* Email address. */ 32 | JRNL_FIELD_META = 7, /* Structured field with additional data. */ 33 | JRNL_FIELD_LAST4 = 8, /* The last 4 digits of the card. */ 34 | JRNL_FIELD_SERVICE = 9, /* Payment service (0=n/a, 1=stripe.com). */ 35 | JRNL_FIELD_ACCOUNT = 10, /* Account number. */ 36 | JRNL_FIELD_CHARGEID = 11, /* Charge id. */ 37 | JRNL_FIELD_RTXID = 12, /* Transaction id. */ 38 | JRNL_FIELD_TXID = 13, /* Reference txid. */ 39 | JRNL_FIELD_EURO = 14, /* Amount converted to Euro. */ 40 | JRNL_FIELD_RECUR = 15 /* Recurrence count. */ 41 | }; 42 | #define NO_OF_JRNL_FIELDS 16 43 | 44 | #define JRNL_FIELD_NAME_DATE "date" 45 | #define JRNL_FIELD_NAME_TYPE "type" 46 | #define JRNL_FIELD_NAME_LIVE "live" 47 | #define JRNL_FIELD_NAME_CURRENCY "currency" 48 | #define JRNL_FIELD_NAME_AMOUNT "amount" 49 | #define JRNL_FIELD_NAME_DESC "desc" 50 | #define JRNL_FIELD_NAME_MAIL "mail" 51 | #define JRNL_FIELD_NAME_META "meta" 52 | #define JRNL_FIELD_NAME_LAST4 "last4" 53 | #define JRNL_FIELD_NAME_SERVICE "service" 54 | #define JRNL_FIELD_NAME_ACCOUNT "account" 55 | #define JRNL_FIELD_NAME_CHARGEID "chargeid" 56 | #define JRNL_FIELD_NAME_TXID "txid" 57 | #define JRNL_FIELD_NAME_RTXID "rtxid" 58 | #define JRNL_FIELD_NAME_EURO "euro" 59 | #define JRNL_FIELD_NAME_RECUR "recur" 60 | 61 | 62 | #endif /*JRNL_FIELDS_H*/ 63 | -------------------------------------------------------------------------------- /src/t-encrypt.c: -------------------------------------------------------------------------------- 1 | /* t-encrypt.c - Regression tests for encrypt.c 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | # include 22 | #endif 23 | #include 24 | #include 25 | #include 26 | 27 | #include "t-common.h" 28 | 29 | #include "encrypt.c" /* The module under test. */ 30 | 31 | 32 | static void 33 | test_encrypt_string (void) 34 | { 35 | gpg_error_t err; 36 | const char fortune[] = "Knowledge, sir, should be free to all!"; 37 | /* -- Harry Mudd, "I, Mudd", stardate 4513.3*/ 38 | char *ciphertext = NULL; 39 | char *plaintext = NULL; 40 | 41 | err = encrypt_string (&ciphertext, fortune, 42 | (ENCRYPT_TO_DATABASE | ENCRYPT_TO_BACKOFFICE)); 43 | if (err) 44 | { 45 | log_info ("test encryption failed: %s <%s>\n", 46 | gpg_strerror (err), gpg_strsource (err)); 47 | fail (0); 48 | goto leave; 49 | } 50 | if (verbose) 51 | log_info ("encrypted: '%s'\n", ciphertext); 52 | 53 | err = decrypt_string (&plaintext, ciphertext); 54 | if (err) 55 | { 56 | log_info ("test decryption failed: %s <%s>\n", 57 | gpg_strerror (err), gpg_strsource (err)); 58 | fail (0); 59 | goto leave; 60 | } 61 | if (verbose) 62 | log_info ("decrypted: '%s'\n", plaintext); 63 | 64 | if (strcmp (fortune, plaintext)) 65 | { 66 | log_info ("encryption/decryption mismatch\n"); 67 | fail (0); 68 | } 69 | 70 | leave: 71 | xfree (ciphertext); 72 | xfree (plaintext); 73 | } 74 | 75 | 76 | int 77 | main (int argc, char **argv) 78 | { 79 | if (argc > 1 && !strcmp (argv[1], "--verbose")) 80 | verbose = 1; 81 | 82 | if (!gpgme_check_version (NEED_GPGME_VERSION)) 83 | log_fatal ("%s is too old (need %s, have %s)\n", "gpgme", 84 | NEED_GPGME_VERSION, gpgme_check_version (NULL)); 85 | 86 | opt.database_key_fpr = "5B83120DB1E3A65AE5A8DCF6AA43F1DCC7FED1B7"; 87 | opt.backoffice_key_fpr = "B21DEAB4F875FB3DA42F1D1D139563682A020D0A"; 88 | 89 | encrypt_setup_keys (); 90 | if (verbose) 91 | encrypt_show_keys (); 92 | 93 | test_encrypt_string (); 94 | 95 | encrypt_release_keys (); 96 | 97 | return !!errorcount; 98 | } 99 | -------------------------------------------------------------------------------- /src/logging.h: -------------------------------------------------------------------------------- 1 | /* logging.h 2 | * Copyright (C) 1999, 2000, 2001, 2004, 2006, 3 | * 2010 Free Software Foundation, Inc. 4 | * 5 | * This file is part of JNLIB, which is a subsystem of GnuPG. 6 | * 7 | * JNLIB is free software; you can redistribute it and/or modify it 8 | * under the terms of either 9 | * 10 | * - the GNU Lesser General Public License as published by the Free 11 | * Software Foundation; either version 3 of the License, or (at 12 | * your option) any later version. 13 | * 14 | * or 15 | * 16 | * - the GNU General Public License as published by the Free 17 | * Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * or both in parallel, as here. 21 | * 22 | * JNLIB is distributed in the hope that it will be useful, but 23 | * WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 | * General Public License for more details. 26 | * 27 | * You should have received a copies of the GNU General Public License 28 | * and the GNU Lesser General Public License along with this program; 29 | * if not, see . 30 | */ 31 | 32 | #ifndef LIBJNLIB_LOGGING_H 33 | #define LIBJNLIB_LOGGING_H 34 | 35 | #include 36 | /* #include "mischelp.h" */ 37 | /* #include "w32help.h" */ 38 | #include "util.h" 39 | 40 | /* Flag values for log_set_prefix. */ 41 | #define JNLIB_LOG_WITH_PREFIX 1 42 | #define JNLIB_LOG_WITH_TIME 2 43 | #define JNLIB_LOG_WITH_PID 4 44 | #define JNLIB_LOG_RUN_DETACHED 256 45 | #define JNLIB_LOG_NO_REGISTRY 512 46 | 47 | int log_get_errorcount (int clear); 48 | void log_inc_errorcount (void); 49 | void log_set_file( const char *name ); 50 | void log_set_fd (int fd); 51 | void log_set_pid_suffix_cb (int (*cb)(unsigned long *r_value)); 52 | void log_set_prefix (const char *text, unsigned int flags); 53 | const char *log_get_prefix (unsigned int *flags); 54 | int log_test_fd (int fd); 55 | int log_get_fd(void); 56 | estream_t log_get_stream (void); 57 | 58 | #ifdef JNLIB_GCC_M_FUNCTION 59 | void bug_at( const char *file, int line, const char *func ) JNLIB_GCC_A_NR; 60 | # define BUG() bug_at( __FILE__ , __LINE__, __FUNCTION__ ) 61 | #else 62 | void bug_at( const char *file, int line ); 63 | # define BUG() bug_at( __FILE__ , __LINE__ ) 64 | #endif 65 | 66 | /* To avoid mandatory inclusion of stdarg and other stuff, do it only 67 | if explicitly requested to do so. */ 68 | #ifdef JNLIB_NEED_LOG_LOGV 69 | #include 70 | enum jnlib_log_levels { 71 | JNLIB_LOG_BEGIN, 72 | JNLIB_LOG_CONT, 73 | JNLIB_LOG_INFO, 74 | JNLIB_LOG_WARN, 75 | JNLIB_LOG_ERROR, 76 | JNLIB_LOG_FATAL, 77 | JNLIB_LOG_BUG, 78 | JNLIB_LOG_DEBUG 79 | }; 80 | void log_log (int level, const char *fmt, ...) JNLIB_GCC_A_PRINTF(2,3); 81 | void log_logv (int level, const char *fmt, va_list arg_ptr); 82 | void log_string (int level, const char *string); 83 | #endif /*JNLIB_NEED_LOG_LOGV*/ 84 | 85 | 86 | void log_bug( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); 87 | void log_fatal( const char *fmt, ... ) JNLIB_GCC_A_NR_PRINTF(1,2); 88 | void log_error( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); 89 | void log_info( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); 90 | void log_debug( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); 91 | void log_printf( const char *fmt, ... ) JNLIB_GCC_A_PRINTF(1,2); 92 | void log_flush (void); 93 | 94 | /* Print a hexdump of BUFFER. With TEXT passes as NULL print just the 95 | raw dump, with TEXT being an empty string, print a trailing 96 | linefeed, otherwise print an entire debug line with TEXT followed 97 | by the hexdump and a final LF. */ 98 | void log_printhex (const char *text, const void *buffer, size_t length); 99 | void log_printval (const char *prefix, const char *value); 100 | 101 | void log_printkeyval (const char *prefix, const char *key, const char *value); 102 | 103 | 104 | void log_clock (const char *string); 105 | 106 | 107 | #endif /*LIBJNLIB_LOGGING_H*/ 108 | -------------------------------------------------------------------------------- /m4/npth.m4: -------------------------------------------------------------------------------- 1 | # npth.m4 - autoconf macro to detect NPTH. 2 | # Copyright (C) 2002, 2003, 2004, 2011 g10 Code GmbH 3 | # 4 | # This file is free software; as a special exception the author gives 5 | # unlimited permission to copy and/or distribute it, with or without 6 | # modifications, as long as this notice is preserved. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | 12 | AC_DEFUN([_AM_PATH_NPTH_CONFIG], 13 | [ AC_ARG_WITH(npth-prefix, 14 | AC_HELP_STRING([--with-npth-prefix=PFX], 15 | [prefix where NPTH is installed (optional)]), 16 | npth_config_prefix="$withval", npth_config_prefix="") 17 | if test "x$npth_config_prefix" != x ; then 18 | NPTH_CONFIG="$npth_config_prefix/bin/npth-config" 19 | fi 20 | AC_PATH_PROG(NPTH_CONFIG, npth-config, no) 21 | 22 | if test "$NPTH_CONFIG" != "no" ; then 23 | npth_version=`$NPTH_CONFIG --version` 24 | fi 25 | npth_version_major=`echo $npth_version | \ 26 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` 27 | npth_version_minor=`echo $npth_version | \ 28 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` 29 | ]) 30 | 31 | dnl AM_PATH_NPTH([MINIMUM-VERSION, 32 | dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) 33 | dnl Test for libnpth and define NPTH_CFLAGS and NPTH_LIBS. 34 | dnl 35 | AC_DEFUN([AM_PATH_NPTH], 36 | [ AC_REQUIRE([_AM_PATH_NPTH_CONFIG])dnl 37 | tmp=ifelse([$1], ,1:0.91,$1) 38 | if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then 39 | req_npth_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` 40 | min_npth_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` 41 | else 42 | req_npth_api=1 43 | min_npth_version="$tmp" 44 | fi 45 | 46 | AC_MSG_CHECKING(for NPTH - version >= $min_npth_version) 47 | ok=no 48 | if test "$NPTH_CONFIG" != "no" ; then 49 | req_major=`echo $min_npth_version | \ 50 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` 51 | req_minor=`echo $min_npth_version | \ 52 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` 53 | if test "$npth_version_major" -gt "$req_major"; then 54 | ok=yes 55 | else 56 | if test "$npth_version_major" -eq "$req_major"; then 57 | if test "$npth_version_minor" -gt "$req_minor"; then 58 | ok=yes 59 | else 60 | if test "$npth_version_minor" -eq "$req_minor"; then 61 | ok=yes 62 | fi 63 | fi 64 | fi 65 | fi 66 | fi 67 | if test $ok = yes; then 68 | AC_MSG_RESULT([yes ($npth_version)]) 69 | else 70 | AC_MSG_RESULT(no) 71 | fi 72 | if test $ok = yes; then 73 | # If we have a recent NPTH, we should also check that the 74 | # API is compatible. 75 | if test "$req_npth_api" -gt 0 ; then 76 | tmp=`$NPTH_CONFIG --api-version 2>/dev/null || echo 0` 77 | if test "$tmp" -gt 0 ; then 78 | AC_MSG_CHECKING([NPTH API version]) 79 | if test "$req_npth_api" -eq "$tmp" ; then 80 | AC_MSG_RESULT([okay]) 81 | else 82 | ok=no 83 | AC_MSG_RESULT([does not match. want=$req_npth_api got=$tmp]) 84 | fi 85 | fi 86 | fi 87 | fi 88 | if test $ok = yes; then 89 | NPTH_CFLAGS=`$NPTH_CONFIG --cflags` 90 | NPTH_LIBS=`$NPTH_CONFIG --libs` 91 | ifelse([$2], , :, [$2]) 92 | npth_config_host=`$NPTH_CONFIG --host 2>/dev/null || echo none` 93 | if test x"$npth_config_host" != xnone ; then 94 | if test x"$npth_config_host" != x"$host" ; then 95 | AC_MSG_WARN([[ 96 | *** 97 | *** The config script $NPTH_CONFIG was 98 | *** built for $npth_config_host and thus may not match the 99 | *** used host $host. 100 | *** You may want to use the configure option --with-npth-prefix 101 | *** to specify a matching config script. 102 | ***]]) 103 | fi 104 | fi 105 | else 106 | NPTH_CFLAGS="" 107 | NPTH_LIBS="" 108 | ifelse([$3], , :, [$3]) 109 | fi 110 | AC_SUBST(NPTH_CFLAGS) 111 | AC_SUBST(NPTH_LIBS) 112 | ]) 113 | -------------------------------------------------------------------------------- /src/tls-ca.pem: -------------------------------------------------------------------------------- 1 | Issuer ...: /CN=Baltimore CyberTrust Root/OU=CyberTrust/O=Baltimore/C=IE 2 | Serial ...: 020000B9 3 | Subject ..: /CN=Baltimore CyberTrust Root/OU=CyberTrust/O=Baltimore/C=IE 4 | 5 | -----BEGIN CERTIFICATE----- 6 | MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ 7 | RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD 8 | VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX 9 | DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y 10 | ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy 11 | VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr 12 | mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr 13 | IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK 14 | mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu 15 | XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy 16 | dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye 17 | jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 18 | BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 19 | DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 20 | 9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx 21 | jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 22 | Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz 23 | ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS 24 | R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp 25 | -----END CERTIFICATE----- 26 | 27 | Issuer ...: /CN=DigiCert High Assurance EV Root CA/OU=www.digicert.com/O=DigiCert Inc/C=US 28 | Serial ...: 02AC5C266A0B409B8F0B79F2AE462577 29 | Subject ..: /CN=DigiCert High Assurance EV Root CA/OU=www.digicert.com/O=DigiCert Inc/C=US 30 | 31 | -----BEGIN CERTIFICATE----- 32 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs 33 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 34 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j 35 | ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL 36 | MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 37 | LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug 38 | RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm 39 | +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW 40 | PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM 41 | xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB 42 | Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 43 | hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg 44 | EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF 45 | MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA 46 | FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec 47 | nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z 48 | eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF 49 | hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 50 | Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 51 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep 52 | +OkuE6N36B9K 53 | -----END CERTIFICATE----- 54 | 55 | Issuer ...: /CN=GTE CyberTrust Global Root/OU=GTE CyberTrust Solutions, Inc./O=GTE Corporation/C=US 56 | Serial ...: 01A5 57 | Subject ..: /CN=GTE CyberTrust Global Root/OU=GTE CyberTrust Solutions, Inc./O=GTE Corporation/C=US 58 | 59 | -----BEGIN CERTIFICATE----- 60 | MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD 61 | VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv 62 | bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv 63 | b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV 64 | UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU 65 | cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds 66 | b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH 67 | iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS 68 | r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 69 | 04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r 70 | GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 71 | 3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P 72 | lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ 73 | -----END CERTIFICATE----- 74 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | # src/Makefile.am 2 | # Copyright (C) 2014 g10 Code GmbH 3 | # 4 | # This file is part of Payproc. 5 | # 6 | # Payproc is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # Payproc is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, see . 18 | 19 | EXTRA_DIST = cJSON.readme tls-ca.pem 20 | 21 | bin_PROGRAMS = payprocd payproc-jrnl payproc-stat payproc-post ppipnhd \ 22 | ppsepaqr 23 | noinst_PROGRAMS = $(module_tests) t-http 24 | noinst_LIBRARIES = libcommon.a libcommonpth.a 25 | dist_pkglibexec_SCRIPTS = geteuroxref 26 | 27 | TESTS = $(module_tests) 28 | 29 | common_sources = \ 30 | util.c util.h \ 31 | libjnlib-config.h \ 32 | logging.c logging.h \ 33 | membuf.c membuf.h \ 34 | strlist.c strlist.h \ 35 | percent.c \ 36 | mbox-util.c mbox-util.h \ 37 | dbutil.c dbutil.h \ 38 | argparse.c argparse.h \ 39 | protocol-io.c protocol-io.h 40 | 41 | common_headers = \ 42 | jrnl-fields.h 43 | 44 | libcommon_a_SOURCES = $(common_sources) 45 | libcommon_a_CFLAGS = $(AM_CFLAGS) $(LIBGPG_ERROR_CFLAGS) -DWITHOUT_NPTH=1 46 | libcommonpth_a_SOURCES = $(common_sources) 47 | libcommonpth_a_CFLAGS = $(AM_CFLAGS) $(LIBGPG_ERROR_CFLAGS) 48 | 49 | utility_sources = \ 50 | form.c form.h \ 51 | http.c http.h \ 52 | cJSON.c cJSON.h 53 | 54 | payprocd_SOURCES = \ 55 | payprocd.c payprocd.h \ 56 | commands.c commands.h \ 57 | currency.c currency.h \ 58 | stripe.c stripe.h \ 59 | paypal.c paypal-ipn.c paypal.h \ 60 | tlssupport.c tlssupport.h \ 61 | cred.c cred.h \ 62 | journal.c journal.h \ 63 | preorder.c preorder.h \ 64 | account.c account.h \ 65 | encrypt.c encrypt.h \ 66 | session.c session.h \ 67 | $(common_headers) \ 68 | $(utility_sources) 69 | payprocd_CFLAGS = $(GPG_ERROR_CFLAGS) $(NPTH_CFLAGS) $(LIBGCRYPT_CFLAGS) \ 70 | $(LIBGNUTLS_CFLAGS) $(SQLITE3_CFLAGS) $(GPGME_CFLAGS) 71 | payprocd_LDADD = -lm libcommonpth.a \ 72 | $(GPG_ERROR_LIBS) $(NPTH_LIBS) $(LIBGCRYPT_LIBS) \ 73 | $(LIBGNUTLS_LIBS) $(SQLITE3_LIBS) $(GPGME_LIBS) 74 | 75 | payproc_jrnl_SOURCES = \ 76 | payproc-jrnl.c \ 77 | $(common_headers) 78 | 79 | payproc_stat_SOURCES = \ 80 | payproc-stat.c \ 81 | $(common_headers) 82 | 83 | payproc_post_SOURCES = \ 84 | payproc-post.c \ 85 | $(common_headers) 86 | 87 | ppipnhd_SOURCES = ppipnhd.c 88 | ppipnhd_CFLAGS = 89 | ppipnhd_LDADD = 90 | 91 | ppsepaqr_SOURCES = ppsepaqr.c 92 | ppsepaqr_CFLAGS = $(QRENCODE_CFLAGS) $(GPG_ERROR_CFLAGS) 93 | ppsepaqr_LDADD = $(QRENCODE_LIBS) -lm libcommon.a $(GPG_ERROR_LIBS) 94 | 95 | module_tests = t-util t-preorder t-encrypt 96 | 97 | AM_CFLAGS = $(GPG_ERROR_CFLAGS) 98 | LDADD = -lm libcommon.a $(GPG_ERROR_LIBS) 99 | 100 | t_common_sources = t-common.h $(utility_sources) 101 | t_common_cflags = $(GPG_ERROR_CFLAGS) $(NPTH_CFLAGS) $(LIBGNUTLS_CFLAGS) 102 | t_common_ldadd = libcommonpth.a $(GPG_ERROR_LIBS) $(NPTH_LIBS) \ 103 | $(LIBGNUTLS_LIBS) -lm 104 | 105 | # (http.c and http.h are part of t_common_sources) 106 | t_http_SOURCES = t-http.c $(t_common_sources) 107 | t_http_CFLAGS = $(t_common_cflags) 108 | t_http_LDADD = $(t_common_ldadd) 109 | 110 | # (util.c is part of t_common_sources) 111 | t_util_SOURCES = t-util.c $(t_common_sources) 112 | t_util_CFLAGS = $(t_common_cflags) $(LIBGCRYPT_CFLAGS) 113 | t_util_LDADD = $(t_common_ldadd) $(LIBGCRYPT_LIBS) 114 | 115 | t_preorder_SOURCES = t-preorder.c $(t_common_sources) journal.c currency.c 116 | t_preorder_CFLAGS = $(t_common_cflags) $(LIBGCRYPT_CFLAGS) $(SQLITE3_CFLAGS) 117 | t_preorder_LDADD = $(t_common_ldadd) $(LIBGCRYPT_LIBS) $(SQLITE3_LIBS) 118 | 119 | t_encrypt_SOURCES = t-encrypt.c $(t_common_sources) journal.c currency.c 120 | t_encrypt_CFLAGS = $(t_common_cflags) $(LIBGCRYPT_CFLAGS) $(SQLITE3_CFLAGS) \ 121 | $(GPGME_CFLAGS) 122 | t_encrypt_LDADD = $(t_common_ldadd) $(LIBGCRYPT_LIBS) $(SQLITE3_LIBS) \ 123 | $(GPGME_LIBS) 124 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Run this to generate all the initial makefiles, etc. 3 | # 4 | # Copyright (C) 2003, 2012 g10 Code GmbH 5 | # 6 | # This file is free software; as a special exception the author gives 7 | # unlimited permission to copy and/or distribute it, with or without 8 | # modifications, as long as this notice is preserved. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 12 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 | 14 | configure_ac="configure.ac" 15 | 16 | cvtver () { 17 | awk 'NR==1 {split($NF,A,".");X=1000000*A[1]+1000*A[2]+A[3];print X;exit 0}' 18 | } 19 | 20 | check_version () { 21 | if [ $(( `("$1" --version || echo "0") | cvtver` >= $2 )) = 1 ]; then 22 | return 0 23 | fi 24 | echo "**Error**: "\`$1\'" not installed or too old." >&2 25 | echo ' Version '$3' or newer is required.' >&2 26 | [ -n "$4" ] && echo ' Note that this is part of '\`$4\''.' >&2 27 | DIE="yes" 28 | return 1 29 | } 30 | 31 | # Allow to override the default tool names 32 | AUTOCONF=${AUTOCONF_PREFIX}${AUTOCONF:-autoconf}${AUTOCONF_SUFFIX} 33 | AUTOHEADER=${AUTOCONF_PREFIX}${AUTOHEADER:-autoheader}${AUTOCONF_SUFFIX} 34 | 35 | AUTOMAKE=${AUTOMAKE_PREFIX}${AUTOMAKE:-automake}${AUTOMAKE_SUFFIX} 36 | ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} 37 | 38 | DIE=no 39 | FORCE= 40 | tmp=`dirname $0` 41 | tsdir=`cd "$tmp"; pwd` 42 | if test x"$1" = x"--force"; then 43 | FORCE=" --force" 44 | shift 45 | fi 46 | 47 | # Reject unsafe characters in $HOME, $tsdir and cwd. We consider spaces 48 | # as unsafe because it is too easy to get scripts wrong in this regard. 49 | am_lf=' 50 | ' 51 | case `pwd` in 52 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 53 | echo "unsafe working directory name"; DIE=yes;; 54 | esac 55 | case $tsdir in 56 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 57 | echo "unsafe source directory: \`$tsdir'"; DIE=yes;; 58 | esac 59 | case $HOME in 60 | *[\;\\\"\#\$\&\'\`$am_lf\ \ ]*) 61 | echo "unsafe home directory: \`$HOME'"; DIE=yes;; 62 | esac 63 | if test "$DIE" = "yes"; then 64 | exit 1 65 | fi 66 | 67 | 68 | # Grep the required versions from configure.ac 69 | autoconf_vers=`sed -n '/^AC_PREREQ(/ { 70 | s/^.*(\(.*\))/\1/p 71 | q 72 | }' ${configure_ac}` 73 | autoconf_vers_num=`echo "$autoconf_vers" | cvtver` 74 | 75 | automake_vers=`sed -n '/^min_automake_version=/ { 76 | s/^.*="\(.*\)"/\1/p 77 | q 78 | }' ${configure_ac}` 79 | automake_vers_num=`echo "$automake_vers" | cvtver` 80 | 81 | if [ -z "$autoconf_vers" -o -z "$automake_vers" ] 82 | then 83 | echo "**Error**: version information not found in "\`${configure_ac}\'"." >&2 84 | exit 1 85 | fi 86 | 87 | 88 | if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then 89 | check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf 90 | fi 91 | if check_version $AUTOMAKE $automake_vers_num $automake_vers; then 92 | check_version $ACLOCAL $automake_vers_num $autoconf_vers automake 93 | fi 94 | 95 | if test "$DIE" = "yes"; then 96 | cat <&2 109 | *** Activating trailing whitespace git pre-commit hook. *** 110 | For more information see this thread: 111 | http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084html 112 | To deactivate this pre-commit hook again move .git/hooks/pre-commit 113 | and .git/hooks/pre-commit.sample out of the way. 114 | EOF 115 | cp -av .git/hooks/pre-commit.sample .git/hooks/pre-commit 116 | chmod +x .git/hooks/pre-commit 117 | fi 118 | tmp=$(git config --get filter.cleanpo.clean) 119 | if [ "$tmp" != "awk '/^\"POT-Creation-Date:/&&!s{s=1;next};!/^#: /{print}'" ] 120 | then 121 | echo "*** Adding GIT filter.cleanpo.clean configuration." >&2 122 | git config --add filter.cleanpo.clean \ 123 | "awk '/^\"POT-Creation-Date:/&&!s{s=1;next};!/^#: /{print}'" 124 | fi 125 | if [ -f scripts/git-hooks/commit-msg -a ! -f .git/hooks/commit-msg ] ; then 126 | cat <&2 127 | *** Activating commit log message check hook. *** 128 | EOF 129 | cp -av scripts/git-hooks/commit-msg .git/hooks/commit-msg 130 | chmod +x .git/hooks/commit-msg 131 | fi 132 | fi 133 | 134 | echo "Running aclocal -I m4 ${ACLOCAL_FLAGS:+$ACLOCAL_FLAGS }..." 135 | $ACLOCAL -I m4 $ACLOCAL_FLAGS 136 | echo "Running autoheader..." 137 | $AUTOHEADER 138 | echo "Running automake --gnu ..." 139 | $AUTOMAKE --gnu; 140 | echo "Running autoconf${FORCE} ..." 141 | $AUTOCONF${FORCE} 142 | 143 | echo "You may now run: 144 | ./configure --enable-maintainer-mode && make 145 | " 146 | -------------------------------------------------------------------------------- /m4/gpg-error.m4: -------------------------------------------------------------------------------- 1 | # gpg-error.m4 - autoconf macro to detect libgpg-error. 2 | # Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH 3 | # 4 | # This file is free software; as a special exception the author gives 5 | # unlimited permission to copy and/or distribute it, with or without 6 | # modifications, as long as this notice is preserved. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # 12 | # Last-changed: 2014-10-02 13 | 14 | 15 | dnl AM_PATH_GPG_ERROR([MINIMUM-VERSION, 16 | dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) 17 | dnl 18 | dnl Test for libgpg-error and define GPG_ERROR_CFLAGS, GPG_ERROR_LIBS, 19 | dnl GPG_ERROR_MT_CFLAGS, and GPG_ERROR_MT_LIBS. The _MT_ variants are 20 | dnl used for programs requireing real multi thread support. 21 | dnl 22 | dnl If a prefix option is not used, the config script is first 23 | dnl searched in $SYSROOT/bin and then along $PATH. If the used 24 | dnl config script does not match the host specification the script 25 | dnl is added to the gpg_config_script_warn variable. 26 | dnl 27 | AC_DEFUN([AM_PATH_GPG_ERROR], 28 | [ AC_REQUIRE([AC_CANONICAL_HOST]) 29 | gpg_error_config_prefix="" 30 | dnl --with-libgpg-error-prefix=PFX is the preferred name for this option, 31 | dnl since that is consistent with how our three siblings use the directory/ 32 | dnl package name in --with-$dir_name-prefix=PFX. 33 | AC_ARG_WITH(libgpg-error-prefix, 34 | AC_HELP_STRING([--with-libgpg-error-prefix=PFX], 35 | [prefix where GPG Error is installed (optional)]), 36 | [gpg_error_config_prefix="$withval"]) 37 | 38 | dnl Accept --with-gpg-error-prefix and make it work the same as 39 | dnl --with-libgpg-error-prefix above, for backwards compatibility, 40 | dnl but do not document this old, inconsistently-named option. 41 | AC_ARG_WITH(gpg-error-prefix,, 42 | [gpg_error_config_prefix="$withval"]) 43 | 44 | if test x"${GPG_ERROR_CONFIG}" = x ; then 45 | if test x"${gpg_error_config_prefix}" != x ; then 46 | GPG_ERROR_CONFIG="${gpg_error_config_prefix}/bin/gpg-error-config" 47 | else 48 | case "${SYSROOT}" in 49 | /*) 50 | if test -x "${SYSROOT}/bin/gpg-error-config" ; then 51 | GPG_ERROR_CONFIG="${SYSROOT}/bin/gpg-error-config" 52 | fi 53 | ;; 54 | '') 55 | ;; 56 | *) 57 | AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) 58 | ;; 59 | esac 60 | fi 61 | fi 62 | 63 | AC_PATH_PROG(GPG_ERROR_CONFIG, gpg-error-config, no) 64 | min_gpg_error_version=ifelse([$1], ,0.0,$1) 65 | AC_MSG_CHECKING(for GPG Error - version >= $min_gpg_error_version) 66 | ok=no 67 | if test "$GPG_ERROR_CONFIG" != "no" \ 68 | && test -f "$GPG_ERROR_CONFIG" ; then 69 | req_major=`echo $min_gpg_error_version | \ 70 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` 71 | req_minor=`echo $min_gpg_error_version | \ 72 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` 73 | gpg_error_config_version=`$GPG_ERROR_CONFIG $gpg_error_config_args --version` 74 | major=`echo $gpg_error_config_version | \ 75 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` 76 | minor=`echo $gpg_error_config_version | \ 77 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` 78 | if test "$major" -gt "$req_major"; then 79 | ok=yes 80 | else 81 | if test "$major" -eq "$req_major"; then 82 | if test "$minor" -ge "$req_minor"; then 83 | ok=yes 84 | fi 85 | fi 86 | fi 87 | fi 88 | if test $ok = yes; then 89 | GPG_ERROR_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --cflags` 90 | GPG_ERROR_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --libs` 91 | GPG_ERROR_MT_CFLAGS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --cflags 2>/dev/null` 92 | GPG_ERROR_MT_LIBS=`$GPG_ERROR_CONFIG $gpg_error_config_args --mt --libs 2>/dev/null` 93 | AC_MSG_RESULT([yes ($gpg_error_config_version)]) 94 | ifelse([$2], , :, [$2]) 95 | gpg_error_config_host=`$GPG_ERROR_CONFIG $gpg_error_config_args --host 2>/dev/null || echo none` 96 | if test x"$gpg_error_config_host" != xnone ; then 97 | if test x"$gpg_error_config_host" != x"$host" ; then 98 | AC_MSG_WARN([[ 99 | *** 100 | *** The config script $GPG_ERROR_CONFIG was 101 | *** built for $gpg_error_config_host and thus may not match the 102 | *** used host $host. 103 | *** You may want to use the configure option --with-libgpg-error-prefix 104 | *** to specify a matching config script or use \$SYSROOT. 105 | ***]]) 106 | gpg_config_script_warn="$gpg_config_script_warn libgpg-error" 107 | fi 108 | fi 109 | else 110 | GPG_ERROR_CFLAGS="" 111 | GPG_ERROR_LIBS="" 112 | GPG_ERROR_MT_CFLAGS="" 113 | GPG_ERROR_MT_LIBS="" 114 | AC_MSG_RESULT(no) 115 | ifelse([$3], , :, [$3]) 116 | fi 117 | AC_SUBST(GPG_ERROR_CFLAGS) 118 | AC_SUBST(GPG_ERROR_LIBS) 119 | AC_SUBST(GPG_ERROR_MT_CFLAGS) 120 | AC_SUBST(GPG_ERROR_MT_LIBS) 121 | ]) 122 | -------------------------------------------------------------------------------- /src/strlist.c: -------------------------------------------------------------------------------- 1 | /* strlist.c - string helpers 2 | * Copyright (C) 1998, 2000, 2001, 2006 Free Software Foundation, Inc. 3 | * 4 | * This file is part of JNLIB, which is a subsystem of GnuPG. 5 | * 6 | * JNLIB is free software; you can redistribute it and/or modify it 7 | * under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * JNLIB is distributed in the hope that it will be useful, but 22 | * WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | * General Public License for more details. 25 | * 26 | * You should have received a copies of the GNU General Public License 27 | * and the GNU Lesser General Public License along with this program; 28 | * if not, see . 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "libjnlib-config.h" 38 | #include "strlist.h" 39 | #ifdef JNLIB_NEED_UTF8CONV 40 | #include "utf8conv.h" 41 | #endif 42 | 43 | void 44 | free_strlist( strlist_t sl ) 45 | { 46 | strlist_t sl2; 47 | 48 | for(; sl; sl = sl2 ) { 49 | sl2 = sl->next; 50 | jnlib_free(sl); 51 | } 52 | } 53 | 54 | 55 | /* Add STRING to the LIST at the front. This function terminates the 56 | process on memory shortage. */ 57 | strlist_t 58 | add_to_strlist( strlist_t *list, const char *string ) 59 | { 60 | strlist_t sl; 61 | 62 | sl = jnlib_xmalloc( sizeof *sl + strlen(string)); 63 | sl->flags = 0; 64 | strcpy(sl->d, string); 65 | sl->next = *list; 66 | *list = sl; 67 | return sl; 68 | } 69 | 70 | 71 | /* Add STRING to the LIST at the front. This function returns NULL 72 | and sets ERRNO on memory shortage. */ 73 | strlist_t 74 | add_to_strlist_try (strlist_t *list, const char *string) 75 | { 76 | strlist_t sl; 77 | 78 | sl = jnlib_malloc (sizeof *sl + strlen (string)); 79 | if (sl) 80 | { 81 | sl->flags = 0; 82 | strcpy (sl->d, string); 83 | sl->next = *list; 84 | *list = sl; 85 | } 86 | return sl; 87 | } 88 | 89 | 90 | /* Same as add_to_strlist() but if IS_UTF8 is *not* set, a conversion 91 | to UTF-8 is done. This function terminates the process on memory 92 | shortage. */ 93 | #ifdef JNLIB_NEED_UTF8CONV 94 | strlist_t 95 | add_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) 96 | { 97 | strlist_t sl; 98 | 99 | if (is_utf8) 100 | sl = add_to_strlist( list, string ); 101 | else 102 | { 103 | char *p = native_to_utf8( string ); 104 | sl = add_to_strlist( list, p ); 105 | jnlib_free ( p ); 106 | } 107 | return sl; 108 | } 109 | #endif /* JNLIB_NEED_UTF8CONV*/ 110 | 111 | 112 | /* Add STRING to the LIST at the end. This function terminates the 113 | process on memory shortage. */ 114 | strlist_t 115 | append_to_strlist( strlist_t *list, const char *string ) 116 | { 117 | strlist_t r, sl; 118 | 119 | sl = jnlib_xmalloc( sizeof *sl + strlen(string)); 120 | sl->flags = 0; 121 | strcpy(sl->d, string); 122 | sl->next = NULL; 123 | if( !*list ) 124 | *list = sl; 125 | else { 126 | for( r = *list; r->next; r = r->next ) 127 | ; 128 | r->next = sl; 129 | } 130 | return sl; 131 | } 132 | 133 | 134 | #ifdef JNLIB_NEED_UTF8CONV 135 | strlist_t 136 | append_to_strlist2( strlist_t *list, const char *string, int is_utf8 ) 137 | { 138 | strlist_t sl; 139 | 140 | if( is_utf8 ) 141 | sl = append_to_strlist( list, string ); 142 | else 143 | { 144 | char *p = native_to_utf8 (string); 145 | sl = append_to_strlist( list, p ); 146 | jnlib_free( p ); 147 | } 148 | return sl; 149 | } 150 | #endif /* JNLIB_NEED_UTF8CONV */ 151 | 152 | 153 | /* Return a copy of LIST. This function terminates the process on 154 | memory shortage.*/ 155 | strlist_t 156 | strlist_copy (strlist_t list) 157 | { 158 | strlist_t newlist = NULL, sl, *last; 159 | 160 | last = &newlist; 161 | for (; list; list = list->next) 162 | { 163 | sl = jnlib_xmalloc (sizeof *sl + strlen (list->d)); 164 | sl->flags = list->flags; 165 | strcpy(sl->d, list->d); 166 | sl->next = NULL; 167 | *last = sl; 168 | last = &sl; 169 | } 170 | return newlist; 171 | } 172 | 173 | 174 | 175 | strlist_t 176 | strlist_prev( strlist_t head, strlist_t node ) 177 | { 178 | strlist_t n; 179 | 180 | for(n=NULL; head && head != node; head = head->next ) 181 | n = head; 182 | return n; 183 | } 184 | 185 | strlist_t 186 | strlist_last( strlist_t node ) 187 | { 188 | if( node ) 189 | for( ; node->next ; node = node->next ) 190 | ; 191 | return node; 192 | } 193 | 194 | 195 | /* Remove the first item from LIST and return its content in an 196 | allocated buffer. This function terminates the process on memory 197 | shortage. */ 198 | char * 199 | strlist_pop (strlist_t *list) 200 | { 201 | char *str=NULL; 202 | strlist_t sl=*list; 203 | 204 | if(sl) 205 | { 206 | str=jnlib_xmalloc(strlen(sl->d)+1); 207 | strcpy(str,sl->d); 208 | 209 | *list=sl->next; 210 | jnlib_free(sl); 211 | } 212 | 213 | return str; 214 | } 215 | -------------------------------------------------------------------------------- /src/membuf.c: -------------------------------------------------------------------------------- 1 | /* membuf.c - A simple implementation of a dynamic buffer. 2 | * Copyright (C) 2001, 2003, 2009, 2011 Free Software Foundation, Inc. 3 | * Copyright (C) 2013 Werner Koch 4 | * 5 | * This file is part of GnuPG. 6 | * 7 | * This file is free software; you can redistribute it and/or modify 8 | * it under the terms of either 9 | * 10 | * - the GNU Lesser General Public License as published by the Free 11 | * Software Foundation; either version 3 of the License, or (at 12 | * your option) any later version. 13 | * 14 | * or 15 | * 16 | * - the GNU General Public License as published by the Free 17 | * Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * or both in parallel, as here. 21 | * 22 | * This file is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program; if not, see . 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | #include "util.h" 39 | #include "membuf.h" 40 | 41 | 42 | /* A simple implementation of a dynamic buffer. Use init_membuf() to 43 | create a buffer, put_membuf to append bytes and get_membuf to 44 | release and return the buffer. Allocation errors are detected but 45 | only returned at the final get_membuf(), this helps not to clutter 46 | the code with out of core checks. */ 47 | 48 | void 49 | init_membuf (membuf_t *mb, int initiallen) 50 | { 51 | mb->len = 0; 52 | mb->size = initiallen; 53 | mb->out_of_core = 0; 54 | mb->buf = xtrymalloc (initiallen); 55 | if (!mb->buf) 56 | mb->out_of_core = errno; 57 | } 58 | 59 | /* Shift the the content of the membuf MB by AMOUNT bytes. The next 60 | operation will then behave as if AMOUNT bytes had not been put into 61 | the buffer. If AMOUNT is greater than the actual accumulated 62 | bytes, the membuf is basically reset to its initial state. */ 63 | void 64 | clear_membuf (membuf_t *mb, size_t amount) 65 | { 66 | /* No need to clear if we are already out of core. */ 67 | if (mb->out_of_core) 68 | return; 69 | if (amount >= mb->len) 70 | mb->len = 0; 71 | else 72 | { 73 | mb->len -= amount; 74 | memmove (mb->buf, mb->buf+amount, mb->len); 75 | } 76 | } 77 | 78 | 79 | void 80 | put_membuf (membuf_t *mb, const void *buf, size_t len) 81 | { 82 | if (mb->out_of_core || !len) 83 | return; 84 | 85 | if (mb->len + len >= mb->size) 86 | { 87 | char *p; 88 | 89 | mb->size += len + 1024; 90 | p = xtryrealloc (mb->buf, mb->size); 91 | if (!p) 92 | { 93 | mb->out_of_core = errno ? errno : ENOMEM; 94 | /* Wipe out what we already accumulated. This is required 95 | in case we are storing sensitive data here. The membuf 96 | API does not provide another way to cleanup after an 97 | error. */ 98 | wipememory (mb->buf, mb->len); 99 | return; 100 | } 101 | mb->buf = p; 102 | } 103 | memcpy (mb->buf + mb->len, buf, len); 104 | mb->len += len; 105 | } 106 | 107 | 108 | void 109 | put_membuf_chr (membuf_t *mb, int c) 110 | { 111 | unsigned char tmp[1]; 112 | 113 | *tmp = c; 114 | put_membuf (mb, tmp, 1); 115 | } 116 | 117 | 118 | void 119 | put_membuf_str (membuf_t *mb, const char *string) 120 | { 121 | put_membuf (mb, string, strlen (string)); 122 | } 123 | 124 | 125 | void 126 | put_membuf_printf (membuf_t *mb, const char *format, ...) 127 | { 128 | int rc; 129 | va_list arg_ptr; 130 | char *buf; 131 | 132 | va_start (arg_ptr, format); 133 | rc = es_vasprintf (&buf, format, arg_ptr); 134 | if (rc < 0) 135 | mb->out_of_core = errno ? errno : ENOMEM; 136 | va_end (arg_ptr); 137 | if (rc >= 0) 138 | { 139 | put_membuf (mb, buf, strlen (buf)); 140 | xfree (buf); 141 | } 142 | } 143 | 144 | 145 | void * 146 | get_membuf (membuf_t *mb, size_t *len) 147 | { 148 | char *p; 149 | 150 | if (mb->out_of_core) 151 | { 152 | if (mb->buf) 153 | { 154 | wipememory (mb->buf, mb->len); 155 | xfree (mb->buf); 156 | mb->buf = NULL; 157 | } 158 | gpg_err_set_errno (mb->out_of_core); 159 | return NULL; 160 | } 161 | 162 | p = mb->buf; 163 | if (len) 164 | *len = mb->len; 165 | mb->buf = NULL; 166 | mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */ 167 | return p; 168 | } 169 | 170 | 171 | /* Same as get_membuf but shrinks the reallocated space to the 172 | required size. */ 173 | void * 174 | get_membuf_shrink (membuf_t *mb, size_t *len) 175 | { 176 | void *p, *pp; 177 | size_t dummylen; 178 | 179 | if (!len) 180 | len = &dummylen; 181 | 182 | p = get_membuf (mb, len); 183 | if (!p) 184 | return NULL; 185 | if (*len) 186 | { 187 | pp = xtryrealloc (p, *len); 188 | if (pp) 189 | p = pp; 190 | } 191 | 192 | return p; 193 | } 194 | 195 | 196 | /* Peek at the membuf MB. On success a pointer to the buffer is 197 | returned which is valid until the next operation on MB. If LEN is 198 | not NULL the current LEN of the buffer is stored there. On error 199 | NULL is returned and ERRNO is set. */ 200 | const void * 201 | peek_membuf (membuf_t *mb, size_t *len) 202 | { 203 | const char *p; 204 | 205 | if (mb->out_of_core) 206 | { 207 | gpg_err_set_errno (mb->out_of_core); 208 | return NULL; 209 | } 210 | 211 | p = mb->buf; 212 | if (len) 213 | *len = mb->len; 214 | return p; 215 | } 216 | -------------------------------------------------------------------------------- /m4/libgcrypt.m4: -------------------------------------------------------------------------------- 1 | # libgcrypt.m4 - Autoconf macros to detect libgcrypt 2 | # Copyright (C) 2002, 2003, 2004, 2011, 2014 g10 Code GmbH 3 | # 4 | # This file is free software; as a special exception the author gives 5 | # unlimited permission to copy and/or distribute it, with or without 6 | # modifications, as long as this notice is preserved. 7 | # 8 | # This file is distributed in the hope that it will be useful, but 9 | # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the 10 | # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # 12 | # Last-changed: 2014-10-02 13 | 14 | 15 | dnl AM_PATH_LIBGCRYPT([MINIMUM-VERSION, 16 | dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) 17 | dnl Test for libgcrypt and define LIBGCRYPT_CFLAGS and LIBGCRYPT_LIBS. 18 | dnl MINIMUN-VERSION is a string with the version number optionalliy prefixed 19 | dnl with the API version to also check the API compatibility. Example: 20 | dnl a MINIMUN-VERSION of 1:1.2.5 won't pass the test unless the installed 21 | dnl version of libgcrypt is at least 1.2.5 *and* the API number is 1. Using 22 | dnl this features allows to prevent build against newer versions of libgcrypt 23 | dnl with a changed API. 24 | dnl 25 | dnl If a prefix option is not used, the config script is first 26 | dnl searched in $SYSROOT/bin and then along $PATH. If the used 27 | dnl config script does not match the host specification the script 28 | dnl is added to the gpg_config_script_warn variable. 29 | dnl 30 | AC_DEFUN([AM_PATH_LIBGCRYPT], 31 | [ AC_REQUIRE([AC_CANONICAL_HOST]) 32 | AC_ARG_WITH(libgcrypt-prefix, 33 | AC_HELP_STRING([--with-libgcrypt-prefix=PFX], 34 | [prefix where LIBGCRYPT is installed (optional)]), 35 | libgcrypt_config_prefix="$withval", libgcrypt_config_prefix="") 36 | if test x"${LIBGCRYPT_CONFIG}" = x ; then 37 | if test x"${libgcrypt_config_prefix}" != x ; then 38 | LIBGCRYPT_CONFIG="${libgcrypt_config_prefix}/bin/libgcrypt-config" 39 | else 40 | case "${SYSROOT}" in 41 | /*) 42 | if test -x "${SYSROOT}/bin/libgcrypt-config" ; then 43 | LIBGCRYPT_CONFIG="${SYSROOT}/bin/libgcrypt-config" 44 | fi 45 | ;; 46 | '') 47 | ;; 48 | *) 49 | AC_MSG_WARN([Ignoring \$SYSROOT as it is not an absolute path.]) 50 | ;; 51 | esac 52 | fi 53 | fi 54 | 55 | AC_PATH_PROG(LIBGCRYPT_CONFIG, libgcrypt-config, no) 56 | tmp=ifelse([$1], ,1:1.2.0,$1) 57 | if echo "$tmp" | grep ':' >/dev/null 2>/dev/null ; then 58 | req_libgcrypt_api=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\1/'` 59 | min_libgcrypt_version=`echo "$tmp" | sed 's/\(.*\):\(.*\)/\2/'` 60 | else 61 | req_libgcrypt_api=0 62 | min_libgcrypt_version="$tmp" 63 | fi 64 | 65 | AC_MSG_CHECKING(for LIBGCRYPT - version >= $min_libgcrypt_version) 66 | ok=no 67 | if test "$LIBGCRYPT_CONFIG" != "no" ; then 68 | req_major=`echo $min_libgcrypt_version | \ 69 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` 70 | req_minor=`echo $min_libgcrypt_version | \ 71 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` 72 | req_micro=`echo $min_libgcrypt_version | \ 73 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` 74 | libgcrypt_config_version=`$LIBGCRYPT_CONFIG --version` 75 | major=`echo $libgcrypt_config_version | \ 76 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` 77 | minor=`echo $libgcrypt_config_version | \ 78 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` 79 | micro=`echo $libgcrypt_config_version | \ 80 | sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` 81 | if test "$major" -gt "$req_major"; then 82 | ok=yes 83 | else 84 | if test "$major" -eq "$req_major"; then 85 | if test "$minor" -gt "$req_minor"; then 86 | ok=yes 87 | else 88 | if test "$minor" -eq "$req_minor"; then 89 | if test "$micro" -ge "$req_micro"; then 90 | ok=yes 91 | fi 92 | fi 93 | fi 94 | fi 95 | fi 96 | fi 97 | if test $ok = yes; then 98 | AC_MSG_RESULT([yes ($libgcrypt_config_version)]) 99 | else 100 | AC_MSG_RESULT(no) 101 | fi 102 | if test $ok = yes; then 103 | # If we have a recent libgcrypt, we should also check that the 104 | # API is compatible 105 | if test "$req_libgcrypt_api" -gt 0 ; then 106 | tmp=`$LIBGCRYPT_CONFIG --api-version 2>/dev/null || echo 0` 107 | if test "$tmp" -gt 0 ; then 108 | AC_MSG_CHECKING([LIBGCRYPT API version]) 109 | if test "$req_libgcrypt_api" -eq "$tmp" ; then 110 | AC_MSG_RESULT([okay]) 111 | else 112 | ok=no 113 | AC_MSG_RESULT([does not match. want=$req_libgcrypt_api got=$tmp]) 114 | fi 115 | fi 116 | fi 117 | fi 118 | if test $ok = yes; then 119 | LIBGCRYPT_CFLAGS=`$LIBGCRYPT_CONFIG --cflags` 120 | LIBGCRYPT_LIBS=`$LIBGCRYPT_CONFIG --libs` 121 | ifelse([$2], , :, [$2]) 122 | libgcrypt_config_host=`$LIBGCRYPT_CONFIG --host 2>/dev/null || echo none` 123 | if test x"$libgcrypt_config_host" != xnone ; then 124 | if test x"$libgcrypt_config_host" != x"$host" ; then 125 | AC_MSG_WARN([[ 126 | *** 127 | *** The config script $LIBGCRYPT_CONFIG was 128 | *** built for $libgcrypt_config_host and thus may not match the 129 | *** used host $host. 130 | *** You may want to use the configure option --with-libgcrypt-prefix 131 | *** to specify a matching config script or use \$SYSROOT. 132 | ***]]) 133 | gpg_config_script_warn="$gpg_config_script_warn libgcrypt" 134 | fi 135 | fi 136 | else 137 | LIBGCRYPT_CFLAGS="" 138 | LIBGCRYPT_LIBS="" 139 | ifelse([$3], , :, [$3]) 140 | fi 141 | AC_SUBST(LIBGCRYPT_CFLAGS) 142 | AC_SUBST(LIBGCRYPT_LIBS) 143 | ]) 144 | -------------------------------------------------------------------------------- /src/paypal-ipn.c: -------------------------------------------------------------------------------- 1 | /* paypal-ipn.c - Paypal IPN processing. 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "util.h" 27 | #include "logging.h" 28 | #include "http.h" 29 | #include "membuf.h" 30 | #include "payprocd.h" 31 | #include "paypal.h" 32 | 33 | 34 | /* Perform a call to paypal.com. KEYSTRING is the secret key, METHOD 35 | is the method without the version (e.g. "tokens") and DATA the 36 | individual part to be appended to the URL (e.g. a token-id). If 37 | FORMDATA is not NULL, a POST operaion is used with that data instead 38 | of the default GET operation. On success the function returns 0 39 | and a status code at R_STATUS. The data send with certain status 40 | code is stored in parsed format at R_JSON - this might be NULL. */ 41 | static gpg_error_t 42 | call_verify (int live, const char *request) 43 | { 44 | gpg_error_t err; 45 | const char *url; 46 | http_session_t session = NULL; 47 | http_t http = NULL; 48 | estream_t fp; 49 | unsigned int status; 50 | const char cmd[] = "cmd=_notify-validate&"; 51 | char response[20]; 52 | 53 | url = (live? "https://www.paypal.com/cgi-bin/webscr" 54 | /**/: "https://www.sandbox.paypal.com/cgi-bin/webscr"); 55 | 56 | 57 | err = http_session_new (&session, NULL); 58 | if (err) 59 | goto leave; 60 | 61 | if (opt.debug_paypal) 62 | log_debug ("paypal-req: %s %s\n", "POST" , url); 63 | 64 | err = http_open (&http, 65 | HTTP_REQ_POST, 66 | url, 67 | NULL, 68 | NULL, 69 | 0, 70 | NULL, 71 | session, 72 | NULL, 73 | NULL); 74 | if (err) 75 | { 76 | log_error ("error accessing '%s': %s\n", url, gpg_strerror (err)); 77 | goto leave; 78 | } 79 | 80 | fp = http_get_write_ptr (http); 81 | es_fprintf (fp, 82 | "Content-Type: application/x-www-form-urlencoded\r\n" 83 | "Content-Length: %zu\r\n", strlen (cmd) + strlen (request)); 84 | 85 | http_start_data (http); 86 | if (es_fputs (cmd, fp)) 87 | err = gpg_error_from_syserror (); 88 | else if (es_fputs (request, fp)) 89 | err = gpg_error_from_syserror (); 90 | 91 | if (err) 92 | { 93 | log_error ("error sending to '%s': %s\n", url, gpg_strerror (err)); 94 | goto leave; 95 | } 96 | 97 | err = http_wait_response (http); 98 | if (err) 99 | { 100 | log_error ("error reading '%s': %s\n", url, gpg_strerror (err)); 101 | goto leave; 102 | } 103 | 104 | status = http_get_status_code (http); 105 | if (status != 200) 106 | { 107 | log_error ("error reading '%s': status=%03d\n", url, status); 108 | err = gpg_error (GPG_ERR_GENERAL); 109 | goto leave; 110 | } 111 | 112 | if (!es_fgets (response, sizeof response, http_get_read_ptr (http))) 113 | { 114 | err = gpg_error_from_syserror (); 115 | log_error ("error reading '%s': %s\n", url, gpg_strerror (err)); 116 | goto leave; 117 | } 118 | 119 | if (opt.debug_paypal) 120 | log_debug ("paypal-rsp: %3d (%s) status='%.100s'\n", 121 | status, gpg_strerror (err), response); 122 | err = !strcmp (response, "VERIFIED")? 0 : gpg_error (GPG_ERR_NOT_FOUND); 123 | 124 | leave: 125 | http_close (http, 0); 126 | http_session_release (session); 127 | return err; 128 | } 129 | 130 | 131 | 132 | 133 | 134 | /* The connection has already been shutdown but the request has been 135 | stored in the dictionary DICT. We extract the original full 136 | request, validate it with Paypal and then do something with the 137 | received notification. */ 138 | void 139 | paypal_proc_ipn (keyvalue_t *dict) 140 | { 141 | gpg_error_t err; 142 | keyvalue_t kv; 143 | char *request; 144 | keyvalue_t form; 145 | 146 | if ((kv = keyvalue_find (*dict, "Request"))) 147 | keyvalue_remove_nl (kv); 148 | request = keyvalue_snatch (*dict, "Request"); 149 | if (!request || !*request) 150 | { 151 | log_error ("ppipnhd: no request given\n"); 152 | xfree (request); 153 | return; 154 | } 155 | 156 | log_info ("ppipnhd: length of request=%zu\n", strlen (request)); 157 | 158 | /* Parse it into a dictionary. */ 159 | err = parse_www_form_urlencoded (&form, request); 160 | if (err) 161 | { 162 | log_error ("ppipnhd: error parsing request: %s\n", 163 | gpg_strerror (err)); 164 | goto leave; 165 | } 166 | 167 | for (kv = form; kv; kv = kv->next) 168 | log_printkeyval (" ", kv->name, kv->value); 169 | 170 | /* To avoid useless verification against Paypal we first check the 171 | mail address. */ 172 | if (strcmp (keyvalue_get_string (form, "receiver_email"), 173 | "paypal-test@g10code.com")) 174 | { 175 | log_error ("ppipnhd: wrong receiver_email\n"); 176 | log_printval (" mail=", keyvalue_get_string (form, "receiver_email")); 177 | goto leave; 178 | } 179 | 180 | if (call_verify (!keyvalue_get_int (form, "test_ipn"), request)) 181 | { 182 | log_error ("ppipnhd: IPN is not authentic\n"); 183 | goto leave; 184 | } 185 | 186 | log_info ("ppipnhd: IPN accepted\n"); 187 | 188 | /* Check for duplicates. */ 189 | 190 | /* Check status of transaction. */ 191 | 192 | 193 | leave: 194 | xfree (request); 195 | keyvalue_release (form); 196 | } 197 | -------------------------------------------------------------------------------- /src/t-util.c: -------------------------------------------------------------------------------- 1 | /* t-util.c - Regression test for util.c 2 | * Copyright (C) 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifdef HAVE_CONFIG_H 21 | # include 22 | #endif 23 | #include 24 | #include 25 | #include 26 | 27 | #include "t-common.h" 28 | 29 | #include "util.h" /* The module under test. */ 30 | 31 | 32 | static void 33 | test_keyvalue_put_meta (void) 34 | { 35 | static struct { const char *string; } tests[] = { 36 | { "Name=Werner&Email=wk=test@gnupg.org&" }, 37 | { "Name=" }, 38 | { "Name=&" }, 39 | { "Name==" }, 40 | { "Name=&Foo=%3d%26" }, 41 | /* Fixme: Add bad case tests. */ 42 | { NULL } 43 | }; 44 | gpg_error_t err; 45 | keyvalue_t data = NULL; 46 | keyvalue_t kv; 47 | int idx; 48 | 49 | for (idx=0; tests[idx].string; idx++) 50 | { 51 | if (verbose) 52 | printf ("test %d: '%s'\n", idx, tests[idx].string); 53 | err = keyvalue_put_meta (&data, tests[idx].string); 54 | if (err) 55 | { 56 | fprintf (stderr, "test %d ('%s') failed: %s\n", 57 | idx, tests[idx].string, gpg_strerror (err)); 58 | fail (idx); 59 | } 60 | else if (verbose) 61 | { 62 | for (kv = data; kv; kv = kv->next) 63 | printf (" %s: %s\n", kv->name, kv->value); 64 | } 65 | keyvalue_release (data); 66 | data = NULL; 67 | } 68 | } 69 | 70 | 71 | static void 72 | do_test_base64_encoding (int idx, const char *plain, const char *encoded) 73 | { 74 | gpg_error_t err; 75 | void *buffer; 76 | size_t buflen; 77 | 78 | buffer = base64_encode (plain, strlen (plain)); 79 | if (!buffer) 80 | fail (idx); 81 | if (strcmp (buffer, encoded)) 82 | fail (idx); 83 | 84 | err = base64_decode (encoded, &buffer, &buflen); 85 | if (err) 86 | fail (idx); 87 | if (!buffer) 88 | fail (idx); 89 | if (buflen != strlen (plain) || memcmp (buffer, plain, buflen)) 90 | fail (idx); 91 | xfree (buffer); 92 | } 93 | 94 | 95 | static void 96 | test_base64_encoding (void) 97 | { 98 | static const char *test_string = "libgpg-error is free software; " 99 | "you can redistribute it and/or modify it under the terms of " 100 | "the GNU Lesser General Public License as published by the Free " 101 | "Software Foundation; either version 2.1 of the License, or " 102 | "(at your option) any later version."; 103 | 104 | static const char *test_b64_string = "bGliZ3BnLWVycm9yIGlzIGZyZWUgc29" 105 | "mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgd" 106 | "W5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljIEx" 107 | "pY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb" 108 | "247IGVpdGhlciB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXI" 109 | "gb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4="; 110 | 111 | do_test_base64_encoding (1, test_string, test_b64_string); 112 | do_test_base64_encoding (2, "", ""); 113 | do_test_base64_encoding (3, "a", "YQ=="); 114 | do_test_base64_encoding (4, "aa", "YWE="); 115 | do_test_base64_encoding (5, "aaa", "YWFh"); 116 | do_test_base64_encoding (6, "aaaa", "YWFhYQ=="); 117 | } 118 | 119 | 120 | static void 121 | test_convert_amount (void) 122 | { 123 | static struct 124 | { 125 | int digits; 126 | const char *string; 127 | unsigned int expected; 128 | } tv[] = { 129 | { 0, "", 0 }, 130 | { 0, " ", 0 }, 131 | { 0, "\t", 0 }, 132 | { 0, "-1", 0 }, 133 | { 2, "1.23", 123 }, 134 | { 2, "+1.23", 123 }, 135 | { 2, "-1.23", 0 }, 136 | { 2, "1.2", 120 }, 137 | { 2, "1.", 100 }, 138 | { 2, "1", 100 }, 139 | { 2, "20", 2000 }, 140 | { 2, "20.01", 2001 }, 141 | { 2, "20.09", 2009 }, 142 | { 2, "23.59", 2359 }, 143 | { 2, "23.50", 2350 }, 144 | { 2, "23.5", 2350 }, 145 | { 2, "23", 2300 }, 146 | { 2, "23+", 0 }, 147 | { 2, "451", 45100 }, 148 | { 2, "451.00", 45100 }, 149 | { 2, "451..00", 0 }, 150 | { 2, "45.1.00", 0 }, 151 | { 2, "4512.00", 451200 }, 152 | { 2, "451200000000000000000000000000000000000000000000.00", 0 }, 153 | { 3, "20", 20000 }, 154 | { 3, "20.01", 20010 }, 155 | { 3, "20.09", 20090 }, 156 | { 3, "23.59", 23590 }, 157 | { 3, "23.50", 23500 }, 158 | { 3, "23.507",23507 }, 159 | { 3, "23.5", 23500 }, 160 | { 1, "20", 200 }, 161 | { 1, "20.01", 0 }, 162 | { 1, "20.09", 0 }, 163 | { 1, "23.59", 0 }, 164 | { 1, "23.50", 0 }, 165 | { 1, "23.5", 235 }, 166 | { 1, "23", 230 }, 167 | { 0, "20", 20 }, 168 | { 0, "20.01", 0 }, 169 | { 0, "20.09", 0 }, 170 | { 0, "23.59", 0 }, 171 | { 0, "23.50", 0 }, 172 | { 0, "23.5", 0 }, 173 | { 0, "23", 23 }, 174 | { 0, "23\"", 0 }, 175 | { 0, "23\'", 0 }, 176 | { 0, "\"23", 0 }, 177 | { 0, "\'23", 0 } 178 | }; 179 | int tidx; 180 | 181 | for (tidx=0; tidx < DIM (tv); tidx++) 182 | { 183 | unsigned int value; 184 | 185 | value = convert_amount (tv[tidx].string, tv[tidx].digits); 186 | if (value == tv[tidx].expected) 187 | pass (); 188 | else 189 | fail (tidx); 190 | } 191 | } 192 | 193 | 194 | int 195 | main (int argc, char **argv) 196 | { 197 | if (argc > 1 && !strcmp (argv[1], "--verbose")) 198 | verbose = 1; 199 | 200 | test_keyvalue_put_meta (); 201 | test_base64_encoding (); 202 | test_convert_amount (); 203 | 204 | return !!errorcount; 205 | } 206 | -------------------------------------------------------------------------------- /src/ppipnhd.c: -------------------------------------------------------------------------------- 1 | /* ppipnhd.c - PayPal IPN Handler CGI. 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | /* This is a CGI acting as a proxy for IPN messages from PayPal. It 21 | merely reads the request, passes it on to payprocd, and sends back 22 | a 200 HTTP response. */ 23 | 24 | #ifdef HAVE_CONFIG_H 25 | # include 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define PGM "ppipnhd" 37 | #define MAX_REQUEST (64*1024) 38 | 39 | 40 | /* Allow building standalone. */ 41 | #ifndef PAYPROCD_SOCKET_NAME 42 | #define PAYPROCD_SOCKET_NAME "/var/run/payproc/dameon" 43 | #define PAYPROCD_TEST_SOCKET_NAME "/var/run/payproc-test/dameon" 44 | #endif 45 | #ifndef PACKAGE_NAME 46 | #define PACKAGE_NAME "payproc" 47 | #endif 48 | #ifndef PACKAGE_VERSION 49 | #define PACKAGE_VERSION __DATE__ 50 | #endif 51 | 52 | 53 | static void 54 | print_status (int n, const char *text) 55 | { 56 | printf ("Status: %d %s\r\n", n, text); 57 | } 58 | 59 | 60 | static void 61 | exit_status (int n, const char *text) 62 | { 63 | print_status (n, text); 64 | fputs ("Content-Type: text/plain\r\n\r\n", stdout); 65 | exit (0); 66 | } 67 | 68 | 69 | /* Connect to the daemon and return stdio stream for the connected a 70 | socket. On error returns NULL and sets ERRNO. */ 71 | static FILE * 72 | connect_daemon (const char *name) 73 | { 74 | int sock; 75 | struct sockaddr_un addr_un; 76 | struct sockaddr *addrp; 77 | size_t addrlen; 78 | FILE *fp; 79 | 80 | if (strlen (name)+1 >= sizeof addr_un.sun_path) 81 | { 82 | errno = EINVAL; 83 | return NULL; 84 | } 85 | 86 | memset (&addr_un, 0, sizeof addr_un); 87 | addr_un.sun_family = AF_LOCAL; 88 | strncpy (addr_un.sun_path, name, sizeof (addr_un.sun_path) - 1); 89 | addr_un.sun_path[sizeof (addr_un.sun_path) - 1] = 0; 90 | addrlen = SUN_LEN (&addr_un); 91 | addrp = (struct sockaddr *)&addr_un; 92 | 93 | sock = socket (AF_LOCAL, SOCK_STREAM, 0); 94 | if (sock == -1) 95 | return NULL; 96 | 97 | if (connect (sock, addrp, addrlen)) 98 | { 99 | int saveerr = errno; 100 | close (sock); 101 | errno = saveerr; 102 | return NULL; 103 | } 104 | 105 | fp = fdopen (sock, "r+b"); 106 | if (!fp) 107 | { 108 | int saveerr = errno; 109 | close (sock); 110 | errno = saveerr; 111 | return NULL; 112 | } 113 | 114 | return fp; 115 | } 116 | 117 | 118 | /* Send the payload to the daemon. Does not return an error. */ 119 | static void 120 | send_to_daemon (const char *buffer) 121 | { 122 | FILE *fp; 123 | int n, c; 124 | 125 | fp = connect_daemon (PAYPROCD_SOCKET_NAME); 126 | if (!fp) 127 | exit_status (500, "Error connecting payprocd"); 128 | 129 | fputs ("PPIPNHD\nRequest: ", fp); 130 | n = 9; 131 | while ((c = *buffer++)) 132 | { 133 | if (n==1024) 134 | { 135 | putc ('\n', fp); 136 | putc (' ', fp); 137 | n = 0; 138 | } 139 | putc (c, fp); 140 | n++; 141 | } 142 | putc ('\n', fp); 143 | putc ('\n', fp); 144 | if (ferror (fp)) 145 | exit_status (500, "Error writing to payprocd"); 146 | 147 | /* Payproc daemon does not return anything real but in case of an 148 | error in this code we check whether the response is OK and not ERR. */ 149 | c = fgetc (fp); 150 | if (c != 'O') 151 | exit_status (500, "Error talking to payprocd"); 152 | /* Eat the response for a clean connection shutdown. */ 153 | while (getc (fp) != EOF) 154 | ; 155 | 156 | fclose (fp); 157 | } 158 | 159 | 160 | int 161 | main (int argc, char **argv) 162 | { 163 | const char *request_method = getenv("REQUEST_METHOD"); 164 | const char *content_length = getenv("CONTENT_LENGTH"); 165 | const char *content_type = getenv("CONTENT_TYPE"); 166 | unsigned long length, n; 167 | char *buffer; 168 | 169 | /* FIXME: Figure out whether this is a test or a live version and 170 | * adjust the socket accordingly. */ 171 | 172 | /* Allow the usual "--version" option only if run outside of the CGI 173 | environment. */ 174 | if (argc > 1 && !strcmp (argv[1], "--version") && !request_method) 175 | { 176 | fputs (PGM " (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout); 177 | return 0; 178 | } 179 | 180 | if (!request_method || strcmp (request_method, "POST")) 181 | exit_status (501, "Only POST allowed"); 182 | 183 | length = content_length? strtoul (content_length, NULL, 10) : 0; 184 | if (!length) 185 | exit_status (411, "Content-Length missing"); 186 | if (length >= MAX_REQUEST) 187 | exit_status (413, "Payload too large"); 188 | 189 | if (!content_type || !*content_type) 190 | exit_status (400, "Content-type missing"); 191 | 192 | buffer = malloc (length+1); 193 | if (!buffer) 194 | exit_status (503, "Service currently unavailable"); 195 | 196 | if (fread (buffer, length, 1, stdin) != 1) 197 | exit_status (400, feof (stdin)? "Payload shorter than indicated" 198 | /* */ : "Error reading payload"); 199 | buffer[length] = 0; /* Make it a string. */ 200 | for (n=0; n < length; n++) 201 | { 202 | if (!buffer[n]) 203 | exit_status (400, "Binary data in payload not allowed"); 204 | if (strchr (" \t\r\n", buffer[n])) 205 | exit_status (400, "Whitespaces in payload not allowed"); 206 | } 207 | 208 | 209 | send_to_daemon (buffer); 210 | free (buffer); 211 | 212 | print_status (200, "OK"); 213 | fputs ("Content-Type: text/plain\r\n\r\n", stdout); 214 | return 0; 215 | } 216 | -------------------------------------------------------------------------------- /src/http.h: -------------------------------------------------------------------------------- 1 | /* http.h - HTTP protocol handler 2 | * Copyright (C) 1999, 2000, 2001, 2003, 2006, 3 | * 2010 Free Software Foundation, Inc. 4 | * 5 | * This file is part of GnuPG. 6 | * 7 | * This file is free software; you can redistribute it and/or modify 8 | * it under the terms of either 9 | * 10 | * - the GNU Lesser General Public License as published by the Free 11 | * Software Foundation; either version 3 of the License, or (at 12 | * your option) any later version. 13 | * 14 | * or 15 | * 16 | * - the GNU General Public License as published by the Free 17 | * Software Foundation; either version 2 of the License, or (at 18 | * your option) any later version. 19 | * 20 | * or both in parallel, as here. 21 | * 22 | * This file is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program; if not, see . 29 | */ 30 | #ifndef GNUPG_COMMON_HTTP_H 31 | #define GNUPG_COMMON_HTTP_H 32 | 33 | #include 34 | #include "strlist.h" 35 | 36 | struct uri_tuple_s 37 | { 38 | struct uri_tuple_s *next; 39 | const char *name; /* A pointer into name. */ 40 | char *value; /* A pointer to value (a Nul is always appended). */ 41 | size_t valuelen; /* The real length of the value; we need it 42 | because the value may contain embedded Nuls. */ 43 | int no_value; /* True if no value has been given in the URL. */ 44 | }; 45 | typedef struct uri_tuple_s *uri_tuple_t; 46 | 47 | struct parsed_uri_s 48 | { 49 | /* All these pointers point into BUFFER; most stuff is not escaped. */ 50 | char *scheme; /* Pointer to the scheme string (always lowercase). */ 51 | unsigned int is_http:1; /* This is a HTTP style URI. */ 52 | unsigned int use_tls:1; /* Whether TLS should be used. */ 53 | unsigned int opaque:1;/* Unknown scheme; PATH has the rest. */ 54 | unsigned int v6lit:1; /* Host was given as a literal v6 address. */ 55 | char *auth; /* username/password for basic auth. */ 56 | char *host; /* Host (converted to lowercase). */ 57 | unsigned short port; /* Port (always set if the host is set). */ 58 | char *path; /* Path. */ 59 | uri_tuple_t params; /* ";xxxxx" */ 60 | uri_tuple_t query; /* "?xxx=yyy" */ 61 | char buffer[1]; /* Buffer which holds a (modified) copy of the URI. */ 62 | }; 63 | typedef struct parsed_uri_s *parsed_uri_t; 64 | 65 | typedef enum 66 | { 67 | HTTP_REQ_GET = 1, 68 | HTTP_REQ_HEAD = 2, 69 | HTTP_REQ_POST = 3, 70 | HTTP_REQ_PATCH = 4, 71 | HTTP_REQ_OPAQUE = 5 /* Internal use. */ 72 | } 73 | http_req_t; 74 | 75 | /* We put the flag values into an enum, so that gdb can display them. */ 76 | enum 77 | { 78 | HTTP_FLAG_TRY_PROXY = 1, /* Try to use a proxy. */ 79 | HTTP_FLAG_SHUTDOWN = 2, /* Close sending end after the request. */ 80 | HTTP_FLAG_LOG_RESP = 8, /* Log the server respone. */ 81 | HTTP_FLAG_FORCE_TLS = 16, /* Force the use opf TLS. */ 82 | HTTP_FLAG_IGNORE_CL = 32, /* Ignore content-length. */ 83 | HTTP_FLAG_IGNORE_IPv4 = 64, /* Do not use IPv4. */ 84 | HTTP_FLAG_IGNORE_IPv6 = 128, /* Do not use IPv6. */ 85 | HTTP_FLAG_AUTH_BEARER = 512 /* Use Bearer authtype instead of Basic. */ 86 | }; 87 | 88 | 89 | struct http_session_s; 90 | typedef struct http_session_s *http_session_t; 91 | 92 | struct http_context_s; 93 | typedef struct http_context_s *http_t; 94 | 95 | void http_register_tls_callback (gpg_error_t (*cb)(http_t,http_session_t,int)); 96 | void http_register_tls_ca (const char *fname); 97 | 98 | gpg_error_t http_session_new (http_session_t *r_session, 99 | const char *tls_priority); 100 | http_session_t http_session_ref (http_session_t sess); 101 | void http_session_release (http_session_t sess); 102 | 103 | void http_session_set_log_cb (http_session_t sess, 104 | void (*cb)(http_session_t, gpg_error_t, 105 | const char *, 106 | const void **, size_t *)); 107 | 108 | 109 | gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri, 110 | int no_scheme_check); 111 | 112 | void http_release_parsed_uri (parsed_uri_t uri); 113 | 114 | gpg_error_t http_raw_connect (http_t *r_hd, 115 | const char *server, unsigned short port, 116 | unsigned int flags, const char *srvtag); 117 | 118 | gpg_error_t http_open (http_t *r_hd, http_req_t reqtype, 119 | const char *url, 120 | const char *httphost, 121 | const char *auth, 122 | unsigned int flags, 123 | const char *proxy, 124 | http_session_t session, 125 | const char *srvtag, 126 | strlist_t headers); 127 | 128 | void http_start_data (http_t hd); 129 | 130 | gpg_error_t http_wait_response (http_t hd); 131 | 132 | void http_close (http_t hd, int keep_read_stream); 133 | 134 | gpg_error_t http_open_document (http_t *r_hd, 135 | const char *document, 136 | const char *auth, 137 | unsigned int flags, 138 | const char *proxy, 139 | http_session_t session, 140 | const char *srvtag, 141 | strlist_t headers); 142 | 143 | estream_t http_get_read_ptr (http_t hd); 144 | estream_t http_get_write_ptr (http_t hd); 145 | unsigned int http_get_status_code (http_t hd); 146 | const char *http_get_tls_info (http_t hd, const char *what); 147 | const char *http_get_header (http_t hd, const char *name); 148 | const char **http_get_header_names (http_t hd); 149 | gpg_error_t http_verify_server_credentials (http_session_t sess); 150 | 151 | char *http_escape_string (const char *string, const char *specials); 152 | char *http_escape_data (const void *data, size_t datalen, const char *specials); 153 | 154 | 155 | #endif /*GNUPG_COMMON_HTTP_H*/ 156 | -------------------------------------------------------------------------------- /doc/api-ref.org: -------------------------------------------------------------------------------- 1 | #+TITLE: API reference for payprocd. 2 | #+STARTUP: showall indent 3 | 4 | * General syntax 5 | 6 | TBD 7 | 8 | * Commands 9 | 10 | A quick way to test commands is the use of the socat(1) tool: 11 | 12 | : socat - unix-client:/var/run/payproc/daemon 13 | 14 | 15 | ** CARDTOKEN 16 | 17 | Request a token for a card 18 | 19 | Example: 20 | 21 | #+begin_example 22 | CARDTOKEN 23 | Number: 4242424242424242 24 | Exp-month: 8 25 | exp-year: 2016 26 | Cvc: 666 27 | Name: Juscelino Kubitschek 28 | 29 | OK 30 | Token: tok_103rEw23ctCHxH4kTpC9BDTm 31 | Last4: 4242 32 | Live: f 33 | 34 | #+end_example 35 | 36 | Note that a request starts off with a command (here CARDTOKEN) and is 37 | terminated by an empty line. The response is either the "OK" or "ERR" 38 | optionally followed by words on the line. The response may then 39 | consists of header lines and is terminated by a blank line. Lines can 40 | be continued on the next line by prefixing a continuation line with a 41 | space. 42 | 43 | The use of CARDTOKEN is not suggested - better use Stripe's 44 | checkout Javascript to avoid handling sensitive card data on your 45 | machine. Having access to an unused card token, it is possible to 46 | charge the card: 47 | 48 | ** CHARGECARD 49 | 50 | #+begin_example 51 | CHARGECARD 52 | Card-Token: tok_103rEw23ctCHxH4kTpC9BDTm 53 | Currency: USD 54 | Amount: 17.50 55 | Desc: OpenPGP card for use with GnuPG 56 | Stmt-Desc: Openpgp card 57 | Meta[name]: Juscelino Kubitschek 58 | Meta[ship-to]: Palácio da Alvorada 59 | 70000 Brasilia 60 | Brazil 61 | 62 | OK 63 | _amount: 1750 64 | Currency: usd 65 | Live: f 66 | Charge-Id: ch_103rEw23ctCHxH4ktmJ5na8N 67 | _timestamp: 20140523T202551 68 | 69 | #+end_example 70 | 71 | An arbitrary number of Meta header lines may be used in the request, 72 | they will all be written to the journal as key-value pairs. An 73 | example for an error return is: 74 | 75 | #+begin_example 76 | ERR 1 (General error) 77 | failure: incorrect_number 78 | failure-mesg: Your card number is incorrect. 79 | Name: Juscelino Kubitschek 80 | 81 | #+end_example 82 | 83 | The "failure" data line contains a short description of the error. It 84 | may be returned to the user. If a "failure-mesg" line is returned, 85 | that may be returned verbatim to the user. There is no guarantee that 86 | a "failure" line will be preset. However, the number after ERR is a 87 | gpg-error error code and may be show to the user. The description 88 | after the number is usually the gpg_strerror of the error code but may 89 | also be a more specific human readable string. 90 | 91 | ** CHECKAMOUNT 92 | 93 | To convert an requested amount to the format used by Stripe, this 94 | command can be used: 95 | 96 | #+begin_example 97 | CHECKAMOUNT 98 | Amount: 17.3 99 | Currency: Eur 100 | 101 | OK 102 | _amount: 1730 103 | Currency: Eur 104 | Amount: 17.3 105 | Euro: 17.30 106 | 107 | #+end_example 108 | 109 | The returned data set also includes a field "Euro" with the input 110 | amount converted to an Euro value. This conversion is done using the 111 | reference data retrieved via cron job. It may be different from the 112 | conversion done by the payment service provider. 113 | 114 | To check recurring donations two additional items are required in the 115 | request: 116 | 117 | #+begin_example 118 | Recur: 12 119 | Stmt-Desc: Foo 120 | #+end_example 121 | 122 | The valid values for "Recur" are 12 for per month, 4 for per quarter, 123 | and 1 for per year. The "Stmt-Desc" is required and will be put on 124 | the credit card statement along with a "Monthly"/"Quarterly"/"Yearly" 125 | prefix. The return value as the additional let "_plan-id". 126 | 127 | 128 | ** PPCHECKOUT 129 | 130 | PayPal Checkout. See the source for details. FIXME. 131 | 132 | #+begin_example 133 | PPCHECKOUT prepare 134 | Amount: 42.50 135 | Currency: EUR 136 | Desc: Donation towards Payproc development 137 | Meta[Mail]: foo@example.org 138 | Return-Url: https://gnupg.org/cgi-bin/procdonate.cgi?mode=confirm-paypal 139 | Cancel-Url: https://gnupg.org/cgi-bin/procdonate.cgi?mode=cancel-paypal 140 | Paypal-Xp: XP-NBWZ-QR6Z-8CXV-Q8XS 141 | #+end_example 142 | 143 | Optional items: Session-Id 144 | 145 | access token 2017-05-18 08:46:23 146 | : A21AAEpPr2fqhAKGkQcsC4TE8MG-nvLjTy6mVZOATgqKUohoinSqwaqaLT9du2Jqrv2bpDDrQiSUlWaMcFYBhIP2Iu_NXKi2Q 147 | 148 | 149 | ** SEPAPREORDER 150 | 151 | #+begin_example 152 | SEPAPREORDER 153 | Amount: 17.3 154 | 155 | OK 156 | Currency: Eur 157 | Amount: 17.30 158 | SEPA-Ref: GYT3L-27 159 | #+end_example 160 | 161 | The error return is similar to CHARGECARD. 162 | 163 | This commands adds a preorder record for a SEPA payment into the 164 | preorder database. That record will be removed after 30 days if it 165 | has not been used. A command line tool can be used to match a 166 | received payment with this record and create a final log record. Note 167 | that a Currency is not required because SEPA does only allow Euro. 168 | The SEPA-Ref is a short random string used to index that record. The 169 | additional number is used to find an entry in the preorder db in case 170 | of a typos in the first string. 171 | 172 | 173 | ** SESSION 174 | 175 | This is a multipurpose command to help implement a state-full service. 176 | Note that the state information is intentional not persistent and thus 177 | won't survive a daemon restart. 178 | 179 | The following sub-commands are available: 180 | 181 | - Create a new session 182 | 183 | : create [TTL] 184 | 185 | A new session is created and the provided data dictionary is stored 186 | by payprocd for future requests. The data dictionary is optional. 187 | On success the returned data has an "_SESSID" item which is to be 188 | used for all further requests. If TTL has been given this is used 189 | instead of the defaul TTL value. 190 | 191 | - Destroy a session. 192 | 193 | : destroy SESSID 194 | 195 | This shall be used to free the internal storage required for the 196 | session and to avoid leaving sensitive information in RAM. 197 | 198 | - Get data from a session. 199 | 200 | : get SESSID 201 | 202 | Return the data stored in the session identified by SESSID. 203 | 204 | - Put data into a session. 205 | 206 | : put SESSID 207 | 208 | Store or update the given data in the session. Deleting an item 209 | from the session dictionary is possible by putting an empty string 210 | for it. 211 | 212 | - Create an alias for the session. 213 | 214 | : alias SESSID 215 | 216 | On success the returned data has an "_ALIASID" item which is to be 217 | used for all further alias related requests. 218 | 219 | - Destroy an alias. 220 | 221 | : dealias ALIASID 222 | 223 | Note that this does not destroy the session. 224 | 225 | - Return the session id for an alias. 226 | 227 | : sessid ALIASID 228 | 229 | On success the returned data has an "_SESSID" item. 230 | 231 | 232 | ** PPIPNHD 233 | 234 | This command is used exclusively by the =ppipnhd= CGI to have payprocd 235 | handle PayPal IPN requests. 236 | -------------------------------------------------------------------------------- /src/percent.c: -------------------------------------------------------------------------------- 1 | /* percent.c - Percent escaping 2 | * Copyright (C) 2008, 2009 Free Software Foundation, Inc. 3 | * 4 | * This file is part of GnuPG. 5 | * 6 | * This file is free software; you can redistribute it and/or modify 7 | * it under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * This file is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with this program; if not, see . 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include "util.h" 38 | 39 | 40 | /* Create a newly alloced string from STRING with all spaces and 41 | control characters converted to plus signs or %xx sequences. The 42 | function returns the new string or NULL in case of a malloc 43 | failure. 44 | 45 | Note that we also escape the quote character to work around a bug 46 | in the mingw32 runtime which does not correcty handle command line 47 | quoting. We correctly double the quote mark when calling a program 48 | (i.e. gpg-protect-tool), but the pre-main code does not notice the 49 | double quote as an escaped quote. We do this also on POSIX systems 50 | for consistency. */ 51 | char * 52 | percent_plus_escape (const char *string) 53 | { 54 | char *buffer, *p; 55 | const char *s; 56 | size_t length; 57 | 58 | for (length=1, s=string; *s; s++) 59 | { 60 | if (*s == '+' || *s == '\"' || *s == '%' 61 | || *(const unsigned char *)s < 0x20) 62 | length += 3; 63 | else 64 | length++; 65 | } 66 | 67 | buffer = p = xtrymalloc (length); 68 | if (!buffer) 69 | return NULL; 70 | 71 | for (s=string; *s; s++) 72 | { 73 | if (*s == '+' || *s == '\"' || *s == '%' 74 | || *(const unsigned char *)s < 0x20) 75 | { 76 | snprintf (p, 4, "%%%02X", *(unsigned char *)s); 77 | p += 3; 78 | } 79 | else if (*s == ' ') 80 | *p++ = '+'; 81 | else 82 | *p++ = *s; 83 | } 84 | *p = 0; 85 | 86 | return buffer; 87 | 88 | } 89 | 90 | 91 | /* Do the percent and plus/space unescaping from STRING to BUFFER and 92 | return the length of the valid buffer. Plus unescaping is only 93 | done if WITHPLUS is true. An escaped Nul character will be 94 | replaced by NULREPL. */ 95 | static size_t 96 | do_unescape (unsigned char *buffer, const unsigned char *string, 97 | int withplus, int nulrepl) 98 | { 99 | unsigned char *p = buffer; 100 | 101 | while (*string) 102 | { 103 | if (*string == '%' && string[1] && string[2]) 104 | { 105 | string++; 106 | *p = xtoi_2 (string); 107 | if (!*p) 108 | *p = nulrepl; 109 | string++; 110 | } 111 | else if (*string == '+' && withplus) 112 | *p = ' '; 113 | else 114 | *p = *string; 115 | p++; 116 | string++; 117 | } 118 | 119 | return (p - buffer); 120 | } 121 | 122 | 123 | /* Count space required after unescaping STRING. Note that this will 124 | never be larger than strlen (STRING). */ 125 | static size_t 126 | count_unescape (const unsigned char *string) 127 | { 128 | size_t n = 0; 129 | 130 | while (*string) 131 | { 132 | if (*string == '%' && string[1] && string[2]) 133 | { 134 | string++; 135 | string++; 136 | } 137 | string++; 138 | n++; 139 | } 140 | 141 | return n; 142 | } 143 | 144 | 145 | /* Helper. */ 146 | static char * 147 | do_plus_or_plain_unescape (const char *string, int withplus, int nulrepl) 148 | { 149 | size_t nbytes, n; 150 | char *newstring; 151 | 152 | nbytes = count_unescape (string); 153 | newstring = xtrymalloc (nbytes+1); 154 | if (newstring) 155 | { 156 | n = do_unescape (newstring, string, withplus, nulrepl); 157 | assert (n == nbytes); 158 | newstring[n] = 0; 159 | } 160 | return newstring; 161 | } 162 | 163 | 164 | /* Create a new allocated string from STRING with all "%xx" sequences 165 | decoded and all plus signs replaced by a space. Embedded Nul 166 | characters are replaced by the value of NULREPL. The function 167 | returns the new string or NULL in case of a malloc failure. */ 168 | char * 169 | percent_plus_unescape (const char *string, int nulrepl) 170 | { 171 | return do_plus_or_plain_unescape (string, 1, nulrepl); 172 | } 173 | 174 | 175 | /* Create a new allocated string from STRING with all "%xx" sequences 176 | decoded. Embedded Nul characters are replaced by the value of 177 | NULREPL. The function returns the new string or NULL in case of a 178 | malloc failure. */ 179 | char * 180 | percent_unescape (const char *string, int nulrepl) 181 | { 182 | return do_plus_or_plain_unescape (string, 0, nulrepl); 183 | } 184 | 185 | 186 | static size_t 187 | do_unescape_inplace (char *string, int withplus, int nulrepl) 188 | { 189 | unsigned char *p, *p0; 190 | 191 | p = p0 = string; 192 | while (*string) 193 | { 194 | if (*string == '%' && string[1] && string[2]) 195 | { 196 | string++; 197 | *p = xtoi_2 (string); 198 | if (!*p) 199 | *p = nulrepl; 200 | string++; 201 | } 202 | else if (*string == '+' && withplus) 203 | *p = ' '; 204 | else 205 | *p = *string; 206 | p++; 207 | string++; 208 | } 209 | 210 | return (p - p0); 211 | } 212 | 213 | 214 | /* Perform percent and plus unescaping in STRING and return the new 215 | valid length of the string. Embedded Nul characters are replaced 216 | by the value of NULREPL. A terminating Nul character is not 217 | inserted; the caller might want to call this function this way: 218 | 219 | foo[percent_plus_unescape_inplace (foo, 0)] = 0; 220 | */ 221 | size_t 222 | percent_plus_unescape_inplace (char *string, int nulrepl) 223 | { 224 | return do_unescape_inplace (string, 1, nulrepl); 225 | } 226 | 227 | 228 | /* Perform percent unescaping in STRING and return the new valid 229 | length of the string. Embedded Nul characters are replaced by the 230 | value of NULREPL. A terminating Nul character is not inserted; the 231 | caller might want to call this function this way: 232 | 233 | foo[percent_unescape_inplace (foo, 0)] = 0; 234 | */ 235 | size_t 236 | percent_unescape_inplace (char *string, int nulrepl) 237 | { 238 | return do_unescape_inplace (string, 0, nulrepl); 239 | } 240 | -------------------------------------------------------------------------------- /src/t-http.c: -------------------------------------------------------------------------------- 1 | /* t-http.c 2 | * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010, 3 | * 2011 Free Software Foundation, Inc. 4 | * Copyright (C) 2014 Werner Koch 5 | * 6 | * This file is part of GnuPG. 7 | * 8 | * This file is free software; you can redistribute it and/or modify 9 | * it under the terms of either 10 | * 11 | * - the GNU Lesser General Public License as published by the Free 12 | * Software Foundation; either version 3 of the License, or (at 13 | * your option) any later version. 14 | * 15 | * or 16 | * 17 | * - the GNU General Public License as published by the Free 18 | * Software Foundation; either version 2 of the License, or (at 19 | * your option) any later version. 20 | * 21 | * or both in parallel, as here. 22 | * 23 | * This file is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | * GNU General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU General Public License 29 | * along with this program; if not, see . 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "util.h" 41 | #include "logging.h" 42 | #include "http.h" 43 | 44 | #ifdef HTTP_USE_GNUTLS 45 | # include 46 | /* static gnutls_dh_params_t dh_params; */ 47 | #endif /*HTTP_USE_GNUTLS*/ 48 | 49 | 50 | 51 | /* static void */ 52 | /* read_dh_params (const char *fname) */ 53 | /* { */ 54 | /* gpg_error_t err; */ 55 | /* int rc; */ 56 | /* FILE *fp; */ 57 | /* struct stat st; */ 58 | /* char *buf; */ 59 | /* size_t buflen; */ 60 | /* gnutls_datum_t datum; */ 61 | 62 | /* fp = fopen (fname, "rb"); */ 63 | /* if (!fp) */ 64 | /* { */ 65 | /* err = gpg_error_from_syserror (); */ 66 | /* log_fatal ("can't open '%s': %s\n", fname, gpg_strerror (err)); */ 67 | /* } */ 68 | 69 | /* if (fstat (fileno(fp), &st)) */ 70 | /* { */ 71 | /* err = gpg_error_from_syserror (); */ 72 | /* log_fatal ("can't stat '%s': %s\n", fname, gpg_strerror (err)); */ 73 | /* } */ 74 | 75 | /* buflen = st.st_size; */ 76 | /* buf = xmalloc (buflen+1); */ 77 | /* if (fread (buf, buflen, 1, fp) != 1) */ 78 | /* { */ 79 | /* err = gpg_error_from_syserror (); */ 80 | /* log_fatal ("error reading '%s': %s\n", fname, gpg_strerror (err)); */ 81 | /* } */ 82 | /* fclose (fp); */ 83 | 84 | /* datum.size = buflen; */ 85 | /* datum.data = buf; */ 86 | 87 | /* rc = gnutls_dh_params_import_pkcs3 (dh_params, &datum, GNUTLS_X509_FMT_PEM); */ 88 | /* if (rc < 0) */ 89 | /* log_fatal ("gnutls_dh_param_import failed: %s\n", gnutls_strerror (rc)); */ 90 | 91 | /* xfree (buf); */ 92 | /* } */ 93 | 94 | 95 | 96 | static gpg_error_t 97 | verify_callback (http_t hd, http_session_t session, int reserved) 98 | { 99 | (void)hd; 100 | (void)reserved; 101 | return http_verify_server_credentials (session); 102 | } 103 | 104 | 105 | static void 106 | my_gnutls_log (int level, const char *text) 107 | { 108 | fprintf (stderr, "gnutls:L%d: %s", level, text); 109 | } 110 | 111 | 112 | int 113 | main (int argc, char **argv) 114 | { 115 | gpg_error_t err; 116 | int rc; 117 | parsed_uri_t uri; 118 | uri_tuple_t r; 119 | http_t hd; 120 | int c; 121 | http_session_t session = NULL; 122 | 123 | gpgrt_init (); 124 | log_set_prefix ("t-http", 1 | 4); 125 | if (argc != 2) 126 | { 127 | fprintf (stderr, "usage: t-http uri\n"); 128 | return 1; 129 | } 130 | argc--; 131 | argv++; 132 | 133 | #ifdef HTTP_USE_GNUTLS 134 | rc = gnutls_global_init (); 135 | if (rc) 136 | log_error ("gnutls_global_init failed: %s\n", gnutls_strerror (rc)); 137 | 138 | http_register_tls_callback (verify_callback); 139 | http_register_tls_ca ("tls-ca.pem"); 140 | 141 | err = http_session_new (&session, NULL); 142 | if (err) 143 | log_error ("http_session_new failed: %s\n", gpg_strerror (err)); 144 | 145 | /* rc = gnutls_dh_params_init(&dh_params); */ 146 | /* if (rc) */ 147 | /* log_error ("gnutls_dh_params_init failed: %s\n", gnutls_strerror (rc)); */ 148 | /* read_dh_params ("dh_param.pem"); */ 149 | 150 | /* rc = gnutls_certificate_set_x509_trust_file */ 151 | /* (certcred, "ca.pem", GNUTLS_X509_FMT_PEM); */ 152 | /* if (rc) */ 153 | /* log_error ("gnutls_certificate_set_x509_trust_file failed: %s\n", */ 154 | /* gnutls_strerror (rc)); */ 155 | 156 | /* gnutls_certificate_set_dh_params (certcred, dh_params); */ 157 | 158 | gnutls_global_set_log_function (my_gnutls_log); 159 | /* gnutls_global_set_log_level (2); */ 160 | 161 | #endif /*HTTP_USE_GNUTLS*/ 162 | 163 | rc = http_parse_uri (&uri, *argv, 1); 164 | if (rc) 165 | { 166 | log_error ("'%s': %s\n", *argv, gpg_strerror (rc)); 167 | return 1; 168 | } 169 | 170 | printf ("Scheme: %s\n", uri->scheme); 171 | if (uri->opaque) 172 | printf ("Value : %s\n", uri->path); 173 | else 174 | { 175 | printf ("Auth : %s\n", uri->auth? uri->auth:"[none]"); 176 | printf ("Host : %s\n", uri->host); 177 | printf ("Port : %u\n", uri->port); 178 | printf ("Path : %s\n", uri->path); 179 | for (r = uri->params; r; r = r->next) 180 | { 181 | printf ("Params: %s", r->name); 182 | if (!r->no_value) 183 | { 184 | printf ("=%s", r->value); 185 | if (strlen (r->value) != r->valuelen) 186 | printf (" [real length=%d]", (int) r->valuelen); 187 | } 188 | putchar ('\n'); 189 | } 190 | for (r = uri->query; r; r = r->next) 191 | { 192 | printf ("Query : %s", r->name); 193 | if (!r->no_value) 194 | { 195 | printf ("=%s", r->value); 196 | if (strlen (r->value) != r->valuelen) 197 | printf (" [real length=%d]", (int) r->valuelen); 198 | } 199 | putchar ('\n'); 200 | } 201 | } 202 | http_release_parsed_uri (uri); 203 | uri = NULL; 204 | 205 | rc = http_open_document (&hd, *argv, NULL, 0, NULL, session, NULL, NULL); 206 | if (rc) 207 | { 208 | log_error ("can't get '%s': %s\n", *argv, gpg_strerror (rc)); 209 | return 1; 210 | } 211 | log_info ("open_http_document succeeded; status=%u\n", 212 | http_get_status_code (hd)); 213 | 214 | { 215 | const char **names; 216 | int i; 217 | 218 | names = http_get_header_names (hd); 219 | if (!names) 220 | log_fatal ("http_get_header_names failed: %s\n", 221 | gpg_strerror (gpg_error_from_syserror ())); 222 | for (i = 0; names[i]; i++) 223 | printf ("HDR: %s: %s\n", names[i], http_get_header (hd, names[i])); 224 | xfree (names); 225 | } 226 | 227 | switch (http_get_status_code (hd)) 228 | { 229 | case 200: 230 | case 400: 231 | case 401: 232 | case 403: 233 | case 404: 234 | while ((c = es_getc (http_get_read_ptr (hd))) != EOF) 235 | putchar (c); 236 | break; 237 | case 301: 238 | case 302: 239 | printf ("Redirected to '%s'\n", http_get_header (hd, "Location")); 240 | break; 241 | } 242 | http_close (hd, 0); 243 | 244 | http_session_release (session); 245 | #ifdef HTTP_USE_GNUTLS 246 | gnutls_global_deinit (); 247 | #endif /*HTTP_USE_GNUTLS*/ 248 | 249 | return 0; 250 | } 251 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* util.h - Utility definitions for payproc 2 | * Copyright (C) 2014, 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #ifndef UTIL_H 21 | #define UTIL_H 22 | 23 | #include 24 | 25 | 26 | #ifndef DIM 27 | # define DIM(v) (sizeof(v)/sizeof((v)[0])) 28 | #endif 29 | #ifndef DIMof 30 | # define DIMof(type,member) DIM(((type *)0)->member) 31 | #endif 32 | 33 | #undef JNLIB_GCC_HAVE_PUSH_PRAGMA 34 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 5 ) 35 | # define JNLIB_GCC_M_FUNCTION 1 36 | # define JNLIB_GCC_A_NR __attribute__ ((noreturn)) 37 | # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4 ) 38 | # define JNLIB_GCC_HAVE_PUSH_PRAGMA 1 39 | # define JNLIB_GCC_A_PRINTF( f, a ) \ 40 | __attribute__ ((format (__gnu_printf__,f,a))) 41 | # define JNLIB_GCC_A_NR_PRINTF( f, a ) \ 42 | __attribute__ ((noreturn, format (__gnu_printf__,f,a))) 43 | # else 44 | # define JNLIB_GCC_A_PRINTF( f, a ) __attribute__ ((format (printf,f,a))) 45 | # define JNLIB_GCC_A_NR_PRINTF( f, a ) \ 46 | __attribute__ ((noreturn, format (printf,f,a))) 47 | # endif 48 | #else 49 | # define JNLIB_GCC_A_NR 50 | # define JNLIB_GCC_A_PRINTF( f, a ) 51 | # define JNLIB_GCC_A_NR_PRINTF( f, a ) 52 | #endif 53 | 54 | #if __GNUC__ >= 4 55 | # define JNLIB_GCC_A_SENTINEL(a) __attribute__ ((sentinel(a))) 56 | #else 57 | # define JNLIB_GCC_A_SENTINEL(a) 58 | #endif 59 | 60 | 61 | #define xtrymalloc(a) malloc ((a)) 62 | #define xtrycalloc(a,b) calloc ((a),(b)) 63 | #define xtryrealloc(a,b) realloc ((a),(b)) 64 | #define xtrystrdup(a) strdup ((a)) 65 | #define xfree(a) free ((a)) 66 | 67 | /* To avoid that a compiler optimizes certain memset calls away, these 68 | macros may be used instead. */ 69 | #define wipememory2(_ptr,_set,_len) do { \ 70 | volatile char *_vptr=(volatile char *)(_ptr); \ 71 | size_t _vlen=(_len); \ 72 | while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \ 73 | } while(0) 74 | #define wipememory(_ptr,_len) wipememory2(_ptr,0,_len) 75 | 76 | /* Macros to replace ctype ones to avoid locale problems. */ 77 | #define spacep(p) (*(p) == ' ' || *(p) == '\t') 78 | #define digitp(p) (*(p) >= '0' && *(p) <= '9') 79 | #define hexdigitp(a) (digitp (a) \ 80 | || (*(a) >= 'A' && *(a) <= 'F') \ 81 | || (*(a) >= 'a' && *(a) <= 'f')) 82 | /* Note this isn't identical to a C locale isspace() without \f and 83 | \v, but works for the purposes used here. */ 84 | #define ascii_isspace(a) ((a)==' ' || (a)=='\n' || (a)=='\r' || (a)=='\t') 85 | 86 | /* The atoi macros assume that the buffer has only valid digits. */ 87 | #define atoi_1(p) (*(p) - '0' ) 88 | #define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) 89 | #define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2)) 90 | #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ 91 | *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) 92 | #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) 93 | #define xtoi_4(p) ((xtoi_2(p) * 256) + xtoi_2((p)+2)) 94 | 95 | 96 | /* The default error source of the application. This is different 97 | from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the 98 | source file and thus is usable in code shared by applications. */ 99 | extern gpg_err_source_t default_errsource; 100 | 101 | /* The size of a buffer suitable to hold a string with an amount. */ 102 | #define AMOUNTBUF_SIZE 48 103 | 104 | /* The size of our standard timestamp ("YYYYMMDDTHHMMSS"). */ 105 | #define TIMESTAMP_SIZE 16 106 | 107 | 108 | /*-- util.c --*/ 109 | void severe_error (void); 110 | void *xmalloc (size_t n); 111 | void *xrealloc (void *a, size_t n); 112 | void *xcalloc (size_t n, size_t m); 113 | char *xstrdup (const char *string); 114 | 115 | /* Concatenate the string S1 with all the following strings up to a 116 | NULL. Returns a malloced buffer with the new string or NULL on a 117 | malloc error or if too many arguments are given. */ 118 | char *strconcat (const char *s1, ...) JNLIB_GCC_A_SENTINEL(0); 119 | 120 | char *ascii_strupr (char *s); 121 | char *ascii_strlwr (char *s); 122 | 123 | char *has_leading_keyword (const char *string, const char *keyword); 124 | const char *memstr (const void *buffer, size_t buflen, const char *sub); 125 | const char *memistr (const void *buffer, size_t buflen, const char *sub); 126 | int memicmp (const char *a, const char *b, size_t n); 127 | char *trim_spaces (char *str); 128 | char **strtokenize (const char *string, const char *delim); 129 | 130 | 131 | /* Object to store a key value pair. */ 132 | struct keyvalue_s 133 | { 134 | struct keyvalue_s *next; 135 | char *value; /* The value of the item (malloced). */ 136 | char name[1]; /* The name of the item (canonicalized). */ 137 | }; 138 | 139 | typedef struct keyvalue_s *keyvalue_t; 140 | 141 | gpg_error_t keyvalue_append_with_nl (keyvalue_t kv, const char *value); 142 | void keyvalue_remove_nl (keyvalue_t kv); 143 | gpg_error_t keyvalue_put (keyvalue_t *list, const char *key, 144 | const char *value); 145 | gpg_error_t keyvalue_put_idx (keyvalue_t *list, const char *key, int idx, 146 | const char *value); 147 | gpg_error_t keyvalue_del (keyvalue_t list, const char *key); 148 | gpg_error_t keyvalue_putf (keyvalue_t *list, const char *key, 149 | const char *format, ...) JNLIB_GCC_A_PRINTF (3,4); 150 | gpg_error_t keyvalue_put_meta (keyvalue_t *list, const char *string); 151 | void keyvalue_release (keyvalue_t kv); 152 | keyvalue_t keyvalue_find (keyvalue_t list, const char *key); 153 | const char *keyvalue_get (keyvalue_t list, const char *key); 154 | char *keyvalue_snatch (keyvalue_t list, const char *key); 155 | const char *keyvalue_get_string (keyvalue_t list, const char *key); 156 | int keyvalue_get_int (keyvalue_t list, const char *key); 157 | unsigned int keyvalue_get_uint (keyvalue_t list, const char *key); 158 | 159 | gpg_error_t parse_www_form_urlencoded (keyvalue_t *r_dict, const char *data); 160 | 161 | char *base64_encode (const void *data, size_t datalen); 162 | gpg_error_t base64_decode (const char *string, void **r_data,size_t *r_datalen); 163 | 164 | int zb32_index (int c); 165 | char *zb32_encode (const void *data, unsigned int databits); 166 | 167 | char *get_current_time (char *timestamp); 168 | char *get_full_isotime (int offset); 169 | 170 | unsigned int convert_amount (const char *string, int decdigits); 171 | char *reconvert_amount (int cents, int decdigits); 172 | 173 | void write_escaped (const char *string, estream_t fp); 174 | void write_meta_field (keyvalue_t dict, estream_t fp); 175 | char *meta_field_to_string (keyvalue_t dict); 176 | 177 | /*-- percent.c --*/ 178 | char *percent_plus_escape (const char *string); 179 | char *percent_plus_unescape (const char *string, int nulrepl); 180 | char *percent_unescape (const char *string, int nulrepl); 181 | size_t percent_plus_unescape_inplace (char *string, int nulrepl); 182 | size_t percent_unescape_inplace (char *string, int nulrepl); 183 | 184 | 185 | #endif /*UTIL_H*/ 186 | -------------------------------------------------------------------------------- /src/cJSON.h: -------------------------------------------------------------------------------- 1 | /* cJSON.h 2 | * Copyright (c) 2009 Dave Gamble 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | * 22 | * SPDX-License-Identifier: MIT 23 | */ 24 | 25 | #ifndef cJSON__h 26 | #define cJSON__h 27 | 28 | #ifdef __cplusplus 29 | extern "C" 30 | { 31 | #if 0 /*(to make Emacs auto-indent happy)*/ 32 | } 33 | #endif 34 | #endif 35 | 36 | /* cJSON Types: */ 37 | #define cJSON_False 0 38 | #define cJSON_True 1 39 | #define cJSON_NULL 2 40 | #define cJSON_Number 3 41 | #define cJSON_String 4 42 | #define cJSON_Array 5 43 | #define cJSON_Object 6 44 | 45 | #define cJSON_IsReference 256 46 | 47 | /* The cJSON structure: */ 48 | typedef struct cJSON 49 | { 50 | /* next/prev allow you to walk array/object chains. Alternatively, 51 | use GetArraySize/GetArrayItem/GetObjectItem */ 52 | struct cJSON *next, *prev; 53 | 54 | /* An array or object item will have a child pointer pointing to a 55 | chain of the items in the array/object. */ 56 | struct cJSON *child; 57 | 58 | int type; /* The type of the item, as above. */ 59 | 60 | char *valuestring; /* The item's string, if type==cJSON_String */ 61 | int valueint; /* The item's number, if type==cJSON_Number */ 62 | double valuedouble; /* The item's number, if type==cJSON_Number */ 63 | 64 | /* The item's name string, if this item is the child of, or is in 65 | the list of subitems of an object. */ 66 | char *string; 67 | } cJSON; 68 | 69 | typedef struct cJSON *cjson_t; 70 | 71 | /* Macros to test the type of an object. */ 72 | #define cjson_is_boolean(a) (!((a)->type & ~1)) 73 | #define cjson_is_false(a) ((a)->type == cJSON_False) 74 | #define cjson_is_true(a) ((a)->type == cJSON_True) 75 | #define cjson_is_null(a) ((a)->type == cJSON_NULL) 76 | #define cjson_is_number(a) ((a)->type == cJSON_Number) 77 | #define cjson_is_string(a) ((a)->type == cJSON_String) 78 | #define cjson_is_array(a) ((a)->type == cJSON_Array) 79 | #define cjson_is_object(a) ((a)->type == cJSON_Object) 80 | 81 | /* Supply a block of JSON, and this returns a cJSON object you can 82 | interrogate. Call cJSON_Delete when finished. */ 83 | extern cJSON *cJSON_Parse(const char *value, size_t *r_erroff); 84 | 85 | /* Render a cJSON entity to text for transfer/storage. Free the char* 86 | when finished. */ 87 | extern char *cJSON_Print(cJSON *item); 88 | 89 | /* Render a cJSON entity to text for transfer/storage without any 90 | formatting. Free the char* when finished. */ 91 | extern char *cJSON_PrintUnformatted(cJSON *item); 92 | 93 | /* Delete a cJSON entity and all subentities. */ 94 | extern void cJSON_Delete(cJSON *c); 95 | 96 | /* Returns the number of items in an array (or object). */ 97 | extern int cJSON_GetArraySize(cJSON *array); 98 | 99 | /* Retrieve item number "item" from array "array". Returns NULL if 100 | unsuccessful. */ 101 | extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); 102 | 103 | /* Get item "string" from object. Case insensitive. */ 104 | extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); 105 | 106 | /* These calls create a cJSON item of the appropriate type. */ 107 | extern cJSON *cJSON_CreateNull(void); 108 | extern cJSON *cJSON_CreateTrue(void); 109 | extern cJSON *cJSON_CreateFalse(void); 110 | extern cJSON *cJSON_CreateBool(int b); 111 | extern cJSON *cJSON_CreateNumber(double num); 112 | extern cJSON *cJSON_CreateString(const char *string); 113 | extern cJSON *cJSON_CreateArray(void); 114 | extern cJSON *cJSON_CreateObject(void); 115 | 116 | /* These utilities create an Array of count items. */ 117 | extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); 118 | extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); 119 | extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); 120 | extern cJSON *cJSON_CreateStringArray(const char **strings,int count); 121 | 122 | /* Append item to the specified array/object. */ 123 | extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); 124 | extern void cJSON_AddItemToObject(cJSON *object, 125 | const char *string, cJSON *item); 126 | 127 | /* Append reference to item to the specified array/object. Use this 128 | when you want to add an existing cJSON to a new cJSON, but don't 129 | want to corrupt your existing cJSON. */ 130 | extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); 131 | extern void cJSON_AddItemReferenceToObject(cJSON *object, 132 | const char *string,cJSON *item); 133 | 134 | /* Remove/Detatch items from Arrays/Objects. */ 135 | extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); 136 | extern void cJSON_DeleteItemFromArray(cJSON *array,int which); 137 | extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); 138 | extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); 139 | 140 | /* Update array items. */ 141 | extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); 142 | extern void cJSON_ReplaceItemInObject(cJSON *object, 143 | const char *string, cJSON *newitem); 144 | 145 | /* Duplicate a cJSON item */ 146 | extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); 147 | 148 | /* Duplicate will create a new, identical cJSON item to the one you 149 | pass, in new memory that will need to be released. With recurse!=0, 150 | it will duplicate any children connected to the item. The 151 | item->next and ->prev pointers are always zero on return from 152 | Duplicate. */ 153 | 154 | /* ParseWithOpts allows you to require (and check) that the JSON is 155 | null terminated, and to retrieve the pointer to the final byte 156 | parsed. */ 157 | extern cJSON *cJSON_ParseWithOpts(const char *value, 158 | const char **return_parse_end, 159 | int require_null_terminated, 160 | size_t *r_erroff); 161 | 162 | extern void cJSON_Minify(char *json); 163 | 164 | /* Macros for creating things quickly. */ 165 | #define cJSON_AddNullToObject(object,name) \ 166 | cJSON_AddItemToObject(object, name, cJSON_CreateNull()) 167 | #define cJSON_AddTrueToObject(object,name) \ 168 | cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) 169 | #define cJSON_AddFalseToObject(object,name) \ 170 | cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) 171 | #define cJSON_AddBoolToObject(object,name,b) \ 172 | cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) 173 | #define cJSON_AddNumberToObject(object,name,n) \ 174 | cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) 175 | #define cJSON_AddStringToObject(object,name,s) \ 176 | cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) 177 | 178 | /* When assigning an integer value, it needs to be propagated to 179 | valuedouble too. */ 180 | #define cJSON_SetIntValue(object,val) \ 181 | ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | #endif /* cJSON__h */ 188 | -------------------------------------------------------------------------------- /src/mbox-util.c: -------------------------------------------------------------------------------- 1 | /* mbox-util.c - Mail address helper functions 2 | * Copyright (C) 1998-2010 Free Software Foundation, Inc. 3 | * Copyright (C) 1998-2015 Werner Koch 4 | * 5 | * This file is part of GnuPG. 6 | * 7 | * This file is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as 9 | * published by the Free Software Foundation; either version 2.1 of 10 | * the License, or (at your option) any later version. 11 | * 12 | * This file is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with this program; if not, see . 19 | */ 20 | 21 | /* NB: This code has been taken from GnuPG. Please keep it in sync 22 | * with GnuPG. */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "util.h" 32 | #include "mbox-util.h" 33 | 34 | 35 | /* static int */ 36 | /* string_count_chr (const char *string, int c) */ 37 | /* { */ 38 | /* int count; */ 39 | 40 | /* for (count=0; *string; string++ ) */ 41 | /* if ( *string == c ) */ 42 | /* count++; */ 43 | /* return count; */ 44 | /* } */ 45 | 46 | static int 47 | mem_count_chr (const void *buffer, int c, size_t length) 48 | { 49 | const char *s = buffer; 50 | int count; 51 | 52 | for (count=0; length; length--, s++) 53 | if (*s == c) 54 | count++; 55 | return count; 56 | } 57 | 58 | 59 | /* This is a case-sensitive version of our memistr. I wonder why no 60 | standard function memstr exists but I better do not use the name 61 | memstr to avoid future conflicts. */ 62 | static const char * 63 | my_memstr (const void *buffer, size_t buflen, const char *sub) 64 | { 65 | const unsigned char *buf = buffer; 66 | const unsigned char *t = (const unsigned char *)buf; 67 | const unsigned char *s = (const unsigned char *)sub; 68 | size_t n = buflen; 69 | 70 | for ( ; n ; t++, n-- ) 71 | { 72 | if (*t == *s) 73 | { 74 | for (buf = t++, buflen = n--, s++; n && *t ==*s; t++, s++, n--) 75 | ; 76 | if (!*s) 77 | return (const char*)buf; 78 | t = (const unsigned char *)buf; 79 | s = (const unsigned char *)sub ; 80 | n = buflen; 81 | } 82 | } 83 | return NULL; 84 | } 85 | 86 | 87 | 88 | /* static int */ 89 | /* string_has_ctrl_or_space (const char *string) */ 90 | /* { */ 91 | /* for (; *string; string++ ) */ 92 | /* if (!(*string & 0x80) && *string <= 0x20) */ 93 | /* return 1; */ 94 | /* return 0; */ 95 | /* } */ 96 | 97 | 98 | /* /\* Return true if STRING has two consecutive '.' after an '@' */ 99 | /* sign. *\/ */ 100 | /* static int */ 101 | /* has_dotdot_after_at (const char *string) */ 102 | /* { */ 103 | /* string = strchr (string, '@'); */ 104 | /* if (!string) */ 105 | /* return 0; /\* No at-sign. *\/ */ 106 | /* string++; */ 107 | /* return !!strstr (string, ".."); */ 108 | /* } */ 109 | 110 | 111 | /* Check whether BUFFER has characters not valid in an RFC-822 112 | address. LENGTH gives the length of BUFFER. 113 | 114 | To cope with OpenPGP we ignore non-ascii characters so that for 115 | example umlauts are legal in an email address. An OpenPGP user ID 116 | must be utf-8 encoded but there is no strict requirement for 117 | RFC-822. Thus to avoid IDNA encoding we put the address verbatim 118 | as utf-8 into the user ID under the assumption that mail programs 119 | handle IDNA at a lower level and take OpenPGP user IDs as utf-8. 120 | Note that we can't do an utf-8 encoding checking here because in 121 | keygen.c this function is called with the native encoding and 122 | native to utf-8 encoding is only done later. */ 123 | int 124 | has_invalid_email_chars (const void *buffer, size_t length) 125 | { 126 | const unsigned char *s = buffer; 127 | int at_seen=0; 128 | const char *valid_chars= 129 | "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 130 | 131 | for ( ; length && *s; length--, s++ ) 132 | { 133 | if ((*s & 0x80)) 134 | continue; /* We only care about ASCII. */ 135 | if (*s == '@') 136 | at_seen=1; 137 | else if (!at_seen && !(strchr (valid_chars, *s) 138 | || strchr ("!#$%&'*+/=?^`{|}~", *s))) 139 | return 1; 140 | else if (at_seen && !strchr (valid_chars, *s)) 141 | return 1; 142 | } 143 | return 0; 144 | } 145 | 146 | 147 | /* Same as is_valid_mailbox (see below) but operates on non-nul 148 | terminated buffer. */ 149 | int 150 | is_valid_mailbox_mem (const void *name_arg, size_t namelen) 151 | { 152 | const char *name = name_arg; 153 | 154 | return !( !name 155 | || !namelen 156 | || has_invalid_email_chars (name, namelen) 157 | || mem_count_chr (name, '@', namelen) != 1 158 | || *name == '@' 159 | || name[namelen-1] == '@' 160 | || name[namelen-1] == '.' 161 | || my_memstr (name, namelen, "..")); 162 | } 163 | 164 | 165 | /* Check whether NAME represents a valid mailbox according to 166 | RFC822. Returns true if so. */ 167 | int 168 | is_valid_mailbox (const char *name) 169 | { 170 | return name? is_valid_mailbox_mem (name, strlen (name)) : 0; 171 | } 172 | 173 | 174 | /* /\* Return the mailbox (local-part@domain) form a standard user id. */ 175 | /* All plain ASCII characters in the result are converted to */ 176 | /* lowercase. Caller must free the result. Returns NULL if no valid */ 177 | /* mailbox was found (or we are out of memory). *\/ */ 178 | /* char * */ 179 | /* mailbox_from_userid (const char *userid) */ 180 | /* { */ 181 | /* const char *s, *s_end; */ 182 | /* size_t len; */ 183 | /* char *result = NULL; */ 184 | 185 | /* s = strchr (userid, '<'); */ 186 | /* if (s) */ 187 | /* { */ 188 | /* /\* Seems to be a standard user id. *\/ */ 189 | /* s++; */ 190 | /* s_end = strchr (s, '>'); */ 191 | /* if (s_end && s_end > s) */ 192 | /* { */ 193 | /* len = s_end - s; */ 194 | /* result = xtrymalloc (len + 1); */ 195 | /* if (!result) */ 196 | /* return NULL; /\* Ooops - out of core. *\/ */ 197 | /* strncpy (result, s, len); */ 198 | /* result[len] = 0; */ 199 | /* /\* Apply some basic checks on the address. We do not use */ 200 | /* is_valid_mailbox because those checks are too strict. *\/ */ 201 | /* if (string_count_chr (result, '@') != 1 /\* Need exactly one '@. *\/ */ 202 | /* || *result == '@' /\* local-part missing. *\/ */ 203 | /* || result[len-1] == '@' /\* domain missing. *\/ */ 204 | /* || result[len-1] == '.' /\* ends with a dot. *\/ */ 205 | /* || string_has_ctrl_or_space (result) */ 206 | /* || has_dotdot_after_at (result)) */ 207 | /* { */ 208 | /* xfree (result); */ 209 | /* result = NULL; */ 210 | /* errno = EINVAL; */ 211 | /* } */ 212 | /* } */ 213 | /* else */ 214 | /* errno = EINVAL; */ 215 | /* } */ 216 | /* else if (is_valid_mailbox (userid)) */ 217 | /* { */ 218 | /* /\* The entire user id is a mailbox. Return that one. Note that */ 219 | /* this fallback method has some restrictions on the valid */ 220 | /* syntax of the mailbox. However, those who want weird */ 221 | /* addresses should know about it and use the regular <...> */ 222 | /* syntax. *\/ */ 223 | /* result = xtrystrdup (userid); */ 224 | /* } */ 225 | /* else */ 226 | /* errno = EINVAL; */ 227 | 228 | /* return result? ascii_strlwr (result): NULL; */ 229 | /* } */ 230 | 231 | 232 | /* /\* Check whether UID is a valid standard user id of the form */ 233 | /* "Heinrich Heine " */ 234 | /* and return true if this is the case. *\/ */ 235 | /* int */ 236 | /* is_valid_user_id (const char *uid) */ 237 | /* { */ 238 | /* if (!uid || !*uid) */ 239 | /* return 0; */ 240 | 241 | /* return 1; */ 242 | /* } */ 243 | -------------------------------------------------------------------------------- /src/argparse.h: -------------------------------------------------------------------------------- 1 | /* argparse.h - Argument parser for option handling. 2 | * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc. 3 | * 4 | * This file is part of JNLIB, which is a subsystem of GnuPG. 5 | * 6 | * JNLIB is free software; you can redistribute it and/or modify it 7 | * under the terms of either 8 | * 9 | * - the GNU Lesser General Public License as published by the Free 10 | * Software Foundation; either version 3 of the License, or (at 11 | * your option) any later version. 12 | * 13 | * or 14 | * 15 | * - the GNU General Public License as published by the Free 16 | * Software Foundation; either version 2 of the License, or (at 17 | * your option) any later version. 18 | * 19 | * or both in parallel, as here. 20 | * 21 | * JNLIB is distributed in the hope that it will be useful, but 22 | * WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | * General Public License for more details. 25 | * 26 | * You should have received a copies of the GNU General Public License 27 | * and the GNU Lesser General Public License along with this program; 28 | * if not, see . 29 | */ 30 | 31 | #ifndef LIBJNLIB_ARGPARSE_H 32 | #define LIBJNLIB_ARGPARSE_H 33 | 34 | #include 35 | 36 | typedef struct 37 | { 38 | int *argc; /* Pointer to ARGC (value subject to change). */ 39 | char ***argv; /* Pointer to ARGV (value subject to change). */ 40 | unsigned int flags; /* Global flags. May be set prior to calling the 41 | parser. The parser may change the value. */ 42 | int err; /* Print error description for last option. 43 | Either 0, ARGPARSE_PRINT_WARNING or 44 | ARGPARSE_PRINT_ERROR. */ 45 | 46 | int r_opt; /* Returns option code. */ 47 | int r_type; /* Returns type of option value. */ 48 | union { 49 | int ret_int; 50 | long ret_long; 51 | unsigned long ret_ulong; 52 | char *ret_str; 53 | } r; /* Return values */ 54 | 55 | struct { 56 | int idx; 57 | int inarg; 58 | int stopped; 59 | const char *last; 60 | void *aliases; 61 | const void *cur_alias; 62 | void *iio_list; 63 | } internal; /* Private - do not change. */ 64 | } ARGPARSE_ARGS; 65 | 66 | typedef struct 67 | { 68 | int short_opt; 69 | const char *long_opt; 70 | unsigned int flags; 71 | const char *description; /* Optional option description. */ 72 | } ARGPARSE_OPTS; 73 | 74 | 75 | /* Global flags (ARGPARSE_ARGS). */ 76 | #define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */ 77 | #define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return 78 | remaining args with R_OPT set to -1. */ 79 | #define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */ 80 | #define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */ 81 | #define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */ 82 | #define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */ 83 | #define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */ 84 | 85 | #define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */ 86 | 87 | /* Flags for each option (ARGPARSE_OPTS). The type code may be 88 | ORed with the OPT flags. */ 89 | #define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */ 90 | #define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */ 91 | #define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */ 92 | #define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */ 93 | #define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */ 94 | #define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */ 95 | #define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */ 96 | #define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */ 97 | #define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */ 98 | 99 | #define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */ 100 | 101 | /* A set of macros to make option definitions easier to read. */ 102 | #define ARGPARSE_x(s,l,t,f,d) \ 103 | { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) } 104 | 105 | #define ARGPARSE_s(s,l,t,d) \ 106 | { (s), (l), ARGPARSE_TYPE_ ## t, (d) } 107 | #define ARGPARSE_s_n(s,l,d) \ 108 | { (s), (l), ARGPARSE_TYPE_NONE, (d) } 109 | #define ARGPARSE_s_i(s,l,d) \ 110 | { (s), (l), ARGPARSE_TYPE_INT, (d) } 111 | #define ARGPARSE_s_s(s,l,d) \ 112 | { (s), (l), ARGPARSE_TYPE_STRING, (d) } 113 | #define ARGPARSE_s_l(s,l,d) \ 114 | { (s), (l), ARGPARSE_TYPE_LONG, (d) } 115 | #define ARGPARSE_s_u(s,l,d) \ 116 | { (s), (l), ARGPARSE_TYPE_ULONG, (d) } 117 | 118 | #define ARGPARSE_o(s,l,t,d) \ 119 | { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) } 120 | #define ARGPARSE_o_n(s,l,d) \ 121 | { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) } 122 | #define ARGPARSE_o_i(s,l,d) \ 123 | { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) } 124 | #define ARGPARSE_o_s(s,l,d) \ 125 | { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) } 126 | #define ARGPARSE_o_l(s,l,d) \ 127 | { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) } 128 | #define ARGPARSE_o_u(s,l,d) \ 129 | { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) } 130 | 131 | #define ARGPARSE_p(s,l,t,d) \ 132 | { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) } 133 | #define ARGPARSE_p_n(s,l,d) \ 134 | { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) } 135 | #define ARGPARSE_p_i(s,l,d) \ 136 | { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) } 137 | #define ARGPARSE_p_s(s,l,d) \ 138 | { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) } 139 | #define ARGPARSE_p_l(s,l,d) \ 140 | { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) } 141 | #define ARGPARSE_p_u(s,l,d) \ 142 | { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) } 143 | 144 | #define ARGPARSE_op(s,l,t,d) \ 145 | { (s), (l), (ARGPARSE_TYPE_ ## t \ 146 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 147 | #define ARGPARSE_op_n(s,l,d) \ 148 | { (s), (l), (ARGPARSE_TYPE_NONE \ 149 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 150 | #define ARGPARSE_op_i(s,l,d) \ 151 | { (s), (l), (ARGPARSE_TYPE_INT \ 152 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 153 | #define ARGPARSE_op_s(s,l,d) \ 154 | { (s), (l), (ARGPARSE_TYPE_STRING \ 155 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 156 | #define ARGPARSE_op_l(s,l,d) \ 157 | { (s), (l), (ARGPARSE_TYPE_LONG \ 158 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 159 | #define ARGPARSE_op_u(s,l,d) \ 160 | { (s), (l), (ARGPARSE_TYPE_ULONG \ 161 | | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) } 162 | 163 | #define ARGPARSE_c(s,l,d) \ 164 | { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) } 165 | 166 | #define ARGPARSE_ignore(s,l) \ 167 | { (s), (l), (ARGPARSE_OPT_IGNORE), "@" } 168 | 169 | #define ARGPARSE_group(s,d) \ 170 | { (s), NULL, 0, (d) } 171 | 172 | #define ARGPARSE_end() { 0, NULL, 0, NULL } 173 | 174 | 175 | /* Other constants. */ 176 | #define ARGPARSE_PRINT_WARNING 1 177 | #define ARGPARSE_PRINT_ERROR 2 178 | 179 | 180 | /* Error values. */ 181 | #define ARGPARSE_IS_ARG (-1) 182 | #define ARGPARSE_INVALID_OPTION (-2) 183 | #define ARGPARSE_MISSING_ARG (-3) 184 | #define ARGPARSE_KEYWORD_TOO_LONG (-4) 185 | #define ARGPARSE_READ_ERROR (-5) 186 | #define ARGPARSE_UNEXPECTED_ARG (-6) 187 | #define ARGPARSE_INVALID_COMMAND (-7) 188 | #define ARGPARSE_AMBIGUOUS_OPTION (-8) 189 | #define ARGPARSE_AMBIGUOUS_COMMAND (-9) 190 | #define ARGPARSE_INVALID_ALIAS (-10) 191 | #define ARGPARSE_OUT_OF_CORE (-11) 192 | 193 | 194 | int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); 195 | int optfile_parse( FILE *fp, const char *filename, unsigned *lineno, 196 | ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts); 197 | void usage( int level ); 198 | const char *strusage( int level ); 199 | void set_strusage( const char *(*f)( int ) ); 200 | void argparse_register_outfnc (int (*fnc)(int, const char *)); 201 | 202 | #endif /*LIBJNLIB_ARGPARSE_H*/ 203 | -------------------------------------------------------------------------------- /src/currency.c: -------------------------------------------------------------------------------- 1 | /* currency.c - Currency management functions 2 | * Copyright (C) 2014 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "payprocd.h" 28 | #include "util.h" 29 | #include "logging.h" 30 | #include "journal.h" 31 | #include "currency.h" 32 | 33 | /* The file with the exchange rates. This is expected to be created 34 | by a cron job and the geteuroxref script. */ 35 | static const char euroxref_fname[] = "/var/lib/payproc/euroxref.dat"; 36 | 37 | 38 | /* The list of supported currencies */ 39 | static struct 40 | { 41 | const char *name; 42 | unsigned char decdigits; 43 | const char *desc; 44 | double rate; /* Exchange rate to Euro. */ 45 | } currency_table[] = { 46 | { "EUR", 2, "Euro", 1.0 }, /* Must be the first entry! */ 47 | { "USD", 2, "US Dollar" }, 48 | { "GBP", 2, "British Pound" }, 49 | { "JPY", 0, "Yen" } 50 | }; 51 | 52 | 53 | void 54 | read_exchange_rates (void) 55 | { 56 | gpg_error_t err = 0; 57 | estream_t fp; 58 | int lnr = 0; 59 | int n, c, idx; 60 | char line[256]; 61 | char *p, *pend; 62 | double rate; 63 | 64 | fp = es_fopen (euroxref_fname, "r"); 65 | if (!fp) 66 | { 67 | err = gpg_error_from_syserror (); 68 | log_error ("error opening '%s': %s\n", 69 | euroxref_fname, gpg_strerror (err)); 70 | return; 71 | } 72 | 73 | while (es_fgets (line, DIM(line)-1, fp)) 74 | { 75 | lnr++; 76 | 77 | n = strlen (line); 78 | if (!n || line[n-1] != '\n') 79 | { 80 | /* Eat until end of line. */ 81 | while ((c=es_getc (fp)) != EOF && c != '\n') 82 | ; 83 | err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG 84 | : GPG_ERR_INCOMPLETE_LINE); 85 | log_error ("error reading '%s', line %d: %s\n", 86 | euroxref_fname, lnr, gpg_strerror (err)); 87 | continue; 88 | } 89 | line[--n] = 0; /* Chop the LF. */ 90 | if (n && line[n-1] == '\r') 91 | line[--n] = 0; /* Chop an optional CR. */ 92 | 93 | /* Allow leading spaces and skip empty and comment lines. */ 94 | for (p=line; spacep (p); p++) 95 | ; 96 | if (!*p || *p == '#') 97 | continue; 98 | 99 | /* Parse the currency name. */ 100 | pend = strchr (p, '='); 101 | if (!pend) 102 | { 103 | log_error ("error parsing '%s', line %d: %s\n", 104 | euroxref_fname, lnr, "missing '='"); 105 | continue; 106 | } 107 | *pend++ = 0; 108 | trim_spaces (p); 109 | if (!*p) 110 | { 111 | log_error ("error parsing '%s', line %d: %s\n", 112 | euroxref_fname, lnr, "currency name missing"); 113 | continue; 114 | } 115 | 116 | /* Note that we start at 1 to skip the first entry which is 117 | EUR. */ 118 | for (idx=1; idx < DIM(currency_table); idx++) 119 | if (!strcasecmp (currency_table[idx].name, p)) 120 | break; 121 | if (!(idx < DIM(currency_table))) 122 | continue; /* Currency not supported. */ 123 | 124 | /* Parse the rate. */ 125 | p = pend; 126 | errno = 0; 127 | rate = strtod (p, &pend); 128 | if ((!rate && p == pend) || errno || rate <= 0.0 || rate > 10000.0) 129 | { 130 | log_error ("error parsing '%s', line %d: %s\n", 131 | euroxref_fname, lnr, "invalid exchange rate"); 132 | continue; 133 | } 134 | p = pend; 135 | trim_spaces (p); 136 | if (*p) 137 | { 138 | log_error ("error parsing '%s', line %d: %s\n", 139 | euroxref_fname, lnr, "garbage after exchange rate"); 140 | continue; 141 | } 142 | 143 | /* Update the tbale. */ 144 | if (currency_table[idx].rate != rate) 145 | { 146 | if (!currency_table[idx].rate) 147 | log_info ("setting exchange rate for %s to %.4f\n", 148 | currency_table[idx].name, rate); 149 | else 150 | log_info ("changing exchange rate for %s from %.4f to %.4f\n", 151 | currency_table[idx].name, currency_table[idx].rate, rate); 152 | 153 | currency_table[idx].rate = rate; 154 | jrnl_store_exchange_rate_record (currency_table[idx].name, rate); 155 | } 156 | } 157 | 158 | es_fclose (fp); 159 | } 160 | 161 | 162 | /* Return the exchange rate for CURRENCY or 0.0 is not known. */ 163 | static double 164 | get_exchange_rate (const char *currency) 165 | { 166 | int i; 167 | 168 | for (i=0; i < DIM(currency_table); i++) 169 | if (!strcasecmp (currency, currency_table[i].name)) 170 | return currency_table[i].rate; 171 | return 0.0; 172 | } 173 | 174 | 175 | /* Check that the currency described by STRING is valid. Returns true 176 | if so. The number of of digits after the decimal point for that 177 | currency is stored at R_DECDIGITS. */ 178 | int 179 | valid_currency_p (const char *string, int *r_decdigits) 180 | { 181 | int i; 182 | 183 | for (i=0; i < DIM(currency_table); i++) 184 | if (!strcasecmp (string, currency_table[i].name)) 185 | { 186 | *r_decdigits = currency_table[i].decdigits; 187 | return 1; 188 | } 189 | return 0; 190 | } 191 | 192 | 193 | /* Return information for currencies. SEQ needs to be iterated from 0 194 | upwards until the function returns NULL. If not NULL a description 195 | of the currency is stored at R_DESC. if not NULL, the latest known 196 | exchange rate is stored at R_RATE. */ 197 | const char * 198 | get_currency_info (int seq, char const **r_desc, double *r_rate) 199 | { 200 | if (seq < 0 || seq >= DIM (currency_table)) 201 | return NULL; 202 | if (r_desc) 203 | *r_desc = currency_table[seq].desc; 204 | if (r_rate) 205 | *r_rate = currency_table[seq].rate; 206 | return currency_table[seq].name; 207 | } 208 | 209 | 210 | /* Convert (AMOUNT, CURRENCY) to an Euro amount and store it in BUFFER 211 | up to a length of BUFSIZE-1. Returns BUFFER. If a conversion is 212 | not possible an empty string is returned. */ 213 | char * 214 | convert_currency (char *buffer, size_t bufsize, 215 | const char *currency, const char *amount) 216 | { 217 | double value, rate; 218 | char *pend; 219 | 220 | if (!bufsize) 221 | log_bug ("buffer too short in convert_currency\n"); 222 | 223 | *buffer = 0; 224 | errno = 0; 225 | value = strtod (amount, &pend); 226 | if ((!value && amount == pend) || errno) 227 | { 228 | log_error ("error converting %s %s to Euro: %s\n", 229 | amount, currency, strerror (errno)); 230 | return buffer; 231 | } 232 | 233 | rate = get_exchange_rate (currency); 234 | if (!rate) 235 | { 236 | if (opt.verbose) 237 | log_info ("error converting %s %s to Euro: %s\n", 238 | amount, currency, "no exchange rate available"); 239 | return buffer; 240 | } 241 | if (rate != 1.0) 242 | { 243 | value /= rate; 244 | value += 0.005; /* So that snprintf rounds the value. */ 245 | } 246 | 247 | if (gpgrt_snprintf (buffer, bufsize, "%.2f", value) < 0) 248 | { 249 | log_error ("error converting %s %s to Euro: %s\n", 250 | amount, currency, strerror (errno)); 251 | *buffer = 0; 252 | return buffer; 253 | } 254 | 255 | return buffer; 256 | } 257 | 258 | 259 | /* Check that the recurrence value in STRING is valid. Returns true if 260 | * so. If R_RECUR is not NULL the recur value is stored as an int at 261 | * that value; 0 is stored for an invalid value. */ 262 | int 263 | valid_recur_p (const char *string, int *r_recur) 264 | { 265 | int recur; 266 | 267 | recur = *string? atoi (string) : 0; 268 | if (!recur || recur == 1 || recur == 4 || recur == 12) 269 | ; 270 | else 271 | { 272 | if (r_recur) 273 | *r_recur = 0; 274 | return 0; /* Bad value. */ 275 | } 276 | 277 | if (r_recur) 278 | *r_recur = recur; 279 | return 1; 280 | } 281 | -------------------------------------------------------------------------------- /src/ppsepaqr.c: -------------------------------------------------------------------------------- 1 | /* ppsepaqr - Create a SEPA QR code 2 | * Copyright (C) 2017 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "util.h" 31 | #include "logging.h" 32 | #include "argparse.h" 33 | 34 | /* Constants to identify the options. */ 35 | enum opt_values 36 | { 37 | aNull = 0, 38 | oVerbose = 'v', 39 | 40 | oDebug = 500, 41 | 42 | oLast 43 | }; 44 | 45 | 46 | /* The list of commands and options. */ 47 | static ARGPARSE_OPTS opts[] = { 48 | ARGPARSE_group (301, "@\nOptions:\n "), 49 | 50 | ARGPARSE_s_n (oVerbose,"verbose", "verbose diagnostics"), 51 | 52 | ARGPARSE_end () 53 | }; 54 | 55 | 56 | /* Gobal options. */ 57 | static struct 58 | { 59 | int verbose; 60 | } opt; 61 | 62 | 63 | 64 | 65 | /* Local prototypes. */ 66 | static char *format_data (const char *iban, const char *name, 67 | const char *amount, const char *text); 68 | static void encode (const char *text, estream_t fp); 69 | 70 | 71 | 72 | 73 | static const char * 74 | my_strusage( int level ) 75 | { 76 | const char *p; 77 | 78 | switch (level) 79 | { 80 | case 11: p = "ppsepaqr"; break; 81 | case 13: p = PACKAGE_VERSION; break; 82 | case 19: p = "Please report bugs to https://bugs.gnupg.org.\n"; break; 83 | case 1: 84 | case 40: p = 85 | "Usage: ppsepaqr [options] IBAN NAME AMOUNT TEXT (-h for help)"; 86 | break; 87 | case 41: p = 88 | "Syntax: ppsepaqr [options] IBAN NAME AMOUNT TEXT\n" 89 | "Print an SVG with the QR code for a SEPA transaction\n"; 90 | break; 91 | default: p = NULL; break; 92 | } 93 | return p; 94 | } 95 | 96 | 97 | int 98 | main (int argc, char **argv) 99 | { 100 | ARGPARSE_ARGS pargs; 101 | char *data; 102 | 103 | /* Set program name etc. */ 104 | set_strusage (my_strusage); 105 | log_set_prefix ("ppsepaqr", JNLIB_LOG_WITH_PREFIX); 106 | 107 | /* Make sure that our subsystems are ready. */ 108 | gpgrt_init (); 109 | 110 | /* Parse the command line. */ 111 | pargs.argc = &argc; 112 | pargs.argv = &argv; 113 | pargs.flags = ARGPARSE_FLAG_KEEP; 114 | while (optfile_parse (NULL, NULL, NULL, &pargs, opts)) 115 | { 116 | switch (pargs.r_opt) 117 | { 118 | case oVerbose: opt.verbose++; break; 119 | 120 | default: pargs.err = ARGPARSE_PRINT_ERROR; break; 121 | } 122 | } 123 | 124 | if (log_get_errorcount (0)) 125 | exit (2); 126 | 127 | if (argc != 4) 128 | usage (1); 129 | 130 | data = format_data (argv[0], argv[1], argv[2], argv[3]); 131 | if (data) 132 | { 133 | encode (data, es_stdout); 134 | if (es_ferror (es_stdout) || es_fflush (es_stdout)) 135 | log_error ("error writing to stdout: %s\n", 136 | gpg_strerror (gpg_error_from_syserror ())); 137 | 138 | xfree (data); 139 | } 140 | 141 | return !!log_get_errorcount (0); 142 | } 143 | 144 | 145 | /* Create a string with the data accroding to "EPC069-12v2.1 Quick 146 | * Response Code - Guidelines to Enable the Data Capture for the 147 | * Initiation of a SCT". Returns a malloced string or NULL on 148 | * error. In the error case a diagnositc has been printed. */ 149 | static char * 150 | format_data (const char *iban, const char *name, const char *amount, 151 | const char *text) 152 | { 153 | char *string; 154 | int anyerr = 0; 155 | unsigned int cents; 156 | char *xamount; 157 | char *xtext; 158 | char *p; 159 | 160 | /* Check various things. */ 161 | if (strlen (iban) < 8 /* arbitrary value - what is the right one?*/ 162 | || strlen (iban) > 34 163 | || strchr (iban, '\n') || strchr (iban, '\r')) 164 | { 165 | log_error ("invalid IBAN given"); 166 | anyerr++; 167 | } 168 | 169 | if (!*name || strlen (name) > 70 170 | || strchr (name, '\n') || strchr (name, '\r')) 171 | { 172 | log_error ("invalid or too long NAME given\n"); 173 | anyerr++; 174 | } 175 | 176 | cents = convert_amount (amount, 2); 177 | if (!cents) 178 | { 179 | log_error ("invalid AMOUNT given\n"); 180 | anyerr++; 181 | } 182 | xamount = reconvert_amount (cents, 2); 183 | if (!xamount) 184 | { 185 | log_error ("error formatting amount: %s\n", 186 | gpg_strerror (gpg_error_from_syserror ())); 187 | return NULL; 188 | } 189 | 190 | xtext = xstrdup (text); 191 | for (p=xtext; *p; p++) 192 | if (*p == '\n' || *p == '\r') 193 | *p = ' '; 194 | trim_spaces (xtext); 195 | if (!*xtext) 196 | { 197 | log_error ("empty TEXT is not allowed\n"); 198 | anyerr++; 199 | } 200 | if (strlen (xtext) > 140) 201 | { 202 | /* FIXME: This may invalidate UTF-8 chars. */ 203 | xtext[140] = 0; 204 | log_info ("TEXT truncated to 140 octets\n"); 205 | } 206 | 207 | if (anyerr) 208 | string = NULL; 209 | else 210 | { 211 | string = strconcat ("BCD\n" 212 | "002\n" 213 | "1\n" 214 | "SCT\n" 215 | "\n", /* BIC is not anymore used. */ 216 | name, "\n", 217 | iban, "\n", 218 | "EUR", xamount, "\n", 219 | "\n" /* Purpose */ 220 | "\n", /* Remittance info (structured) */ 221 | xtext, "\n", /* Remittance info (unstructured) */ 222 | "", /* Information. */ 223 | NULL ); 224 | if (!string) 225 | log_error ("strconcat failed: %s\n", 226 | gpg_strerror (gpg_error_from_syserror ())); 227 | } 228 | 229 | es_free (xamount); 230 | xfree (xtext); 231 | return string; 232 | } 233 | 234 | 235 | /* Encode to QR and render as SVG to FP */ 236 | static void 237 | encode (const char *text, estream_t fp) 238 | { 239 | QRcode *code; 240 | unsigned int symwidth; 241 | float realwidth; 242 | const unsigned char *row; 243 | unsigned int x, y, width, x2; 244 | 245 | code = QRcode_encodeString (text, 0, QR_ECLEVEL_M, QR_MODE_8, 1); 246 | if (!code) 247 | { 248 | log_error ("QR encoding failed: %s\n", 249 | gpg_strerror (gpg_error_from_syserror ())); 250 | return; 251 | } 252 | 253 | #define SVG_MARGIN 4 254 | #define SVG_PIXELS 3 255 | #define SVG_DPI 72 256 | 257 | symwidth = code->width + SVG_MARGIN * 2; 258 | realwidth = (symwidth * SVG_PIXELS) / (SVG_DPI * (100.0/2.54) / 100.0); 259 | 260 | es_fprintf (fp, 261 | "\n" 266 | " \n" 267 | " \n" 269 | " \n", 270 | realwidth, realwidth, 271 | symwidth, symwidth, 272 | symwidth, symwidth ); 273 | 274 | for (y = 0; y < code->width; y++) 275 | { 276 | row = code->data + (y * code->width); 277 | for (x = 0; x < code->width; x++) 278 | { 279 | for (width=0, x2=x; (row[x2] & 1) && x2 < code->width; x2++, width++) 280 | ; 281 | if (width) 282 | { 283 | es_fprintf (fp, 284 | " \n", 287 | SVG_MARGIN + x, SVG_MARGIN + y, width); 288 | x += width - 1; 289 | } 290 | } 291 | } 292 | 293 | es_fputs (" \n" 294 | " \n" 295 | "\n", 296 | fp); 297 | 298 | QRcode_free (code); 299 | } 300 | -------------------------------------------------------------------------------- /src/protocol-io.c: -------------------------------------------------------------------------------- 1 | /* protocol-io.c - Server protocol helper helper functions. 2 | * Copyright (C) 2015 g10 Code GmbH 3 | * 4 | * This file is part of Payproc. 5 | * 6 | * Payproc is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * Payproc is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include "util.h" 27 | #include "logging.h" 28 | #include "payprocd.h" 29 | #include "protocol-io.h" 30 | 31 | /* Maximum length of an input line. */ 32 | #define MAX_LINELEN 2048 33 | 34 | 35 | /* Transform a data line name into a standard capitalized format; e.g. 36 | "Content-Type". Conversion stops at the colon. As usual we don't 37 | use the localized versions of ctype.h. Parts inside of brackets 38 | ([]) are not changed. */ 39 | static void 40 | capitalize_name (char *name) 41 | { 42 | int first = 1; 43 | int bracket = 0; 44 | 45 | for (; *name && *name != ':'; name++) 46 | { 47 | if (bracket) 48 | { 49 | if (*name == ']') 50 | bracket--; 51 | } 52 | else if (*name == '[') 53 | bracket++; 54 | else if (*name == '-') 55 | first = 1; 56 | else if (first) 57 | { 58 | if (*name >= 'a' && *name <= 'z') 59 | *name = *name - 'a' + 'A'; 60 | first = 0; 61 | } 62 | else if (*name >= 'A' && *name <= 'Z') 63 | *name = *name - 'A' + 'a'; 64 | } 65 | } 66 | 67 | 68 | /* Store a data LINE away. The function expects that the terminating 69 | linefeed has already been stripped. Line continuation is supported 70 | as well as merging of headers with the same name. This function 71 | may modify LINE. DATAITEMS is a pointer to a key-value list which 72 | received the the data. With FILTER set capitalize field names and 73 | do not allow special names. */ 74 | static gpg_error_t 75 | store_data_line (char *line, int filter, keyvalue_t *dataitems) 76 | { 77 | char *p, *value; 78 | keyvalue_t kv; 79 | 80 | if (*line == ' ' || *line == '\t') 81 | { 82 | /* Continuation. */ 83 | if (!*dataitems) 84 | return gpg_error (GPG_ERR_PROTOCOL_VIOLATION); 85 | return keyvalue_append_with_nl (*dataitems, line+1); 86 | } 87 | 88 | /* A name must start with a letter. Note that for items used only 89 | internally a name may start with an underscore. */ 90 | if (filter) 91 | { 92 | capitalize_name (line); 93 | if (*line < 'A' || *line > 'Z') 94 | return gpg_error (GPG_ERR_INV_NAME); 95 | } 96 | 97 | p = strchr (line, ':'); 98 | if (!p) 99 | return GPG_ERR_PROTOCOL_VIOLATION; 100 | *p++ = 0; 101 | while (*p == ' ' || *p == '\t') 102 | p++; 103 | value = p; 104 | 105 | for (kv = *dataitems; kv; kv = kv->next) 106 | if (!strcmp (kv->name, line)) 107 | break; 108 | if (kv) 109 | { 110 | /* We have already seen a line with that name. */ 111 | /* Fixme: We should use this to allow for an array, like it is 112 | done by the addrutil tool. */ 113 | return GPG_ERR_PROTOCOL_VIOLATION; 114 | } 115 | 116 | /* Insert a new data item. */ 117 | return keyvalue_put (dataitems, line, value); 118 | } 119 | 120 | 121 | /* Read a protocol chunk into R_COMMAND and update DATATITEMS with 122 | the data item. Return 0 on success. Note that on error NULL is 123 | stored at R_command but DATAITEMS may have changed. With FILTER 124 | set capitalize field names and do not allow special names. */ 125 | static gpg_error_t 126 | read_data (estream_t stream, int filter, 127 | char **r_command, keyvalue_t *dataitems) 128 | { 129 | gpg_error_t err; 130 | char *buffer = NULL; /* Line buffer. */ 131 | size_t buffer_size = 0; /* Current length of buffer. */ 132 | ssize_t nread; 133 | size_t maxlen; 134 | size_t n; 135 | 136 | *r_command = NULL; 137 | 138 | /* Read the command line. */ 139 | maxlen = MAX_LINELEN; 140 | nread = es_read_line (stream, &buffer, &buffer_size, &maxlen); 141 | if (nread < 0) 142 | { 143 | err = gpg_error_from_syserror (); 144 | es_free (buffer); 145 | log_error ("reading request failed: %s\n", gpg_strerror (err)); 146 | return err; 147 | } 148 | if (!maxlen) 149 | { 150 | es_free (buffer); 151 | log_error ("reading request failed: %s\n", "command line too long"); 152 | return GPG_ERR_TRUNCATED; 153 | } 154 | if (!nread) 155 | { 156 | es_free (buffer); 157 | log_error ("reading request failed: %s\n", 158 | "EOF while reading command line"); 159 | return GPG_ERR_EOF; 160 | } 161 | /* Strip linefeed. */ 162 | n = strlen (buffer); 163 | if (n && buffer[n-1] == '\n') 164 | { 165 | buffer[--n] = 0; 166 | if (n && buffer[n-1] == '\r') 167 | buffer[--n] = 0; 168 | } 169 | 170 | *r_command = xtrystrdup (buffer); 171 | if (!*r_command) 172 | { 173 | err = gpg_err_code_from_syserror (); 174 | es_free (buffer); 175 | return err; 176 | } 177 | 178 | /* Read data lines and wait for the terminating empty line. */ 179 | do 180 | { 181 | maxlen = MAX_LINELEN; 182 | nread = es_read_line (stream, &buffer, &buffer_size, &maxlen); 183 | if (nread < 0) 184 | { 185 | err = gpg_err_code_from_syserror (); 186 | es_free (buffer); 187 | log_error ("reading request failed: %s\n", gpg_strerror (err)); 188 | xfree (*r_command); 189 | *r_command = NULL; 190 | return err; 191 | } 192 | if (!maxlen) 193 | { 194 | es_free (buffer); 195 | log_error ("reading request failed: %s\n", "data line too long"); 196 | xfree (*r_command); 197 | *r_command = NULL; 198 | return GPG_ERR_TRUNCATED; 199 | } 200 | if (!nread) 201 | { 202 | es_free (buffer); 203 | log_error ("reading request failed: %s\n", 204 | "EOF while reading data line"); 205 | xfree (*r_command); 206 | *r_command = NULL; 207 | return GPG_ERR_EOF; 208 | } 209 | 210 | /* Strip linefeed. */ 211 | n = strlen (buffer); 212 | if (n && buffer[n-1] == '\n') 213 | { 214 | buffer[--n] = 0; 215 | if (n && buffer[n-1] == '\r') 216 | buffer[--n] = 0; 217 | } 218 | 219 | if (*buffer && *buffer != '#' ) 220 | { 221 | err = store_data_line (buffer, filter, dataitems); 222 | if (err) 223 | { 224 | es_free (buffer); 225 | xfree (*r_command); 226 | *r_command = NULL; 227 | return err; 228 | } 229 | } 230 | } 231 | while (*buffer); 232 | es_free (buffer); 233 | 234 | return 0; 235 | } 236 | 237 | 238 | /* Read the request into R_COMMAND and update DATATITEMS with the data 239 | from the request. Return 0 on success. Note that on error NULL is 240 | stored at R_command but DATAITEMS may have changed. */ 241 | gpg_error_t 242 | protocol_read_request (estream_t stream, 243 | char **r_command, keyvalue_t *dataitems) 244 | { 245 | return read_data (stream, 1, r_command, dataitems); 246 | } 247 | 248 | 249 | /* Read the response and update DATAITEMS with the data from the 250 | response. Return 0 on success. On error an error is returned. If 251 | that error has been returned by the server the description of the 252 | error is stored in DATAITEM under the key "_errdesc"; if the error 253 | is local "_errdesc" is not set. */ 254 | gpg_error_t 255 | protocol_read_response (estream_t stream, keyvalue_t *dataitems) 256 | { 257 | gpg_error_t err, err2; 258 | char *status; 259 | const char *s; 260 | 261 | keyvalue_del (*dataitems, "_errdesc"); 262 | err = read_data (stream, 0, &status, dataitems); 263 | if (err) 264 | return err; 265 | 266 | if (has_leading_keyword (status, "OK")) 267 | ; 268 | else if ((s = has_leading_keyword (status, "ERR"))) 269 | { 270 | unsigned long n; 271 | char *endp; 272 | 273 | n = strtoul (s, &endp, 10); 274 | if (!n) 275 | err = gpg_error (GPG_ERR_PROTOCOL_VIOLATION); 276 | else 277 | { 278 | err = n; 279 | for (s = endp; *s == ' ' || *s == '\t'; s++) 280 | ; 281 | if (!*s) 282 | s = gpg_strerror (err); 283 | 284 | err2 = keyvalue_put (dataitems, "_errdesc", s); 285 | if (err2) 286 | { 287 | keyvalue_del (*dataitems, "_errdesc"); 288 | err = err2; 289 | } 290 | } 291 | } 292 | else 293 | err = gpg_error (GPG_ERR_INV_RESPONSE); 294 | 295 | xfree (status); 296 | return err; 297 | } 298 | -------------------------------------------------------------------------------- /src/cJSON.readme: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Dave Gamble 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | Welcome to cJSON. 24 | 25 | cJSON aims to be the dumbest possible parser that you can get your job 26 | done with. It's a single file of C, and a single header file. 27 | 28 | JSON is described best here: http://www.json.org/ It's like XML, but 29 | fat-free. You use it to move data around, store things, or just 30 | generally represent your program's state. 31 | 32 | 33 | First up, how do I build? Add cJSON.c to your project, and put 34 | cJSON.h somewhere in the header search path. For example, to build 35 | the test app: 36 | 37 | gcc cJSON.c test.c -o test -lm 38 | ./test 39 | 40 | 41 | As a library, cJSON exists to take away as much legwork as it can, but 42 | not get in your way. As a point of pragmatism (i.e. ignoring the 43 | truth), I'm going to say that you can use it in one of two modes: Auto 44 | and Manual. Let's have a quick run-through. 45 | 46 | 47 | I lifted some JSON from this page: http://www.json.org/fatfree.html 48 | That page inspired me to write cJSON, which is a parser that tries to 49 | share the same philosophy as JSON itself. Simple, dumb, out of the 50 | way. 51 | 52 | Some JSON: 53 | { 54 | "name": "Jack (\"Bee\") Nimble", 55 | "format": { 56 | "type": "rect", 57 | "width": 1920, 58 | "height": 1080, 59 | "interlace": false, 60 | "frame rate": 24 61 | } 62 | } 63 | 64 | Assume that you got this from a file, a webserver, or magic JSON 65 | elves, whatever, you have a char * to it. Everything is a cJSON 66 | struct. Get it parsed: 67 | 68 | cJSON *root = cJSON_Parse(my_json_string); 69 | 70 | This is an object. We're in C. We don't have objects. But we do have 71 | structs. What's the framerate? 72 | 73 | cJSON *format = cJSON_GetObjectItem(root,"format"); 74 | int framerate = cJSON_GetObjectItem(format,"frame rate")->valueint; 75 | 76 | Want to change the framerate? 77 | 78 | cJSON_GetObjectItem(format,"frame rate")->valueint=25; 79 | 80 | Back to disk? 81 | 82 | char *rendered=cJSON_Print(root); 83 | 84 | Finished? Delete the root (this takes care of everything else). 85 | 86 | cJSON_Delete(root); 87 | 88 | That's AUTO mode. If you're going to use Auto mode, you really ought 89 | to check pointers before you dereference them. If you want to see how 90 | you'd build this struct in code? 91 | 92 | cJSON *root,*fmt; 93 | root=cJSON_CreateObject(); 94 | cJSON_AddItemToObject(root, "name", 95 | cJSON_CreateString("Jack (\"Bee\") Nimble")); 96 | cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); 97 | cJSON_AddStringToObject(fmt,"type", "rect"); 98 | cJSON_AddNumberToObject(fmt,"width", 1920); 99 | cJSON_AddNumberToObject(fmt,"height", 1080); 100 | cJSON_AddFalseToObject (fmt,"interlace"); 101 | cJSON_AddNumberToObject(fmt,"frame rate", 24); 102 | 103 | Hopefully we can agree that's not a lot of code? There's no overhead, 104 | no unnecessary setup. Look at test.c for a bunch of nice examples, 105 | mostly all ripped off the json.org site, and a few from elsewhere. 106 | 107 | What about manual mode? First up you need some detail. Let's cover 108 | how the cJSON objects represent the JSON data. cJSON doesn't 109 | distinguish arrays from objects in handling; just type. Each cJSON 110 | has, potentially, a child, siblings, value, a name. 111 | 112 | - The root object has: Object Type and a Child 113 | - The Child has name "name", with value "Jack ("Bee") Nimble", and a sibling: 114 | - Sibling has type Object, name "format", and a child. 115 | - That child has type String, name "type", value "rect", and a sibling: 116 | - Sibling has type Number, name "width", value 1920, and a sibling: 117 | - Sibling has type Number, name "height", value 1080, and a sibling: 118 | - Sibling hs type False, name "interlace", and a sibling: 119 | - Sibling has type Number, name "frame rate", value 24 120 | 121 | Here's the structure: 122 | 123 | typedef struct cJSON { 124 | struct cJSON *next,*prev; 125 | struct cJSON *child; 126 | 127 | int type; 128 | 129 | char *valuestring; 130 | int valueint; 131 | double valuedouble; 132 | 133 | char *string; 134 | } cJSON; 135 | 136 | By default all values are 0 unless set by virtue of being meaningful. 137 | 138 | next/prev is a doubly linked list of siblings. next takes you to your sibling, 139 | prev takes you back from your sibling to you. 140 | 141 | Only objects and arrays have a "child", and it's the head of the 142 | doubly linked list. 143 | 144 | A "child" entry will have prev==0, but next potentially points on. The 145 | last sibling has next=0. 146 | 147 | The type expresses Null/True/False/Number/String/Array/Object, all of 148 | which are #defined in cJSON.h 149 | 150 | A Number has valueint and valuedouble. If you're expecting an int, 151 | read valueint, if not read valuedouble. 152 | 153 | Any entry which is in the linked list which is the child of an object 154 | will have a "string" which is the "name" of the entry. When I said 155 | "name" in the above example, that's "string". "string" is the JSON 156 | name for the 'variable name' if you will. 157 | 158 | Now you can trivially walk the lists, recursively, and parse as you 159 | please. You can invoke cJSON_Parse to get cJSON to parse for you, and 160 | then you can take the root object, and traverse the structure (which 161 | is, formally, an N-tree), and tokenise as you please. If you wanted to 162 | build a callback style parser, this is how you'd do it (just an 163 | example, since these things are very specific): 164 | 165 | void parse_and_callback(cJSON *item,const char *prefix) 166 | { 167 | while (item) 168 | { 169 | char *newprefix=malloc(strlen(prefix)+strlen(item->name)+2); 170 | sprintf(newprefix,"%s/%s",prefix,item->name); 171 | int dorecurse=callback(newprefix, item->type, item); 172 | if (item->child && dorecurse) 173 | parse_and_callback(item->child,newprefix); 174 | item=item->next; 175 | free(newprefix); 176 | } 177 | } 178 | 179 | The prefix process will build you a separated list, to simplify your 180 | callback handling. 181 | 182 | The 'dorecurse' flag would let the callback decide to handle 183 | sub-arrays on it's own, or let you invoke it per-item. For the item 184 | above, your callback might look like this: 185 | 186 | int callback(const char *name,int type,cJSON *item) 187 | { 188 | if (!strcmp(name,"name")) { /* populate name */ } 189 | else if (!strcmp(name,"format/type") { /* handle "rect" */ } 190 | else if (!strcmp(name,"format/width") { /* 800 */ } 191 | else if (!strcmp(name,"format/height") { /* 600 */ } 192 | else if (!strcmp(name,"format/interlace") { /* false */ } 193 | else if (!strcmp(name,"format/frame rate") { /* 24 */ } 194 | return 1; 195 | } 196 | 197 | Alternatively, you might like to parse iteratively. 198 | You'd use: 199 | 200 | void parse_object(cJSON *item) 201 | { 202 | int i; for (i=0;ichild; 214 | while (subitem) 215 | { 216 | // handle subitem 217 | if (subitem->child) parse_object(subitem->child); 218 | 219 | subitem=subitem->next; 220 | } 221 | } 222 | 223 | Of course, this should look familiar, since this is just a 224 | stripped-down version of the callback-parser. 225 | 226 | This should cover most uses you'll find for parsing. The rest should 227 | be possible to infer.. and if in doubt, read the source! There's not a 228 | lot of it! ;) 229 | 230 | 231 | In terms of constructing JSON data, the example code above is the 232 | right way to do it. You can, of course, hand your sub-objects to 233 | other functions to populate. Also, if you find a use for it, you can 234 | manually build the objects. For instance, suppose you wanted to build 235 | an array of objects? 236 | 237 | cJSON *objects[24]; 238 | 239 | cJSON *Create_array_of_anything(cJSON **items,int num) 240 | { 241 | int i;cJSON *prev, *root=cJSON_CreateArray(); 242 | for (i=0;i<24;i++) 243 | { 244 | if (!i) root->child=objects[i]; 245 | else prev->next=objects[i], objects[i]->prev=prev; 246 | prev=objects[i]; 247 | } 248 | return root; 249 | } 250 | 251 | and simply: Create_array_of_anything(objects,24); 252 | 253 | cJSON doesn't make any assumptions about what order you create things 254 | in. You can attach the objects, as above, and later add children to 255 | each of those objects. 256 | 257 | As soon as you call cJSON_Print, it renders the structure to text. 258 | 259 | 260 | 261 | The test.c code shows how to handle a bunch of typical cases. If you 262 | uncomment the code, it'll load, parse and print a bunch of test files, 263 | also from json.org, which are more complex than I'd care to try and 264 | stash into a const char array[]. 265 | 266 | 267 | Enjoy cJSON! 268 | 269 | 270 | - Dave Gamble, Aug 2009 271 | --------------------------------------------------------------------------------