<commit_before>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <fstream>
#include <locale>
#include <clocale>
#include <string>
#include <cstring>

/* Use the POSIX glob(3) function if available. On a native Windows port,
 * you'll need to make your own glob(3) implementation and define HAVE_GLOB, or
 * entirely reimplement ls.
 */
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif

#include "../interp.hxx"
#include "../command.hxx"
#include "../function.hxx"
#include "list.hxx"
#include "../common.hxx"

using namespace std;

namespace tglng {
#ifdef HAVE_GLOB
//Define glob parms which might not exist
#ifndef GLOB_BRACE
#  define GLOB_BRACE 0
#endif
#ifndef GLOB_TILDE
#  define GLOB_TILDE 0
#endif
  bool fs_ls(wstring* out, const wstring* in,
             Interpreter& interp, unsigned) {
    glob_t results;

    out->clear();

    locale theLocale("");

    //Transcode in[0] to a narrow string
    typedef codecvt<wchar_t, char, mbstate_t> converter_t;
    const converter_t& converter =
      use_facet<converter_t>(theLocale);
    vector<char> pattern(in->size() * converter.max_length() + 1);
    mbstate_t mbstate;
    const wchar_t* from_next;
    char* end;
    converter_t::result conversionResult =
      converter.out(mbstate, in->data(), in->data() + in->size(),
                    from_next, &pattern[0], &pattern[0] + pattern.size() - 1,
                    end);
    if (conversionResult != converter_t::ok) {
      wcerr << L"Could not convert glob pattern to narrow string: "
            << *in << endl;
      return false;
    }

    //Ensure it is NUL-terminated
    *end = 0;

    //Perform the glob
    //If it fails, just return an empty list (*out is already empty);
    //otherwise, convert to a list.
    if (!glob(&pattern[0], GLOB_BRACE|GLOB_TILDE, NULL, &results)) {
      for (unsigned i = 0; i < results.gl_pathc; ++i) {
        //Convert the filename back to a wide string
        vector<wchar_t> str(strlen(results.gl_pathv[i]));
        const char* nfrom_next;
        wchar_t* wend;
        mbstate = mbstate_t();
        conversionResult =
          converter.in(mbstate, results.gl_pathv[i],
                       results.gl_pathv[i] + strlen(results.gl_pathv[i]),
                       nfrom_next, &str[0], &str[0] + str.size(), wend);
        if (conversionResult != converter_t::ok) {
          //Print a warning about this one
          cerr << "WARN: Could not convert narrow filename to wide string: "
               << results.gl_pathv[i] << endl;
          continue;
        }

        //OK, add to the list
        list::lappend(*out, wstring(&str[0], wend));
      }
    }

    return true;
  }

  static GlobalBinding<TFunctionParser<1,1,fs_ls> > _ls(L"ls");
#endif /* HAVE_GLOB */
}
<commit_msg>Add read and read-binary, and fix leak in ls.<commit_after>#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <iostream>
#include <fstream>
#include <locale>
#include <clocale>
#include <string>
#include <cstring>
#include <cerrno>

/* Use the POSIX glob(3) function if available. On a native Windows port,
 * you'll need to make your own glob(3) implementation and define HAVE_GLOB, or
 * entirely reimplement ls.
 */
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif

#include "../interp.hxx"
#include "../command.hxx"
#include "../function.hxx"
#include "list.hxx"
#include "../common.hxx"

using namespace std;

namespace tglng {
#ifdef HAVE_GLOB
//Define glob parms which might not exist
#ifndef GLOB_BRACE
#  define GLOB_BRACE 0
#endif
#ifndef GLOB_TILDE
#  define GLOB_TILDE 0
#endif
  bool fs_ls(wstring* out, const wstring* in,
             Interpreter& interp, unsigned) {
    glob_t results;

    out->clear();

    locale theLocale("");

    //Transcode in[0] to a narrow string
    typedef codecvt<wchar_t, char, mbstate_t> converter_t;
    const converter_t& converter =
      use_facet<converter_t>(theLocale);
    vector<char> pattern(in->size() * converter.max_length() + 1);
    mbstate_t mbstate;
    const wchar_t* from_next;
    char* end;
    converter_t::result conversionResult =
      converter.out(mbstate, in->data(), in->data() + in->size(),
                    from_next, &pattern[0], &pattern[0] + pattern.size() - 1,
                    end);
    if (conversionResult != converter_t::ok) {
      wcerr << L"Could not convert glob pattern to narrow string: "
            << *in << endl;
      return false;
    }

    //Ensure it is NUL-terminated
    *end = 0;

    //Perform the glob
    //If it fails, just return an empty list (*out is already empty);
    //otherwise, convert to a list.
    if (!glob(&pattern[0], GLOB_BRACE|GLOB_TILDE, NULL, &results)) {
      for (unsigned i = 0; i < results.gl_pathc; ++i) {
        //Convert the filename back to a wide string
        vector<wchar_t> str(strlen(results.gl_pathv[i]));
        const char* nfrom_next;
        wchar_t* wend;
        mbstate = mbstate_t();
        conversionResult =
          converter.in(mbstate, results.gl_pathv[i],
                       results.gl_pathv[i] + strlen(results.gl_pathv[i]),
                       nfrom_next, &str[0], &str[0] + str.size(), wend);
        if (conversionResult != converter_t::ok) {
          //Print a warning about this one
          cerr << "WARN: Could not convert narrow filename to wide string: "
               << results.gl_pathv[i] << endl;
          continue;
        }

        //OK, add to the list
        list::lappend(*out, wstring(&str[0], wend));
      }

      globfree(&results);
    }

    return true;
  }

  static GlobalBinding<TFunctionParser<1,1,fs_ls> > _ls(L"ls");
#endif /* HAVE_GLOB */

  /**
   * Converts the given wstring to a char*, stored within dst. The actual size
   * of dst is not defined; rather, the only guarantee is that &dst[0] is a
   * valid NTBS.
   *
   * If successful, returns true; otherwise, prints a diagnostic and returns
   * false.
   */
  static bool wstrtofn(vector<char>& dst, const wstring& src) {
    typedef codecvt<wchar_t, char, mbstate_t> converter_t;
    locale theLocale("");
    const converter_t& converter =
      use_facet<converter_t>(theLocale);

    dst.resize(src.size() * converter.max_length() + 1);
    mbstate_t state;
    const wchar_t* from_next;
    char* end;
    converter_t::result result =
      converter.out(state, src.data(), src.data() + src.size(),
                    from_next, &dst[0], &dst[0] + dst.size() - 1,
                    end);
    if (result != converter_t::ok) {
      wcerr << L"Could not convert filename to narrow string: "
            << src << endl;
      return false;
    }

    //NUL-terminate
    *end = 0;

    return true;
  }

  static void blitstr(wstring& dst, const wstring& src) {
    dst = src;
  }
  static void blitstr(wstring& dst, const string& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (wchar_t)(unsigned char)src[i];
  }
  static void blitstr(string& dst, const wstring& src) {
    dst.resize(src.size());
    for (unsigned i = 0; i < src.size(); ++i)
      dst[i] = (char)src[i];
  }

  template<typename Ifstream, typename String, bool Text>
  bool fs_read(wstring* out, const wstring* in,
               Interpreter& interp, unsigned) {
    vector<char> fname;
    if (!wstrtofn(fname, in[0]))
      return false;
    Ifstream input(&fname[0], Text? ios::in : ios::in | ios::binary);
    if (!input) {
      cerr << strerror(errno) << endl;
      out[0].clear();
      out[1] = L"0";
      return true;
    }

    String str;
    static String eof((size_t)1, 4);
    getline(input, str, eof[0]);
    blitstr(out[0], str);

    if (!input.fail() && !input.eof())
      out[1] = L"1";
    else
      out[1] = L"0";

    return true;
  }

  static GlobalBinding<TFunctionParser<2,1,fs_read<wifstream, wstring, true> > >
  _read(L"read");
  static GlobalBinding<TFunctionParser<
                         2,1,fs_read<ifstream, string, false> > >
  _readBinary(L"read-binary");
}
<|endoftext|>


<commit_before>//
// Test Suite for C-API GEOSContains

#include <tut.hpp>
// geos
#include <geos_c.h>
#include <geos/io/WKBReader.h>
#include <geos/geom/PrecisionModel.h>
// std
#include <cstdarg>
#include <cstdio>
#include <cstdlib>

namespace tut
{
    //
    // Test Group
    //

    // Common data used in test cases.
    struct test_capigeoscontains_data
    {
        GEOSGeometry* geom1_;
        GEOSGeometry* geom2_;

        static void notice(const char *fmt, ...)
        {
            std::fprintf( stdout, "NOTICE: ");

            va_list ap;
            va_start(ap, fmt);
            std::vfprintf(stdout, fmt, ap);
            va_end(ap);

            std::fprintf(stdout, "\n");
        }

        test_capigeoscontains_data()
            : geom1_(0), geom2_(0)
        {
            initGEOS(notice, notice);
        }

        ~test_capigeoscontains_data()
        {
            GEOSGeom_destroy(geom1_);
            GEOSGeom_destroy(geom2_);
            geom1_ = 0;
            geom2_ = 0;
            finishGEOS();
        }

    };

    typedef test_group<test_capigeoscontains_data> group;
    typedef group::object object;

    group test_capigeoscontains_group("capi::GEOSContains");

    //
    // Test Cases
    //

    template<>
    template<>
    void object::test<1>()
    {
        geom1_ = GEOSGeomFromWKT("POLYGON EMPTY");
        geom2_ = GEOSGeomFromWKT("POLYGON EMPTY");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(r1, 0);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(r2, 0);
    }

    template<>
    template<>
    void object::test<2>()
    {
        geom1_ = GEOSGeomFromWKT("POLYGON((1 1,1 5,5 5,5 1,1 1))");
        geom2_ = GEOSGeomFromWKT("POINT(2 2)");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(int(r1), 1);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(int(r2), 0);
    }

    template<>
    template<>
    void object::test<3>()
    {
        geom1_ = GEOSGeomFromWKT("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))");
        geom2_ = GEOSGeomFromWKT("POLYGON((1 1,1 2,2 2,2 1,1 1))");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(int(r1), 1);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(int(r2), 0);
    }

    // Test outer polygon contains inner polygon with two coincident vertices
    // with results compared depending on precision used with FIXED PMs.
    template<>
    template<>
    void object::test<4>()
    {
        // Coincident vertives of both polygons at
        // -700.67089999181 93743.4218587986, -713.450135807349 93754.1677576647,
        std::string const outer("01030000800100000009000000af9dd0005ee585c0f802efbff6e2f6400000000000000000955acde0994b86c039a922afa2e3f64000000000000000002af6fb4f5d1887c07adb1c4071e3f6400000000000000000e5962b388d4f87c0bd3aeda7bae2f640000000000000000087c61344030887c07d585e6ff6e1f6400000000000000000fc8a31b5166186c0230588b20ae1f640000000000000000034733daf050186c0ed9f3ac98ae1f6400000000000000000f190aef659b385c0df2876538ce2f6400000000000000000af9dd0005ee585c0f802efbff6e2f6400000000000000000");
        std::string const inner("0103000080010000000a000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000467f1177ebf386c05de1971187e2f6400000000000000000fcf677888fc886c04e855a544be2f6400000000000000000c61226e540b686c0c0662d1fe7e1f640000000000000000042dc1bece8a486c09b85529f8ae1f6400000000000000000891047cde55e86c038cfa59c4ee1f6400000000000000000ae9dd0005ee585c0fa02efbff6e2f6400000000000000000975acde0994b86c038a922afa2e3f6400000000000000000287e339b09f986c01b1a083a10e3f6400000000000000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000");

        // A contains B if precision is limited to 1e+10
        {
            geos::geom::PrecisionModel pm(1e+10);
            geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
            geos::io::WKBReader reader(*factory);

            std::istringstream sOuter(outer);
            geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
            std::istringstream sInner(inner);
            geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
            ensure(0 != geom1_);
            ensure(0 != geom2_);

            int ret = GEOSContains(geom1_, geom2_);
            ensure_equals(ret, 1);
            ret = GEOSContains(geom2_, geom1_);
            ensure_equals(ret, 0);
        }

        // A does NOT contain B if precision is extended to 1e+11 or beyond
        {
            geos::geom::PrecisionModel pm(1e+11);
            geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
            geos::io::WKBReader reader(*factory);

            std::istringstream sOuter(outer);
            geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
            std::istringstream sInner(inner);
            geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
            ensure(0 != geom1_);
            ensure(0 != geom2_);

            int ret = GEOSContains(geom1_, geom2_);
            ensure_equals(ret, 1);
            ret = GEOSContains(geom2_, geom1_);
            ensure_equals(ret, 0);
        }
    }

    // Test outer rectangle contains inner rectangle with one coincident vertex
    // and two vertices of the inner rectangle are on the boundary (lay on segments)
    // of the outer rectangle.
    template<>
    template<>
    void object::test<5>()
    {
        geos::geom::PrecisionModel pm; // (1e+13);
        geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        // Coincident vertext at -753.167968418005 93709.4279185742
        //POLYGON ((-753.167968418005 93754.0955183194,-816.392328351464 93754.0955183194,-816.392328351464 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93754.0955183194))
        std::string const outer("01030000800100000005000000bd70d3ff578987c09e373e87a1e3f6400000000000000000a9f60b7d238389c09e373e87a1e3f6400000000000000000a9f60b7d238389c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09e373e87a1e3f6400000000000000000");
        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
        //POLYGON ((-753.167968418005 93747.6909727677,-799.641978447015 93747.6909727677,-799.641978447015 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93747.6909727677))
        std::string const inner("01030000800100000005000000bd70d3ff578987c0f875390e3be3f6400000000000000000579598c522fd88c0f875390e3be3f6400000000000000000579598c522fd88c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c0f875390e3be3f6400000000000000000");
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
        ensure(0 != geom1_);
        ensure(0 != geom2_);
    }

} // namespace tut

<commit_msg>Test check refinement missing from r4156<commit_after>//
// Test Suite for C-API GEOSContains

#include <tut.hpp>
// geos
#include <geos_c.h>
#include <geos/io/WKBReader.h>
#include <geos/geom/PrecisionModel.h>
// std
#include <cstdarg>
#include <cstdio>
#include <cstdlib>

namespace tut
{
    //
    // Test Group
    //

    // Common data used in test cases.
    struct test_capigeoscontains_data
    {
        GEOSGeometry* geom1_;
        GEOSGeometry* geom2_;

        static void notice(const char *fmt, ...)
        {
            std::fprintf( stdout, "NOTICE: ");

            va_list ap;
            va_start(ap, fmt);
            std::vfprintf(stdout, fmt, ap);
            va_end(ap);

            std::fprintf(stdout, "\n");
        }

        test_capigeoscontains_data()
            : geom1_(0), geom2_(0)
        {
            initGEOS(notice, notice);
        }

        ~test_capigeoscontains_data()
        {
            GEOSGeom_destroy(geom1_);
            GEOSGeom_destroy(geom2_);
            geom1_ = 0;
            geom2_ = 0;
            finishGEOS();
        }

    };

    typedef test_group<test_capigeoscontains_data> group;
    typedef group::object object;

    group test_capigeoscontains_group("capi::GEOSContains");

    //
    // Test Cases
    //

    template<>
    template<>
    void object::test<1>()
    {
        geom1_ = GEOSGeomFromWKT("POLYGON EMPTY");
        geom2_ = GEOSGeomFromWKT("POLYGON EMPTY");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(r1, 0);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(r2, 0);
    }

    template<>
    template<>
    void object::test<2>()
    {
        geom1_ = GEOSGeomFromWKT("POLYGON((1 1,1 5,5 5,5 1,1 1))");
        geom2_ = GEOSGeomFromWKT("POINT(2 2)");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(int(r1), 1);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(int(r2), 0);
    }

    template<>
    template<>
    void object::test<3>()
    {
        geom1_ = GEOSGeomFromWKT("MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)))");
        geom2_ = GEOSGeomFromWKT("POLYGON((1 1,1 2,2 2,2 1,1 1))");

        ensure( 0 != geom1_ );
        ensure( 0 != geom2_ );

        char const r1 = GEOSContains(geom1_, geom2_);

        ensure_equals(int(r1), 1);

        char const r2 = GEOSContains(geom2_, geom1_);

        ensure_equals(int(r2), 0);
    }

    // Test outer polygon contains inner polygon with two coincident vertices
    // with results compared depending on precision used with FIXED PMs.
    template<>
    template<>
    void object::test<4>()
    {
        // Coincident vertives of both polygons at
        // -700.67089999181 93743.4218587986, -713.450135807349 93754.1677576647,
        std::string const outer("01030000800100000009000000af9dd0005ee585c0f802efbff6e2f6400000000000000000955acde0994b86c039a922afa2e3f64000000000000000002af6fb4f5d1887c07adb1c4071e3f6400000000000000000e5962b388d4f87c0bd3aeda7bae2f640000000000000000087c61344030887c07d585e6ff6e1f6400000000000000000fc8a31b5166186c0230588b20ae1f640000000000000000034733daf050186c0ed9f3ac98ae1f6400000000000000000f190aef659b385c0df2876538ce2f6400000000000000000af9dd0005ee585c0f802efbff6e2f6400000000000000000");
        std::string const inner("0103000080010000000a000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000467f1177ebf386c05de1971187e2f6400000000000000000fcf677888fc886c04e855a544be2f6400000000000000000c61226e540b686c0c0662d1fe7e1f640000000000000000042dc1bece8a486c09b85529f8ae1f6400000000000000000891047cde55e86c038cfa59c4ee1f6400000000000000000ae9dd0005ee585c0fa02efbff6e2f6400000000000000000975acde0994b86c038a922afa2e3f6400000000000000000287e339b09f986c01b1a083a10e3f6400000000000000000ac21f88bbaff86c05f45d8c7b4e2f6400000000000000000");

        // A contains B if precision is limited to 1e+10
        {
            geos::geom::PrecisionModel pm(1e+10);
            geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
            geos::io::WKBReader reader(*factory);

            std::istringstream sOuter(outer);
            geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
            std::istringstream sInner(inner);
            geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
            ensure(0 != geom1_);
            ensure(0 != geom2_);

            int ret = GEOSContains(geom1_, geom2_);
            ensure_equals(ret, 1);
            ret = GEOSContains(geom2_, geom1_);
            ensure_equals(ret, 0);
        }

        // A does NOT contain B if precision is extended to 1e+11 or beyond
        {
            geos::geom::PrecisionModel pm(1e+11);
            geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
            geos::io::WKBReader reader(*factory);

            std::istringstream sOuter(outer);
            geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
            std::istringstream sInner(inner);
            geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
            ensure(0 != geom1_);
            ensure(0 != geom2_);

            int ret = GEOSContains(geom1_, geom2_);
            ensure_equals(ret, 0);
            ret = GEOSContains(geom2_, geom1_);
            ensure_equals(ret, 0);
        }
    }

    // Test outer rectangle contains inner rectangle with one coincident vertex
    // and two vertices of the inner rectangle are on the boundary (lay on segments)
    // of the outer rectangle.
    template<>
    template<>
    void object::test<5>()
    {
        geos::geom::PrecisionModel pm; // (1e+13);
        geos::geom::GeometryFactory::unique_ptr factory = geos::geom::GeometryFactory::create(&pm);
        geos::io::WKBReader reader(*factory);

        // Coincident vertext at -753.167968418005 93709.4279185742
        //POLYGON ((-753.167968418005 93754.0955183194,-816.392328351464 93754.0955183194,-816.392328351464 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93754.0955183194))
        std::string const outer("01030000800100000005000000bd70d3ff578987c09e373e87a1e3f6400000000000000000a9f60b7d238389c09e373e87a1e3f6400000000000000000a9f60b7d238389c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09e373e87a1e3f6400000000000000000");
        std::istringstream sOuter(outer);
        geom1_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sOuter));
        //POLYGON ((-753.167968418005 93747.6909727677,-799.641978447015 93747.6909727677,-799.641978447015 93709.4279185742,-753.167968418005 93709.4279185742,-753.167968418005 93747.6909727677))
        std::string const inner("01030000800100000005000000bd70d3ff578987c0f875390e3be3f6400000000000000000579598c522fd88c0f875390e3be3f6400000000000000000579598c522fd88c09625c1d8d6e0f6400000000000000000bd70d3ff578987c09625c1d8d6e0f6400000000000000000bd70d3ff578987c0f875390e3be3f6400000000000000000");
        std::istringstream sInner(inner);
        geom2_ = reinterpret_cast<GEOSGeometry*>(reader.readHEX(sInner));
        ensure(0 != geom1_);
        ensure(0 != geom2_);

        int ret = GEOSContains(geom1_, geom2_);
        ensure_equals(ret, 1);
        ret = GEOSContains(geom2_, geom1_);
        ensure_equals(ret, 0);
    }

} // namespace tut

<|endoftext|>


<commit_before><commit_msg>Update template<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * x11_dragdrop.cpp
 *****************************************************************************
 * Copyright (C) 2003 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulière <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef X11_SKINS

#include <X11/Xlib.h>
#include <X11/Xatom.h>

#include "x11_dragdrop.hpp"
#include "x11_display.hpp"
#include "x11_factory.hpp"
#include "../commands/cmd_add_item.hpp"

#include <string>
#include <list>

X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
                          Window win, bool playOnDrop ):
    SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
    m_playOnDrop( playOnDrop )
{
}

void X11DragDrop::dndEnter( ldata_t data )
{
    Window src = data[0];

    // Retrieve available data types
    list<string> dataTypes;
    if( data[1] & 1 )   // More than 3 data types ?
    {
        Atom type;
        int format;
        unsigned long nitems, nbytes;
        Atom *dataList;
        Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 );
        XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False,
                            XA_ATOM, &type, &format, &nitems, &nbytes,
                            (unsigned char**)&dataList );
        for( unsigned long i=0; i<nitems; i++ )
        {
            string dataType = XGetAtomName( XDISPLAY, dataList[i] );
            dataTypes.push_back( dataType );
        }
        XFree( (void*)dataList );
    }
    else
    {
        for( int i = 2; i < 5; i++ )
        {
            if( data[i] != None )
            {
                string dataType = XGetAtomName( XDISPLAY, data[i] );
                dataTypes.push_back( dataType );
            }
        }
    }

    // Find the right target
    m_target = None;
    list<string>::iterator it;
    for( it = dataTypes.begin(); it != dataTypes.end(); it++ )
    {
        if( *it == "text/plain" || *it == "STRING" )
        {
            m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
            break;
        }
    }
}

void X11DragDrop::dndPosition( ldata_t data )
{
    Window src = data[0];
    Time time = data[2];

    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );

    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );

    // Convert the selection into the given target
    // NEEDED or it doesn't work!
    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
                       time );

    actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );

    XEvent event;
    event.type = ClientMessage;
    event.xclient.window = src;
    event.xclient.display = XDISPLAY;
    event.xclient.message_type = typeAtom;
    event.xclient.format = 32;
    event.xclient.data.l[0] = m_wnd;
    if( m_target != None )
    {
        // Accept the drop
        event.xclient.data.l[1] = 1;
    }
    else
    {
        // Do not accept the drop
        event.xclient.data.l[1] = 0;
    }
    int w = X11Factory::instance( getIntf() )->getScreenWidth();
    int h = X11Factory::instance( getIntf() )->getScreenHeight();
    event.xclient.data.l[2] = 0;
    event.xclient.data.l[3] = (w << 16) | h;
    event.xclient.data.l[4] = actionAtom;

    // Tell the source whether we accept the drop
    XSendEvent( XDISPLAY, src, False, 0, &event );
}

void X11DragDrop::dndLeave( ldata_t data )
{
}

void X11DragDrop::dndDrop( ldata_t data )
{
    Window src = data[0];
    Time time = data[2];

    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );

    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );

    // Convert the selection into the given target
    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
                       time );

    // Read the selection
    Atom type;
    int format;
    unsigned long nitems, nbytes;
    char *buffer;
    XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
                        AnyPropertyType, &type, &format, &nitems, &nbytes,
                        (unsigned char**)&buffer );
    string selection = "";
    if( buffer != NULL )
    {
        selection = buffer;
    }
    XFree( buffer );

    if( selection != "" )
    {
        // TODO: multiple files handling
        string::size_type end = selection.find( "\n", 0 );
        selection = selection.substr( 0, end - 1 );
        end = selection.find( "\r", 0 );
        selection = selection.substr( 0, end - 1 );

        // Find the protocol, if any
        if( selection.find( "file://", 0 ) == 0 )
        {
            selection.erase( 0, 7 );
        }

        char *psz_fileName = new char[selection.size() + 1];
        strncpy( psz_fileName, selection.c_str(), selection.size() + 1 );

        // Add the file
        CmdAddItem cmd( getIntf(), psz_fileName, m_playOnDrop );
        cmd.execute();

        delete[] psz_fileName;
    }

    // Tell the source we accepted the drop
    XEvent event;
    event.type = ClientMessage;
    event.xclient.window = src;
    event.xclient.display = XDISPLAY;
    event.xclient.message_type = typeAtom;
    event.xclient.format = 32;
    event.xclient.data.l[0] = m_wnd;
    event.xclient.data.l[1] = 1;            // drop accepted
    event.xclient.data.l[2] = actionAtom;
    XSendEvent( XDISPLAY, src, False, 0, &event );
}

#endif
<commit_msg>Skins2: Cosmetics and make better use of a test that's done anyway.<commit_after>/*****************************************************************************
 * x11_dragdrop.cpp
 *****************************************************************************
 * Copyright (C) 2003 the VideoLAN team
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulière <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifdef X11_SKINS

#include <X11/Xlib.h>
#include <X11/Xatom.h>

#include "x11_dragdrop.hpp"
#include "x11_display.hpp"
#include "x11_factory.hpp"
#include "../commands/cmd_add_item.hpp"

#include <string>
#include <list>

X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
                          Window win, bool playOnDrop ):
    SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
    m_playOnDrop( playOnDrop )
{
}

void X11DragDrop::dndEnter( ldata_t data )
{
    Window src = data[0];

    // Retrieve available data types
    list<string> dataTypes;
    if( data[1] & 1 )   // More than 3 data types ?
    {
        Atom type;
        int format;
        unsigned long nitems, nbytes;
        Atom *dataList;
        Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 );
        XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False,
                            XA_ATOM, &type, &format, &nitems, &nbytes,
                            (unsigned char**)&dataList );
        for( unsigned long i=0; i<nitems; i++ )
        {
            string dataType = XGetAtomName( XDISPLAY, dataList[i] );
            dataTypes.push_back( dataType );
        }
        XFree( (void*)dataList );
    }
    else
    {
        for( int i = 2; i < 5; i++ )
        {
            if( data[i] != None )
            {
                string dataType = XGetAtomName( XDISPLAY, data[i] );
                dataTypes.push_back( dataType );
            }
        }
    }

    // Find the right target
    m_target = None;
    list<string>::iterator it;
    for( it = dataTypes.begin(); it != dataTypes.end(); it++ )
    {
        if( *it == "text/plain" || *it == "STRING" )
        {
            m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
            break;
        }
    }
}

void X11DragDrop::dndPosition( ldata_t data )
{
    Window src = data[0];
    Time time = data[2];

    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );

    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );

    // Convert the selection into the given target
    // NEEDED or it doesn't work!
    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
                       time );

    actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );

    XEvent event;
    event.type = ClientMessage;
    event.xclient.window = src;
    event.xclient.display = XDISPLAY;
    event.xclient.message_type = typeAtom;
    event.xclient.format = 32;
    event.xclient.data.l[0] = m_wnd;
    // Accept the drop (1), or not (0).
    event.xclient.data.l[1] = m_target != None ? 1 : 0;
    OSFactory *pOsFactory = X11Factory::instance( getIntf() );
    int w = pOsFactory->getScreenWidth();
    int h = pOsFactory->getScreenHeight();
    event.xclient.data.l[2] = 0;
    event.xclient.data.l[3] = (w << 16) | h;
    event.xclient.data.l[4] = actionAtom;

    // Tell the source whether we accept the drop
    XSendEvent( XDISPLAY, src, False, 0, &event );
}

void X11DragDrop::dndLeave( ldata_t data )
{
}

void X11DragDrop::dndDrop( ldata_t data )
{
    Window src = data[0];
    Time time = data[2];

    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );

    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );

    // Convert the selection into the given target
    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
                       time );

    // Read the selection
    Atom type;
    int format;
    unsigned long nitems, nbytes;
    char *buffer;
    XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
                        AnyPropertyType, &type, &format, &nitems, &nbytes,
                        (unsigned char**)&buffer );
    string selection = "";
    if( buffer != NULL )
    {
        selection = buffer;
        XFree( buffer );
    }

    if( selection != "" )
    {
        // TODO: multiple files handling
        string::size_type end = selection.find( "\n", 0 );
        selection = selection.substr( 0, end - 1 );
        end = selection.find( "\r", 0 );
        selection = selection.substr( 0, end - 1 );

        // Find the protocol, if any
        if( selection.find( "file://", 0 ) == 0 )
        {
            selection.erase( 0, 7 );
        }

        char *psz_fileName = new char[selection.size() + 1];
        strncpy( psz_fileName, selection.c_str(), selection.size() + 1 );

        // Add the file
        CmdAddItem cmd( getIntf(), psz_fileName, m_playOnDrop );
        cmd.execute();

        delete[] psz_fileName;
    }

    // Tell the source we accepted the drop
    XEvent event;
    event.type = ClientMessage;
    event.xclient.window = src;
    event.xclient.display = XDISPLAY;
    event.xclient.message_type = typeAtom;
    event.xclient.format = 32;
    event.xclient.data.l[0] = m_wnd;
    event.xclient.data.l[1] = 1;            // drop accepted
    event.xclient.data.l[2] = actionAtom;
    XSendEvent( XDISPLAY, src, False, 0, &event );
}

#endif
<|endoftext|>


<commit_before>/*
	kopetemessagemanager.cpp - Manages all chats

	Copyright   : (c) 2002 by Martijn Klingens <klingens@kde.org>
                      (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>
		      (c) 2002 by Daniel Stone <dstone@kde.org>

	*************************************************************************
	*                                                                       *
	* This program is free software; you can redistribute it and/or modify  *
	* it under the terms of the GNU General Public License as published by  *
	* the Free Software Foundation; either version 2 of the License, or     *
	* (at your option) any later version.                                   *
	*                                                                       *
	*************************************************************************
*/

#include "kopetemessagemanager.h"
#include "kopetechatwindow.h"
#include "kopeteevent.h"
#include "kopete.h"
#include "kopeteprefs.h"

#include "kopetemessagelog.h"

#include <kcolorbutton.h>
#include <kdebug.h>
#include <klocale.h>
#include <knotifyclient.h>

#include <qstylesheet.h>

struct KMMPrivate {
	KopeteContactPtrList  				 mContactList;
	const KopeteContact  				*mUser;
	KopeteChatWindow 				*mChatWindow;
	KopeteEmailWindow 				*mEmailWindow, *mEmailReplyWindow;
	KopeteEvent 					*mUnreadMessageEvent;
	KopeteMessageList 				 mMessageQueue;
	KopeteMessageLog 				*mLogger;
	int 						 mReadMode;
	KopeteMessageManager::WidgetType		 mWidget;
	QMap<const KopeteContact *, QStringList> 	 resources;
	KopeteProtocol 					*mProtocol;
	bool 						 mSendEnabled;
	int                                              mId;
};

KopeteMessageManager::KopeteMessageManager( const KopeteContact *user, KopeteContactPtrList others,
		KopeteProtocol *protocol, int id, QString logFile, enum WidgetType widget,
		QObject *parent, const char *name) : QObject( parent, name)
{
	d = new KMMPrivate;
	d->mSendEnabled = true;
	d->mContactList = others;
	d->mUser = user;
	d->mChatWindow = 0L;
	d->mEmailWindow = 0L;
	d->mEmailReplyWindow = 0L;
	d->mUnreadMessageEvent = 0L;
	d->mProtocol = protocol;
	d->mWidget = widget;
	d->mId = id;

	readModeChanged();
	connect( KopetePrefs::prefs(), SIGNAL(queueChanged()), this, SLOT(readModeChanged()));

	if (!logFile.isEmpty())	{
		QString logFileName = "kopete/" + logFile;
		d->mLogger = new KopeteMessageLog(logFileName, this);
	}
	else
		d->mLogger = 0L;
}

KopeteMessageManager::~KopeteMessageManager()
{
	emit dying(this);
	delete d;
	d = 0;
}

void KopeteMessageManager::slotSendEnabled(bool e)
{
	d->mSendEnabled = e;
	if (d->mWidget == ChatWindow) {
		if (d->mChatWindow)
			d->mChatWindow->setSendEnabled(e);
	}
	if (d->mWidget == Email) {
		if (d->mEmailWindow)
			d->mEmailWindow->setSendEnabled(e);
	}
}

void KopeteMessageManager::newChatWindow() {
	if (d->mWidget == ChatWindow) {
		d->mChatWindow = new KopeteChatWindow(d->mUser, d->mContactList);
		d->mChatWindow->setSendEnabled(d->mSendEnabled);

		/* When the window is shown, we have to delete this contact event */
		kdDebug() << "[KopeteMessageManager] Connecting message box shown() to event killer" << endl;
		connect (d->mChatWindow, SIGNAL(shown()), this, SLOT(slotCancelUnreadMessageEvent()));
		connect (d->mChatWindow, SIGNAL(sendMessage(KopeteMessage &)), this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mChatWindow, SIGNAL(closeClicked()), this, SLOT(slotChatWindowClosing()));

		connect (this, SIGNAL(contactAdded(const KopeteContact *)), d->mChatWindow, SLOT(slotContactAdded(const KopeteContact *)));
		connect (this, SIGNAL(contactRemoved(const KopeteContact *)), d->mChatWindow, SLOT(slotContactRemoved(const KopeteContact *)));
	}
	if (d->mWidget == Email) {
		d->mEmailWindow = new KopeteEmailWindow(d->mUser, d->mContactList);
		d->mEmailWindow->setSendEnabled(d->mSendEnabled);
		connect (d->mEmailWindow, SIGNAL(shown()), this, SLOT(slotCancelUnreadMessageEvent()));
		connect (d->mEmailWindow, SIGNAL(sendMessage(KopeteMessage &)),
			 this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mEmailWindow, SIGNAL(closeClicked()), this, SLOT(slotChatWindowClosing()));
		connect (d->mEmailWindow, SIGNAL(replyClicked()), this, SLOT(slotReply()));
	}
}

void KopeteMessageManager::newReplyWindow() {
	if (d->mWidget == Email) {
		kdDebug() << "[KopeteMessageManager] newReplyWindow() called for email-type window" << endl;
		d->mEmailReplyWindow = new KopeteEmailWindow(d->mUser, d->mContactList);
		d->mEmailReplyWindow->setSendEnabled(true);
		d->mEmailReplyWindow->setReplyMode(true);
		d->mEmailReplyWindow->show();
		d->mEmailReplyWindow->raise();
		connect (d->mEmailReplyWindow, SIGNAL(sendMessage(KopeteMessage &)),
			 this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mEmailReplyWindow, SIGNAL(closeClicked()),
			 this, SLOT(slotReplyWindowClosing()));
	}
}

void KopeteMessageManager::setReadMode(int mode)
{
	if ((mode == Queued) || (mode == Popup))
	{
		d->mReadMode = mode;
	}
	else
	{
		kdDebug() << "[KopeteMessageManager] ERROR: unknown reading method, setting to default" << endl;
		d->mReadMode = Queued;
	}
}

int KopeteMessageManager::readMode() const
{
	return d->mReadMode;
}

KopeteMessageManager::WidgetType KopeteMessageManager::widget() const
{
	return d->mWidget;
}

void KopeteMessageManager::readMessages()
{
	if (d->mWidget == ChatWindow) {
		if (d->mChatWindow == 0L) {
			kdDebug() << "[KopeteMessageManager] mChatWindow just doesn't exist" << endl;
			newChatWindow();
		}
		if (d->mChatWindow->isMinimized())
			kdDebug() << "[KopeteMessageManager] mChatWindow is minimized" << endl;
		if (d->mChatWindow->isHidden())
			kdDebug() << "[KopeteMessageManager] mChatWindow is hidden" << endl;
		if(KopetePrefs::prefs()->raiseMsgWindow())
			d->mChatWindow->raise();	// make it top window
		for (KopeteMessageList::Iterator it = d->mMessageQueue.begin(); it != d->mMessageQueue.end(); it++)
		{
			kdDebug() << "[KopeteMessageManager] Inserting message from " << (*it).from()->displayName() << endl;
			emit messageReceived( *it );
			d->mChatWindow->messageReceived(*it);
		}
		d->mChatWindow->show();	// show message window again
	}
	else if (d->mWidget == Email) {
		if (d->mEmailWindow == 0L) {
			kdDebug() << "[KopeteMessageManager] mEmailWindow just doesn't exist" << endl;
			newChatWindow();
		}
		if (d->mEmailWindow->isMinimized())
			kdDebug() << "[KopeteMessageManager] mEmailWindow is minimized" << endl;
		if (d->mEmailWindow->isHidden())
			kdDebug() << "[KopeteMessageManager] mEmailWindow is hidden" << endl;
		if(KopetePrefs::prefs()->raiseMsgWindow())
			d->mEmailWindow->raise();
		for (KopeteMessageList::Iterator it = d->mMessageQueue.begin(); it != d->mMessageQueue.end(); it++) {
			kdDebug() << "[KopeteMessageManager] Inserting message from " << (*it).from()->displayName() << endl;
			emit messageReceived( *it );
			d->mEmailWindow->messageReceived(*it);
		}
		d->mEmailWindow->show();
	}
	else {
		kdDebug() << "[KopeteMessageManager] Widget is non-oldschool: " << d->mWidget << endl;
	}

	d->mMessageQueue.clear();
}

const KopeteContactPtrList& KopeteMessageManager::members() const
{
	return d->mContactList;
}

const KopeteContact* KopeteMessageManager::user() const
{
	return d->mUser;
}

const KopeteProtocol* KopeteMessageManager::protocol() const
{
	return d->mProtocol;
}

int KopeteMessageManager::id() const
{
	return d->mId;
}

void KopeteMessageManager::setID( int id )
{
	d->mId = id;
}

void KopeteMessageManager::slotReadMessages() {
	readMessages();
}

void KopeteMessageManager::slotReply() {
	kdDebug() << "[KopeteMessageManager] slotReply() called." << endl;
	if (d->mEmailReplyWindow == 0L) {
		/* PLTHARG! */
		kdDebug() << "[KopeteMessageManager] mEmailReplyWindow == 0L, calling nRW()" << endl;
		newReplyWindow();
	}
	else {
		kdDebug() << "[KopeteMessageManager] mEmailWindow != 0L, not starting a new one (duh)." << endl;
	}
}

void KopeteMessageManager::slotMessageSent(KopeteMessage &message) {

	emit messageQueued( message );
	emit messageSent(message, this);
	if ( KopetePrefs::prefs()->soundNotify() )
	    KNotifyClient::event("kopete_outgoing");
}

void KopeteMessageManager::slotChatWindowClosing() {
	if (d->mWidget == ChatWindow) {
		kdDebug() << "[KopeteMessageManager] Chat Window closed, now 0L" << endl;
		d->mChatWindow = 0L;
	}
	else if (d->mWidget == Email) {
		kdDebug() << "[KopeteMessageManager] Email Window closed, now 0L." << endl;
		delete d->mEmailWindow;
		d->mEmailWindow = 0L;
	}
}

void KopeteMessageManager::slotReplyWindowClosing() {
	if (d->mWidget == Email) {
		delete d->mEmailReplyWindow;
		d->mEmailReplyWindow = 0L;
	}
}

void KopeteMessageManager::slotCancelUnreadMessageEvent() {
	if (d->mUnreadMessageEvent == 0L)
	{
		kdDebug() << "[KopeteMessageManager] No event to delete" << endl;
	}
	else
	{
		kdDebug() << "[KopeteMessageManager] cancelUnreadMessageEvent Deleting Event" << endl;
		delete d->mUnreadMessageEvent;
		d->mUnreadMessageEvent = 0L;
		kdDebug() << "[KopeteMessageManager] cancelUnreadMessageEvent Event Deleted" << endl;
	}
}

void KopeteMessageManager::slotEventDeleted(KopeteEvent *e) {
	kdDebug() << "[KopeteMessageManager] Event done(), now 0L" << endl;
	if ( e == d->mUnreadMessageEvent)
		d->mUnreadMessageEvent = 0L;
}

void KopeteMessageManager::appendMessage( const KopeteMessage &msg ) {
	d->mMessageQueue.append(msg);

	if( d->mLogger )
	{
		d->mLogger->append( msg );
	}

	/* First stage, see what to do */
	bool isvisible = false;

	if (d->mWidget == ChatWindow) {
		if (d->mChatWindow == 0L)
			newChatWindow();
		else if (!d->mChatWindow->isVisible())
			isvisible = false;
		else
			isvisible = true;
	}
	else if (d->mWidget == Email) {
		if (d->mEmailWindow == 0L)
			newChatWindow();
		else if (!d->mEmailWindow->isVisible())
			isvisible = false;
		else
			isvisible = true;
	}

	if (d->mReadMode == Popup)
		readMessages();
	else if (d->mReadMode == Queued) {
		/* Second stage, do it */
		if (isvisible) {
			readMessages();
		}
		else { /* Bug, WHOOHOO! If a window's on another desktop, we queue regardless. Grrr. */
			/* Create an event if a prevoius one not exist */
			if ((d->mUnreadMessageEvent == 0L) && (msg.direction() == KopeteMessage::Inbound)) {
		 		d->mUnreadMessageEvent = new KopeteEvent( i18n("Message from %1").arg(msg.from()->displayName()),
									       "kopete/pics/newmsg.png", this, SLOT(slotReadMessages()));
				connect(d->mUnreadMessageEvent, SIGNAL(done(KopeteEvent *)),
					this, SLOT(slotEventDeleted(KopeteEvent *)));
				kopeteapp->notifyEvent( d->mUnreadMessageEvent );
			}
		}
	}
	if ( KopetePrefs::prefs()->soundNotify() && isvisible && (msg.direction() != KopeteMessage::Outbound) )
	    KNotifyClient::event("kopete_incoming");
}
void KopeteMessageManager::addContact( const KopeteContact *c )
{
	kdDebug() << "KopeteMessageManager::addContact" <<endl;
	for ( KopeteContact *tmp = d->mContactList.first(); tmp; tmp = d->mContactList.next() )
	{
		if ( tmp == c )
		{
			kdDebug() << "[KopeteMessageManager] Contact already exists" <<endl;
			return;
		}
	}

	kdDebug() << "[KopeteMessageManager] Contact Joined session" <<endl;
	d->mContactList.append(c);
	emit contactAdded(c);
}

void KopeteMessageManager::removeContact( const KopeteContact *c )
{
	if(d->mContactList.count()==1)
	{
		kdDebug() << "KopeteMessageManager::removeContact - Contact not removed. Keep always one contact" <<endl;
	}
	else
	{
		d->mContactList.take( d->mContactList.find(c) );
		emit contactRemoved(c);
	}
}

void KopeteMessageManager::readModeChanged()
{
	if ( KopetePrefs::prefs()->useQueue() )
	{
		d->mReadMode = Queued;
	}
	else
	{
		d->mReadMode = Popup;
	}
}

#include "kopetemessagemanager.moc"
/*
 * Local variables:
 * c-indentation-style: k&r
 * c-basic-offset: 8
 * indent-tabs-mode: t
 * End:
 */
// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>- don't raise() and show() the message window on own messages (this was   really annoying) - remove some code duplication<commit_after>/*
	kopetemessagemanager.cpp - Manages all chats

	Copyright   : (c) 2002 by Martijn Klingens <klingens@kde.org>
                      (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>
		      (c) 2002 by Daniel Stone <dstone@kde.org>

	*************************************************************************
	*                                                                       *
	* This program is free software; you can redistribute it and/or modify  *
	* it under the terms of the GNU General Public License as published by  *
	* the Free Software Foundation; either version 2 of the License, or     *
	* (at your option) any later version.                                   *
	*                                                                       *
	*************************************************************************
*/

#include "kopetemessagemanager.h"
#include "kopetechatwindow.h"
#include "kopeteevent.h"
#include "kopete.h"
#include "kopeteprefs.h"

#include "kopetemessagelog.h"

#include <kcolorbutton.h>
#include <kdebug.h>
#include <klocale.h>
#include <knotifyclient.h>

#include <qstylesheet.h>

struct KMMPrivate {
	KopeteContactPtrList  				 mContactList;
	const KopeteContact  				*mUser;
	KopeteChatWindow 				*mChatWindow;
	KopeteEmailWindow 				*mEmailWindow, *mEmailReplyWindow;
	KopeteEvent 					*mUnreadMessageEvent;
	KopeteMessageList 				 mMessageQueue;
	KopeteMessageLog 				*mLogger;
	int 						 mReadMode;
	KopeteMessageManager::WidgetType		 mWidget;
	QMap<const KopeteContact *, QStringList> 	 resources;
	KopeteProtocol 					*mProtocol;
	bool 						 mSendEnabled;
	int                                              mId;
};

KopeteMessageManager::KopeteMessageManager( const KopeteContact *user, KopeteContactPtrList others,
		KopeteProtocol *protocol, int id, QString logFile, enum WidgetType widget,
		QObject *parent, const char *name) : QObject( parent, name)
{
	d = new KMMPrivate;
	d->mSendEnabled = true;
	d->mContactList = others;
	d->mUser = user;
	d->mChatWindow = 0L;
	d->mEmailWindow = 0L;
	d->mEmailReplyWindow = 0L;
	d->mUnreadMessageEvent = 0L;
	d->mProtocol = protocol;
	d->mWidget = widget;
	d->mId = id;

	readModeChanged();
	connect( KopetePrefs::prefs(), SIGNAL(queueChanged()), this, SLOT(readModeChanged()));

	if (!logFile.isEmpty())	{
		QString logFileName = "kopete/" + logFile;
		d->mLogger = new KopeteMessageLog(logFileName, this);
	}
	else
		d->mLogger = 0L;
}

KopeteMessageManager::~KopeteMessageManager()
{
	emit dying(this);
	delete d;
	d = 0;
}

void KopeteMessageManager::slotSendEnabled(bool e)
{
	d->mSendEnabled = e;
	if (d->mWidget == ChatWindow) {
		if (d->mChatWindow)
			d->mChatWindow->setSendEnabled(e);
	}
	if (d->mWidget == Email) {
		if (d->mEmailWindow)
			d->mEmailWindow->setSendEnabled(e);
	}
}

void KopeteMessageManager::newChatWindow() {
	if (d->mWidget == ChatWindow) {
		d->mChatWindow = new KopeteChatWindow(d->mUser, d->mContactList);
		d->mChatWindow->setSendEnabled(d->mSendEnabled);

		/* When the window is shown, we have to delete this contact event */
		kdDebug() << "[KopeteMessageManager] Connecting message box shown() to event killer" << endl;
		connect (d->mChatWindow, SIGNAL(shown()), this, SLOT(slotCancelUnreadMessageEvent()));
		connect (d->mChatWindow, SIGNAL(sendMessage(KopeteMessage &)), this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mChatWindow, SIGNAL(closeClicked()), this, SLOT(slotChatWindowClosing()));

		connect (this, SIGNAL(contactAdded(const KopeteContact *)), d->mChatWindow, SLOT(slotContactAdded(const KopeteContact *)));
		connect (this, SIGNAL(contactRemoved(const KopeteContact *)), d->mChatWindow, SLOT(slotContactRemoved(const KopeteContact *)));
	}
	if (d->mWidget == Email) {
		d->mEmailWindow = new KopeteEmailWindow(d->mUser, d->mContactList);
		d->mEmailWindow->setSendEnabled(d->mSendEnabled);
		connect (d->mEmailWindow, SIGNAL(shown()), this, SLOT(slotCancelUnreadMessageEvent()));
		connect (d->mEmailWindow, SIGNAL(sendMessage(KopeteMessage &)),
			 this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mEmailWindow, SIGNAL(closeClicked()), this, SLOT(slotChatWindowClosing()));
		connect (d->mEmailWindow, SIGNAL(replyClicked()), this, SLOT(slotReply()));
	}
}

void KopeteMessageManager::newReplyWindow() {
	if (d->mWidget == Email) {
		kdDebug() << "[KopeteMessageManager] newReplyWindow() called for email-type window" << endl;
		d->mEmailReplyWindow = new KopeteEmailWindow(d->mUser, d->mContactList);
		d->mEmailReplyWindow->setSendEnabled(true);
		d->mEmailReplyWindow->setReplyMode(true);
		d->mEmailReplyWindow->show();
		d->mEmailReplyWindow->raise();
		connect (d->mEmailReplyWindow, SIGNAL(sendMessage(KopeteMessage &)),
			 this, SLOT(slotMessageSent(KopeteMessage &)));
		connect (d->mEmailReplyWindow, SIGNAL(closeClicked()),
			 this, SLOT(slotReplyWindowClosing()));
	}
}

void KopeteMessageManager::setReadMode(int mode)
{
	if ((mode == Queued) || (mode == Popup))
	{
		d->mReadMode = mode;
	}
	else
	{
		kdDebug() << "[KopeteMessageManager] ERROR: unknown reading method, setting to default" << endl;
		d->mReadMode = Queued;
	}
}

int KopeteMessageManager::readMode() const
{
	return d->mReadMode;
}

KopeteMessageManager::WidgetType KopeteMessageManager::widget() const
{
	return d->mWidget;
}

void KopeteMessageManager::readMessages()
{
	if ((d->mWidget == ChatWindow && !d->mChatWindow) ||
	    (d->mWidget == Email && !d->mEmailWindow) ) {
		kdDebug() << "[KopeteMessageManager] mChatWindow just doesn't exist" << endl;
		newChatWindow();
	}

	QWidget *window = (d->mWidget == ChatWindow) ? d->mChatWindow : ((d->mWidget == Email) ? d->mEmailWindow : 0L);
	if ( !window ) {
		kdDebug() << "[KopeteMessageManager] Widget is non-oldschool: " << d->mWidget << endl;
		d->mMessageQueue.clear();
		return;
	}

	if (window->isMinimized())
		kdDebug() << "[KopeteMessageManager] window is minimized" << endl;
	if (window->isHidden())
		kdDebug() << "[KopeteMessageManager] window is hidden" << endl;

	bool foreignMessage = false;
	for (KopeteMessageList::Iterator it = d->mMessageQueue.begin(); it != d->mMessageQueue.end(); it++)
	{
		kdDebug() << "[KopeteMessageManager] Inserting message from " << (*it).from()->displayName() << endl;
		if ( (*it).from() != d->mUser )
			foreignMessage = true;

		emit messageReceived( *it );
		if ( d->mWidget == ChatWindow ) // ### why don't they implement the same interface?
			d->mChatWindow->messageReceived(*it);
		else if ( d->mWidget == Email )
			d->mEmailWindow->messageReceived(*it);
	}

	// only show the window when a message from someone else (i.e. not an own message) arrived or
	// when no message at all arrived (happens when you click on a contact, creating the window)
	if ( foreignMessage || d->mMessageQueue.isEmpty() )
	{
		if(KopetePrefs::prefs()->raiseMsgWindow())
			window->raise(); // make it top window

		window->show();	// show message window again (but not for own messages)
	}

	d->mMessageQueue.clear();
}

const KopeteContactPtrList& KopeteMessageManager::members() const
{
	return d->mContactList;
}

const KopeteContact* KopeteMessageManager::user() const
{
	return d->mUser;
}

const KopeteProtocol* KopeteMessageManager::protocol() const
{
	return d->mProtocol;
}

int KopeteMessageManager::id() const
{
	return d->mId;
}

void KopeteMessageManager::setID( int id )
{
	d->mId = id;
}

void KopeteMessageManager::slotReadMessages() {
	readMessages();
}

void KopeteMessageManager::slotReply() {
	kdDebug() << "[KopeteMessageManager] slotReply() called." << endl;
	if (d->mEmailReplyWindow == 0L) {
		/* PLTHARG! */
		kdDebug() << "[KopeteMessageManager] mEmailReplyWindow == 0L, calling nRW()" << endl;
		newReplyWindow();
	}
	else {
		kdDebug() << "[KopeteMessageManager] mEmailWindow != 0L, not starting a new one (duh)." << endl;
	}
}

void KopeteMessageManager::slotMessageSent(KopeteMessage &message) {

	emit messageQueued( message );
	emit messageSent(message, this);
	if ( KopetePrefs::prefs()->soundNotify() )
	    KNotifyClient::event("kopete_outgoing");
}

void KopeteMessageManager::slotChatWindowClosing() {
	if (d->mWidget == ChatWindow) {
		kdDebug() << "[KopeteMessageManager] Chat Window closed, now 0L" << endl;
		d->mChatWindow = 0L;
	}
	else if (d->mWidget == Email) {
		kdDebug() << "[KopeteMessageManager] Email Window closed, now 0L." << endl;
		delete d->mEmailWindow;
		d->mEmailWindow = 0L;
	}
}

void KopeteMessageManager::slotReplyWindowClosing() {
	if (d->mWidget == Email) {
		delete d->mEmailReplyWindow;
		d->mEmailReplyWindow = 0L;
	}
}

void KopeteMessageManager::slotCancelUnreadMessageEvent() {
	if (d->mUnreadMessageEvent == 0L)
	{
		kdDebug() << "[KopeteMessageManager] No event to delete" << endl;
	}
	else
	{
		kdDebug() << "[KopeteMessageManager] cancelUnreadMessageEvent Deleting Event" << endl;
		delete d->mUnreadMessageEvent;
		d->mUnreadMessageEvent = 0L;
		kdDebug() << "[KopeteMessageManager] cancelUnreadMessageEvent Event Deleted" << endl;
	}
}

void KopeteMessageManager::slotEventDeleted(KopeteEvent *e) {
	kdDebug() << "[KopeteMessageManager] Event done(), now 0L" << endl;
	if ( e == d->mUnreadMessageEvent)
		d->mUnreadMessageEvent = 0L;
}

void KopeteMessageManager::appendMessage( const KopeteMessage &msg ) {
	d->mMessageQueue.append(msg);

	if( d->mLogger )
	{
		d->mLogger->append( msg );
	}

	/* First stage, see what to do */
	bool isvisible = false;

	if (d->mWidget == ChatWindow) {
		if (d->mChatWindow == 0L)
			newChatWindow();
		else if (!d->mChatWindow->isVisible())
			isvisible = false;
		else
			isvisible = true;
	}
	else if (d->mWidget == Email) {
		if (d->mEmailWindow == 0L)
			newChatWindow();
		else if (!d->mEmailWindow->isVisible())
			isvisible = false;
		else
			isvisible = true;
	}

	if (d->mReadMode == Popup)
		readMessages();
	else if (d->mReadMode == Queued) {
		/* Second stage, do it */
		if (isvisible) {
			readMessages();
		}
		else { /* Bug, WHOOHOO! If a window's on another desktop, we queue regardless. Grrr. */
			/* Create an event if a prevoius one not exist */
			if ((d->mUnreadMessageEvent == 0L) && (msg.direction() == KopeteMessage::Inbound)) {
		 		d->mUnreadMessageEvent = new KopeteEvent( i18n("Message from %1").arg(msg.from()->displayName()),
									       "kopete/pics/newmsg.png", this, SLOT(slotReadMessages()));
				connect(d->mUnreadMessageEvent, SIGNAL(done(KopeteEvent *)),
					this, SLOT(slotEventDeleted(KopeteEvent *)));
				kopeteapp->notifyEvent( d->mUnreadMessageEvent );
			}
		}
	}
	if ( KopetePrefs::prefs()->soundNotify() && isvisible && (msg.direction() != KopeteMessage::Outbound) )
	    KNotifyClient::event("kopete_incoming");
}
void KopeteMessageManager::addContact( const KopeteContact *c )
{
	kdDebug() << "KopeteMessageManager::addContact" <<endl;
	for ( KopeteContact *tmp = d->mContactList.first(); tmp; tmp = d->mContactList.next() )
	{
		if ( tmp == c )
		{
			kdDebug() << "[KopeteMessageManager] Contact already exists" <<endl;
			return;
		}
	}

	kdDebug() << "[KopeteMessageManager] Contact Joined session" <<endl;
	d->mContactList.append(c);
	emit contactAdded(c);
}

void KopeteMessageManager::removeContact( const KopeteContact *c )
{
	if(d->mContactList.count()==1)
	{
		kdDebug() << "KopeteMessageManager::removeContact - Contact not removed. Keep always one contact" <<endl;
	}
	else
	{
		d->mContactList.take( d->mContactList.find(c) );
		emit contactRemoved(c);
	}
}

void KopeteMessageManager::readModeChanged()
{
	if ( KopetePrefs::prefs()->useQueue() )
	{
		d->mReadMode = Queued;
	}
	else
	{
		d->mReadMode = Popup;
	}
}

#include "kopetemessagemanager.moc"
/*
 * Local variables:
 * c-indentation-style: k&r
 * c-basic-offset: 8
 * indent-tabs-mode: t
 * End:
 */
// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2013, Pelagicore AB <jonatan.palsson@pelagicore.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

Config::Config() : root(0)
{
}

Config::~Config()
{
	if (root) {
		json_decref(root);
	}
}

int Config::read(const char *path)
{
	if (root) {
		printf("Already loaded configuration!");
		return -EINVAL;
	}

	json_error_t error;

	root = json_load_file(path, 0, &error);

	if (!root) {
		printf("error: on line %d: %s\n", error.line, error.text);
		return -EINVAL;
	}

	debug("Using config file %s\n", path);
	return 0;
}

char *Config::getString(const char *property)
{
	json_t *element = NULL;

	if (root == NULL) {
		debug ("Root JSON object is not initialized");
		return NULL;
	}

	element = json_object_get(root, property);
	if (json_is_string (element)) {
		debug ("%s is called on a string\n", __FUNCTION__);
		return strdup (json_string_value (element));
	} else if (json_is_array (element)) {
		debug ("%s is called on an array\n", __FUNCTION__);
		size_t  len    = json_array_size (element);
		size_t  buflen = 100;
		int     j      = 0;
		char   *buf    = (char*)calloc (sizeof (char), buflen);

		for (int i = 0; i < len; i++) {
			json_t *line    = json_array_get (element, i);
			const char   *strline = json_string_value (line);
			int     linelen = 0;

			/* Entire array must be strings */
			if (!json_is_string (line)) {
				debug ("line %d is not a string!\n", i);
				free (buf);
				return NULL;
			}

			/* Ensure new string fits in buffer */
			linelen = strlen (strline);
			if (j + linelen > buflen) {
				debug ("buf is %d, and line is %d\n", buflen, linelen);
				buflen = (j + strlen (strline)) * 2;
				char *newbuf = (char*)calloc (sizeof (char), buflen);

				strncpy (newbuf, buf, buflen);
				free (buf);
				buf = newbuf;
				j += linelen;
			}

			/* We already ensured this fits */
			if (i > 0)
				strcat (buf, "\n");

			strcat (buf, strline);
		}

		return buf;
	}

	debug ("%s is called on an unknown type\n", __FUNCTION__);
	return NULL;
}
<commit_msg>config: Fixed memory trashing when reading arrays longer than 100 bytes<commit_after>/*
 * Copyright (C) 2013, Pelagicore AB <jonatan.palsson@pelagicore.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

Config::Config() : root(0)
{
}

Config::~Config()
{
	if (root) {
		json_decref(root);
	}
}

int Config::read(const char *path)
{
	if (root) {
		printf("Already loaded configuration!");
		return -EINVAL;
	}

	json_error_t error;

	root = json_load_file(path, 0, &error);

	if (!root) {
		printf("error: on line %d: %s\n", error.line, error.text);
		return -EINVAL;
	}

	debug("Using config file %s\n", path);
	return 0;
}

char *Config::getString(const char *property)
{
	json_t *element = NULL;

	if (root == NULL) {
		debug ("Root JSON object is not initialized");
		return NULL;
	}

	element = json_object_get(root, property);
	if (json_is_string (element)) {
		debug ("%s is called on a string\n", __FUNCTION__);
		return strdup (json_string_value (element));
	} else if (json_is_array (element)) {
		debug ("%s is called on an array\n", __FUNCTION__);
		size_t  len    = json_array_size (element);
		int  buflen = 100;
		int     j      = 0;
		char   *buf    = (char*)calloc (sizeof (char), buflen);

		for (int i = 0; i < len; i++) {
			json_t *line    = json_array_get (element, i);
			const char *strline = json_string_value (line);
			int     linelen = 0;

			/* Entire array must be strings */
			if (!json_is_string (line)) {
				debug ("line %d is not a string!\n", i);
				free (buf);
				return NULL;
			}

			/* Ensure new string fits in buffer */
			linelen = strlen (strline);
			if (j + linelen > buflen) {
				debug ("buf is %d, and line is %d\n", buflen, linelen);
				buflen = (j + strlen (strline)) * 2;
				char *newbuf = (char*)calloc (sizeof (char), buflen);

				strncpy (newbuf, buf, buflen);
				free (buf);
				buf = newbuf;
			}
			j += linelen;

			/* We already ensured this fits */
			if (i > 0)
				strcat (buf, "\n");

			strcat (buf, strline);
		}

		return buf;
	}

	debug ("%s is called on an unknown type\n", __FUNCTION__);
	return NULL;
}
<|endoftext|>


<commit_before>/* The MIT License (MIT)

Copyright (c) 2015 Gabriel Corona

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <cstdlib>

#include <regex>

#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#else
#define SD_LISTEN_FDS_START 3
#endif

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options.hpp>

#include "dnsfwd.hpp"

namespace {

static const char* kernel_logformat[8] = {
  "<0>",
  "<1>",
  "<2>",
  "<3>",
  "<4>",
  "<5>",
  "<6>",
  "<7>"
};

static const char* daemon_logformat[8] = {
  "<24>",
  "<25>",
  "<26>",
  "<27>",
  "<28>",
  "<29>",
  "<30>",
  "<31>"
};

static const char* human_logformat[8] = {
  "EMERG: ",
  "ALERT: ",
  "CRIT: ",
  "ERR: ",
  "WARN: ",
  "NOTICE: ",
  "INFO: ",
  "DEBUG: "
};

}

namespace dnsfwd {

int loglevel = 5;

const char** logformat = kernel_logformat;

namespace {

endpoint parse_endpoint(std::string const& e)
{

  std::smatch match;

  std::regex ipv6_port("^\\[([^\\]]*)\\]:([0-9a-zA-Z]*)$");
  std::regex ipv6_no_port("^\\[([^\\]]*)\\]$");
  std::regex other_port("^([^:]*):([0-9a-zA-Z]*)$");
  std::regex other_no_port("^([^:]*)$");

  if (std::regex_match(e, match, ipv6_port)
    || std::regex_match(e, match, ipv6_no_port)
    || std::regex_match(e, match, other_port)
    || std::regex_match(e, match, other_no_port)) {
    endpoint res;
    res.name = match[1];
    if (match.size() > 1)
      res.port = match[2];
    return std::move(res);
  } else {
    LOG(ERR) << "Invalid endpoint specification\n";
    std::exit(1);
  }
}

}

boost::asio::ip::udp::endpoint endpoint::udp_endpoint(
  boost::asio::io_service& service, const char* default_port) const
{
  boost::asio::ip::udp::resolver resolver(service);
  boost::asio::ip::udp::resolver::query query(
    this->name, this->port.empty() ? default_port : this->port);
  boost::asio::ip::udp::resolver::iterator endpoint_iterator =
    resolver.resolve(query);
  boost::asio::ip::udp::resolver::iterator end;
  return *endpoint_iterator;
}

void setup_config(dnsfwd::config& config, int argc, char** argv)
{
  using boost::program_options::options_description;
  using boost::program_options::value;
  using boost::program_options::variables_map;
  using boost::program_options::store;
  using boost::program_options::option;
  using boost::program_options::notify;
  using boost::program_options::parse_command_line;
  using boost::program_options::command_line_parser;
  using boost::program_options::positional_options_description;

  options_description desc("Allowed options");
  desc.add_options()
    ("help", "help")
    ("bind-udp", value<std::vector<std::string>>(), "bind to the given UDP address")
    ("connect-tcp", value<std::vector<std::string>>(), "connect to the given TCP endpoint")
    ("loglevel", value<int>(), "loglevel")
    ("logformat", value<std::string>(), "logformat")
    ;

  variables_map vm;
  store(command_line_parser(argc, argv).options(desc).run(), vm);
  notify(vm);

  if (vm.count("help")) {
    std::cout << desc << "\n";
    std::exit(0);
  }

  if (vm.count("logformat")) {
    std::string format = vm["logformat"].as<std::string>();
    if (format == "kernel") {
      logformat = kernel_logformat;
    } else if (format == "daemon") {
      logformat = daemon_logformat;
    } else if (format == "human") {
      logformat = human_logformat;
    } else {
      LOG(ERR) << "unexpected log format\n";
      std::exit(1);
    }
  }

  if (vm.count("loglevel")) {
    int loglevel = vm["loglevel"].as<int>();
    if (loglevel < 0 || loglevel > 8) {
      LOG(ERR) << "unexpected loglevel\n";
      std::exit(1);
    }
    ::dnsfwd::loglevel = loglevel;
  }

  if (vm.count("bind-udp"))
    for (std::string const& e : vm["bind-udp"].as<std::vector<std::string>>())
      config.bind_udp.push_back(parse_endpoint(e));
  if (vm.count("connect-tcp"))
    for (std::string const& e : vm["connect-tcp"].as<std::vector<std::string>>())
      config.connect_tcp.push_back(parse_endpoint(e));

  #ifdef USE_SYSTEMD
    if (!config.listen_fds) {
      config.listen_fds = sd_listen_fds(1);
      if (config.listen_fds < 0)
        config.listen_fds = 0;
    }
  #endif
}

}
<commit_msg>Remove useless std::move()<commit_after>/* The MIT License (MIT)

Copyright (c) 2015 Gabriel Corona

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include <cstdlib>

#include <regex>

#ifdef USE_SYSTEMD
#include <systemd/sd-daemon.h>
#else
#define SD_LISTEN_FDS_START 3
#endif

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options.hpp>

#include "dnsfwd.hpp"

namespace {

static const char* kernel_logformat[8] = {
  "<0>",
  "<1>",
  "<2>",
  "<3>",
  "<4>",
  "<5>",
  "<6>",
  "<7>"
};

static const char* daemon_logformat[8] = {
  "<24>",
  "<25>",
  "<26>",
  "<27>",
  "<28>",
  "<29>",
  "<30>",
  "<31>"
};

static const char* human_logformat[8] = {
  "EMERG: ",
  "ALERT: ",
  "CRIT: ",
  "ERR: ",
  "WARN: ",
  "NOTICE: ",
  "INFO: ",
  "DEBUG: "
};

}

namespace dnsfwd {

int loglevel = 5;

const char** logformat = kernel_logformat;

namespace {

endpoint parse_endpoint(std::string const& e)
{

  std::smatch match;

  std::regex ipv6_port("^\\[([^\\]]*)\\]:([0-9a-zA-Z]*)$");
  std::regex ipv6_no_port("^\\[([^\\]]*)\\]$");
  std::regex other_port("^([^:]*):([0-9a-zA-Z]*)$");
  std::regex other_no_port("^([^:]*)$");

  if (std::regex_match(e, match, ipv6_port)
    || std::regex_match(e, match, ipv6_no_port)
    || std::regex_match(e, match, other_port)
    || std::regex_match(e, match, other_no_port)) {
    endpoint res;
    res.name = match[1];
    if (match.size() > 1)
      res.port = match[2];
    return res;
  } else {
    LOG(ERR) << "Invalid endpoint specification\n";
    std::exit(1);
  }
}

}

boost::asio::ip::udp::endpoint endpoint::udp_endpoint(
  boost::asio::io_service& service, const char* default_port) const
{
  boost::asio::ip::udp::resolver resolver(service);
  boost::asio::ip::udp::resolver::query query(
    this->name, this->port.empty() ? default_port : this->port);
  boost::asio::ip::udp::resolver::iterator endpoint_iterator =
    resolver.resolve(query);
  boost::asio::ip::udp::resolver::iterator end;
  return *endpoint_iterator;
}

void setup_config(dnsfwd::config& config, int argc, char** argv)
{
  using boost::program_options::options_description;
  using boost::program_options::value;
  using boost::program_options::variables_map;
  using boost::program_options::store;
  using boost::program_options::option;
  using boost::program_options::notify;
  using boost::program_options::parse_command_line;
  using boost::program_options::command_line_parser;
  using boost::program_options::positional_options_description;

  options_description desc("Allowed options");
  desc.add_options()
    ("help", "help")
    ("bind-udp", value<std::vector<std::string>>(), "bind to the given UDP address")
    ("connect-tcp", value<std::vector<std::string>>(), "connect to the given TCP endpoint")
    ("loglevel", value<int>(), "loglevel")
    ("logformat", value<std::string>(), "logformat")
    ;

  variables_map vm;
  store(command_line_parser(argc, argv).options(desc).run(), vm);
  notify(vm);

  if (vm.count("help")) {
    std::cout << desc << "\n";
    std::exit(0);
  }

  if (vm.count("logformat")) {
    std::string format = vm["logformat"].as<std::string>();
    if (format == "kernel") {
      logformat = kernel_logformat;
    } else if (format == "daemon") {
      logformat = daemon_logformat;
    } else if (format == "human") {
      logformat = human_logformat;
    } else {
      LOG(ERR) << "unexpected log format\n";
      std::exit(1);
    }
  }

  if (vm.count("loglevel")) {
    int loglevel = vm["loglevel"].as<int>();
    if (loglevel < 0 || loglevel > 8) {
      LOG(ERR) << "unexpected loglevel\n";
      std::exit(1);
    }
    ::dnsfwd::loglevel = loglevel;
  }

  if (vm.count("bind-udp"))
    for (std::string const& e : vm["bind-udp"].as<std::vector<std::string>>())
      config.bind_udp.push_back(parse_endpoint(e));
  if (vm.count("connect-tcp"))
    for (std::string const& e : vm["connect-tcp"].as<std::vector<std::string>>())
      config.connect_tcp.push_back(parse_endpoint(e));

  #ifdef USE_SYSTEMD
    if (!config.listen_fds) {
      config.listen_fds = sd_listen_fds(1);
      if (config.listen_fds < 0)
        config.listen_fds = 0;
    }
  #endif
}

}
<|endoftext|>


<commit_before>/*******************************************************************************
 * libproxy - A library for proxy configuration
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include <cstdlib>

#include "../extension_config.hpp"
using namespace libproxy;

class envvar_config_extension : public config_extension {
public:
	vector<url> get_config(const url &dst) {
		const char *proxy = NULL;
                vector<url> response;

		// If the URL is an ftp url, try to read the ftp proxy
		if (dst.get_scheme() == "ftp") {
			if (!(proxy = getenv("ftp_proxy")))
				proxy = getenv("FTP_PROXY");
		}

		// If the URL is an https url, try to read the https proxy
		if (dst.get_scheme() == "https") {
			if (!(proxy = getenv("https_proxy")))
				proxy = getenv("HTTPS_PROXY");
		}

		// If the URL is not ftp or no ftp_proxy was found, get the http_proxy
		if (!proxy) {
			if (!(proxy = getenv("http_proxy")))
				proxy = getenv("HTTP_PROXY");
		}

		if (!proxy)
			throw runtime_error("Unable to read configuration");

                response.push_back(url(proxy));
		return response;
	}

	string get_ignore(const url&) {
		char *ignore = getenv("no_proxy");
		      ignore = ignore ? ignore : getenv("NO_PROXY");
		return string(ignore ? ignore : "");
	}

	// Make sure that envvar is pushed to the back behind all other config extensions
	virtual bool operator<(const base_extension&) const {
		return false;
	}
};

MM_MODULE_INIT_EZ(envvar_config_extension, true, NULL, NULL);
<commit_msg>config_envvar: Add environment variable for pacrunner debugging<commit_after>/*******************************************************************************
 * libproxy - A library for proxy configuration
 * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 ******************************************************************************/

#include <cstdlib>

#include "../extension_config.hpp"
using namespace libproxy;

class envvar_config_extension : public config_extension {
public:
	vector<url> get_config(const url &dst) {
		const char *proxy = NULL;
                vector<url> response;

		// If _PX_DEBUG_PACURL is set, use it as the PAC URL.
		if (proxy = getenv("_PX_DEBUG_PACURL")) {
			response.push_back(url(string("pac+") + proxy));
			return response;
		}

		// If the URL is an ftp url, try to read the ftp proxy
		if (dst.get_scheme() == "ftp") {
			if (!(proxy = getenv("ftp_proxy")))
				proxy = getenv("FTP_PROXY");
		}

		// If the URL is an https url, try to read the https proxy
		if (dst.get_scheme() == "https") {
			if (!(proxy = getenv("https_proxy")))
				proxy = getenv("HTTPS_PROXY");
		}

		// If the URL is not ftp or no ftp_proxy was found, get the http_proxy
		if (!proxy) {
			if (!(proxy = getenv("http_proxy")))
				proxy = getenv("HTTP_PROXY");
		}

		if (!proxy)
			throw runtime_error("Unable to read configuration");

                response.push_back(url(proxy));
		return response;
	}

	string get_ignore(const url&) {
		char *ignore = getenv("no_proxy");
		      ignore = ignore ? ignore : getenv("NO_PROXY");
		return string(ignore ? ignore : "");
	}

	// Make sure that envvar is pushed to the back behind all other config extensions
	virtual bool operator<(const base_extension&) const {
		return false;
	}
};

MM_MODULE_INIT_EZ(envvar_config_extension, true, NULL, NULL);
<|endoftext|>