+
+void
+libdcp::init ()
+{
+ if (xmlSecInit() < 0) {
+ throw MiscError ("could not initialise xmlsec");
+ }
+
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+ if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+ throw MiscError ("unable to load default xmlsec-crypto library");
+ }
+#endif
+
+ if (xmlSecCryptoAppInit(0) < 0) {
+ throw MiscError ("could not initialise crypto");
+ }
+
+ if (xmlSecCryptoInit() < 0) {
+ throw MiscError ("could not initialise xmlsec-crypto");
+ }
+}
+
+bool libdcp::operator== (libdcp::Size const & a, libdcp::Size const & b)
+{
+ return (a.width == b.width && a.height == b.height);
+}
+
+bool libdcp::operator!= (libdcp::Size const & a, libdcp::Size const & b)
+{
+ return !(a == b);
+}
+
+/** The base64 decode routine in KM_util.cpp gives different values to both
+ * this and the command-line base64 for some inputs. Not sure why.
+ */
+int
+libdcp::base64_decode (string const & in, unsigned char* out, int out_length)
+{
+ BIO* b64 = BIO_new (BIO_f_base64 ());
+
+ /* This means the input should have no newlines */
+ BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
+
+ /* Copy our input string, removing newlines */
+ char in_buffer[in.size() + 1];
+ char* p = in_buffer;
+ for (size_t i = 0; i < in.size(); ++i) {
+ if (in[i] != '\n' && in[i] != '\r') {
+ *p++ = in[i];
+ }
+ }
+
+ BIO* bmem = BIO_new_mem_buf (in_buffer, p - in_buffer);
+ bmem = BIO_push (b64, bmem);
+ int const N = BIO_read (bmem, out, out_length);
+ BIO_free_all (bmem);
+
+ return N;
+}
+
+/** @param tm Local time.
+ * @return String of the form 2014-04-02T18:05:23+04:00, where the UTC offset is derived
+ * from the current system time zone.
+ */
+string
+libdcp::tm_to_string (struct tm* tm)
+{
+ char buffer[64];
+ strftime (buffer, 64, "%Y-%m-%dT%H:%M:%S", tm);
+
+ /* Compute current UTC offset */
+ boost::posix_time::ptime const utc_now = boost::posix_time::second_clock::universal_time ();
+ boost::posix_time::ptime const now = boost::date_time::c_local_adjustor<boost::posix_time::ptime>::utc_to_local (utc_now);
+
+ return string (buffer) + utc_offset_to_string (now - utc_now);
+}
+
+/** @param b Offset from UTC to local time.
+ * @return string of the form e.g. -01:00.
+ */
+string
+libdcp::utc_offset_to_string (boost::posix_time::time_duration b)
+{
+ bool const negative = b.is_negative ();
+ if (negative) {
+ b = boost::posix_time::time_duration (-b.hours(), b.minutes(), 0, 0);
+ }
+
+ stringstream o;
+ if (negative) {
+ o << "-";
+ } else {
+ o << "+";
+ }
+
+ o << setw(2) << setfill('0') << b.hours() << ":" << setw(2) << setfill('0') << b.minutes();
+ return o.str ();
+}
+
+string
+libdcp::ptime_to_string (boost::posix_time::ptime t)
+{
+ struct tm t_tm = boost::posix_time::to_tm (t);
+ return tm_to_string (&t_tm);
+}
+
+
+/* Apparently there is no way to create an ofstream using a UTF-8
+ filename under Windows. We are hence reduced to using fopen
+ with this wrapper.
+*/
+FILE *
+libdcp::fopen_boost (boost::filesystem::path p, string t)
+{
+#ifdef LIBDCP_WINDOWS
+ wstring w (t.begin(), t.end());
+ /* c_str() here should give a UTF-16 string */
+ return _wfopen (p.c_str(), w.c_str ());
+#else
+ return fopen (p.c_str(), t.c_str ());
+#endif
+}