text:
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <memory>
#include <set>

#include "base/bind.h"
#include "base/enterprise_util.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_service_factory.h"
#include "chrome/browser/net/dns_probe_test_util.h"
#include "chrome/browser/net/net_error_tab_helper.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/embedder_support/pref_names.h"
#include "components/error_page/common/net_error_info.h"
#include "components/google/core/common/google_util.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_WIN)
#include "base/win/win_util.h"
#endif

using base::BindOnce;
using base::BindRepeating;
using base::FilePath;
using base::Unretained;
using content::BrowserThread;
using content::WebContents;
using error_page::DnsProbeStatus;
using net::URLRequestFailedJob;
using ui_test_utils::NavigateToURL;

namespace chrome_browser_net {

namespace {

// Wraps DnsProbeService and delays probes until someone calls
// StartDelayedProbes.  This allows the DnsProbeBrowserTest to enforce a
// stricter ordering of events.
class DelayingDnsProbeService : public DnsProbeService {
 public:
  DelayingDnsProbeService(
      const DnsProbeServiceFactory::NetworkContextGetter&
          network_context_getter,
      const DnsProbeServiceFactory::DnsConfigChangeManagerGetter&
          dns_config_change_manager_getter)
      : dns_probe_service_impl_(DnsProbeServiceFactory::CreateForTesting(
            network_context_getter,
            dns_config_change_manager_getter,
            base::DefaultTickClock::GetInstance())) {}

  ~DelayingDnsProbeService() override { EXPECT_TRUE(delayed_probes_.empty()); }

  static std::unique_ptr<KeyedService> Create(
      const DnsProbeServiceFactory::NetworkContextGetter&
          network_context_getter,
      const DnsProbeServiceFactory::DnsConfigChangeManagerGetter&
          dns_config_change_manager_getter,
      content::BrowserContext* context) {
    return std::make_unique<DelayingDnsProbeService>(
        network_context_getter, dns_config_change_manager_getter);
  }

  void ProbeDns(ProbeCallback callback) override {
    delayed_probes_.push_back(std::move(callback));
  }

  net::DnsConfigOverrides GetCurrentConfigOverridesForTesting() override {
    return dns_probe_service_impl_->GetCurrentConfigOverridesForTesting();
  }

  void StartDelayedProbes() {
    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

    std::vector<ProbeCallback> probes;
    probes.swap(delayed_probes_);

    for (std::vector<ProbeCallback>::iterator i = probes.begin();
         i != probes.end(); ++i) {
      dns_probe_service_impl_->ProbeDns(std::move(*i));
    }
  }

  int delayed_probe_count() const {
    CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    return delayed_probes_.size();
  }

 private:
  std::unique_ptr<DnsProbeService> dns_probe_service_impl_;
  std::vector<ProbeCallback> delayed_probes_;
};

class DnsProbeBrowserTest : public InProcessBrowserTest {
 public:
  DnsProbeBrowserTest();
  ~DnsProbeBrowserTest() override;

  void SetUpOnMainThread() override;
  void TearDownOnMainThread() override;

 protected:
  bool InterceptURLLoaderRequest(
      content::URLLoaderInterceptor::RequestParams* params);

  // Sets the browser object that other methods apply to, and that has the
  // DnsProbeStatus messages of its currently active tab monitored.
  void SetActiveBrowser(Browser* browser);

  // Sets the results the FakeHostResolver will return for the current config
  // and Google config DnsProbeRunners. Since this mocks out the NetworkContext
  // and HostResolver used by the DnsProbeService it doesn't really give an
  // end-to-end test, but content::TestHostResolver mocks don't affect the
  // probes since they use HostResolverSource::DNS, so this is the best that
  // can be done currently.
  void SetFakeHostResolverResults(
      std::vector<FakeHostResolver::SingleResult> current_config_results,
      std::vector<FakeHostResolver::SingleResult> google_config_results);

  void NavigateToDnsError();
  void NavigateToOtherError();

  void StartDelayedProbes(int expected_delayed_probe_count);
  DnsProbeStatus WaitForSentStatus();
  int pending_status_count() const { return dns_probe_status_queue_.size(); }

  std::string Title();
  bool PageContains(const std::string& expected);

  // Checks that the error page is being displayed with the specified status
  // text.  The status text should be either a network error or DNS probe
  // status.
  void ExpectDisplayingErrorPage(const std::string& status_text);

 private:
  void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status);

  network::mojom::NetworkContext* GetNetworkContext() {
    return network_context_.get();
  }

  mojo::Remote<network::mojom::DnsConfigChangeManager>
  GetDnsConfigChangeManager();

  std::unique_ptr<FakeHostResolverNetworkContext> network_context_;
  std::unique_ptr<FakeDnsConfigChangeManager> dns_config_change_manager_;
  raw_ptr<DelayingDnsProbeService, DanglingUntriaged>
      delaying_dns_probe_service_;

  // Browser that methods apply to.
  raw_ptr<Browser, DanglingUntriaged> active_browser_;
  // Helper that current has its DnsProbeStatus messages monitored.
  raw_ptr<NetErrorTabHelper, DanglingUntriaged> monitored_tab_helper_;

  std::unique_ptr<base::RunLoop> awaiting_dns_probe_status_run_loop_;
  // Queue of statuses received but not yet consumed by WaitForSentStatus().
  std::list<DnsProbeStatus> dns_probe_status_queue_;

  std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_;
};

DnsProbeBrowserTest::DnsProbeBrowserTest()
    : active_browser_(nullptr), monitored_tab_helper_(nullptr) {}

DnsProbeBrowserTest::~DnsProbeBrowserTest() {
  // No tests should have any unconsumed probe statuses.
  EXPECT_EQ(0, pending_status_count());
}

void DnsProbeBrowserTest::SetUpOnMainThread() {
  NetErrorTabHelper::set_state_for_testing(NetErrorTabHelper::TESTING_DEFAULT);

  browser()->profile()->GetPrefs()->SetBoolean(
      embedder_support::kAlternateErrorPagesEnabled, true);

  ASSERT_TRUE(embedded_test_server()->Start());

  url_loader_interceptor_ = std::make_unique<content::URLLoaderInterceptor>(
      base::BindRepeating(&DnsProbeBrowserTest::InterceptURLLoaderRequest,
                          base::Unretained(this)));

  SetActiveBrowser(browser());
}

void DnsProbeBrowserTest::TearDownOnMainThread() {
  url_loader_interceptor_.reset();

  NetErrorTabHelper::set_state_for_testing(NetErrorTabHelper::TESTING_DEFAULT);
}

bool DnsProbeBrowserTest::InterceptURLLoaderRequest(
    content::URLLoaderInterceptor::RequestParams* params) {
  if (params->url_request.url.spec() == "http://mock.http/title2.html") {
    content::URLLoaderInterceptor::WriteResponse("chrome/test/data/title2.html",
                                                 params->client.get());
    return true;
  }

  // Just returning false is enough to respond to http(s)://mock.failed.request
  // requests, which are the only requests that come in besides the LinkDoctor
  // requests.
  return false;
}

void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) {
  delaying_dns_probe_service_ = static_cast<DelayingDnsProbeService*>(
      DnsProbeServiceFactory::GetInstance()->SetTestingFactoryAndUse(
          browser->profile(),
          base::BindRepeating(
              &DelayingDnsProbeService::Create,
              base::BindRepeating(&DnsProbeBrowserTest::GetNetworkContext,
                                  base::Unretained(this)),
              base::BindRepeating(
                  &DnsProbeBrowserTest::GetDnsConfigChangeManager,
                  base::Unretained(this)))));
  // If currently watching a NetErrorTabHelper, stop doing so before start
  // watching another.
  if (monitored_tab_helper_) {
    monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
        NetErrorTabHelper::DnsProbeStatusSnoopCallback());
  }
  active_browser_ = browser;
  monitored_tab_helper_ = NetErrorTabHelper::FromWebContents(
      active_browser_->tab_strip_model()->GetActiveWebContents());
  monitored_tab_helper_->set_dns_probe_status_snoop_callback_for_testing(
      BindRepeating(&DnsProbeBrowserTest::OnDnsProbeStatusSent,
                    Unretained(this)));
}

void DnsProbeBrowserTest::SetFakeHostResolverResults(
    std::vector<FakeHostResolver::SingleResult> current_config_results,
    std::vector<FakeHostResolver::SingleResult> google_config_results) {
  ASSERT_FALSE(network_context_);

  network_context_ = std::make_unique<FakeHostResolverNetworkContext>(
      std::move(current_config_results), std::move(google_config_results));
}

void DnsProbeBrowserTest::NavigateToDnsError() {
  ASSERT_TRUE(NavigateToURL(
      active_browser_,
      URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED)));
}

void DnsProbeBrowserTest::NavigateToOtherError() {
  ASSERT_TRUE(NavigateToURL(
      active_browser_,
      URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED)));
}

void DnsProbeBrowserTest::StartDelayedProbes(int expected_delayed_probe_count) {
  ASSERT_TRUE(delaying_dns_probe_service_);

  int actual_delayed_probe_count =
      delaying_dns_probe_service_->delayed_probe_count();
  EXPECT_EQ(expected_delayed_probe_count, actual_delayed_probe_count);

  delaying_dns_probe_service_->StartDelayedProbes();
}

DnsProbeStatus DnsProbeBrowserTest::WaitForSentStatus() {
  CHECK(!awaiting_dns_probe_status_run_loop_);
  while (dns_probe_status_queue_.empty()) {
    awaiting_dns_probe_status_run_loop_ = std::make_unique<base::RunLoop>();
    awaiting_dns_probe_status_run_loop_->Run();
    awaiting_dns_probe_status_run_loop_ = nullptr;
  }

  CHECK(!dns_probe_status_queue_.empty());
  DnsProbeStatus status = dns_probe_status_queue_.front();
  dns_probe_status_queue_.pop_front();
  return status;
}

// Check title by roundtripping to renderer, to make sure any probe results
// sent before this have been applied.
std::string DnsProbeBrowserTest::Title() {
  std::string title;

  WebContents* contents =
      active_browser_->tab_strip_model()->GetActiveWebContents();

  return content::EvalJs(contents, "document.title;").ExtractString();
}

// Check text by roundtripping to renderer, to make sure any probe results
// sent before this have been applied.
bool DnsProbeBrowserTest::PageContains(const std::string& expected) {
  std::string text_content =
      content::EvalJs(
          active_browser_->tab_strip_model()->GetActiveWebContents(),
          "document.body.textContent;")
          .ExtractString();

  return text_content.find(expected) != std::string::npos;
}

void DnsProbeBrowserTest::ExpectDisplayingErrorPage(
    const std::string& status_text) {
  EXPECT_FALSE(PageContains("http://mock.http/title2.html"));
  EXPECT_TRUE(PageContains(status_text));
}

void DnsProbeBrowserTest::OnDnsProbeStatusSent(
    DnsProbeStatus dns_probe_status) {
  dns_probe_status_queue_.push_back(dns_probe_status);
  if (awaiting_dns_probe_status_run_loop_)
    awaiting_dns_probe_status_run_loop_->Quit();
}

mojo::Remote<network::mojom::DnsConfigChangeManager>
DnsProbeBrowserTest::GetDnsConfigChangeManager() {
  mojo::Remote<network::mojom::DnsConfigChangeManager>
      dns_config_change_manager_remote;
  dns_config_change_manager_ = std::make_unique<FakeDnsConfigChangeManager>(
      dns_config_change_manager_remote.BindNewPipeAndPassReceiver());
  return dns_config_change_manager_remote;
}

// Test Fixture for tests where the DNS probes should succeed.
class DnsProbeSuccessfulProbesTest : public DnsProbeBrowserTest {
  void SetUpOnMainThread() override {
    SetFakeHostResolverResults({{net::OK, net::ResolveErrorInfo(net::OK),
                                 FakeHostResolver::kOneAddressResponse}},
                               {{net::OK, net::ResolveErrorInfo(net::OK),
                                 FakeHostResolver::kOneAddressResponse}});
    DnsProbeBrowserTest::SetUpOnMainThread();
  }
};

// Test Fixture for tests where the DNS probes should not resolve.
class DnsProbeFailingProbesTest : public DnsProbeBrowserTest {
  void SetUpOnMainThread() override {
    SetFakeHostResolverResults(
        {{net::ERR_NAME_NOT_RESOLVED,
          net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
          FakeHostResolver::kNoResponse}},
        {{net::ERR_NAME_NOT_RESOLVED,
          net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
          FakeHostResolver::kNoResponse}});
    DnsProbeBrowserTest::SetUpOnMainThread();
  }
};

class DnsProbeCurrentConfigFailingProbesTest : public DnsProbeBrowserTest {
 protected:
  void SetUpOnMainThread() override {
    SetFakeHostResolverResults(
        {{net::ERR_NAME_NOT_RESOLVED,
          net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
          FakeHostResolver::kNoResponse}},
        {{net::OK, net::ResolveErrorInfo(net::OK),
          FakeHostResolver::kOneAddressResponse}});
    DnsProbeBrowserTest::SetUpOnMainThread();
  }
};

class DnsProbeCurrentSecureConfigFailingProbesTest
    : public DnsProbeBrowserTest {
 protected:
  void SetUpInProcessBrowserTestFixture() override {
    // Normal boilerplate to setup a MockConfigurationPolicyProvider.
    ON_CALL(policy_provider_, IsInitializationComplete(testing::_))
        .WillByDefault(testing::Return(true));
    ON_CALL(policy_provider_, IsFirstPolicyLoadComplete(testing::_))
        .WillByDefault(testing::Return(true));
    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
        &policy_provider_);
  }

  void SetUpOnMainThread() override {
#if BUILDFLAG(IS_WIN)
    // Mark as not enterprise managed to prevent the secure DNS mode from
    // being downgraded to off.
    base::win::ScopedDomainStateForTesting scoped_domain(false);
    // TODO(crbug.com/1339062): What is the correct function to use here?
    EXPECT_FALSE(base::win::IsEnrolledToDomain());
#endif

    // Set the mocked policy provider to act as if no policies are in use by
    // updating to an empty PolicyMap. Done to prevent potential unintended
    // Secure DNS downgrade.
    policy_provider_.UpdateChromePolicy(policy::PolicyMap());

    // Override parental-controls detection to not detect anything, to prevent a
    // potential Secure DNS downgrade of off. Trigger an update to network
    // service to ensure the override takes effect if parental controls have
    // already been read.
    StubResolverConfigReader* config_reader =
        SystemNetworkContextManager::GetStubResolverConfigReader();
    config_reader->OverrideParentalControlsForTesting(
        /*parental_controls_override=*/false);
    config_reader->UpdateNetworkService(/*record_metrics=*/false);
    content::FlushNetworkServiceInstanceForTesting();

    // Update prefs to enable Secure DNS in secure mode.
    PrefService* local_state = g_browser_process->local_state();
    local_state->SetString(prefs::kDnsOverHttpsMode,
                           SecureDnsConfig::kModeSecure);
    local_state->SetString(prefs::kDnsOverHttpsTemplates,
                           "https://bar.test/dns-query{?dns}");

    SetFakeHostResolverResults(
        {{net::ERR_NAME_NOT_RESOLVED,
          net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
          FakeHostResolver::kNoResponse}},
        {{net::OK, net::ResolveErrorInfo(net::OK),
          FakeHostResolver::kOneAddressResponse}});
    DnsProbeBrowserTest::SetUpOnMainThread();
  }

  testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_;
};

// Test Fixture for tests where the DNS probes should fail to connect to a DNS
// server (timeout or unreachable host).
class DnsProbeUnreachableProbesTest : public DnsProbeBrowserTest {
  void SetUpOnMainThread() override {
    SetFakeHostResolverResults({{net::ERR_NAME_NOT_RESOLVED,
                                 net::ResolveErrorInfo(net::ERR_DNS_TIMED_OUT),
                                 FakeHostResolver::kNoResponse}},
                               {{net::ERR_NAME_NOT_RESOLVED,
                                 net::ResolveErrorInfo(net::ERR_DNS_TIMED_OUT),
                                 FakeHostResolver::kNoResponse}});
    DnsProbeBrowserTest::SetUpOnMainThread();
  }
};

// Make sure probes don't break non-DNS error.
IN_PROC_BROWSER_TEST_F(DnsProbeSuccessfulProbesTest, OtherErrorWith) {
  NavigateToOtherError();
  ExpectDisplayingErrorPage("ERR_CONNECTION_REFUSED");
}

IN_PROC_BROWSER_TEST_F(DnsProbeCurrentConfigFailingProbesTest, BadConfig) {
  NavigateToDnsError();

  EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_STARTED");
  EXPECT_EQ(0, pending_status_count());

  StartDelayedProbes(1);

  EXPECT_EQ(error_page::DNS_PROBE_FINISHED_BAD_CONFIG, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_FINISHED_BAD_CONFIG");
}

IN_PROC_BROWSER_TEST_F(DnsProbeCurrentSecureConfigFailingProbesTest,
                       BadSecureConfig) {
  NavigateToDnsError();

  EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_STARTED");
  EXPECT_EQ(0, pending_status_count());

  StartDelayedProbes(1);

  EXPECT_EQ(error_page::DNS_PROBE_FINISHED_BAD_SECURE_CONFIG,
            WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_FINISHED_BAD_SECURE_CONFIG");
}

// Make sure probes update DNS error page properly when they're supposed to.
IN_PROC_BROWSER_TEST_F(DnsProbeUnreachableProbesTest, NoInternetProbeResult) {
  NavigateToDnsError();

  EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_STARTED");
  EXPECT_EQ(0, pending_status_count());

  StartDelayedProbes(1);

  EXPECT_EQ(error_page::DNS_PROBE_FINISHED_NO_INTERNET, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_FINISHED_NO_INTERNET");
}

// Double-check to make sure sync failures don't explode.
IN_PROC_BROWSER_TEST_F(DnsProbeFailingProbesTest, SyncFailure) {
  NavigateToDnsError();

  EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_STARTED");
  EXPECT_EQ(0, pending_status_count());

  StartDelayedProbes(1);

  EXPECT_EQ(error_page::DNS_PROBE_FINISHED_INCONCLUSIVE, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("ERR_NAME_NOT_RESOLVED");
  EXPECT_EQ(0, pending_status_count());
}

// Make sure probes don't run for subframe DNS errors.
IN_PROC_BROWSER_TEST_F(DnsProbeSuccessfulProbesTest, NoProbeInSubframe) {
  ASSERT_TRUE(NavigateToURL(
      browser(), embedded_test_server()->GetURL("/iframe_dns_error.html")));

  // By the time NavigateToURL returns, the browser will have seen the failed
  // provisional load.  If a probe was started (or considered but not run),
  // then the NetErrorTabHelper would have sent a NetErrorInfo message.  Thus,
  // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't)
  // start a probe for this DNS error.
  EXPECT_EQ(0, pending_status_count());
}

// Make sure browser sends NOT_RUN properly when probes are disabled.
IN_PROC_BROWSER_TEST_F(DnsProbeUnreachableProbesTest, ProbesDisabled) {
  // Disable probes (And corrections).
  browser()->profile()->GetPrefs()->SetBoolean(
      embedder_support::kAlternateErrorPagesEnabled, false);

  NavigateToDnsError();

  EXPECT_EQ(error_page::DNS_PROBE_NOT_RUN, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("ERR_NAME_NOT_RESOLVED");
}

// Test incognito mode. DNS probes should still be enabled.
IN_PROC_BROWSER_TEST_F(DnsProbeFailingProbesTest, Incognito) {
  Browser* incognito = CreateIncognitoBrowser();
  SetActiveBrowser(incognito);

  // Just one commit and one sent status, since the corrections are disabled.
  NavigateToDnsError();
  EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());

  // Checking the page runs the RunLoop, so make sure nothing hairy happens.
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("DNS_PROBE_STARTED");
  EXPECT_EQ(0, pending_status_count());

  StartDelayedProbes(1);

  EXPECT_EQ(error_page::DNS_PROBE_FINISHED_INCONCLUSIVE, WaitForSentStatus());
  EXPECT_EQ(0, pending_status_count());
  ExpectDisplayingErrorPage("ERR_NAME_NOT_RESOLVED");
}

}  // namespace

}  // namespace chrome_browser_net


text:
class Parslet::Atoms::Sequence < Parslet::Atoms::Base
  attr_reader :parslets
  def initialize(*parslets)
    super()

    @parslets = parslets
    @error_msgs = {
      :failed  => "Failed to match sequence (#{self.inspect})"
    }
  end

  def >>(parslet)
    self.class.new(* @parslets+[parslet])
  end

  def try(source, context)
    succ([:sequence]+parslets.map { |p|
      success, value = p.apply(source, context)

      unless success
        return context.err(self, source, @error_msgs[:failed], [value])
      end

      value
    })
  end

  precedence SEQUENCE
  def to_s_inner(prec)
    parslets.map { |p| p.to_s(prec) }.join(' ')
  end
end

redpajama_set_name: RedPajamaGithub


text:
<?php

declare(strict_types=1);

namespace BartFeenstra\Functional;

use function BartFeenstra\Functional\Predicate\instance_of;

/**
 * Get's a value's human-readable (type) representation.
 *
 * @param mixed $value
 *
 * @return string
 */
function type($value): string
{
    if (is_object($value)) {
        return get_class($value);
    } elseif (is_scalar($value)) {
        return var_export($value, true);
    } else {
        return gettype($value);
    }
}

/**
 * Tries code and converts exceptions to errors.
 *
 * @param callable $goal
 *   The code to try and execute. Signature: `function(): mixed`.
 * @param string ...$except
 *   The fully qualified names of \Throwable implementations to limit the catch to. Any throwable not listed, will not
 *   be caught. If not given, all throwables will be caught.
 *
 * @return \BartFeenstra\Functional\Result
 *
 * @throws \Throwable
 *   If $except is given, any throwable thrown by $goal that is not in $except.
 */
function try_except(callable $goal, string ...$except): Result
{
    try {
        return new OkValue($goal());
    } catch (\Throwable $t) {
        if (!$except or instance_of(...$except)($t)) {
            return new ThrowableError($t);
        }
        throw $t;
    }
}

/**
 * Tries code multiple times, and converts exceptions to errors.
 *
 * This is a combination of \BartFeenstra\Functional\try_except(), and the retry keyword proposed for PHP's standard
 * library (https://wiki.php.net/rfc/retry-keyword).
 *
 * @param callable $goal
 *   The code to try and execute. Signature: `function(): mixed`.
 * @param int|null $attempts
 *   The number of times to try to reach the goal. Use NULL to retry infinitely. Defaults to 2 attempts / 1 retry.
 * @param string ...$except
 *   The fully qualified names of \Throwable implementations to limit the catch to. Any throwable not listed, will not
 *   be caught. If not given, all throwables will be caught.
 *
 * @return \BartFeenstra\Functional\Result
 *
 * @throws \Throwable
 *   If $except is given, any throwable thrown by $goal that is not in $except.
 */
function retry_except(callable $goal, ?int $attempts = 2, string ...$except): Result
{
    $retry = true;
    $remainingAttempts = $attempts;
    do {
        if (is_int($attempts)) {
            if ($remainingAttempts > 2) {
                $remainingAttempts--;
            } else {
                $retry = false;
            }
        }
        try {
            return new OkValue($goal());
        } catch (\Throwable $t) {
            if (!$except or instance_of(...$except)($t)) {
                if ($retry) {
                    continue;
                }
                return new ThrowableError($t);
            }
            throw $t;
        }
    } while ($retry);
}

/**
 * Curries a callable.
 *
 * @see https://en.wikipedia.org/wiki/Currying
 *
 * @param callable $callable
 *   The callable to curry.
 *
 * @return callable
 *   The curried callable.
 *
 * @throws \TypeError
 *   Thrown if the callable cannot be curried.
 */
function curry(callable $callable): callable
{
    $r = new \ReflectionFunction(\Closure::fromCallable($callable));
    $requiredParameters = $r->getNumberOfRequiredParameters();

    if ($requiredParameters < 1) {
        throw new \TypeError(sprintf(
            'Callables must have at least one required parameter in order to be curried, but a callable with %d required parameters was given.',
            $requiredParameters
        ));
    } elseif ($requiredParameters === 1) {
        return $callable;
    }

    // Curries the callable for a single parameter only, and keeps track of arguments that have been passed on already,
    // and when it must stop the curry and invoke the callable.
    $curry = function (callable $curry, array $arguments, callable $callable, int $remainingRequiredParameters) {
        $remainingRequiredParameters--;

        // If any other parameter need to be curried after this one, do so.
        if ($remainingRequiredParameters > 0) {
            return function ($argument) use ($curry, $arguments, $callable, $remainingRequiredParameters) {
                $arguments[] = $argument;
                return $curry($curry, $arguments, $callable, $remainingRequiredParameters);
            };
        }

        // This was the last parameter to be curried, so invoke the original callable.
        return function ($argument) use ($arguments, $callable) {
            $arguments[] = $argument;
            return $callable(...$arguments);
        };
    };

    // Initialize the curry, with an empty argument list, as the callable is not invoked yet.
    return $curry($curry, [], $callable, $requiredParameters);
}

/**
 * Partially applies a callable, left-sided.
 *
 * @see https://en.wikipedia.org/wiki/Partial_application
 *
 * @param callable $callable
 *   The callable to apply.
 * @param mixed ...$fixedArguments
 *   The arguments to fix.
 *
 * @return callable
 */
function apply_l(callable $callable, ...$fixedArguments): callable
{
    return function () use ($callable, $fixedArguments) {
        return call_user_func($callable, ...$fixedArguments, ...func_get_args());
    };
}

/**
 * Partially applies a callable, right-sided.
 *
 * @see https://en.wikipedia.org/wiki/Partial_application
 *
 * @param callable $callable
 *   The callable to apply.
 * @param mixed ...$fixedArguments
 *   The arguments to fix.
 *
 * @return callable
 */
function apply_r(callable $callable, ...$fixedArguments): callable
{
    $r = new \ReflectionFunction(\Closure::fromCallable($callable));
    $index = $r->getNumberOfParameters() - count($fixedArguments);
    return apply_i($callable, $index, ...$fixedArguments);
}

/**
 * Partially applies a callable, fixing positioned arguments.
 *
 * @see https://en.wikipedia.org/wiki/Partial_application
 *
 * @param callable $callable
 *   The callable to apply.
 * @param int $index
 *   The index of the argument to fix.
 * @param mixed ...$fixedArguments
 *   The arguments to fix.
 *
 * @return callable
 */
function apply_i(callable $callable, int $index, ...$fixedArguments): callable
{
    return function () use ($callable, $index, $fixedArguments) {
        $arguments = func_get_args();
        array_splice($arguments, $index, 0, $fixedArguments);
        return call_user_func($callable, ...$arguments);
    };
}


text:
<?php

namespace BackEnd\Controller;

use Zend\View\Model\JsonModel;
use Zend\Config\Config;
use Zend\Config\Writer\PhpArray;
use Custom\Util\Util;
use BackEnd\Model\Nav\Position;
use BackEnd\Model\User\Acl;
use Custom\Mvc\ActionEvent;
class AjaxController extends AbstractController
{
	public function regionAction()
	{
		$pid = $this->params()->fromQuery('p');
		$regionTable = $this->_getTable('RegionTable');
		$assign = $regionTable->getRegionByPid($pid);
		print_r(json_encode($assign));die;
	}
	public function memberListAction()
	{
		$member = $this->_getTable('MemberTable');
		$rs = $member->getAll();
		$data = array();
		if ($rs) {
			foreach ($rs as $v) {
				$data[] = array(
					'UserID' => $v->UserID,
					'UserName' => $v->UserName,
					'Email' => $v->Email,
					'Mobile' => $v->Mobile,
				);
			}
		}
		return new JsonModel($data);
	}
	public function approvedAction()
	{
		$table = $this->_getTable('IdentityTable');
		$rs = array();
		$ids = $this->params()->fromPost('ids');
		$approved = $this->params()->fromPost('key');
		$approved = $approved == 1 ? 1 : 0;
		$ids = explode(',', trim($ids, ','));

		if($table->updateStatus($approved, $ids)) {
			$rs = array('code' => 0, 'msg' => '设置成功', 'data' => $ids);
		} else {
			$rs = array('code' => -1, 'msg' => '数据错误');
		}
		return new JsonModel($rs);
	}
	public function smsReplyApprovedAction() {
		$id = $this->params()->fromQuery('id');
		$result = $this->params()->fromQuery('result');
		$table = $this->_getTable('SmsReplyTable');
		$rs = array();
		if ($id) {
			$container = $this->_getSession();
			$up = array(
					'result' => $result,
					'deal_time' => date('Y-m-d H:i:s'),
					'deal_user' => $container->Name
			);
			$table->update($up, array('id' => $id));
			$rs = array('code' => 0, 'msg' => '已确认处理!', 'data' => $id);
		}
		return new JsonModel($rs);
	}
	public function saveCommonLinksAction()
	{
	    $category = $this->params()->fromPost('cate');
	    $html = $this->params()->fromPost('html');
	    $cache = array(
	    	'category' => $category,
	        'html' => $html,
	    );
	    $config = new Config($cache);

	    $writer = new PhpArray();

	    //echo $writer->toString($conf);die;
	    //@file_put_contents(APPLICATION_PATH.'/data/sys_config.php', $writer->toString($conf));
	    $writer->toFile(APPLICATION_PATH.'/data/commonLinks/'.$category.'.php', $config);
	    return new JsonModel(array('code' => 0, 'msg' => 'ok'));
	}
	public function delIconAction() {
		$linkTable = $this->_getTable('LinkTable');
		$id = $this->params()->fromPost('id');
		$icon = $this->params()->fromPost('icon');
		$up[$icon] = '';
		$link = $linkTable->getOneById($id);
		if ($link && $linkTable->updateFieldsByID($up, $id)) {
			$file = APPLICATION_PATH . '/public' . $link->{$icon};
			unlink($file);
			$rs = array('code' => 0, 'msg' => '已删除');
		} else {
			$rs = array('code' => -1, 'msg' => '删除失败');
		}
		return new JsonModel($rs);
	}
	public function getResourceAction() {
		$type = $this->params()->fromPost('type');
		$type = $type ? $type : 'add';
		$role = $this->params()->fromPost('role');
		$data = array();
		$table = $this->_getTable('ResourceTable');
		if (!$role) {
			$rs = array('code' => -200, 'msg' => '参数错误');
		} else {
			$acl = $this->getServiceLocator()->get('acl');
			$resources = $acl->acl->getResources();

			$hasResources = array();
			$noneResources = array();
			foreach($resources as $v){
				if($acl->acl->isAllowed($role , $v)){
					$hasResources[] = $v;
				}else{
					$noneResources[] = $v;
				}
			}
			if ($type == 'add') {
				$data = $table->getSourceByNames($noneResources);
			} else {
				$data = $table->getSourceByNames($hasResources);
			}
			$rs = array('code' => 0, 'msg' => 'sucess', 'data' => $data);
		}
		return new JsonModel($rs);
	}
	public function saveAclAction() {
		$type = $this->params()->fromPost('type');
		$role = $this->params()->fromPost('role');
		$resources = $this->params()->fromPost('resources');
		if ((!$type) || (!$role) || (empty($resources))) {
			$rs = array('code' => -200, 'msg' => '参数错误');
		} elseif (in_array($type, array('add', 'del'))) {
			if($resources){
				$acl = $this->getServiceLocator()->get('acl');
				$table = $this->_getTable('AclTable');
				if ($type == 'add') {
					$acl->acl->allow($role , $resources);
					foreach($resources as $resource){
						$myacl = new Acl();
						$myacl->ResourceName = $resource;
						$myacl->RoleName = $role;
						$myacl->AddTime = Util::getDateTime('Y-m-d h:i:s');
						$table->save($myacl);
					}
					$msg = "添加成功!";
				} else {
					$acl->acl->removeAllow($role , $resources);
					$table->remove($role , $resources);
					$msg = "删除成功!";
				}
				$acl->saveAcl();

				$this->trigger(ActionEvent::ACTION_INSERT);
				$this->trigger(ActionEvent::ACTION_DELETE);
				$rs = array('code' => 0, 'msg' => $msg);
			}
		}
		return new JsonModel($rs);
	}
	private function _addLink($id, $pos, $table) {
		$flg = 0;
		if (is_numeric($id)) {
			$position = new Position();
			$position->exchangeArray(array('link_id' => $id, 'pos' => $pos));
			$flg = $table->addLinkToPos($position);
		}
		return $flg;
	}
}


text:
<?php

// No direct access
defined('_HZEXEC_') or die();

//push the stylesheet to the view
\Hubzero\Document\Assets::addPluginStylesheet('projects', 'publications');
\Hubzero\Document\Assets::addPluginStylesheet('projects', 'publications', 'curation.css');

$this->css()
	->js()
	->css('jquery.fancybox.css', 'system')
	->css('curation.css')
	->js('curation.js');

$status = $this->pub->getStatusName();
$class  = $this->pub->getStatusCss();
$typetitle = \Components\Publications\Helpers\Html::writePubCategory($this->pub->category()->alias, $this->pub->category()->name);
?>

<?php echo $this->title; ?>

<a class="btn icon-browse" href="<?php echo Route::url('index.php?option=' . $this->option . '&controller=' . $this->controller); ?>"><?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LIST'); ?>

	<form action="<?php echo Route::url('index.php?option=' . $this->option . '&controller=' . $this->controller); ?>" method="post" id="curation-form" name="curation-form">
		<input type="hidden" name="option" value="<?php echo $this->option; ?>" />
		<input type="hidden" name="controller" value="<?php echo $this->controller; ?>" />
		<input type="hidden" name="id" id="pid" value="<?php echo $this->pub->id; ?>" data-route="<?php echo Route::url('index.php?option=' . $this->option . '&controller=' . $this->controller . '&id=' . $this->pub->id . '&task=save'); ?>" />
		<input type="hidden" name="vid" id="vid" value="<?php echo $this->pub->version_id; ?>" />
		<input type="hidden" name="task" id="task" value="save" />

					<?php echo $typetitle; ?> <?php echo \Hubzero\Utility\Str::truncate($this->pub->title, 65); ?> | <?php echo Lang::txt('COM_PUBLICATIONS_CURATION_VERSION') . ' ' . $this->pub->version_label; ?>

					<img src="<?php echo Route::url('index.php?option=com_publications&id=' . $this->pub->id . '&v=' . $this->pub->version_id) . '/Image:thumb'; ?>" alt="" />

					<?php
					echo $this->pub->reviewed ? Lang::txt('COM_PUBLICATIONS_CURATION_RESUBMITTED') : Lang::txt('COM_PUBLICATIONS_CURATION_SUBMITTED');
					$name = $this->pub->modifier('name');
					$name = $name ?: Lang::txt('JUNKNOWN');
					echo ' ' . Date::of($this->pub->submitted)->toLocal('M d, Y') . ' ' . Lang::txt('COM_PUBLICATIONS_CURATION_BY', $name);
					?>

				<?php if ($this->pub->curator()): ?>

						<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_ASSIGNED_CURATOR') . ' ' . $this->pub->curator('name') . ' (' . $this->pub->curator('username') . ')';  ?>

				<?php endif; ?>
				<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_REVIEW_AND_ACT'); ?>

					<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LEGEND_NONE'); ?>
					<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LEGEND_PASS'); ?>
					<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LEGEND_FAIL'); ?>
					<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LEGEND_UPDATE'); ?>

						<input type="submit" value="<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LOOKS_BAD'); ?>" class="btn btn-primary active icon-kickback btn-curate curate-kickback" />

						<input type="submit" value="<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_LOOKS_GOOD'); ?>" class="btn btn-success active icon-apply btn-curate curate-save" />

			<?php if ($this->history && $this->history->comment): ?>

<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_SUBMITTER_COMMENT'); ?>

<?php echo $this->history->comment; ?>

			<?php endif; ?>

				<?php
				foreach ($this->pub->curation('blocks') as $blockId => $block):

					// Skip inactive blocks
					if (isset($block->active) && $block->active == 0):
						continue;
					endif;

					$this->pub->_curationModel->setBlock($block->name, $blockId);

					// Get block content
					echo $block->name == 'review' ? '' : $this->pub->_curationModel->parseBlock('curator');
				endforeach;
				?>

	</form>

			<form id="notice-form" name="noticeForm" action="<?php echo Route::url('index.php?option=' . $this->option . '&controller=' . $this->controller); ?>" method="post">
				<fieldset>
					<legend><?php echo Lang::txt('COM_PUBLICATIONS_CURATION_NOTICE_TITLE'); ?></legend>

					<input type="hidden" name="option" value="<?php echo $this->option; ?>" />
					<input type="hidden" name="controller" value="<?php echo $this->controller; ?>" />
					<input type="hidden" name="task" value="save" />
					<input type="hidden" name="id" value="<?php echo $this->pub->get('id'); ?>" />
					<input type="hidden" name="vid" value="<?php echo $this->pub->get('version_id'); ?>" />
					<input type="hidden" name="ajax" value="1" />
					<input type="hidden" name="no_html" value="1" />
					<input type="hidden" name="p" id="props" value="" />
					<input type="hidden" name="pass" value="0" />

							<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_NOTICE_LABEL'); ?>
							<textarea name="review" id="notice-review" class="form-control" rows="5" cols="10"></textarea>

				</fieldset>

					<input type="submit" id="notice-submit" class="btn" value="<?php echo Lang::txt('COM_PUBLICATIONS_CURATION_MARK_AS_FAIL'); ?>" />

			</form>


text:
// -- ROS includes
#include <ros/ros.h>
#include <dynamic_reconfigure/server.h>
#include <ueye/paramsConfig.h>
#include <image_transport/image_transport.h>
#include <camera_info_manager/camera_info_manager.h>
#include <sensor_msgs/fill_image.h>
#include <sensor_msgs/CameraInfo.h>
#include <pluginlib/class_list_macros.h>
#include <nodelet/nodelet.h>

// -- CVT includes
#include <cvt/io/UEyeUsbCamera.h>
#include <cvt/io/UEyeStereo.h>
#include <cvt/util/Time.h>
#include <cvt_ros_bridge/cvt_ros_bridge.h>
#include <cvt/vision/StereoCameraCalibration.h>

using namespace cvt;

namespace ueye_cam
{

    class UEyeStereoCamNodelet : public nodelet::Nodelet
    {
        public:
            typedef boost::shared_ptr< camera_info_manager::CameraInfoManager >
            CameraInfoManPtr;

            typedef boost::shared_ptr< UEyeStereo > UEyeStereoPtr;
            typedef boost::shared_ptr<dynamic_reconfigure::Server<ueye::paramsConfig> > DynamicReconfServerPtr;

            UEyeStereoCamNodelet() {}
            ~UEyeStereoCamNodelet(); // dtor is virtual in nodelet::Nodelet

            virtual void onInit();

        private:
            UEyeStereoPtr                       _stereo;
            image_transport::CameraPublisher	_pub0;
            image_transport::CameraPublisher	_pub1;

            CameraInfoManPtr                    _cInfo0;
            CameraInfoManPtr                    _cInfo1;

            sensor_msgs::Image                  _msg0;
            sensor_msgs::Image                  _msg1;
            sensor_msgs::CameraInfo             _camInfoMsg0;
            sensor_msgs::CameraInfo             _camInfoMsg1;
            ueye::paramsConfig                  _config;
            static const std::string            leftCamID;
            static const std::string            rightCamID;

            //For dynamic_reconfigure
            DynamicReconfServerPtr server;
            dynamic_reconfigure::Server<ueye::paramsConfig>::CallbackType f;

            ros::Timer                          _timer;

            void publishCallback( const ros::TimerEvent& event );
            void reconfigureCallback(ueye::paramsConfig &config,
                                     uint32_t level);
            void updateCamInfo( const UEyeUsbCamera& cam,
                                sensor_msgs::CameraInfo & camInfo );
    };

    const std::string UEyeStereoCamNodelet::leftCamID =     "4002738790";
    const std::string UEyeStereoCamNodelet::rightCamID =    "4002738788";

    PLUGINLIB_DECLARE_CLASS( ueye_cam, UEyeStereoCamNodelet, ueye_cam::UEyeStereoCamNodelet, nodelet::Nodelet )

    void UEyeStereoCamNodelet::onInit()
    {
        NODELET_DEBUG("Initializing nodelet...");

        const ros::NodeHandle& nh(getPrivateNodeHandle());
        ros::NodeHandle _nh0(nh, "left");
        ros::NodeHandle _nh1(nh, "right");

        image_transport::ImageTransport _it0( _nh0 );
        image_transport::ImageTransport _it1( _nh1 );
        _pub0   = _it0.advertiseCamera( "image_raw", 2 );
        _pub1   = _it1.advertiseCamera( "image_raw", 2 );

        {   // init stereo camera
            std::string leftId;
            std::string rightId;

            // get values from parameter server and init camera
            nh.param<std::string>( "left_id",  leftId,  leftCamID.c_str() );
            nh.param<std::string>( "right_id", rightId, rightCamID.c_str() );
            _stereo = UEyeStereoPtr(new UEyeStereo( leftId.c_str(), rightId.c_str()));

            // get camera calibration
            String name_left_cam( String( "ueye_" ) + leftId.c_str() );
            String name_right_cam( String( "ueye_" ) + rightId.c_str() );

            String resourcePath( "package://ueye/resources/" );
            String saveURL0( resourcePath + name_left_cam + ".yaml" );
            String saveURL1( resourcePath + name_right_cam + ".yaml" );

            _cInfo0 = CameraInfoManPtr( new camera_info_manager::CameraInfoManager(
                                            _nh0, name_left_cam.c_str(), saveURL0.c_str() ) );

            _cInfo1 = CameraInfoManPtr( new camera_info_manager::CameraInfoManager(
                                            _nh1, name_right_cam.c_str(), saveURL1.c_str() ) );

            if ( _cInfo0->validateURL( saveURL0.c_str() ) ) {
                _cInfo0->loadCameraInfo( saveURL0.c_str() );
            }
            if ( _cInfo1->validateURL( saveURL1.c_str() ) ) {
                _cInfo1->loadCameraInfo( saveURL1.c_str() );
            }
        }

        {   // update camera info?
            _msg0.header.frame_id = "/ueye_stereo";
            _camInfoMsg0.header.frame_id = _msg0.header.frame_id;
            _msg1.header.frame_id = _msg0.header.frame_id;
            _camInfoMsg1.header.frame_id = _msg1.header.frame_id;

            updateCamInfo( _stereo->master(), _camInfoMsg0 );
            updateCamInfo( _stereo->slave(),  _camInfoMsg1 );
        }

        //For dynamic_reconfigure
        f = boost::bind( &UEyeStereoCamNodelet::reconfigureCallback, this, _1, _2 );
        server = DynamicReconfServerPtr(
                     new dynamic_reconfigure::Server<ueye::paramsConfig>());
        server->setCallback( f );

        {   // timer for the camera images
            int fps;
            nh.param( "fps", fps, 30 );
            _timer = nh.createTimer(
                         ros::Duration( 1.0f / static_cast<float>( fps ) ),
                         &UEyeStereoCamNodelet::publishCallback, this );
            _timer.start();
        }
    }

    UEyeStereoCamNodelet::~UEyeStereoCamNodelet()
    {
        _timer.stop();
    }

    void UEyeStereoCamNodelet::updateCamInfo( const UEyeUsbCamera& cam,
                                              sensor_msgs::CameraInfo & camInfo )
    {
        if( cam.width() != camInfo.width ||
            cam.height() != camInfo.height ){
            camInfo.width = cam.width();
            camInfo.height = cam.height();
        }
    }

    void UEyeStereoCamNodelet::publishCallback( const ros::TimerEvent& )
    {
        size_t iter = 0;

        if ( _stereo->nextFrame() ) {
            const cvt::Image& i0 = _stereo->masterFrame();
            const cvt::Image& i1 = _stereo->slaveFrame();
            ++iter;

            // publish the frame
            _msg0.header.seq = iter;
            _msg1.header.seq = iter;
            _msg0.header.stamp = ros::Time::now();
            _msg1.header.stamp = _msg0.header.stamp;

            // maybe not so smart after all, this can be done with ros::image_proc
            // would be useful to publish a stereo-rectified version here as well:
            //        cvt::StereoCameraCalibration stereoCC();
            //        stereoCC.load(cvt::String("ueye_stereo_cc.xml"));
            //        stereoCC.undistortRectify();

            // update caminfo stuff
            _camInfoMsg0 = _cInfo0->getCameraInfo();
            _camInfoMsg1 = _cInfo1->getCameraInfo();
            _camInfoMsg0.header= _msg0.header;
            _camInfoMsg1.header= _msg1.header;

            cvt_ros_bridge::image2RosMsg( i0, _msg0 );
            cvt_ros_bridge::image2RosMsg( i1, _msg1 );
            _pub0.publish( _msg0, _camInfoMsg0 );
            _pub1.publish( _msg1, _camInfoMsg1 );
        }
    }

    //Work in progress
    void UEyeStereoCamNodelet::reconfigureCallback(
            ueye::paramsConfig &config, uint32_t /*level*/ ) {

        if( config.hor_mirror != _config.hor_mirror ){
            _stereo->setHorizontalMirror( config.hor_mirror );
        }

        if( config.ver_mirror != _config.ver_mirror ){
            _stereo->setVerticalMirror( config.ver_mirror );
        }

        if( config.pixel_clock != _config.pixel_clock ){
            _stereo->setPixelClock( config.pixel_clock );
        }

        if( config.auto_sensor_shutter != _config.auto_sensor_shutter ){
            _stereo->setAutoSensorShutter( config.auto_sensor_shutter );
        }

        if( config.auto_shutter != _config.auto_shutter ){
            _stereo->setAutoShutter( config.auto_shutter );
        }

        if( config.framerate != _config.framerate ){
            _stereo->setFramerate( config.framerate );
            _timer.setPeriod( ros::Duration( 1.0f / ( config.framerate + 5 ) ) );
        }

        if( config.exposure_time != _config.exposure_time ){
            _stereo->setExposureTime( config.exposure_time );
        }

        if( config.framerate != _config.framerate ){
            _timer.setPeriod( ros::Duration( 1.0f / config.framerate) );
        }

        if( config.auto_gain != _config.auto_gain ){
            _stereo->setAutoGain( config.auto_gain );
        }

        if( config.gain_boost != _config.gain_boost ){
            _stereo->setGainBoost( config.gain_boost );
        }

        /* NOT IMPLEMENTED YET
    //Image Dimensions
    _cam0->setImageWidth(  config.image_width ) ;
    _cam1->setImageWidth(  config.image_width ) ;
    _cam0->setImageHeight(  config.image_height ) ;
    _cam1->setImageHeight(  config.image_height ) ;
    //Image Offsets
    _cam0->setImageTopOffset(  config.image_top_C1 ) ;
    _cam1->setImageTopOffset(  config.image_top_C2 ) ;
    _cam0->setImageLeftOffset(  config.image_left_C1 ) ;
    _cam1->setImageLeftOffset(  config.image_left_C2 ) ;
*/
        _config = config;
    }
    // -------------

}


text:
<?php
namespace Topxia\WebBundle\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Topxia\Common\Paginator;
use Topxia\Common\FileToolkit;
use Topxia\Common\ArrayToolkit;
use Topxia\Service\Util\CloudClientFactory;

class CourseLessonController extends BaseController
{
    //加载播放器的地址
    public function playerAction(Request $request, $courseId, $lessonId = 0)
    {
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);
        if (empty($lesson)) {
            throw $this->createNotFoundException();
        }

        $timelimit = $this->setting('magic.lesson_watch_time_limit');

        if(!$lesson["free"] && empty($timelimit)) {
            list($course, $member) = $this->getCourseService()->tryTakeCourse($courseId);
        }

        return $this->forward('TopxiaWebBundle:Player:show', array(
            'id' => $lesson["mediaId"],
            'mode' => empty($lesson["free"]) ? $request->query->get('mode', '') : ''
        ));
    }

    public function previewAction(Request $request, $courseId, $lessonId = 0)
    {
        $course = $this->getCourseService()->getCourse($courseId);
        if (empty($lessonId)) {
            $lessonId = $request->query->get('lessonId');
        }
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);

        if (empty($lesson)) {
            throw $this->createNotFoundException();
        }

        if (!empty($course['status']) && $course['status'] == 'closed') {
            return $this->render('TopxiaWebBundle:CourseLesson:preview-notice-modal.html.twig', array('course' => $course));
        }

        $timelimit = $this->setting('magic.lesson_watch_time_limit');

        $user = $this->getCurrentUser();

        //课时不免费并且不满足1.有时间限制设置2.课时为视频课时3.视频课时非优酷等外链视频时提示购买
        if (empty($lesson['free']) && !($timelimit && $lesson['type'] == 'video' && $lesson['mediaSource'] == 'self')) {

            if (!$user->isLogin()) {
                throw $this->createAccessDeniedException();
            }
            if($course["parentId"]>0){
                return $this->redirect($this->generateUrl('classroom_buy_hint', array('courseId' => $course["id"])));
            }
            return $this->forward('TopxiaWebBundle:CourseOrder:buy', array('id' => $courseId), array('preview' => true , 'lessonId' => $lesson['id']) );
        }

        //在可预览情况下查看网站设置是否可匿名预览
        $allowAnonymousPreview = $this->setting('course.allowAnonymousPreview', 1);
        if (empty($allowAnonymousPreview) && !$user->isLogin()) {
            throw $this->createAccessDeniedException();
        }

        $hasVideoWatermarkEmbedded = 0;

        if ($lesson['type'] == 'video' && $lesson['mediaSource'] == 'self') {
            $file = $this->getUploadFileService()->getFile($lesson['mediaId']);

            if (empty($lesson['free']) && empty($timelimit) && $file['storage'] != 'cloud') {
                if (!$user->isLogin()) {
                    throw $this->createAccessDeniedException();
                }
                return $this->forward('TopxiaWebBundle:CourseOrder:buy', array('id' => $courseId), array('preview' => true, 'lessonId' => $lesson['id']));
            }

            if (!empty($file['metas2']) && !empty($file['metas2']['sd']['key'])) {
                $factory = new CloudClientFactory();
                $client = $factory->createClient();
                $hls = $client->generateHLSQualitiyListUrl($file['metas2'], 3600);

                if (isset($file['convertParams']['convertor']) && ($file['convertParams']['convertor'] == 'HLSEncryptedVideo')) {

                    $token = $this->getTokenService()->makeToken('hls.playlist', array('data' => array('id' => $file['id'], 'mode' => 'preview'), 'times' => 3, 'duration' => 3600));

                    $hls = array(
                        'url' => $this->generateUrl('hls_playlist', array(
                            'id' => $file['id'],
                            'token' => $token['token'],
                            'line' => $request->query->get('line'),
                        ), true),
                    );
                } else {
                    $hls = $client->generateHLSQualitiyListUrl($file['metas2'], 3600);
                }
            }
            if (!empty($file['convertParams']['hasVideoWatermark'])) {
                $hasVideoWatermarkEmbedded = 1;
            }
        } elseif ($lesson['mediaSource'] == 'youku') {
            $matched = preg_match('/\/sid\/(.*?)\/v\.swf/s', $lesson['mediaUri'], $matches);
            if ($matched) {
                $lesson['mediaUri'] = "http://player.youku.com/embed/{$matches[1]}";
                $lesson['mediaSource'] = 'iframe';
            } else {
                $lesson['mediaUri'] = $lesson['mediaUri'];
            }
        } elseif ($lesson['mediaSource'] == 'tudou') {
            $matched = preg_match('/\/v\/(.*?)\/v\.swf/s', $lesson['mediaUri'], $matches);
            if ($matched) {
                $lesson['mediaUri'] = "http://www.tudou.com/programs/view/html5embed.action?code={$matches[1]}";
                $lesson['mediaSource'] = 'iframe';
            } else {
                $lesson['mediaUri'] = $lesson['mediaUri'];
            }
        }

         //判断用户是否为VIP
        $vipStatus = $courseVip = null;
        if ($this->isPluginInstalled('Vip') && $this->setting('vip.enabled')) {
            $courseVip = $course['vipLevelId'] > 0 ? $this->getLevelService()->getLevel($course['vipLevelId']) : null;
            if ($courseVip) {
                $vipStatus = $this->getVipService()->checkUserInMemberLevel($user['id'], $courseVip['id']);
            }
        }

        return $this->render('TopxiaWebBundle:CourseLesson:preview-modal.html.twig', array(
            'user' => $user,
            'course' => $course,
            'lesson' => $lesson,
            'hasVideoWatermarkEmbedded' => $hasVideoWatermarkEmbedded,
            'hlsUrl' => (isset($hls) && is_array($hls) && !empty($hls['url'])) ? $hls['url'] : '',
            'vipStatus' => $vipStatus
        ));
    }

    public function showAction(Request $request, $courseId, $lessonId)
    {
        list($course, $member) = $this->getCourseService()->tryTakeCourse($courseId);

        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);
        $json = array();
        $json['number'] = $lesson['number'];

        $chapter = empty($lesson['chapterId']) ? null : $this->getCourseService()->getChapter($course['id'], $lesson['chapterId']);
        if ($chapter['type'] == 'unit') {
            $unit = $chapter;
            $json['unitNumber'] = $unit['number'];

            $chapter = $this->getCourseService()->getChapter($course['id'], $unit['parentId']);
            $json['chapterNumber'] = empty($chapter) ? 0 : $chapter['number'];
        } else {
            $json['chapterNumber'] = empty($chapter) ? 0 : $chapter['number'];
            $json['unitNumber'] = 0;
        }

        $json['title'] = $lesson['title'];
        $json['summary'] = $lesson['summary'];
        $json['type'] = $lesson['type'];
        $json['content'] = $lesson['content'];
        $json['status'] = $lesson['status'];
        $json['quizNum'] = $lesson['quizNum'];
        $json['materialNum'] = $lesson['materialNum'];
        $json['mediaId'] = $lesson['mediaId'];
        $json['mediaSource'] = $lesson['mediaSource'];
        $json['startTimeFormat'] = date("m-d H:i", $lesson['startTime']);
        $json['endTimeFormat'] = date("H:i", $lesson['endTime']);
        $json['startTime'] = $lesson['startTime'];
        $json['endTime'] = $lesson['endTime'];
        $json['id'] = $lesson['id'];
        $json['courseId'] = $lesson['courseId'];
        $json['videoWatermarkEmbedded'] = 0;
        $json['liveProvider'] = $lesson["liveProvider"];
        $json['nowDate'] = time();

        $app = $this->getAppService()->findInstallApp('Homework');
        if (!empty($app)) {
            $homework = $this->getHomeworkService()->getHomeworkByLessonId($lesson['id']);
            $exercise = $this->getExerciseService()->getExerciseByLessonId($lesson['id']);
            $json['homeworkOrExerciseNum'] = $homework['itemCount'] + $exercise['itemCount'];
        } else {
            $json['homeworkOrExerciseNum'] = 0;
        }

        $json['isTeacher'] = $this->getCourseService()->isCourseTeacher($courseId, $this->getCurrentUser()->id);
        if ($lesson['type'] == 'live' && $lesson['replayStatus'] == 'generated') {
            $json['replays'] = $this->getCourseService()->getCourseLessonReplayByLessonId($lesson['id']);
            if (!empty($json['replays'])) {
                foreach ($json['replays'] as $key => $value) {
                    $url = $this->generateUrl('live_course_lesson_replay_entry', array(
                        'courseId' => $lesson['courseId'],
                        'lessonId' => $lesson['id'],
                        'courseLessonReplayId' => $value['id'],
                    ), true);
                    $json['replays'][$key]["url"] = $url;
                }
            }
        }

        if ($json['mediaSource'] == 'self') {
            $file = $this->getUploadFileService()->getFile($lesson['mediaId']);
            if (!empty($file)) {
                if ($file['storage'] == 'cloud') {
                    $factory = new CloudClientFactory();
                    $client = $factory->createClient();

                    $json['mediaConvertStatus'] = $file['convertStatus'];

                    if (!empty($file['convertParams']['hasVideoWatermark'])) {
                        $json['videoWatermarkEmbedded'] = 1;
                    }

                    if (!empty($file['metas2']) && !empty($file['metas2']['sd']['key'])) {
                        if (isset($file['convertParams']['convertor']) && ($file['convertParams']['convertor'] == 'HLSEncryptedVideo')) {
                            $token = $this->getTokenService()->makeToken('hls.playlist', array(
                                'data' => $file['id'],
                                'times' => 3,
                                'duration' => 3600,
                                'userId' => $this->getCurrentUser()->getId()
                            ));

                            $url = array(
                                'url' => $this->generateUrl('hls_playlist', array(
                                    'id' => $file['id'],
                                    'token' => $token['token'],
                                    'line' => $request->query->get('line'),
                                ), true),
                            );
                        } else {
                            $url = $client->generateHLSQualitiyListUrl($file['metas2'], 3600);
                        }
                        $json['mediaHLSUri'] = $url['url'];

                        if ($this->setting('magic.lesson_watch_limit') && $course['watchLimit'] > 0) {
                            $user = $this->getCurrentUser();
                            $watchStatus = $this->getCourseService()->checkWatchNum($user['id'], $lesson['id']);
                            if ($watchStatus['status'] == 'error') {
                                $wathcLimitTime = $this->container->get('topxia.twig.web_extension')->durationTextFilter($watchStatus['watchLimitTime']);
                                $json['mediaError'] = "您的观看时长已到 {$wathcLimitTime},不能再观看。";
                            }
                        }
                    } elseif ($file['type'] == 'ppt') {
                        $json['mediaUri'] = $this->generateUrl('course_lesson_ppt', array('courseId' => $course['id'], 'lessonId' => $lesson['id']));
                    } else {
                        if (!empty($file['metas']) && !empty($file['metas']['hd']['key'])) {
                            $key = $file['metas']['hd']['key'];
                        } else {
                            if ($file['type'] == 'video') {
                                $key = null;
                            } else {
                                $key = $file['hashId'];
                            }
                        }

                        if ($key) {
                            $url = $client->generateFileUrl($client->getBucket(), $key, 3600);
                            $json['mediaUri'] = $url['url'];
                        } else {
                            $json['mediaUri'] = '';
                        }
                    }

                } else {
                    $json['mediaUri'] = $this->generateUrl('course_lesson_media', array('courseId' => $course['id'], 'lessonId' => $lesson['id']));
                    if ($this->setting('magic.lesson_watch_limit') && $course['watchLimit'] > 0) {
                        $user = $this->getCurrentUser();
                        $watchStatus = $this->getCourseService()->checkWatchNum($user['id'], $lesson['id']);
                        if ($watchStatus['status'] == 'error') {
                            $wathcLimitTime = $this->container->get('topxia.twig.web_extension')->durationTextFilter($watchStatus['watchLimitTime']);
                            $json['mediaError'] = "您的观看时长已到 {$wathcLimitTime},不能再观看。";
                        }
                    }
                }
            } else {
                $json['mediaUri'] = '';
                if ($lesson['type'] == 'video') {
                    $json['mediaError'] = '抱歉,视频文件不存在,暂时无法学习。';
                } elseif ($lesson['type'] == 'audio') {
                    $json['mediaError'] = '抱歉,音频文件不存在,暂时无法学习。';
                } elseif ($lesson['type'] == 'ppt') {
                    $json['mediaError'] = '抱歉,PPT文件不存在,暂时无法学习。';
                }
            }
        } elseif ($json['mediaSource'] == 'youku' && $this->isMobile()) {
            $matched = preg_match('/\/sid\/(.*?)\/v\.swf/s', $lesson['mediaUri'], $matches);
            if ($matched) {
                $json['mediaUri'] = "http://player.youku.com/embed/{$matches[1]}";
                $json['mediaSource'] = 'iframe';
            } else {
                $json['mediaUri'] = $lesson['mediaUri'];
            }
        } elseif ($json['mediaSource'] == 'tudou') {
            $matched = preg_match('/\/v\/(.*?)\/v\.swf/s', $lesson['mediaUri'], $matches);
            if ($matched) {
                $json['mediaUri'] = "http://www.tudou.com/programs/view/html5embed.action?code={$matches[1]}";
                $json['mediaSource'] = 'iframe';
            } else {
                $json['mediaUri'] = $lesson['mediaUri'];
            }
        } else {
            $json['mediaUri'] = $lesson['mediaUri'];
        }

        $json['canLearn'] = $this->getCourseService()->canLearnLesson($lesson['courseId'], $lesson['id']);

        return $this->createJsonResponse($json);
    }

    public function mediaAction(Request $request, $courseId, $lessonId)
    {
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);
        if (empty($lesson) || empty($lesson['mediaId']) || ($lesson['mediaSource'] != 'self')) {
            throw $this->createNotFoundException();
        }

        if (!$lesson['free']) {
            $this->getCourseService()->tryTakeCourse($courseId);
        }

        $file = $this->getUploadFileService()->getFile($lesson['mediaId']);
        if (empty($file)) {
            throw $this->createNotFoundException();
        }

        if ($file['storage'] == 'cloud') {
            throw $this->createNotFoundException();
        }

        return $this->createLocalMediaResponse($request, $file, false);
    }

    public function detailDataAction($courseId, $lessonId)
    {
        $students = array();
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);

        $count = $this->getCourseService()->searchLearnCount(array('courseId' => $courseId, 'lessonId' => $lessonId));
        $paginator = new Paginator($this->get('request'), $count, 20);

        $learns = $this->getCourseService()->searchLearns(array('courseId' => $courseId, 'lessonId' => $lessonId), array('startTime', 'ASC'), $paginator->getOffsetCount(),  $paginator->getPerPageCount());

        foreach ($learns as $key => $learn) {
            $user = $this->getUserService()->getUser($learn['userId']);
            $students[$key]['nickname'] = $user['nickname'];
            $students[$key]['startTime'] = $learn['startTime'];
            $students[$key]['finishedTime'] = $learn['finishedTime'];
            $students[$key]['learnTime'] = $learn['learnTime'];
            $students[$key]['watchTime'] = $learn['watchTime'];

            if ($lesson['type'] == 'testpaper') {
                $paperId = $lesson['mediaId'];
                $score = $this->getTestpaperService()->findTestpaperResultByTestpaperIdAndUserIdAndActive($paperId, $user['id']);

                $students[$key]['result'] = $score['score'];
            }
        }

        $lesson['length'] = intval($lesson['length']/60);

        return $this->render('TopxiaWebBundle:CourseLesson:lesson-data-modal.html.twig', array(
            'lesson' => $lesson,
            'paginator' => $paginator,
            'students' => $students,
            ));
    }

    public function mediaDownloadAction(Request $request, $courseId, $lessonId)
    {
        if (!$this->setting('course.student_download_media')) {
            return $this->createMessageResponse('未开启课时音视频下载。');
        }
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);
        if (empty($lesson) || empty($lesson['mediaId']) || ($lesson['mediaSource'] != 'self')) {
            throw $this->createNotFoundException();
        }

        $this->getCourseService()->tryTakeCourse($courseId);

        return $this->fileAction($request, $lesson['mediaId'], true);
    }

    public function pptAction(Request $request, $courseId, $lessonId)
    {
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);

        if (empty($lesson)) {
            throw $this->createNotFoundException();
        }

        if (!$lesson['free']) {
            $this->getCourseService()->tryTakeCourse($courseId);
        }

        if ($lesson['type'] != 'ppt' || empty($lesson['mediaId'])) {
            throw $this->createNotFoundException();
        }

        $file = $this->getUploadFileService()->getFile($lesson['mediaId']);
        if (empty($file)) {
            throw $this->createNotFoundException();
        }

        if ($file['convertStatus'] != 'success') {
            if ($file['convertStatus'] == 'error') {
                $url = $this->generateUrl('course_manage_files', array('id' => $courseId));
                $message = sprintf('PPT文档转换失败,请到课程文件管理中,重新转换。', $url);

                return $this->createJsonResponse(array(
                    'error' => array('code' => 'error', 'message' => $message),
                ));
            } else {
                return $this->createJsonResponse(array(
                    'error' => array('code' => 'processing', 'message' => 'PPT文档还在转换中,还不能查看,请稍等。'),
                ));
            }
        }

        $factory = new CloudClientFactory();
        $client = $factory->createClient();

        $result = $client->pptImages($file['metas2']['imagePrefix'], $file['metas2']['length'].'');

        return $this->createJsonResponse($result);
    }

    public function documentAction(Request $request, $courseId, $lessonId)
    {
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);

        if (empty($lesson)) {
            throw $this->createNotFoundException();
        }

        if (!$lesson['free']) {
            $this->getCourseService()->tryTakeCourse($courseId);
        }

        if ($lesson['type'] != 'document' || empty($lesson['mediaId'])) {
            throw $this->createNotFoundException();
        }

        $file = $this->getUploadFileService()->getFile($lesson['mediaId']);
        if (empty($file)) {
            throw $this->createNotFoundException();
        }

        if ($file['convertStatus'] != 'success') {
            if ($file['convertStatus'] == 'error') {
                $url = $this->generateUrl('course_manage_files', array('id' => $courseId));
                $message = sprintf('文档转换失败,请到课程文件管理中,重新转换。', $url);

                return $this->createJsonResponse(array(
                    'error' => array('code' => 'error', 'message' => $message),
                ));
            } else {
                return $this->createJsonResponse(array(
                    'error' => array('code' => 'processing', 'message' => '文档还在转换中,还不能查看,请稍等。'),
                ));
            }
        }

        $factory = new CloudClientFactory();
        $client = $factory->createClient();

        $metas2 = $file['metas2'];
        $url = $client->generateFileUrl($client->getBucket(), $metas2['pdf']['key'], 3600);
        $result['pdfUri'] = $url['url'];
        $url = $client->generateFileUrl($client->getBucket(), $metas2['swf']['key'], 3600);
        $result['swfUri'] = $url['url'];

        return $this->createJsonResponse($result);
    }

    public function flashAction(Request $request, $courseId, $lessonId)
    {
        $lesson = $this->getCourseService()->getCourseLesson($courseId, $lessonId);

        if (empty($lesson)) {
            throw $this->createNotFoundException();
        }

        if (!$lesson['free']) {
            $this->getCourseService()->tryTakeCourse($courseId);
        }

        if ($lesson['type'] != 'flash' || empty($lesson['mediaId'])) {
            throw $this->createNotFoundException();
        }

        $file = $this->getUploadFileService()->getFile($lesson['mediaId']);
        if (empty($file)) {
            throw $this->createNotFoundException();
        }

        $factory = new CloudClientFactory();
        $client = $factory->createClient();

        if ($file["hashId"]) {
            $url = $client->generateFileUrl($client->getBucket(), $file["hashId"], 3600);
            $result['mediaUri'] = $url['url'];
        } else {
            $result['mediaUri'] = '';
        }

        return $this->createJsonResponse($result);
    }

    public function fileAction(Request $request, $fileId, $isDownload = false)
    {
        $file = $this->getUploadFileService()->getFile($fileId);
        if (empty($file)) {
            throw $this->createNotFoundException();
        }

        if ($file['storage'] == 'cloud') {
            if ($isDownload) {
                $key = $file['hashId'];
            } else {
                if (!empty($file['metas']) && !empty($file['metas']['hd']['key'])) {
                    $key = $file['metas']['hd']['key'];
                } else {
                    $key = $file['hashId'];
                }
            }
            if (empty($key)) {
                throw $this->createNotFoundException();
            }

            $factory = new CloudClientFactory();
            $client = $factory->createClient();

            if ($isDownload) {
                $client->download($client->getBucket(), $key, 3600, $file['filename']);
            } else {
                $client->download($client->getBucket(), $key);
            }
        }

        return $this->createLocalMediaResponse($request, $file, $isDownload);
    }

    public function learnStatusAction(Request $request, $courseId, $lessonId)
    {
        $user = $this->getCurrentUser();
        $status = $this->getCourseService()->getUserLearnLessonStatus($user['id'], $courseId, $lessonId);

        return $this->createJsonResponse(array('status' => $status ?: 'unstart'));
    }

    public function learnStartAction(Request $request, $courseId, $lessonId)
    {
        $result = $this->getCourseService()->startLearnLesson($courseId, $lessonId);

        return $this->createJsonResponse($result);
    }

    public function learnFinishAction(Request $request, $courseId, $lessonId)
    {
        $user = $this->getCurrentUser();

        $this->getCourseService()->finishLearnLesson($courseId, $lessonId);

        $member = $this->getCourseService()->getCourseMember($courseId, $user['id']);

        $response = array(
            'learnedNum' => empty($member['learnedNum']) ? 0 : $member['learnedNum'],
            'isLearned' => empty($member['isLearned']) ? 0 : $member['isLearned'],
        );

        return $this->createJsonResponse($response);
    }

    public function learnCancelAction(Request $request, $courseId, $lessonId)
    {
        $this->getCourseService()->cancelLearnLesson($courseId, $lessonId);

        return $this->createJsonResponse(true);
    }

    public function watchNumAction(Request $request, $courseId, $lessonId)
    {
        $user = $this->getCurrentUser();
        $result = $this->getCourseService()->waveWatchNum($user['id'], $lessonId, 1);

        return $this->createJsonResponse($result);
    }

    protected function createLocalMediaResponse(Request $request, $file, $isDownload = false)
    {
        $response = BinaryFileResponse::create($file['fullpath'], 200, array(), false);
        $response->trustXSendfileTypeHeader();

        if ($isDownload) {
            $file['filename'] = urlencode($file['filename']);
            if (preg_match("/MSIE/i", $request->headers->get('User-Agent'))) {
                $response->headers->set('Content-Disposition', 'attachment; filename="'.$file['filename'].'"');
            } else {
                $response->headers->set('Content-Disposition', "attachment; filename*=UTF-8''".$file['filename']);
            }
        }

        $mimeType = FileToolkit::getMimeTypeByExtension($file['ext']);
        if ($mimeType) {
            $response->headers->set('Content-Type', $mimeType);
        }

        return $response;
    }

    protected function isMobile()
    {
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
            return true;
        }
        //如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
        if (isset($_SERVER['HTTP_VIA'])) {
            //找不到为flase,否则为true
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
        }
        //判断手机发送的客户端标志,兼容性有待提高
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $clientkeywords = array('nokia', 'sony', 'ericsson', 'mot', 'samsung', 'htc', 'sgh', 'lg', 'sharp',
                    'sie-', 'philips', 'panasonic', 'alcatel', 'lenovo', 'iphone', 'ipod', 'blackberry', 'meizu',
                    'android', 'netfront', 'symbian', 'ucweb', 'windowsce', 'palm', 'operamini', 'operamobi',
                    'openwave', 'nexusone', 'cldc', 'midp', 'wap', 'mobile', );
            // 从HTTP_USER_AGENT中查找手机浏览器的关键字
            if (preg_match("/(".implode('|', $clientkeywords).")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
                return true;
            }
        }
        //协议法,因为有可能不准确,放到最后判断
        if (isset($_SERVER['HTTP_ACCEPT'])) {
            // 如果只支持wml并且不支持html那一定是移动设备
            // 如果支持wml和html但是wml在html之前则是移动设备
            if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
                return true;
            }
        }

        return false;
    }

    public function listAction(Request $request, $courseId, $member, $previewUrl, $mode = 'full')
    {
        $user = $this->getCurrentUser();
        $learnStatuses = $this->getCourseService()->getUserLearnLessonStatuses($user['id'], $courseId);
        $items = $this->getCourseService()->getCourseItems($courseId);
        $course = $this->getCourseService()->getCourse($courseId);

        $homeworkPlugin = $this->getAppService()->findInstallApp('Homework');
        $homeworkLessonIds =array();
        $exercisesLessonIds =array();

        if($homeworkPlugin) {
            $lessonIds = ArrayToolkit::column($items, 'id');
            $homeworks = $this->getHomeworkService()->findHomeworksByCourseIdAndLessonIds($course['id'], $lessonIds);
            $exercises = $this->getExerciseService()->findExercisesByLessonIds($lessonIds);
            $homeworkLessonIds = ArrayToolkit::column($homeworks,'lessonId');
            $exercisesLessonIds = ArrayToolkit::column($exercises,'lessonId');
        }

        if ($this->setting('magic.lesson_watch_limit')) {
            $lessonLearns = $this->getCourseService()->findUserLearnedLessons($user['id'], $courseId);
        } else {
            $lessonLearns = array();
        }

        return $this->Render('TopxiaWebBundle:CourseLesson/Widget:list.html.twig', array(
            'items' => $items,
            'course' => $course,
            'member' => $member,
            'previewUrl' => $previewUrl,
            'learnStatuses' => $learnStatuses,
            'lessonLearns' => $lessonLearns,
            'currentTime' => time(),
            'homeworkLessonIds' => $homeworkLessonIds,
            'exercisesLessonIds' => $exercisesLessonIds,
            'mode' => $mode,
        ));
    }

    protected function getCourseService()
    {
        return $this->getServiceKernel()->createService('Course.CourseService');
    }

    protected function getTokenService()
    {
        return $this->getServiceKernel()->createService('User.TokenService');
    }

    protected function getUploadFileService()
    {
        return $this->getServiceKernel()->createService('File.UploadFileService');
    }

    protected function getTestpaperService()
    {
        return $this->getServiceKernel()->createService('Testpaper.TestpaperService');
    }

    //Homework plugins(contains Exercise)
    protected function getHomeworkService()
    {
        return $this->getServiceKernel()->createService('Homework:Homework.HomeworkService');
    }

    protected function getExerciseService()
    {
        return $this->getServiceKernel()->createService('Homework:Homework.ExerciseService');
    }

    protected function getAppService()
    {
        return $this->getServiceKernel()->createService('CloudPlatform.AppService');
    }

    protected function getCourseMemberService()
    {
        return $this->getServiceKernel()->createService('Course.CourseMemberService');
    }

    protected function getVipService()
    {
        return $this->getServiceKernel()->createService('Vip:Vip.VipService');
    }

    protected function getLevelService()
    {
        return $this->getServiceKernel()->createService('Vip:Vip.LevelService');
    }
}


text:
import { BigIntOrderedMap, Content, GraphNode, unixToDa } from '@urbit/api';
import bigInt, { BigInteger } from 'big-integer';

export const makeComment = (
  author: string,
  time: number,
  parentIndex: string,
  contents: Content[]
): [BigInteger, GraphNode] => {
  const da = unixToDa(time);
  const index = `${parentIndex}/${da.toString()}`;

  const children = new BigIntOrderedMap<GraphNode>().gas([
    [
      bigInt.one,
      {
        post: {
          index: `${index}/1`,
          author,
          'time-sent': time,
          signatures: [],
          contents: contents,
          hash: null
        },
        children: new BigIntOrderedMap()
      }
    ]
  ]);

  return [
    da,
    {
      post: {
        index,
        author,
        'time-sent': time,
        signatures: [],
        contents: [],
        hash: null
      },
      children
    }
  ];
};


text:
package headfirst.designpatterns.decorator.starbuzzWithSizes;

public class Mocha extends CondimentDecorator {
	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Mocha";
	}

	public double cost() {
		return beverage.cost() + .20;
	}
}


text:
#pragma config(Hubs,  S1, HTMotor,  HTServo,  HTMotor,  HTMotor)
#pragma config(Sensor, S2,     SMUX,           sensorI2CCustom)
#pragma config(Sensor, S3,     HTSPB,          sensorI2CCustom)
#pragma config(Sensor, S4,     SMUX2,          sensorI2CCustom)
#pragma config(Motor,  mtr_S1_C1_1,     leftTread,     tmotorTetrix, openLoop, reversed)
#pragma config(Motor,  mtr_S1_C1_2,     rightTread,    tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C3_1,     flag,          tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C3_2,     harvester,     tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C4_1,     rightHang,     tmotorTetrix, openLoop)
#pragma config(Motor,  mtr_S1_C4_2,     leftHang,      tmotorTetrix, openLoop, reversed)
#pragma config(Servo,  srvo_S1_C2_1,    servo1,               tServoNone)
#pragma config(Servo,  srvo_S1_C2_2,    servo2,               tServoNone)
#pragma config(Servo,  srvo_S1_C2_3,    flagServo,            tServoNone)
#pragma config(Servo,  srvo_S1_C2_4,    wrist,                tServoNone)
#pragma config(Servo,  srvo_S1_C2_5,    elbow,                tServoNone)
#pragma config(Servo,  srvo_S1_C2_6,    stopper,              tServoNone)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

//Copyright (c) 2014 Jon Xia, RM Robotics

#include "../headers/drivers.h"
#include "../headers/smux_sensor_definitions.h"

typedef struct {
	int flagSpeed;
} nxtState;

void initialize(nxtState *state);
void updateInput(nxtState *state);
void updateRobot(nxtState *state);
void showDiagnostics(nxtState *state);

task main()
{
	nxtState currentState;
	initialize(currentState);

	while(true){
		updateInput(currentState);
		updateRobot(currentState);
		showDiagnostics(currentState);
	}
}

void initialize(nxtState *state) {
	memset(state, 0, sizeof(state));
}

void updateInput(nxtState *state) {
	if (nNxtButtonPressed == 1){
		state->flagSpeed = 100;
	}else if (nNxtButtonPressed == 2){
		state->flagSpeed = -100;
	}else {
		state->flagSpeed = 0;
		state->flagSpeed = 0;
	}
}

void updateRobot(nxtState *state) {
	motor[flag]=state->flagSpeed;
}

void showDiagnostics(nxtState *state) {
	//create label
	string batteryLevel = "power = ";

	//store variable in a string
	string string5 = externalBatteryAvg;

	//concat variable with label
	strcat(batteryLevel, string5);

	eraseDisplay();

	//display label and value
	nxtDisplayTextLine(1, "Flag Turner");
	nxtDisplayTextLine(2, "LftBtn:ccw,RtBtn:cw");
	nxtDisplayTextLine(3, batteryLevel);
}


text:
layout: default
title: OpenHack - Vancouver, BC
---

## Vancouver, BC

![Vancouver City Center](/vancouver/city.jpg)

### Info

* Time: TBD
* Location: TBD

Pretty much everything is TBD at the moment. If you're interested in
being a apart of the Vancouver OpenHack community, please head to the
Vancouver OpenHack [issue
tracker](https://github.com/distracteddev/vancouver-open-hack/issues) to
share your thoughts and introduce yourself.

### Next meetups

First, we need to find a location, then we need some people ><. Or maybe
its the other way around?

### Past meetups

One step at a time.


text:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <alpha android:fromAlpha="0" android:toAlpha="1" android:duration="400"/>

    <!--
    <scale
        android:interpolator="@android:anim/linear_interpolator"
        android:fromXScale="0.0"
        android:toXScale="1.0"
        android:fromYScale="0.0"
        android:toYScale="1.0"
        android:fillAfter="false"
        android:startOffset="200"
        android:duration="200"
        android:pivotX = "50%"
        android:pivotY = "-90%"
        />
    <translate
        android:fromXDelta="-30%"
        android:toXDelta="0"
        android:fromYDelta="50%"
        android:toYDelta="0"
        android:startOffset="200"
        android:duration="200"
        />
        -->
</set>


text:
<?xml version="1.0" encoding="utf-8"?>
<!--Generated by crowdin.net-->
<!--
     Copyright (C) 2012-2014 The CyanogenMod Project

     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
  <plurals name="n_folders">
    <item quantity="other"><xliff:g id="folders">%1$d</xliff:g> folder</item>
  </plurals>
  <plurals name="n_files">
    <item quantity="other"><xliff:g id="files">%1$d</xliff:g> file</item>
  </plurals>
  <plurals name="search_found_items">
    <item quantity="other"><xliff:g id="count">%d</xliff:g> item ditemukan</item>
  </plurals>
  <plurals name="selection_folders">
    <item quantity="other"><xliff:g id="folders">%1$d</xliff:g> folder terpilih.</item>
  </plurals>
  <plurals name="selection_files">
    <item quantity="other"><xliff:g id="files">%1$d</xliff:g> file terpilih.</item>
  </plurals>
</resources>


text:
namespace rx
{

class FenceNVImpl
{
  public:
    FenceNVImpl() { };
    virtual ~FenceNVImpl() { };

    virtual gl::Error set() = 0;
    virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0;
    virtual gl::Error finishFence(GLboolean *outFinished) = 0;

  private:
    DISALLOW_COPY_AND_ASSIGN(FenceNVImpl);
};

class FenceSyncImpl
{
  public:
    FenceSyncImpl() { };
    virtual ~FenceSyncImpl() { };

    virtual gl::Error set() = 0;
    virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
    virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
    virtual gl::Error getStatus(GLint *outResult) = 0;

  private:
    DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl);
};

}

#endif // LIBANGLE_RENDERER_FENCEIMPL_H_


text:
class Camera{
public:
  Camera();
  Camera(glm::vec3 const& pos);
  Camera(std::string const& name, glm::vec3 const& eye, glm::vec3 const& direction, glm::vec3 const& up, float& fov);
  Camera(Camera const& cam);
  ~Camera();

  Camera& operator=(Camera& tmp);

  std::string get_name() const;
  glm::vec3 get_position() const;
  glm::vec3 get_direction() const;
  float get_fov_x() const;
  glm::vec3 get_up() const;
  Ray eyeRay(float x, float y) const;
  void setResolution(int width, int height);
  unsigned width() const;
  unsigned height() const;

private:
  std::string name_;
  glm::vec3 eye_;
  glm::vec3 direction_;
  glm::vec3 up_;
  float fovX_;
  int width_;
  int height_;
};

#endif


text:
function volume_struct = CreateFunctionalVolumeStruct(studypath, image, bold_reps)

volume_struct = cell(bold_reps,1);
for vol = 1:bold_reps
	volume_struct{vol} = strcat(studypath, image, ',', int2str(vol));
end


text:
#include "core/cexception.h"
#include "modules/db/sqlite3/sqlite3.h"
#include "modules/std/core/map.h"
#include "modules/std/core/str.h"

namespace clever { namespace modules { namespace db {

static Value* _sqlite_to_value(sqlite3_stmt* stmt, int column)
{
	Value* value = new Value;

	switch (sqlite3_column_type(stmt, column)) {
		case SQLITE_INTEGER:
			value->setInt(sqlite3_column_int64(stmt, column));
			break;
		case SQLITE_FLOAT:
			value->setDouble(sqlite3_column_double(stmt, column));
			break;
		case SQLITE_NULL:
			break;
		case SQLITE_TEXT:
			{
				const char* str = reinterpret_cast<const char*>(sqlite3_column_text(stmt, column));
				value->setStr(new StrObject(str));
			}
			break;
		case SQLITE_BLOB:
			{
				const char* buf = static_cast<const char*>(sqlite3_column_blob(stmt, column));
				value->setStr(new StrObject(buf));
			}
			break;
	}

	return value;
}

// SQLite3 constructor
CLEVER_METHOD(SQLite3Type::ctor)
{
	if (!clever_check_args("s")) {
		return;
	}

	SQLite3Conn* conn = new SQLite3Conn(*args[0]->getStr());

	if (sqlite3_open(args[0]->getStr()->c_str(), &conn->handle) != SQLITE_OK) {
		clever_throw("An error occurred when opening database: %s",
			sqlite3_errmsg(conn->handle));

		clever_delref(conn);
		return;
	}

	result->setObj(this, conn);
}

// SQLite3::exec(String pattern)
CLEVER_METHOD(SQLite3Type::exec)
{
	if (!clever_check_args("s")) {
		return;
	}

	SQLite3Conn* conn = clever_get_this(SQLite3Conn*);
	char* errmsg = NULL;

	sqlite3_exec(conn->handle,
		args[0]->getStr()->c_str(),
		NULL,
		NULL,
		&errmsg);

	if (errmsg) {
		clever_throw("An error occurred when executing a statement: %s",
			errmsg);

		sqlite3_free(errmsg);
		return;
	}

	result->setBool(true);
}

// SQLite3::query(String query)
CLEVER_METHOD(SQLite3Type::query)
{
	if (!clever_check_args("s")) {
		return;
	}

	SQLite3Conn* conn = clever_get_this(SQLite3Conn*);
	sqlite3_stmt* stmt;

	if (sqlite3_prepare_v2(conn->handle,
		args[0]->getStr()->c_str(),
		args[0]->getStr()->size(),
		&stmt,
		NULL) != SQLITE_OK) {
		clever_throw("An error occurred when preparing query: %s",
			sqlite3_errmsg(conn->handle));
		return;
	}

	switch (sqlite3_step(stmt)) {
		case SQLITE_DONE:
		case SQLITE_ROW:
			sqlite3_reset(stmt);
			break;
		case SQLITE_ERROR:
			clever_throw("%s", sqlite3_errmsg(conn->handle));
			return;
	}

	SQLite3Result* res = new SQLite3Result(stmt);

	conn->results.push_back(res);
	clever_addref(res);

	result->setObj(result_type, res);
}

// SQLite3::getLastId()
CLEVER_METHOD(SQLite3Type::getLastId)
{
	if (!clever_check_no_args()) {
		return;
	}

	SQLite3Conn* conn = clever_get_this(SQLite3Conn*);

	result->setInt(sqlite3_last_insert_rowid(conn->handle));
}

// SQLite3::prepare(String statement)
CLEVER_METHOD(SQLite3Type::prepare)
{
	if (!clever_check_args("s")) {
		return;
	}

	SQLite3Conn* conn = clever_get_this(SQLite3Conn*);
	sqlite3_stmt* stmt;

	if (sqlite3_prepare_v2(conn->handle,
		args[0]->getStr()->c_str(),
		args[0]->getStr()->size(),
		&stmt,
		NULL) != SQLITE_OK) {
		clever_throw("An error occurred when preparing query: %s",
			sqlite3_errmsg(conn->handle));
		return;
	}

	SQLite3Stmt* stmt_obj = new SQLite3Stmt(stmt, conn);

	conn->results.push_back(stmt_obj);
	clever_addref(stmt_obj);

	result->setObj(stmt_type, stmt_obj);
}

// SQLite3::close()
CLEVER_METHOD(SQLite3Type::close)
{
	if (!clever_check_no_args()) {
		return;
	}

	SQLite3Conn* conn = clever_get_this(SQLite3Conn*);

	result->setBool(conn->close() == SQLITE_OK);
}

// SQLite3Stmt::bindValue(Int num, Objet value)
CLEVER_METHOD(SQLite3TypeStmt::bindValue)
{
	if (!clever_check_args("i.")) {
		return;
	}

	SQLite3Stmt* stmt = clever_get_this(SQLite3Stmt*);

	std::stringstream ss;

	ss << ":" << args[0]->getInt();

	int nparam = sqlite3_bind_parameter_index(stmt->stmt, ss.str().c_str());

	stmt->bound_params.push_back(BoundParamPair(nparam, args[1]));

	clever_addref(args[1]);
}

// SQLite3Stmt::execute()
CLEVER_METHOD(SQLite3TypeStmt::execute)
{
	if (!clever_check_no_args()) {
		return;
	}

	SQLite3Stmt* stmt = clever_get_this(SQLite3Stmt*);

	std::vector<BoundParamPair>::const_iterator it(stmt->bound_params.begin()),
		end(stmt->bound_params.end());

	for (; it != end; ++it) {
		if (it->second->isInt()) {
			sqlite3_bind_int64(stmt->stmt, it->first, it->second->getInt());
		} else if (it->second->isStr()) {
			sqlite3_bind_text(stmt->stmt, it->first,
				it->second->getStr()->c_str(),
				it->second->getStr()->size(), SQLITE_STATIC);
		} else if (it->second->isDouble()) {
			sqlite3_bind_double(stmt->stmt, it->first, it->second->getDouble());
		} else if (it->second->isNull()) {
			sqlite3_bind_null(stmt->stmt, it->first);
		} else {
			clever_throw("Unknown parameter type `%T'",
				it->second->getType());
			return;
		}
	}

	switch (sqlite3_step(stmt->stmt)) {
		case SQLITE_ROW:
		case SQLITE_DONE:
			{
				sqlite3_reset(stmt->stmt);
				SQLite3Result* res = new SQLite3Result(stmt->stmt);

				stmt->conn->results.push_back(res);
				clever_addref(stmt);
				clever_addref(res);

				stmt->clear();

				result->setObj(getParentType()->getResultType(), res);
			}
			break;
		default:
			sqlite3_reset(stmt->stmt);
			result->setBool(false);
			return;
	}
}

// SQLite3Result::fetch()
CLEVER_METHOD(SQLite3TypeResult::fetch)
{
	if (!clever_check_no_args()) {
		return;
	}

	SQLite3Result* res = clever_get_this(SQLite3Result*);
	int ret_code = sqlite3_step(res->stmt);

	if (ret_code != SQLITE_ROW) {
		result->setBool(false);
		return;
	}

	MapObject* map = new MapObject;

	for (int i = 0, n = sqlite3_data_count(res->stmt); i < n; ++i) {
		map->getData().insert(MapObjectPair(
			sqlite3_column_name(res->stmt, i), _sqlite_to_value(res->stmt, i)));
	}

	result->setObj(CLEVER_MAP_TYPE, map);
}

// SQLite3Result::finalize()
CLEVER_METHOD(SQLite3TypeResult::finalize)
{
	if (!clever_check_no_args()) {
		return;
	}

	SQLite3Result* res = clever_get_this(SQLite3Result*);

	sqlite3_reset(res->stmt);
}

// SQLite3 type initialization
CLEVER_TYPE_INIT(SQLite3Type::init)
{
	setConstructor((MethodPtr)&SQLite3Type::ctor);

	addMethod(new Function("exec",      (MethodPtr)&SQLite3Type::exec));
	addMethod(new Function("query",     (MethodPtr)&SQLite3Type::query));
	addMethod(new Function("prepare",   (MethodPtr)&SQLite3Type::prepare));
	addMethod(new Function("getLastId", (MethodPtr)&SQLite3Type::getLastId));
	addMethod(new Function("close",     (MethodPtr)&SQLite3Type::close));
}

// SQLite3Stmt type initialization
CLEVER_TYPE_INIT(SQLite3TypeStmt::init)
{
	addMethod(new Function("bindValue", (MethodPtr)&SQLite3TypeStmt::bindValue));
	addMethod(new Function("execute",   (MethodPtr)&SQLite3TypeStmt::execute));
}

// SQLite3Stmt type initialization
CLEVER_TYPE_INIT(SQLite3TypeResult::init)
{
	addMethod(new Function("fetch",    (MethodPtr)&SQLite3TypeResult::fetch));
	addMethod(new Function("finalize", (MethodPtr)&SQLite3TypeResult::finalize));
}

}}} // clever::modules::std


text:
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>pentaho</groupId>
    <artifactId>pentaho-osgi-bundles</artifactId>
    <version>7.1-SNAPSHOT</version>
  </parent>
  <artifactId>pentaho-i18n-webservice-bundle</artifactId>
  <version>7.1-SNAPSHOT</version>
  <packaging>bundle</packaging>
  <name>Pentaho Community Edition Project: ${project.artifactId}</name>
  <description>a Pentaho open source project</description>
  <url>http://www.pentaho.com</url>
  <dependencies>
    <dependency>
      <groupId>pentaho</groupId>
      <artifactId>pentaho-i18n-bundle</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.felix</groupId>
      <artifactId>org.apache.felix.framework</artifactId>
      <version>${felix.version}</version>
    </dependency>
    <dependency>
      <groupId>com.googlecode.json-simple</groupId>
      <artifactId>json-simple</artifactId>
      <version>${json-simple.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxrs</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-frontend-jaxws</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.cxf</groupId>
      <artifactId>cxf-rt-transports-http-jetty</artifactId>
      <version>${cxf.version}</version>
    </dependency>
    <dependency>
      <groupId>org.ops4j.pax.web</groupId>
      <artifactId>pax-web-extender-whiteboard</artifactId>
      <version>${pax-web-extender-whiteboard.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.felix</groupId>
      <artifactId>org.apache.felix.http.api</artifactId>
      <version>${org.apache.felix.http.api.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>${mockito.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
  <build>
    <resources>
      <resource>
        <filtering>false</filtering>
        <directory>src/main/resources</directory>
        <includes>
          <include>**/*</include>
        </includes>
        <excludes>
          <exclude>META-INF/**/*</exclude>
          <exclude>OSGI-INF/blueprint/*</exclude>
        </excludes>
      </resource>
      <resource>
        <filtering>true</filtering>
        <directory>src/main/resources</directory>
        <includes>
          <include>META-INF/**/*</include>
          <include>OSGI-INF/blueprint/*</include>
        </includes>
      </resource>
    </resources>
    <finalName>${project.artifactId}</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>${maven-bundle-plugin.version}</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Bundle-Version>${project.version}</Bundle-Version>
            <Import-Package>org.apache.felix.http.api,*</Import-Package>
          </instructions>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>