text:
// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.

package com.google.collide.server.fe;

import collide.server.CollideServer;
import com.google.collide.dto.shared.JsonFieldConstants;
import com.google.collide.server.maven.MavenResources;
import com.google.collide.server.shared.BusModBase;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.net.JksOptions;
import io.vertx.core.net.NetSocket;
import io.vertx.core.shareddata.LocalMap;
import io.vertx.core.shareddata.Shareable;
import io.vertx.ext.bridge.PermittedOptions;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.sockjs.BridgeOptions;
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
import io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions;
import org.apache.http.HttpStatus;
import xapi.gwtc.api.CompiledDirectory;
import xapi.log.X_Log;
import xapi.reflect.X_Reflect;
import xapi.server.vertx.VertxContext;
import xapi.server.vertx.scope.RequestScopeVertx;
import xapi.server.vertx.VertxRequest;
import xapi.server.vertx.VertxResponse;
import xapi.util.api.Pointer;

import java.io.File;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * A simple web server module that can serve static files bundled with the webserver, as well as
 * serve files from the directory that the webserver was launched in via simple URL path prefixes.
 *
 *  This web server can also bridge event bus messages to/from client side JavaScript and the server
 * side event bus.
 *
 * (Implementation based on the stock WebServer module bundled with the Vert.x distribution)
 */
public class WebFE extends BusModBase implements Handler<HttpServerRequest> {

  private static final String WEBROOT_PATH = "/res/";
  private static final String BUNDLED_STATIC_FILES_PATH = "/static/";
  private static final String AUTH_PATH = "/_auth";
  private static final String CODESERVER_FRAGMENT = "/code/";
  private static final String EVENTBUS_FRAGMENT = "/eventbus";
  private static final String SOURCEMAP_PATH = "/sourcemaps/";

  private static final String AUTH_COOKIE_NAME = "_COLLIDE_SESSIONID";

  /**
   * The directory that we will be serving our bundled web application client form. We serve content
   * from here when the URL matches {@link #WEBROOT_PATH}
   */
  private String bundledStaticFilesPrefix;

  /**
   * The directory that we are serving files from as the "web root". We serve content from here when
   * the URL matches {@link #BUNDLED_STATIC_FILES_PATH}
   */
  private String webRootPrefix;

  /**
   * The directory in which we are compiling temporary files (for gwt builds),
   * used when invoking the code server /{@link #CODESERVER_FRAGMENT}/your.gwt.module/command
   * where command = compile | clean | kill
   *
   * Defaults to the value from MavenConfig, which will default to /tmp
   */
  private String workDir;

  /**
   * The master production directory for your webapp, to which we will sync all changes.
   * If this value == webRootPrefix, then mvn collide:deploy will sync to your collide work directory.
   * Web invoke: /{@link #CODESERVER_FRAGMENT}/deploy
   *
   * Defaults to the value from MavenConfig, which will default to {@link #WEBROOT_PATH}/war
   */
  private String warDir;

  /**
   * Your project / maven configuration file.
   */
  private MavenResources config;
  private SockJSHandler sjsServer;
  private Router router;
  private String collideHome;
  private CollideServer server;

  @Override
  public void start() {
    super.start();

    final HttpServerOptions opts = new HttpServerOptions();

    // Configure SSL.
    if (getOptionalBooleanConfig("ssl", false)) {
      opts.setSsl(true)
          .setLogActivity(true)
          .setKeyStoreOptions(new JksOptions()
            .setPassword(getOptionalStringConfig("keyStorePassword", "password"))
            .setPath(getOptionalStringConfig("keyStorePath", "server-keystore.jks"))
          );
    }

    // Configure the event bus bridge.
    boolean bridge = getOptionalBooleanConfig("bridge", false);
    if (bridge) {

      final SockJSHandlerOptions sockOpts = new SockJSHandlerOptions()
          .setHeartbeatInterval(2_000)
          .setSessionTimeout(15_000)
//            .setLibraryURL(getOptionalStringConfig("suffix", "") + "/eventbus")
          ;
      JsonArray inboundPermitted = getOptionalArrayConfig("in_permitted", new JsonArray());
      JsonArray outboundPermitted = getOptionalArrayConfig("out_permitted", new JsonArray());
      final BridgeOptions bridgeOpts = new BridgeOptions()
          .setReplyTimeout(15_000)
          .setPingTimeout(15_000);
      bridgeOpts.setInboundPermitted(toOpts(inboundPermitted));
      bridgeOpts.setOutboundPermitted(toOpts(outboundPermitted));

      sjsServer = SockJSHandler.create(vertx, sockOpts);
      sjsServer.bridge(bridgeOpts);

      router = Router.router(vertx);
//
      router.route("/eventbus/*").handler(sjsServer);

//          getOptionalStringConfig("auth_address", "participants.authorise"));
    }

    HttpServer server = vertx.createHttpServer(opts);
    server.requestHandler(this);

    String bundledStaticFiles = getMandatoryStringConfig("staticFiles");
    String webRoot = getMandatoryStringConfig("webRoot");
    String workDirectory = getOptionalStringConfig("workDir", "/tmp");
    String collide = getOptionalStringConfig("collideHome",
        X_Reflect.getFileLoc(WebFE.class).replace(
            "/server/build/classes/main/".replace('/', File.separatorChar) , ""));
    String warDirectory = getOptionalStringConfig("warDir", webRoot + File.separator + "war");

    bundledStaticFilesPrefix = bundledStaticFiles + File.separator;
    webRootPrefix = webRoot + File.separator;
    workDir = workDirectory + File.separator;
    warDir = warDirectory + File.separator;
    collideHome = collide + File.separator;
    this.server = new CollideServer(
        bundledStaticFilesPrefix, webRootPrefix, workDir, warDir, collideHome
    );
    int port = getOptionalIntConfig("port", 8080);
    String host = getOptionalStringConfig("host", "127.0.0.1");
    System.out.println("Connecting to "+host+":"+port);
    server.listen(port, host);

    vertx.eventBus().<JsonObject>consumer("frontend.symlink", event -> {
        //TODO: require these messages to be signed by code private to the server
        try{
        String dto = event.body().getString("dto");
        X_Log.trace("Symlinking",dto);
        CompiledDirectory dir = CompiledDirectory.fromString(dto, ShareableCompileDirectory::new);
        vertx.sharedData().getLocalMap("symlinks").put(
            dir.getUri()
            , dir);
        }catch (Exception e) {
          e.printStackTrace();
        }
    });
  }
  public static class ShareableCompileDirectory extends CompiledDirectory implements Shareable{}

  private List<PermittedOptions> toOpts(JsonArray inboundPermitted) {
    return ((List<?>)inboundPermitted.getList())
        .stream()
        .map(name->new PermittedOptions().setAddressRegex(String.valueOf(name)))
        .collect(Collectors.toList());
  }

  private class SymlinkRequest{
    String urlFragment;
    String defaultTarget;
    String userAgent;
    HttpServerResponse response;
  }
  private class SymlinkResponse{
    boolean handled;
    String resolved;
  }

  @Override
  public void handle(HttpServerRequest req) {
    if (req.path().startsWith("/xapi")) {
      handleXapi(req);
      return;
    }
    if (req.path().equals("/") || req.path().equals("/demo")) {
      //send login page
      authAndWriteHostPage(req);
      return;
    }
    String path = req.path().replace("/demo/", "/");
    if (path.contains("..")) {
      //sanitize hack attempts
      sendStatusCode(req, 404);
        return;
    } else if (path.startsWith(EVENTBUS_FRAGMENT)) {
      System.out.println("Sending to event bus: " + router.get(req.path()));
      router.accept(req);
//      req.upgrade()
        return;
    } else if (path.startsWith(CODESERVER_FRAGMENT)) {
      sendToCodeServer(req);//listen on http so we can send compile requests without sockets hooked up.
        return;
    } else if (path.startsWith(AUTH_PATH)) {
        writeSessionCookie(req);
        return;
      } else if (path.startsWith(WEBROOT_PATH) && (webRootPrefix != null)){
        //TODO: sanitize this path
        //check for symlinks
        logger.info(path);
        SymlinkRequest request = new SymlinkRequest();
        request.urlFragment = path.substring(WEBROOT_PATH.length());
        request.defaultTarget = webRootPrefix;
        request.response = req.response();
        SymlinkResponse response = processSymlink(request);
        if (response.handled)
          return;
      } else if (path.contains(SOURCEMAP_PATH)){
        //forward sourcemap paths to appropriate internal server
        SymlinkRequest request = new SymlinkRequest();
        request.urlFragment = path;
        // dump headers in case we can pull in the permutation here...
        request.userAgent = req.headers().get("User-Agent");
        request.defaultTarget = webRootPrefix;
        request.response = req.response();
        SymlinkResponse response = processSymlink(request);
        if (response.handled)
          return;

      } else if (path.startsWith(BUNDLED_STATIC_FILES_PATH) && (bundledStaticFilesPrefix != null)) {
        Pointer<String> file = new Pointer<String>(path.substring(BUNDLED_STATIC_FILES_PATH.length()));
        //check for symlinks
        SymlinkRequest request = new SymlinkRequest();
        request.urlFragment = file.get();
        request.defaultTarget = bundledStaticFilesPrefix;
        request.response = req.response();
        SymlinkResponse response = processSymlink(request);
        if (response.handled)
          return;
      }
      //if we didn't return, we're out of options.
      doFail(req);
  }

  private void doFail(HttpServerRequest req) {
    //TODO: add a pluggable proxy here.
    sendStatusCode(req, HttpStatus.SC_NOT_FOUND);
  }
  private SymlinkResponse processSymlink(final SymlinkRequest request) {
    SymlinkResponse response = new SymlinkResponse();

    LocalMap<String, Object> map = vertx.sharedData().getLocalMap("symlinks");
    Set<String> keys= map.keySet();
    String uri = request.urlFragment;
//    System.out.println("Dereferencing request uri: "+uri+" against "+keys);
    if (uri.length() == 0) {
      return response;
    }
    if (uri.charAt(0)=='/')uri = uri.substring(1);
    for (Object key : keys){
      final String symlink = String.valueOf(key);
      if (uri.contains(symlink)){
        Object link =  map.get(symlink);
        //TODO: also serve up _gen, _extra, _source, etc.
        if (("/"+uri).contains(SOURCEMAP_PATH)){
          X_Log.info("Checking against symlink ",uri," .contains( ",symlink," )");
          //serve up file from our sourcemap directory
          try{
            if (uri.endsWith(".java")||uri.endsWith("gwtSourceMap.json")){
              //client is requesting actual source file.

              //try to proxy the request to tcp server in gwt compiler.
              int port =
                  (int) link.getClass().getMethod("getPort").invoke(link);
              final String cls = uri;
              final Pointer<Boolean> success = new Pointer<Boolean>(false);
              vertx.createNetClient().connect(port, "localhost",
                  async -> {
                  final NetSocket event = async.result();
                    if (cls.endsWith("json")) {
                      // requesting sourcemap file
                      request.response.headers().set("Content-Type","application/json");
                      event.write(cls+"\n" + "User-Agent: "+request.userAgent);
                    } else {
                      // requesting source file
                      // chop off the module name from cls
                      event.write(cls.substring(1+cls.indexOf('/',SOURCEMAP_PATH.length())));
                      request.response.headers().set("Content-Type","text/plain");
                    }

                    final Buffer buf = Buffer.buffer(4096);
                    event.handler(buf::appendBuffer);
                    event.closeHandler(ev-> {
                        int len = buf.length();
                        if (len > 0) {
                          success.set(true);
                          request.response.putHeader("Content-Length", Integer.toString(buf.length()));
                          request.response.putHeader("Content-Type",
                            cls.endsWith("json") ? "application/json" : "text/plain");
                          request.response.end(buf);
                          synchronized (success) {
                            success.notify();
                          }
                        }
                    });
              });
              synchronized (success) {
                success.wait(5000);
              }
              response.handled = success.get();
              return response;
            }

            String base = String.valueOf(link.getClass().getMethod("getSourceMapDir").invoke(link));

            //current super dev mode only produces one permutation for chrome,
            //so there >should< only be be one sourcemap file to find.
            //in the future, we will have to resolve the correct permutation to send.

            //for now, we'll just search for the file requested.
            File f = new File(base);
            if (f.exists()&&f.isDirectory()){
              String suffix = uri.substring(1+uri.lastIndexOf('.'));
              for (File child : f.listFiles()){
                if (child.getName().endsWith(suffix)){
                  response.handled=true;
                  response.resolved = child.getAbsolutePath();
                  applySourceMapHeader(request.response, response.resolved);
                  request.response.sendFile(response.resolved);
                  return response;
                }
              }
            }
          }catch (Exception e) {
            e.printStackTrace();
          }
        }

        try{
          response.resolved =
              link.getClass().getMethod("getWarDir").invoke(link)+"/"+symlink
              +uri.substring(symlink.length());
          logger.info("Symlink resolved to "+response.resolved);
          response.handled = true;
          applySourceMapHeader(request.response, response.resolved);
          request.response.sendFile(response.resolved);
          return response;
        }catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    response.handled=true;
    if (request.urlFragment.contains(SOURCEMAP_PATH)) {
      // This is for statically compiled gwt source (built through gradle),
      // which will have a different structure than our dynamic superdev compiles;
      String[] bits = request.urlFragment.split("/");
      String moduleName = bits[2];
      if (request.urlFragment.endsWith(".json")) {
        // we are safe to assume _sourceMap0 since there will never be more than 1 iteration on a full compile
        String extras = bundledStaticFilesPrefix.replace("out/"+moduleName, "extra/"+moduleName);
        if (bits[4].contains("sourceMap0.json")) {
          // super dev mode...
          String mapFile = bits[4].replaceAll("(_sourcemap)?[.]json", "_sourceMap0.json");
          response.resolved = extras + "/symbolMaps/" + mapFile;
        } else {
          // full compile; source maps are stored per split point, in a different structure...

          String mapFile = bits[4].replaceAll("([A-F0-9]+)[.]json", "$1");
          if (mapFile.matches("^[0-9]+$")) {
            response.resolved = extras + "symbolMaps/" + moduleName + "_sourceMap" + mapFile + ".json";
          } else {
            response.resolved = extras + "symbolMaps/" + mapFile + "_sourceMap0.json";
          }
        }
      } else {
        String sourceFolder = bundledStaticFilesPrefix.replace("out/"+moduleName, "sourcemaps") + moduleName+ "/src/";
        response.resolved = sourceFolder + request.urlFragment.split(SOURCEMAP_PATH)[1];

      }
    } else {
      response.resolved = request.defaultTarget+request.urlFragment;
      applySourceMapHeader(request.response, response.resolved);
    }
    request.response.sendFile(response.resolved);
    return response ;
  }

  private void applySourceMapHeader(HttpServerResponse response, String moduleName) {
    if (moduleName.endsWith(".cache.js")){
      int last = moduleName.lastIndexOf('/');
      String strongName = moduleName.substring(last+1).split("[.]cache")[0];
      moduleName = moduleName.substring(moduleName.lastIndexOf('/',last-1)+1,last);
      // TODO: perform reverse-lookup on shortened module name
      // TODO: link strong name to user session for this module
      response.putHeader("X-SourceMap",BUNDLED_STATIC_FILES_PATH+moduleName +SOURCEMAP_PATH+strongName+".json");
      response.putHeader("Access-Control-Allow-Origin", "*");
    }
  }

  private void sendToCodeServer(HttpServerRequest req) {
    Cookie cookie = Cookie.getCookie(AUTH_COOKIE_NAME, req);
    if (cookie == null) {
      sendRedirect(req, "/static/login.html");
      return;
    }
    //TODO: forward commands to message bus, so we can allow throttled guest compiles.
//    QueryStringDecoder qsd = new QueryStringDecoder(req.query, false);
//    Map<String, List<String>> params = qsd.getParameters();
//
//    List<String> loginSessionIdList = params.get(JsonFieldConstants.SESSION_USER_ID);
//    List<String> usernameList = params.get(JsonFieldConstants.SESSION_USERNAME);
//    if (loginSessionIdList == null || loginSessionIdList.size() == 0 ||
//        usernameList == null || usernameList.size() == 0) {
//      sendStatusCode(req, 400);
//      return;
//    }
//
//    final String sessionId = loginSessionIdList.get(0);
//    final String username = usernameList.get(0);
//    List<String> modules = qsd.getParameters().get("module");
//
//    if (modules != null){
//      MavenResources config = getConfig(req);
//      CodeSvr.startOrRefresh(logToVertx(req),config,modules);
//    }
  }

  private MavenResources getConfig(HttpServerRequest req) {
//    req.response.
    MavenResources res = new MavenResources();
    res.setSrcRoot(webRootPrefix);
    res.setWorkDir(workDir);
    res.setWarTargetDir(warDir);
    res.setWarSrcDir(warDir);
    return res;
  }

  private void authAndWriteHostPage(HttpServerRequest req) {
    Cookie cookie = Cookie.getCookie(AUTH_COOKIE_NAME, req);
    if (cookie != null) {
      // We found a session ID. Lets go ahead and serve up the host page.
      doAuthAndWriteHostPage(req, cookie.value);
      return;
    }

    // We did not find the session ID. Lets go ahead and serve up the login page that should take
    // care of installing a cookie and reloading the page.
    sendRedirect(req, "/static/login.html");
  }

  // TODO: If we want to make this secure, setup SSL and set this as a Secure cookie.
  // Also probably want to resurrect XsrfTokens and the whole nine yards. But for now, this is
  // purely a tracking cookie.
  /**
   * Writes cookies for the session ID that is posted to it.
   */
  private void writeSessionCookie(final HttpServerRequest req) {
    if (!"POST".equals(req.method().name())) {
      sendStatusCode(req, HttpStatus.SC_METHOD_NOT_ALLOWED);
      return;
    }

    // Extract the post data.
    req.bodyHandler(new Handler<Buffer>() {
        @Override
      public void handle(Buffer buff) {
        String contentType = req.headers().get("Content-Type");
        if (String.valueOf(contentType).startsWith("application/x-www-form-urlencoded")) {
          QueryStringDecoder qsd = new QueryStringDecoder(buff.toString(), false);
          Map<String, List<String>> params = qsd.parameters();

          List<String> loginSessionIdList = params.get(JsonFieldConstants.SESSION_USER_ID);
          List<String> usernameList = params.get(JsonFieldConstants.SESSION_USERNAME);
          if (loginSessionIdList == null || loginSessionIdList.size() == 0 ||
              usernameList == null || usernameList.size() == 0) {
            System.out.println("Failed to write session cookie; "+loginSessionIdList+" / "+usernameList);
            sendStatusCode(req, 400);
            return;
          }

          final String sessionId = loginSessionIdList.get(0);
          final String username = usernameList.get(0);
          X_Log.info("Writing session cookie; ",username," / ",sessionId);
          vertx.eventBus().<JsonObject>send("participants.authorise",
              new JsonObject().put("sessionID", sessionId).put("username", username),
              async -> {
                final Message<JsonObject> event = async.result();
              X_Log.trace("Writing session cookie; ",event.body());
              if ("ok".equals(event.body().getString("status"))) {
                req.response().headers().set("Set-Cookie",
                    AUTH_COOKIE_NAME + "=" + sessionId + "__" + username + "; HttpOnly");
                sendStatusCode(req, HttpStatus.SC_OK);
              } else {
                sendStatusCode(req, HttpStatus.SC_FORBIDDEN);
              }
            }
          );
        } else {
          sendRedirect(req, "/static/login.html");
        }
      }
    });
  }

  private void doAuthAndWriteHostPage(final HttpServerRequest req, String authCookie) {
    String[] cookieParts = authCookie.split("__");
    if (cookieParts.length != 2) {
      sendRedirect(req, "/static/login.html");
      return;
    }

    final String sessionId = cookieParts[0];
    String username = cookieParts[1];
    final HttpServerResponse response = req.response();
    vertx.eventBus().<JsonObject>send("participants.authorise", new JsonObject().put(
        "sessionID", sessionId).put("username", username).put("createClient", true),
        async -> {
          final Message<JsonObject> event = async.result();
        if ("ok".equals(event.body().getString("status"))) {
          String activeClientId = event.body().getString("activeClient");
          String username1 = event.body().getString("username");
          if (activeClientId == null || username1 == null) {
            sendStatusCode(req, HttpStatus.SC_INTERNAL_SERVER_ERROR);
            return;
          }
          String path = req.path();
          String module = "Demo";

          if (path.endsWith("demo/")) {
            path = path.replace("/demo", "");
            module = "Demo";
          }
          String responseText = getHostPage(path, module, sessionId, username1, activeClientId);
          response.setStatusCode(HttpStatus.SC_OK);
          byte[] page = responseText.getBytes(Charset.forName("UTF-8"));
          response.putHeader("Content-Length", Integer.toString(page.length));
          response.putHeader("Content-Type", "text/html");
          response.end(Buffer.buffer(page));
        } else {
          sendRedirect(req, "/static/login.html");
        }
      }
    );
  }

  /**
   * Generate the header for the host page that includes the client bootstrap information as well as
   * relevant script includes.
   */
  private String getHostPage(String path, String module, String userId, String username, String activeClientId) {
    StringBuilder sb = new StringBuilder();
    sb.append("<!doctype html>\n");
    sb.append("<html>\n");
    sb.append("  <head>\n");
    sb.append("<title>CollIDE - Collaborative Development</title>\n");
    if (path.endsWith("/"))
      path = path.substring(0, path.length()-1);
//    if (module.indexOf('/') == -1)
//      module = module + '/' + module;
    sb.append("<script src=\"" + path +"/static/sockjs.js\"></script>\n");
    sb.append("<script src=\"" + path+"/static/vertxbus.js\"></script>\n");
    sb.append("<script src=\"" +path+"/static/" + module + "." +
    		"nocache.js\"></script>\n");

    // Embed the bootstrap session object.
    emitBootstrapJson(sb, userId, username, activeClientId);
    emitDefaultStyles(sb);
    sb.append("  </head>\n<body><div id='gwt_root'></div></body>\n</html>");
    return sb.toString();
  }

  private void emitDefaultStyles(StringBuilder sb) {
    sb.append("<style>\n#gwt_root {\n")
      .append("position: absolute;\n")
      .append("top: 0;\n")
      .append("left: 0;\n")
      .append("bottom: 0;\n")
      .append("right: 0;\n")
      .append("}\n</style>");
  }

  private void emitBootstrapJson(
      StringBuilder sb, String userId, String username, String activeClientId) {
    sb.append("<script>\n")
    .append("window['__session'] = {\n")
        .append(JsonFieldConstants.SESSION_USER_ID).append(": \"").append(userId).append("\",\n")
        .append(JsonFieldConstants.SESSION_ACTIVE_ID).append(": \"").append(activeClientId)
        .append("\",\n").append(JsonFieldConstants.SESSION_USERNAME).append(": \"")
        .append(username).append("\"\n};\n")

        .append("window['collide'] = {\n")
        .append("name: 'Guest', module: 'collide.demo.Child', open: '" +
                //"/core/fu/src/main/xapi" +
        		//"/xapi/fu/In.xapi"
                "/test.wti"
            + "' };")
        .append("</script>");
  }

  private void sendRedirect(HttpServerRequest req, String url) {
    if (req.path().startsWith("/collide")) {
      url = "/collide" + url;
      url = url.replace("login.html", "login_collide.html");
      System.out.println("Got it"+req.path());
    }
    System.out.println(req.path());
    req.response().putHeader("Location", url);
    sendStatusCode(req, HttpStatus.SC_MOVED_TEMPORARILY);
  }

  private void sendStatusCode(HttpServerRequest req, int statusCode) {
    req.response().setStatusCode(statusCode);
    req.response().end();
  }

  private void handleXapi(HttpServerRequest req) {
//    VertxContext.fromNative()
    final VertxRequest request = new VertxRequest(req, null);
    final VertxResponse resp = new VertxResponse(req.response());
    Cookie cookie = Cookie.getCookie(AUTH_COOKIE_NAME, req);
    String sessionId = null;
    if (cookie != null) {
      sessionId = cookie.value.split("__")[0];
    }
    server.inScope(sessionId, session->(RequestScopeVertx) session.getRequestScope(request, resp), (scope, fail, onDone)->{
      if (fail != null) {
          authAndWriteHostPage(req);
          onDone.done();
      } else {
          server.serviceRequest(scope, (r, error)-> {
            if (error != null) {
              authAndWriteHostPage(req);
            }
            onDone.done();
          });
      }
    });
  }

}


text:
beforeEach(function() {
  addFixture('storagecharts.html');
});
afterEach(function() {
  clearMyFixtures();
});

describe('init', function() {
  it(' should work without any element', function() {
    StorageCharts2.init();
  });
});

describe('view charts', function() {
  it('unit selector helper - hu_size', function() {
    var select = document.createElement('select');
    select.id = 'chunits_hus';
    var option = document.createElement('option');
    option.id = 'uc_val';
    option.text = '3';
    select.appendChild(option);
    document.body.appendChild(select);
    StorageCharts2.getHistoUsUnitsSelect(2048);
  });
  it('unit selector helper - hus_size', function() {
    var select = document.createElement('select');
    select.id = 'chunits';
    var option = document.createElement('option');
    option.id = 'uc_val';
    option.text = '3';
    select.appendChild(option);
    document.body.appendChild(select);
    StorageCharts2.getLinesUsseUnitsSelect(2048);
  });
});

redpajama_set_name: RedPajamaGithub


text:
package org.ebayopensource.turmeric.tools.codegen.util;

import org.ebayopensource.turmeric.runtime.common.types.SOACommonConstants;
import org.ebayopensource.turmeric.common.v1.types.ErrorMessage;

/**
 * Maintains all code generation tool constants
 *
 * @author rmandapati
 */
public interface CodeGenConstants {

	public static final String GEN_SRC_FOLDER = "gen-src";
	public static final String GEN_META_SRC_FOLDER = "gen-meta-src";
	public static final String META_SRC_FOLDER = "meta-src";
	public static final String META_INF_FOLDER = "META-INF";
	public static final String TYPES_FOLDER = "types";

	public static final String CLIENT_GEN_FOLDER = "client";
	public static final String SERVICE_GEN_FOLDER = "service";
	public static final String COMMON_GEN_FOLDER = "common";
	public static final String TEST_GEN_FOLDER = "gen-test";

	public static final String DEFAULT_CLIENT_NAME = "default";
	public static final String ASYNC_NAME = "Async";
	public static final String DOT = ".";

	public static final String ALL = "all";

	// Config related
	public static final int NUM_OF_APP_RETRIES = 1;
	public static final int NUM_OF_CONN_RETRIES = 3;

	public static final String DEFAULT_SERVICE_URL = "http://localhost:8080/";

	public static final String SOA_COMMON_TYPES_PKG = ErrorMessage.class.getPackage().getName();
	public static final String SOA_COMMON_TYPES_NS = SOACommonConstants.SOA_TYPES_NAMESPACE;

	//The following {  are the names of the properties stored in the service_metadata.properties file
	//For adding any new properties to this file, pls define a constant here
	public static final String SERVICE_NAME = "service_name";
	public static final String ADMIN_NAME = "admin_name";
	public static final String SERVICE_VERSION = "service_version";
	public static final String SERVICE_INTF_CLASS_NAME = "service_interface_class_name";
	public static final String SERVICE_LAYER = "service_layer";
	public static final String ORIGINAL_WSDL_URI = "original_wsdl_uri";
	public static final String SERVICE_NAMESPACE = "service_namespace";
	String SERVICE_NS_PART = "service_namespace_part";
	String SVC_DOMAIN_NAME = "domainName";
    // }

    /* The following are the names of the properties stored in the service_intf_project.properties file
     * For adding any new properties to this file, pls define a constant here
     */
	public static final String SERVICE_LOCATION = "service_location";
	public static final String INTERFACE_SOURCE_TYPE  = "interface_source_type";
	public static final String NS_2_PKG = "ns2pkg";
	public static final String ENABLE_NAMESPACE_FOLDING = "enabledNamespaceFolding";
	public static final String PUBLIC_SERVICE_NAME = "publicServiceName";
	String CTNS = "ctns";
	String SVC_INTF_PROJECT_PROPERTIES_FILE_VERSION = "sipp_version";
	String SVC_CONSUMER_VERSION = "smp_version";
	String PROPERTY_SHARED_CONSUMER_SHORTER_PATH = "short_path_for_shared_consumer";

	/*
	 * These constant are defined for consumerProperties file which is created by plugin
	 */
	public static final String SERVICE_CONSUMER_PROPS_FILE = "service_consumer_project.properties";
	public static final String ENVMAPPER_PROP = "envMapper";
	String CONS_PROJECT_PROPERTIES_FILE_VERSION = "scpp_version";
	String NO_BASE_CONSUMERPROP = "not_generate_base_consumer";

	/**
	 * This file is created by plugin and has version info
	 */
	String SERVICE_IMPL_PROPERTIES_FILE = "service_impl_project.properties";
	String CONS_SERVICE_IMPL_VERSION ="simp_version";

	/*
	 * for codegn logging
	 */
	public static final String CODEGEN_LOG_CONFIG = "CODEGEN_LOG_CONFIG"; // name of the environment variable

	//Constants related to poll method
	String POLL_METHOD_NAME ="poll";
	String POLL_METHOD_PARAM_BLOCK = "block";
	String POLL_METHOD_PARAM_PARTIAL = "partial";

	String MIN_VERSION_FOR_GENERATING_POLL_METHOD = "2.1.1";

    String PKG_PARAM = "@pkg@";
	String NAMESPACE_PARAM = "@ns@";
	String WSDL_2_JAVA_NS_TO_PKG_PATTERN = NAMESPACE_PARAM + "=" + PKG_PARAM;

}


text:
angular.module("umbraco").directive('skybrudLoader', function () {
    return {
        restrict: 'E',
        replace: true,
        template: '

'
    };
});


text: {{title}}


text:
import { Component, HostListener, ElementRef, Renderer, ViewContainerRef, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router, ActivatedRouteSnapshot, RouterState, RouterStateSnapshot } from '@angular/router';
import { TranslateService } from 'ng2-translate';
import { UserLoginService } from './user/user-login/user-login.service';
import { UserRegisterService } from './user/user-register/user-register.service';
import { User } from './user/model/user-model';
import 'rxjs/add/operator/merge';
import { Message } from 'primeng/primeng';

@Component({
	selector: 'app-root',
	templateUrl: './app.component.html',
	styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy{
	public msgs: Message[] = [];
	public currentUser: User;
	private globalClickCallbackFn: Function;
	private loginSuccessCallbackFn: Function;

	constructor(
		public elementRef: ElementRef,
		public renderer: Renderer,
		public router: Router,
		public activatedRoute: ActivatedRoute,
		public translate: TranslateService,
		public userLoginService: UserLoginService,
		public userRegisterService: UserRegisterService
	) {

	}

	ngOnInit() {
		this.globalClickCallbackFn = this.renderer.listen(this.elementRef.nativeElement, 'click', (event: any) => {
			console.log('全局监听点击事件>' + event);
		});

		this.currentUser = JSON.parse(localStorage.getItem('currentUser'));

		this.userLoginService.currentUser
			.merge(this.userRegisterService.currentUser)
			.subscribe(
			data => {
				this.currentUser = data;
				let activatedRouteSnapshot: ActivatedRouteSnapshot = this.activatedRoute.snapshot;
				let routerState: RouterState = this.router.routerState;
				let routerStateSnapshot: RouterStateSnapshot = routerState.snapshot;

				console.log(activatedRouteSnapshot);
				console.log(routerState);
				console.log(routerStateSnapshot);

				//如果是从/login这个URL进行的登录,跳转到首页,否则什么都不做
				if (routerStateSnapshot.url.indexOf('/login') !== -1) {
					this.router.navigateByUrl('/home');
				}
			},
			error => console.error(error)
			);

		this.translate.addLangs(['zh', 'en']);
		this.translate.setDefaultLang('zh');

		const browserLang = this.translate.getBrowserLang();
		console.log('检测到的浏览器语言>' + browserLang);
		this.translate.use(browserLang.match(/zh|en/) ? browserLang : 'zh');
	}

	ngOnDestroy() {
		if (this.globalClickCallbackFn) {
			this.globalClickCallbackFn();
		}
	}

	toggle(button: any) {
		console.log(button);
	}

	public doLogout(): void {
		this.userLoginService.logout();
		this.msgs = [];
        this.msgs.push({severity:'success', summary:'Success Message', detail:'退出成功'});
		this.router.navigateByUrl('');
	}
}


text:
<?php
/**
 * Custom functions that act independently of the theme templates
 *
 * Eventually, some of the functionality here could be replaced by core features
 *
 * @package dazzling
 */

/**
 * Get our wp_nav_menu() fallback, wp_page_menu(), to show a home link.
 *
 * @param array $args Configuration arguments.
 * @return array
 */
function dazzling_page_menu_args( $args ) {
	$args['show_home'] = true;
	return $args;
}
add_filter( 'wp_page_menu_args', 'dazzling_page_menu_args' );

/**
 * Adds custom classes to the array of body classes.
 *
 * @param array $classes Classes for the body element.
 * @return array
 */
function dazzling_body_classes( $classes ) {
	// Adds a class of group-blog to blogs with more than 1 published author.
	if ( is_multi_author() ) {
		$classes[] = 'group-blog';
	}

	return $classes;
}
add_filter( 'body_class', 'dazzling_body_classes' );

/**
 * Filters wp_title to print a neat <title> tag based on what is being viewed.
 *
 * @param string $title Default title text for current view.
 * @param string $sep Optional separator.
 * @return string The filtered title.
 */
function dazzling_wp_title( $title, $sep ) {
	global $page, $paged;

	if ( is_feed() ) {
		return $title;
	}

	// Add the blog name
	$title .= get_bloginfo( 'name' );

	// Add the blog description for the home/front page.
	$site_description = get_bloginfo( 'description', 'display' );
	if ( $site_description && ( is_home() || is_front_page() ) ) {
		$title .= " $sep $site_description";
	}

	// Add a page number if necessary:
	if ( $paged >= 2 || $page >= 2 ) {
		$title .= " $sep " . sprintf( __( 'Page %s', 'dazzling' ), max( $paged, $page ) );
	}

	return $title;
}
add_filter( 'wp_title', 'dazzling_wp_title', 10, 2 );

// Mark Posts/Pages as Untiled when no title is used
add_filter( 'the_title', 'dazzling_title' );

function dazzling_title( $title ) {
  if ( $title == '' ) {
    return 'Untitled';
  } else {
    return $title;
  }
}

// Add Filters

add_filter('widget_text', 'do_shortcode'); // Allow shortcodes in Dynamic Sidebar

/**
 * Sets the authordata global when viewing an author archive.
 *
 * This provides backwards compatibility with
 * http://core.trac.wordpress.org/changeset/25574
 *
 * It removes the need to call the_post() and rewind_posts() in an author
 * template to print information about the author.
 *
 * @global WP_Query $wp_query WordPress Query object.
 * @return void
 */
function dazzling_setup_author() {
	global $wp_query;

	if ( $wp_query->is_author() && isset( $wp_query->post ) ) {
		$GLOBALS['authordata'] = get_userdata( $wp_query->post->post_author );
	}
}
add_action( 'wp', 'dazzling_setup_author' );

/************* search form *****************/

// Search Form
function dazzling_wpsearch($form) {
    $form = '<form method="get" class="form-search" action="' . home_url( '/' ) . '">

        <input type="text" class="form-control search-query" value="' . get_search_query() . '" name="s" id="s" placeholder="'. esc_attr__('Search...','dazzling') .'">

          <button type="submit" class="btn btn-default" name="submit" id="searchsubmit" value="Go"></button>

</form>';
    return $form;
} // don't remove this bracket!

/****************** password protected post form *****/

add_filter( 'the_password_form', 'custom_password_form' );

function custom_password_form() {
	global $post;
	$label = 'pwbox-'.( empty( $post->ID ) ? rand() : $post->ID );
	$o = '<form class="protected-post-form" action="' . get_option('siteurl') . '/wp-login.php?action=postpass" method="post">

        ' . __( "
This post is password protected. To view it please enter your password below:
" ,'dazzling') . '
        ' . __( "Password:" ,'dazzling') . '

        <input class="form-control" value="' . get_search_query() . '" name="post_password" id="' . $label . '" type="password">
        <button type="submit" class="btn btn-default" name="submit" id="searchsubmit" vvalue="' . esc_attr__( "Submit",'dazzling' ) . '">' . __( "Submit" ,'dazzling') . '</button>

</form>';
	return $o;
}

// Add Bootstrap classes for table
add_filter( 'the_content', 'dazzling_add_custom_table_class' );
function dazzling_add_custom_table_class( $content ) {
    return str_replace( '
', '
', $content );
}

// //Display social links
function dazzling_social(){
    $services = array ('facebook','twitter','googleplus','youtube','linkedin','pinterest','rss','tumblr','flickr','instagram','dribbble','skype');

    echo '

';

    foreach ( $services as $service ) :

        $active[$service] = of_get_option ('social_'.$service);
        if ($active[$service]) { echo '

';}

    endforeach;
    echo '

';

}

// header menu (should you choose to use one)
function dazzling_header_menu() {
        // display the WordPress Custom Menu if available
        wp_nav_menu(array(
                    'menu'              => 'primary',
                    'theme_location'    => 'primary',
                    'depth'             => 2,
                    'container'         => 'div',
                    'container_class'   => 'collapse navbar-collapse navbar-ex1-collapse',
                    'menu_class'        => 'nav navbar-nav',
                    'fallback_cb'       => 'wp_bootstrap_navwalker::fallback',
                    'walker'            => new wp_bootstrap_navwalker()
        ));
} /* end header menu */

// footer menu (should you choose to use one)
function dazzling_footer_links() {
        // display the WordPress Custom Menu if available
        wp_nav_menu(array(
                'container' => '',                              // remove nav container
                'container_class' => 'footer-links clearfix',   // class of container (should you choose to use it)
                'menu' => __( 'Footer Links', 'dazzling' ),   // nav name
                'menu_class' => 'nav footer-nav clearfix',      // adding custom nav class
                'theme_location' => 'footer-links',             // where it's located in the theme
                'before' => '',                                 // before the menu
                'after' => '',                                  // after the menu
                'link_before' => '',                            // before each link
                'link_after' => '',                             // after each link
                'depth' => 0,                                   // limit the depth of the nav
                'fallback_cb' => 'dazzling_footer_links_fallback'  // fallback function
        ));
} /* end dazzling footer link */

// Get Post Views - for Popular Posts widget
function dazzling_getPostViews($postID){
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
        return "0 View";
    }
    return $count.' Views';
}
function dazzling_setPostViews($postID) {
    $count_key = 'post_views_count';
    $count = get_post_meta($postID, $count_key, true);
    if($count==''){
        $count = 0;
        delete_post_meta($postID, $count_key);
        add_post_meta($postID, $count_key, '0');
    }else{
        $count++;
        update_post_meta($postID, $count_key, $count);
    }
}

// Call for action text area
function dazzling_call_for_action() {
  if ( is_front_page() && of_get_option('w2f_cfa_text')!=''){
    echo '
';
      echo '
';
        echo '
';
          echo ''. of_get_option('w2f_cfa_text').'';
          echo '
';
          echo '
 <button class="btn btn-lg cfa-button"> '. of_get_option('w2f_cfa_button'). '';
          echo ' </button>
';
      echo '
';
    echo '
';
  } else; {
  //Do nothing
  }
}

// Featured image slider
function dazzling_featured_slider() {
    if ( is_front_page() && of_get_option('dazzling_slider_checkbox') == 1 ) {
      echo '
';
        echo '
';

          $count = of_get_option('dazzling_slide_number');
          $slidecat =of_get_option('dazzling_slide_categories');

          $query = new WP_Query( array( 'cat' =>$slidecat,'posts_per_page' =>$count ) );
          if ($query->have_posts()) :
            while ($query->have_posts()) : $query->the_post();

            echo '
';
              if ( (function_exists('has_post_thumbnail')) && (has_post_thumbnail()) ) :
                echo get_the_post_thumbnail();
              endif;

                echo '
';
                  echo '';
                    if ( get_the_title() != '' ) echo '
'. get_the_title().'
';
                    if ( get_the_excerpt() != '' ) echo '
' . get_the_excerpt() .'
';
                  echo '';
                echo '
';

                endwhile;
              endif;

            echo '
';
        echo '
';
      echo '
';
    } else; {
      // Do nothing
    }
}

/**
 * function to show the footer info, copyright information
 */
function dazzling_footer_info() {
global $dazzling_footer_info;
  printf( __( 'Theme by %1$s Powered by %2$s', 'dazzling' ) , 'Colorlib', 'WordPress');
}

// Get theme options

if (!function_exists('get_dazzling_theme_options'))  {
    function get_dazzling_theme_options(){

      echo '';
    }
}
add_action('wp_head','get_dazzling_theme_options',10);

// Theme Options sidebar
add_action( 'optionsframework_after','dazzling_options_display_sidebar' );

function dazzling_options_display_sidebar() { ?>

<?php _e('Support and Documentation','dazzling') ?>

Follow @colorlib

<?php _e('dazzling Documentation','dazzling'); ?>

<?php _e('The best way to contact us with support questions and bug reports is via','dazzling') ?> <?php _e('Colorlib support forum','dazzling') ?>.

<?php _e('If you like this theme, I\'d appreciate any of the following:','dazzling') ?>

<a class="button" href="http://wordpress.org/support/view/theme-reviews/dazzling?filter=5" title="<?php esc_attr_e('Rate this Theme', 'dazzling'); ?>" target="_blank"><?php printf(__('Rate this Theme','dazzling')); ?>

<?php printf(__('Like on Facebook','dazzling')); ?>

<?php printf(__('Follow on Twitter','dazzling')); ?>

<?php }

/*
 * This one shows/hides the an option when a checkbox is clicked.
 *
 */

add_action( 'optionsframework_custom_scripts', 'optionsframework_custom_scripts' );

function optionsframework_custom_scripts() { ?>

<?php
}


text:
package org.mapfish.print.http;

import org.springframework.http.client.ClientHttpRequestFactory;

/**
 * A http request factory that allows configuration callbacks to be registered, allowing low-level customizations to the request
 * object.
 *
 * @author Jesse on 9/3/2014.
 */
public interface MfClientHttpRequestFactory extends ClientHttpRequestFactory {

    /**
     * Register a callback for config using a http request.
     *
     * @param callback the configuration callback
     */
    void register(final RequestConfigurator callback);
    /**
     * A Callback allowing low-level customizations to an http request created by this factory.
     */
    public interface RequestConfigurator {
        /**
         * Configure the request.
         *
         * @param request the request to configure
         */
        void configureRequest(final ConfigurableRequest request);
    }
}


text:
// Header for C3PaneWindow class

#ifndef __C3PANEWINDOW__MULBERRY__
#define __C3PANEWINDOW__MULBERRY__

#include "C3PaneWindowFwd.h"

#include "CCommander.h"
#include "CWindowStatus.h"

#include "CHelpFrame.h"

#include "CSplitterView.h"
#include "CToolbarView.h"
#include "C3PaneAccounts.h"
#include "C3PaneItems.h"
#include "C3PaneMainPanel.h"
#include "C3PanePreview.h"

// Messages

// Resources

// Classes
class CMbox;
class CServerView;
class CCalendarStoreView;
class CSplitterView;
class CToolbarView;
class C3PaneMainPanel;
class C3PaneAccounts;
class C3PaneItems;
class C3PanePreview;
class C3PaneAdbkToolbar;
class C3PaneCalendarToolbar;
class C3PaneMailboxToolbar;

class C3PaneWindow : public CView,
						public CWindowStatus,
						public CCommander
{
	friend class C3PaneParentPanel;

	DECLARE_DYNCREATE(C3PaneWindow)

public:
	static C3PaneWindow* 		s3PaneWindow;
	static CMultiDocTemplate*	s3PaneDocTemplate;

					C3PaneWindow();
	virtual 		~C3PaneWindow();

	static void Create3PaneWindow();		// Create it or bring it to the front
	static void Destroy3PaneWindow();		// Destroy the window

	static C3PaneWindow* ManualCreate();					// Manually create document

	virtual void	OnDraw(CDC* pDC) {}

	virtual BOOL	OnCmdMsg(UINT nID, int nCode, void* pExtra,
     							 AFX_CMDHANDLERINFO* pHandlerInfo);		// Special chain of command
	virtual bool	HandleChar(UINT nChar, UINT nRepCnt, UINT nFlags);

			void	SetGeometry(N3Pane::EGeometry geometry);
			void	SetViewType(N3Pane::EViewType geometry);

			void	SetUseSubstitute(bool subs);

			bool	GetZoomList() const
				{ return mListZoom; }
			void	ZoomList(bool zoom);
			bool	GetZoomItems() const
				{ return mItemsZoom; }
			void	ZoomItems(bool zoom);
			bool	GetZoomPreview() const
				{ return mPreviewZoom; }
			void	ZoomPreview(bool zoom);

			void	ShowList(bool show);
			bool	IsListVisible() const
				{ return mListVisible; }
			void	ShowItems(bool show);
			bool	IsItemsVisible() const
				{ return mItemsVisible; }
			void	ShowPreview(bool show);
			bool	IsPreviewVisible() const
				{ return mPreviewVisible; }

			void	ShowStatus(bool show);
			void	UpdateView();

			void	DoneInitMailAccounts();
			void	DoneInitAdbkAccounts();
			void	DoneInitCalendarAccounts();

			bool	AttemptClose();
			void	DoClose();

	C3PaneMailboxToolbar*	GetMailboxToolbar() const
		{ return mMailboxToolbar; }
	C3PaneAdbkToolbar*		GetAdbkToolbar() const
		{ return mAdbkToolbar; }
	C3PaneCalendarToolbar*	GetCalendarToolbar() const
		{ return mCalendarToolbar; }

	CServerView*		GetServerView() const;
	CAdbkManagerView*	GetContactsView() const;
	CCalendarStoreView*	GetCalendarStoreView() const;

			void	GetOpenItems(cdstrvect& items) const;
			void	CloseOpenItems();
			void	SetOpenItems(const cdstrvect& items);

protected:
	CToolbarView			mToolbarView;
	C3PaneMailboxToolbar*	mMailboxToolbar;
	C3PaneAdbkToolbar*		mAdbkToolbar;
	C3PaneCalendarToolbar*	mCalendarToolbar;
	CSplitterView			mSplitter1;
	CSplitterView			mSplitter2;
	C3PaneMainPanel			mListView;
	C3PaneMainPanel			mItemsView;
	C3PaneMainPanel			mPreviewView;
	C3PaneAccounts			mAccounts;
	C3PaneItems				mItems;
	C3PanePreview			mPreview;

	N3Pane::EGeometry		mGeometry;
	N3Pane::EViewType		mViewType;
	bool					mListVisible;
	bool					mItemsVisible;
	bool					mPreviewVisible;
	bool					mStatusVisible;
	bool					mListZoom;
	bool					mItemsZoom;
	bool					mPreviewZoom;

	void OptionsInit();
	void OptionsSetView();
	void OptionsSaveView();

	CToolbarView*	GetToolbarView()
		{ return &mToolbarView; }
	C3PaneMainPanel* GetListView()
		{ return &mListView; }
	C3PaneMainPanel* GetItemsView()
		{ return &mItemsView; }
	C3PaneMainPanel* GetPreviewView()
		{ return &mPreviewView; }

private:
			void	Init3PaneWindow();
			void	InstallToolbars();
			void	InstallViews();

public:
	virtual void	ResetState(bool force = false);			// Reset state from prefs
	virtual void	SaveDefaultState();						// Save state in prefs

protected:
	// Common updaters
	afx_msg void OnUpdateNever(CCmdUI* pCmdUI);

	afx_msg void OnUpdateZoomList(CCmdUI* pCmdUI);
	afx_msg void OnUpdateZoomItems(CCmdUI* pCmdUI);
	afx_msg void OnUpdateZoomPreview(CCmdUI* pCmdUI);

	afx_msg void OnUpdateShowList(CCmdUI* pCmdUI);
	afx_msg void OnUpdateShowItems(CCmdUI* pCmdUI);
	afx_msg void OnUpdateShowPreview(CCmdUI* pCmdUI);
	afx_msg void OnUpdateMenuShowList(CCmdUI* pCmdUI);
	afx_msg void OnUpdateMenuShowItems(CCmdUI* pCmdUI);
	afx_msg void OnUpdateMenuShowPreview(CCmdUI* pCmdUI);

	afx_msg void OnUpdateWindowLayout(CCmdUI* pCmdUI);

	// message handlers
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy(void);
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnSetFocus(CWnd* pOldWnd);

	afx_msg void OnZoomList(void);
	afx_msg void OnZoomItems(void);
	afx_msg void OnZoomPreview(void);

	afx_msg void OnShowList(void);
	afx_msg void OnShowItems(void);
	afx_msg void OnShowPreview(void);

	afx_msg void OnResetPaneState(void);
	afx_msg void OnSaveDefaultPaneState(void);

	afx_msg void OnWindowLayout(UINT nID);

	DECLARE_MESSAGE_MAP()
};

#endif


text:
import { Renderer, Tooltip } from 'francy-core';

/* global d3 */

export default class Chart extends Renderer {

  constructor({ appendTo, callbackHandler }, context) {
    super({ appendTo: appendTo, callbackHandler: callbackHandler }, context);
    this.axis = undefined;
    this.yScale = undefined;
    this.xScale = undefined;
    this.datasets = undefined;
    this.datasetNames = undefined;
    this.tooltip = undefined;
  }

  initialize() {
    this.tooltip = new Tooltip(this.options, this.context);

    this.element = this.parent.select('g.francy-content');

    this.axis = this.data.canvas.chart.axis;
    this.datasets = this.data.canvas.chart.data;
    this.datasetNames = Object.keys(this.datasets);

    this.xScale = d3.scaleLinear().range([0, this.width]).domain(this.axis.x.domain);
    this.yScale = d3.scaleLinear().range([this.height, 0]).domain(this.axis.y.domain);

    this.allValues = [];
    this.datasetNames.forEach(key => this.allValues = this.allValues.concat(this.datasets[key]));

    if (!this.axis.y.domain.length) {
      this.yScale.domain([0, d3.max(this.allValues, d => d)]);
    }

    if (!this.axis.x.domain.length) {
      this.xScale.domain([0, this.allValues.length / this.datasetNames.length]);
    }
  }

  _renderAxis() {
    // force rebuild axis again
    let xAxisGroup = this.element.selectAll('g.francy-x-axis');

    if (!xAxisGroup.node()) {
      xAxisGroup = this.element.append('g').attr('class', 'francy-x-axis');
    }

    xAxisGroup.selectAll('*').remove();

    // add the x Axis
    xAxisGroup
      .attr('transform', `translate(0,${this.height})`)
      .call(d3.axisBottom(this.xScale))
      .append('text')
      .attr('dy', 50)
      .attr('dx', this.width / 2)
      .attr('fill', 'black')
      .attr('class', 'francy-axis')
      .style('text-anchor', 'end')
      .text(this.axis.x.title);

    // force rebuild axis again
    let yAxisGroup = this.element.selectAll('g.francy-y-axis');

    if (!yAxisGroup.node()) {
      yAxisGroup = this.element.append('g').attr('class', 'francy-y-axis');
    }

    yAxisGroup.selectAll('*').remove();

    // add the y Axis
    yAxisGroup
      .call(d3.axisLeft(this.yScale))
      .append('text')
      .attr('dx', -50)
      .attr('dy', this.height / 2)
      .attr('fill', 'black')
      .attr('class', 'francy-axis')
      .style('text-anchor', 'end')
      .text(this.axis.y.title);
  }

  _renderLegend() {
    if (this.data.canvas.chart.showLegend) {

      let legendGroup = this.element.selectAll('.francy-legend');

      if (!legendGroup.node()) {
        legendGroup = this.element.append('g').attr('class', 'francy-legend');
      }

      // force rebuild legend again
      legendGroup.selectAll('*').remove();

      let legend = legendGroup.selectAll('g').data(this.datasetNames.slice());

      legend.exit().remove();

      legend = legend.enter()
        .append('g')
        .attr('transform', (d, i) => `translate(0,${i * 20})`)
        .merge(legend);

      legend.append('rect')
        .attr('x', this.width + 20)
        .attr('width', 19)
        .attr('height', 19)
        .style('fill', (d, i) => Chart.colors(i * 5));

      legend.append('text')
        .attr('x', this.width + 80)
        .attr('y', 9)
        .attr('dy', '.35em')
        .style('text-anchor', 'end')
        .text(d => d);
    }
  }

  static tooltip(dataset, value) {
    return { 'A': { 'title': 'Dataset', 'text': dataset }, 'B': { 'title': 'Value', 'text': value } };
  }

  static get colors() {
    return d3.scaleSequential().domain([0, 100]).interpolator(d3.interpolateRainbow);
  }

  static domainRange(max) {
    return Array.from(new Array(max), (_, i) => i).map(x => x);
  }

}


text:
package com.wixpress.guineapig.entities.ui

case class TerminateExperimentResult(success: Boolean, specCanBeDeleted: Boolean, specKey: String)


text:
package com.att.cadi.sso;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import com.att.cadi.Access.Level;
import com.att.cadi.CadiException;
import com.att.cadi.PropAccess;
import com.att.cadi.Symm;
import com.att.cadi.config.Config;
import com.att.cadi.util.MyConsole;
import com.att.cadi.util.SubStandardConsole;
import com.att.cadi.util.TheConsole;

public class AAFSSO {
	public static final MyConsole  cons = TheConsole.implemented()?new TheConsole():new SubStandardConsole();

	private Properties diskprops = null; // use for temp storing User/Password on disk
	private File dot_aaf = null, sso=null; // instantiated, if ever, with diskprops

	boolean removeSSO=false;
	boolean loginOnly = false;
	private PropAccess access;
	private StringBuilder err;
	private String user,encrypted_pass;
	private boolean use_X509;

	private PrintStream os, stdout=null,stderr=null;

	private Method close;

	public AAFSSO(String[] args) throws IOException, CadiException {
		List<String> larg = new ArrayList<String>(args.length);

		// Cover for bash's need to escape *... (\\*)
		// also, remove SSO if required
		for (int i = 0; i < args.length; ++i) {
			if ("\\*".equals(args[i])) {
				args[i] = "*";
			}

			if("-logout".equalsIgnoreCase(args[i])) {
				removeSSO=true;
			} else if("-login".equalsIgnoreCase(args[i])) {
				loginOnly = true;
			} else {
				larg.add(args[i]);
			}
		}

		String[] nargs = new String[larg.size()];
		larg.toArray(nargs);

		dot_aaf = new File(System.getProperty("user.home")+"/.aaf");
		if(!dot_aaf.exists()) {
			dot_aaf.mkdirs();
		}
		File f = new File(dot_aaf,"sso.out");
		os = new PrintStream(new FileOutputStream(f,true));
		stdout = System.out;
		stderr = System.err;
		System.setOut(os);
		System.setErr(os);

		access = new PropAccess(os,nargs);
		Config.setDefaultRealm(access);

		user = access.getProperty(Config.AAF_MECHID);
		encrypted_pass = access.getProperty(Config.AAF_MECHPASS);

		File dot_aaf_kf = new File(dot_aaf,"keyfile");

		sso = new File(dot_aaf,"sso.props");
		if(removeSSO) {
			if(dot_aaf_kf.exists()) {
				dot_aaf_kf.setWritable(true,true);
				dot_aaf_kf.delete();
			}
			if(sso.exists()) {
				sso.delete();
			}
			System.out.println("AAF SSO information removed");
			System.exit(0);
		}

		if(!dot_aaf_kf.exists()) {
			FileOutputStream fos = new FileOutputStream(dot_aaf_kf);
			try {
				fos.write(Symm.encrypt.keygen());
				dot_aaf_kf.setExecutable(false,false);
				dot_aaf_kf.setWritable(false,false);
				dot_aaf_kf.setReadable(false,false);
				dot_aaf_kf.setReadable(true, true);
			} finally {
				fos.close();
			}
		}

		String keyfile = access.getProperty(Config.CADI_KEYFILE); // in case it's CertificateMan props
		if(keyfile==null) {
			access.setProperty(Config.CADI_KEYFILE, dot_aaf_kf.getAbsolutePath());
		}

		String alias = access.getProperty(Config.CADI_ALIAS);
		if(user==null && alias!=null && access.getProperty(Config.CADI_KEYSTORE_PASSWORD)!=null) {
			user = alias;
			access.setProperty(Config.AAF_MECHID, user);
			use_X509 = true;
		} else {
			use_X509 = false;
			Symm decryptor = Symm.obtain(dot_aaf_kf);
			if (user==null) {
				if(sso.exists() && sso.lastModified()>System.currentTimeMillis()-(8*60*60*1000 /* 8 hours */)) {
					String cm_url = access.getProperty(Config.CM_URL); // SSO might overwrite...
					FileInputStream fos = new FileInputStream(sso);
					try {
						access.load(fos);
						user = access.getProperty(Config.AAF_MECHID);
						encrypted_pass = access.getProperty(Config.AAF_MECHPASS);
						// decrypt with .aaf, and re-encrypt with regular Keyfile
						access.setProperty(Config.AAF_MECHPASS,
								access.encrypt(decryptor.depass(encrypted_pass)));
						if(cm_url!=null) { //Command line CM_URL Overwrites ssofile.
							access.setProperty(Config.CM_URL, cm_url);
						}
					} finally {
						fos.close();
					}
				} else {
					diskprops = new Properties();
					String realm = Config.getDefaultRealm();
					// Turn on Console Sysout
					System.setOut(stdout);
					user=cons.readLine("aaf_id(%s@%s): ",System.getProperty("user.name"),realm);
					if(user==null) {
						user = System.getProperty("user.name")+'@'+realm;
					} else if(user.length()==0) { //
						user = System.getProperty("user.name")+'@' + realm;
					} else if(user.indexOf('@')<0 && realm!=null) {
						user = user+'@'+realm;
					}
					access.setProperty(Config.AAF_MECHID,user);
					diskprops.setProperty(Config.AAF_MECHID,user);
					encrypted_pass = new String(cons.readPassword("aaf_password: "));
					System.setOut(os);
					encrypted_pass = Symm.ENC+decryptor.enpass(encrypted_pass);
					access.setProperty(Config.AAF_MECHPASS,encrypted_pass);
					diskprops.setProperty(Config.AAF_MECHPASS,encrypted_pass);
					diskprops.setProperty(Config.CADI_KEYFILE, access.getProperty(Config.CADI_KEYFILE));
				}
			}
		}
		if (user == null) {
			err = new StringBuilder("Add -D" + Config.AAF_MECHID + "=<id> ");
		}

		if (encrypted_pass == null && alias==null) {
			if (err == null) {
				err = new StringBuilder();
			} else {
				err.append("and ");
			}
			err.append("-D" + Config.AAF_MECHPASS + "=<passwd> ");
		}
	}

	public void setLogDefault() {
		access.setLogLevel(PropAccess.DEFAULT);
		if(stdout!=null) {
			System.setOut(stdout);
		}
	}

	public void setStdErrDefault() {
		access.setLogLevel(PropAccess.DEFAULT);
		if(stderr!=null) {
			System.setErr(stderr);
		}
	}

	public void setLogDefault(Level level) {
		access.setLogLevel(level);
		if(stdout!=null) {
			System.setOut(stdout);
		}
	}

	public boolean loginOnly() {
		return loginOnly;
	}

	public void addProp(String key, String value) {
		if(diskprops!=null) {
			diskprops.setProperty(key, value);
		}
	}

	public void writeFiles() throws IOException {
		// Store Creds, if they work
		if(diskprops!=null) {
			if(!dot_aaf.exists()) {
				dot_aaf.mkdirs();
			}
			FileOutputStream fos = new FileOutputStream(sso);
			try {
				diskprops.store(fos, "AAF Single Signon");
			} finally {
				fos.close();
				sso.setWritable(false,false);
				sso.setExecutable(false,false);
				sso.setReadable(false,false);
				sso.setReadable(true,true);
			}
		}
		if(sso!=null) {
			sso.setReadable(false,false);
			sso.setWritable(false,false);
			sso.setExecutable(false,false);
			sso.setReadable(true,true);
			sso.setWritable(true,true);
		}
	}

	public PropAccess access() {
		return access;
	}

	public StringBuilder err() {
		return err;
	}

	public String user() {
		return user;
	}

	public String enc_pass() {
		return encrypted_pass;
	}

	public boolean useX509() {
		return use_X509;
	}

	public void close() {
		if(close!=null) {
			try {
				close.invoke(null);
			} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
				// nothing to do here.
			}
			close = null;
		}
	}
}


text:
import peewee as pw
import pytest
from muffin_peewee import Plugin as Peewee, JSONField

@pytest.fixture(scope='module')
def aiolib():
    return 'asyncio', {'use_uvloop': False}

@pytest.fixture(scope='session', autouse=True)
def setup_logging():
    import logging

    logger = logging.getLogger('peewee')
    logger.setLevel(logging.DEBUG)

@pytest.fixture
async def db(app):
    db = Peewee(app, connection='sqlite:///:memory:', auto_connection=False)
    async with db:
        async with db.connection():
            yield db

@pytest.fixture
async def Resource(db):

    @db.manager.register
    class Resource(pw.Model):
        active = pw.BooleanField(default=False)
        name = pw.CharField(null=False)
        count = pw.IntegerField(null=True)
        config = JSONField(default={})

    assert Resource._manager

    await db.manager.create_tables(Resource)

    return Resource

@pytest.fixture
async def ResourceEndpoint(Resource, api):
    from muffin_rest.peewee import PWRESTHandler

    @api.route
    class ResourceEndpoint(PWRESTHandler):

        class Meta:
            filters = 'active', 'name', ('oid', {'field': 'id'}),
            limit = 10
            model = Resource
            sorting = ('id', {'default': 'desc'}), 'name', Resource.count
            delete_recursive = True

        @PWRESTHandler.route('/resource/action')
        async def action(self, request, resource=None):
            """Description for the action."""
            resources = await self.meta.manager.fetchall(self.collection)
            return await self.dump(request, resources)

    return ResourceEndpoint

@pytest.fixture
async def resource(Resource, db):
    return await db.manager.create(Resource, name='test')

def test_imports():
    from muffin_rest import PWRESTHandler, PWFilter, PWFilters, PWSort, PWSorting

    assert PWRESTHandler
    assert PWFilter
    assert PWFilters
    assert PWSort
    assert PWSorting

async def test_base(api, ResourceEndpoint, Resource):
    assert ResourceEndpoint
    assert ResourceEndpoint.meta.name == 'resource'
    assert ResourceEndpoint.meta.manager

    # Schema
    assert ResourceEndpoint.meta.Schema
    assert ResourceEndpoint.meta.Schema._declared_fields
    ff = ResourceEndpoint.meta.Schema._declared_fields['active']
    assert ff.load_default is False

    # Sorting
    assert ResourceEndpoint.meta.sorting
    assert list(ResourceEndpoint.meta.sorting.mutations.keys()) == ['id', 'name', 'count']
    assert ResourceEndpoint.meta.sorting.default == [Resource.id.desc()]

    assert api.router.plain['/resource']
    assert api.router.dynamic[0].pattern.pattern == '^/resource/(?P<id>[^/]+)$'

async def test_get(client, ResourceEndpoint, resource):
    res = await client.get('/api/resource')
    assert res.status_code == 200
    json = await res.json()
    assert json
    assert json[0]['config'] == {}
    assert json[0]['count'] is None
    assert json[0]['id'] == '1'
    assert json[0]['name'] == 'test'

    res = await client.get('/api/resource/1')
    assert res.status_code == 200
    assert await res.json() == {
        'active': False,
        'config': {},
        'count': None,
        'id': '1',
        'name': 'test',
    }

    res = await client.get('/api/resource/unknown')
    assert res.status_code == 404
    assert await res.json() == {'error': True, 'message': 'Resource not found'}

    res = await client.get('/api/resource/action?custom=123')
    assert res.status_code == 200
    json = await res.json()
    assert json

async def test_create(client, ResourceEndpoint):
    res = await client.post('/api/resource', json={'active': True})
    assert res.status_code == 400
    json = await res.json()
    assert json['errors']
    assert 'name' in json['errors']

    res = await client.post('/api/resource', data={'name': 'test2', 'active': True, 'unknown': 22})
    assert res.status_code == 200
    json = await res.json()
    assert json['id'] == '1'
    assert json['name'] == 'test2'
    assert json['active']

async def test_edit(client, resource, ResourceEndpoint):
    res = await client.put('/api/resource/1', data={'name': 'new'})
    assert res.status_code == 200
    json = await res.json()
    assert json['name'] == 'new'
    assert json['id'] == '1'

async def test_delete(client, resource, ResourceEndpoint, Resource, db):
    res = await client.delete('/api/resource/1')
    assert res.status_code == 200
    json = await res.json()
    assert not json

    assert not await db.manager.fetchone(Resource.select().where(Resource.id == 1))

async def test_sort(client, ResourceEndpoint, Resource, db):
    await db.manager.create(Resource, name='test2', count=2)
    await db.manager.create(Resource, name='test3', count=3)
    await db.manager.create(Resource, name='test4', count=1)

    # Default sort
    res = await client.get('/api/resource')
    assert res.status_code == 200
    json = await res.json()
    assert json[0]['id'] == '3'
    assert json[1]['id'] == '2'

    res = await client.get('/api/resource?sort=-count')
    assert res.status_code == 200
    json = await res.json()
    assert json[0]['id'] == '2'
    assert json[1]['id'] == '1'

async def test_filters(client, ResourceEndpoint, Resource, db):
    await db.manager.create(Resource, name='test2', count=2)
    await db.manager.create(Resource, name='test3', count=3)
    await db.manager.create(Resource, name='test4', count=1)

    res = await client.get('/api/resource?where={"name":"test"}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 0

    res = await client.get('/api/resource?where={"name": {"$in": ["test3", "test2"]}}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 2

    res = await client.get('/api/resource?where={"name": {"$starts": "test"}}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 3

    res = await client.get('/api/resource?where={"name": {"$ends": "3"}}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 1

    res = await client.get('/api/resource?where={"oid": {"$between": ["2", "3"]}}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 2

    res = await client.get('/api/resource?where={"oid": {"$gt": "2"}}')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 1

async def test_paginate(client, ResourceEndpoint, Resource, db):
    for n in range(12):
        await db.manager.create(Resource, name=f"test{n}")

    res = await client.get('/api/resource')
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 10

    res = await client.get('/api/resource?limit=5')
    assert res.status_code == 200
    assert res.headers['x-total'] == '12'
    assert res.headers['x-limit'] == '5'
    assert res.headers['x-offset'] == '0'
    json = await res.json()
    assert len(json) == 5

    res = await client.get('/api/resource?limit=5&offset=9')
    assert res.status_code == 200
    assert res.headers['x-total'] == '12'
    assert res.headers['x-limit'] == '5'
    assert res.headers['x-offset'] == '9'
    json = await res.json()
    assert len(json) == 3

async def test_batch_ops(client, ResourceEndpoint, db, Resource):
    # Batch operations (only POST/DELETE are supported for now)
    res = await client.post('/api/resource', json=[
        {'name': 'test3', 'active': True},
        {'name': 'test4', 'active': True},
        {'name': 'test6', 'active': True},
    ])
    assert res.status_code == 200
    json = await res.json()
    assert len(json) == 3
    assert json[0]['id'] == '1'
    assert json[1]['id'] == '2'
    assert json[2]['id'] == '3'

    res = await client.delete('/api/resource', json=['1', '2', '3'])
    assert res.status_code == 200

    assert not await db.manager.count(Resource.select().where(Resource.id << ('11', '12', '13')))

async def test_openapi(client, ResourceEndpoint):
    res = await client.get('/api/openapi.json')
    assert res.status_code == 200
    json = await res.json()
    assert json

async def test_endpoint_inheritance(Resource):
    from muffin_rest.peewee import PWRESTHandler

    class ResourceEndpoint(PWRESTHandler):

        class Meta:
            model = Resource

    assert ResourceEndpoint.meta.name == 'resource'

    class ChildEndpoint(ResourceEndpoint):

        class Meta:
            name = 'child'

    assert ChildEndpoint.meta.name == 'child'

async def test_aiomodels(client, db, api):

    events = []

    class TestModel(db.Model):

        data = pw.CharField()

        async def save(self, **kwargs):
            events.append('custom-save')
            return await super().save(**kwargs)

        async def delete_instance(self, **kwargs):
            events.append('custom-delete')
            return await super().delete_instance(**kwargs)

    await db.manager.create_tables(TestModel)

    from muffin_rest.peewee import PWRESTHandler

    @api.route
    class Test(PWRESTHandler):

        class Meta:
            model = TestModel

    res = await client.post('/api/testmodel', json={'data': 'test'})
    assert res.status_code == 200
    json = await res.json()
    assert json['id']

    assert events
    assert 'custom-save' in events

    res = await client.delete(f"/api/testmodel/{json['id']}")
    assert res.status_code == 200

    assert 'custom-delete' in events


text:
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired, Length, Email

class SubscribeForm(FlaskForm):
    email = StringField('Email Address', validators = [DataRequired(), Length(max = 120), Email()])

class UnsubscribeForm(FlaskForm):
    email = StringField('Email Address', validators = [DataRequired(), Length(max = 120), Email()])


text:
<?php

class TestAjax extends WP_Ajax_UnitTestCase {
	function setUp() {
		parent::setUp();

		$settings = get_option('pmp_settings');

		if (empty($settings['pmp_api_url']) || empty($settings['pmp_client_id']) || empty($settings['pmp_client_secret']))
			$this->skip = true;
		else {
			$this->skip = false;
			$this->sdk_wrapper = new SDKWrapper( $settings );

			// A test query that's all but guaranteed to return at least one result.
			$this->query = array(
				'text' => 'Obama',
				'limit' => 10,
				'profile' => 'story'
			);

			$this->editor = $this->factory->user->create();
			$user = get_user_by('id', $this->editor);
			$user->set_role('editor');
			wp_set_current_user($user->ID);

			$this->group = array(
				'attributes' => array(
					'title' => 'WP PMP Unit Test Group ' . time()
				)
			);

			$this->collection = array(
				'attributes' => array(
					'title' => 'WP PMP Unit Test Collection ' . time()
				)
			);
		}
	}

	function test_pmp_search() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$_POST['query'] = addslashes(json_encode($this->query));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_search");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_draft_post() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$result = $this->sdk_wrapper->query2json('queryDocs', $this->query);
		$pmp_story = $result['items'][0];

		$_POST['pmp_guid'] = $pmp_story['attributes']['guid'];
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_draft_post");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_publish_post() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$result = $this->sdk_wrapper->query2json('queryDocs', $this->query);
		$pmp_story = $result['items'][0];

		$_POST['pmp_guid'] = $pmp_story['attributes']['guid'];
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_draft_post");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_create_group() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$_POST['group'] = addslashes(json_encode($this->group));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_create_group");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);

			// Stash the group guid for later use
			if ($result['success'])
				$GLOBALS['pmp_stash']['test_group_guid'] = $result['data']['items'][0]['attributes']['guid'];
		}
	}

	function test_pmp_modify_group() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$this->group['attributes'] = array_merge($this->group['attributes'], array(
			'guid' => $GLOBALS['pmp_stash']['test_group_guid'],
			'description' => 'A test description'
		));
		$_POST['group'] = addslashes(json_encode($this->group));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_modify_group");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_default_group() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$this->group['attributes'] = array_merge($this->group['attributes'], array(
			'guid' => 'test-guid-does-not-matter',
		));
		$_POST['group'] = addslashes(json_encode($this->group));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_default_group");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_save_users() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$_POST['data'] = addslashes(json_encode(array(
			'collection_guid' => $GLOBALS['pmp_stash']['test_group_guid'],
			'items_guids' => array(pmp_get_my_guid())
		)));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_save_users");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);

			// Clean up/delete test group
			if ($result['success']) {
				$group_doc = $this->sdk_wrapper->fetchDoc($GLOBALS['pmp_stash']['test_group_guid']);
				$group_doc->delete();
			}
		}
	}

	function test_pmp_create_collection() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$_POST['collection'] = addslashes(json_encode($this->collection));
		$_POST['profile'] = 'series';
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_create_collection");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);

			// Stash the collection guid for later use
			if ($result['success'])
				$GLOBALS['pmp_stash']['test_collection_guid'] = $result['data']['items'][0]['attributes']['guid'];
		}
	}

	function test_pmp_modify_collection() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$this->collection['attributes'] = array_merge($this->collection['attributes'], array(
			'guid' => $GLOBALS['pmp_stash']['test_collection_guid'],
			'description' => 'A test description'
		));
		$_POST['profile'] = 'series';
		$_POST['collection'] = addslashes(json_encode($this->collection));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_modify_collection");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_default_collection() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$this->collection['attributes'] = array_merge($this->collection['attributes'], array(
			'guid' => 'test-guid-does-not-matter',
		));
		$_POST['collection'] = addslashes(json_encode($this->collection));
		$_POST['profile'] = 'series';
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_default_collection");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);

			// Clean up/delete test collection
			if ($result['success']) {
				$collection_doc = $this->sdk_wrapper->fetchDoc($GLOBALS['pmp_stash']['test_collection_guid']);
				$collection_doc->delete();
			}
		}
	}

	function test_pmp_save_query() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$test_query = (object) array(
			'options' => (object) array(
				'title' => '',
				'query_auto_create' => 'off'
			),
			'query' => (object) array(
				'text' => 'TKTK'
			)
		);
		$_POST['data'] = addslashes(json_encode($test_query));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_save_query");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
			$this->assertTrue($result['search_id'] >= 0);
		}
	}

	function test_pmp_delete_saved_query() {
		if ($this->skip) {
			$this->markTestSkipped(
				'This test requires site options `pmp_api_url`, `pmp_client_id` and `pmp_client_secret`');
			return;
		}

		$test_query = (object) array(
			'search_id' => 0
		);
		$_POST['data'] = addslashes(json_encode($test_query));
		$_POST['security'] = wp_create_nonce('pmp_ajax_nonce');

		try {
			$this->_handleAjax("pmp_delete_saved_query");
		} catch (WPAjaxDieContinueException $e) {
			$result = json_decode($this->_last_response, true);
			$this->assertTrue($result['success']);
		}
	}

	function test_pmp_get_select_options() {
		$this->markTestIncomplete('This test has not been implemented yet.');
	}

	function test__pmp_create_doc() {
		$this->markTestSkipped(
			'Functional test of `_pmp_create_doc` performed by `test_pmp_create_collection` and `test_pmp_create_group`');
	}

	function test__pmp_modify_doc() {
		$this->markTestSkipped(
			'Functional test of `_pmp_modify_doc` performed by `test_pmp_modify_collection` and `test_pmp_modify_group`');
	}

	function test__pmp_ajax_create_post() {
		$this->markTestSkipped(
			'Functional test of `_pmp_ajax_create_post` performed by `test_pmp_draft_post` and `test_pmp_publish_post`');
	}

	function test__pmp_create_post() {
		$this->markTestSkipped(
			'Functional test of `_pmp_create_post` performed by `test_pmp_draft_post` and `test_pmp_publish_post`');
	}

	function test__pmp_select_for_post() {
		$this->markTestSkipped(
			'Functional test of `_pmp_select_for_post` performed by `test_pmp_get_select_options`');
	}
}


text:
class ExternalResqueWorker
  DEFAULT_STARTUP_TIMEOUT = 1.minute

  attr_accessor :pid, :startup_timeout
  private_class_method :new

  # It's very difficult to ensure a worker is paused before it works any jobs if jobs exist before the worker is created. Run this before actually having jobs enqueued if you don't want them to run at first.
  def self.create_and_pause_shortly_thereafter(queues_to_watch = '*')
    new(queues_to_watch)
  end

  def initialize(queues_to_watch = '*')
    @queues = [queues_to_watch].flatten
    start
  end

  def start
    raise "PEDANTICALLY CODED TO ONLY WORK IN TEST ENV" unless Rails.env.test?
    if self.pid = fork
      Process.detach(pid)
      # Since pausing is done by signal USR2, there will be a time between when the worker starts and when we can pause it.
      wait_for_worker_to_start
      pause
    else
      STDOUT.reopen(File.open("#{Rails.root}/log/external_resque_worker.log", "a+")) # stops it from giving us the extra test output
      start_child
    end
  end

  def self.kill_all_existing_workers
    while Resque::Worker.all.size > 0
      Resque::Worker.all.each do |w|
        Process.kill("TERM", w.pid) rescue nil
        w.prune_dead_workers
      end
    end
  end

  def process_all
    unpause
    sleep 1 until done?
    pause
  end

  def pause(pid = self.pid)
    Process.kill("USR2", pid)
  end

  def unpause
    Process.kill("CONT", pid)
  end

  def queues
    @queues.map {|queue| queue == "*" ? Resque.queues.sort : queue }.flatten.uniq
  end

  private

  def done?
    our_queues_empty = queues.all? do |queue|
      Resque.peek(queue).blank?
    end

    our_workers_done = (Resque::Worker.working.map{ |worker| worker.job['queue'] }.flatten & queues).empty?

    our_queues_empty and our_workers_done
  end

  def start_parent
    at_exit do
      Process.kill("KILL", pid) if pid
    end
  end

  def start_child
    # Array form of exec() is required here, otherwise the worker is not a direct
    # child process of test.
    # If it's not the direct child process then the PID returned from fork() is
    # wrong, which means we can't communicate with the worker.
    exec('bundle', 'exec', 'rake', "--silent", 'environment', 'resque:work', "QUEUE=#{@queues.join(',')}", "INTERVAL=0.25", "RAILS_ENV=test", "VVERBOSE=1")
  end

  def wait_for_worker_to_start
    self.startup_timeout ||= DEFAULT_STARTUP_TIMEOUT
    start = Time.now.to_i
    while (Time.now.to_i - start) < startup_timeout
      return if worker_started?
      sleep 1
    end

    raise "Timeout while waiting for the worker to start. Waited #{startup_timeout} seconds."
  end

  def worker_started?
    Resque.workers.any? { |worker| worker.worker_pids.include? self.pid.to_s }
  end
end


text:
import smtplib
import datetime
import logging
from email.mime.multipart import MIMEMultipart

from nvnotifier import git
from .lib import convert_timeout_to_second

logger = logging.getLogger(__name__)

def send_mail(host, port, sender, receiver, subject, text):
    msg = MIMEMultipart()
    msg['Subject'] = subject
    msg['From'] = sender
    msg['To'] = receiver
    msg.preamble = text

    try:
        s = smtplib.SMTP(host, port)
    except ConnectionRefusedError:
        logger.error("Cannot connect to SMTP server %s:%s", host, port)
        raise

    s.send_message(msg)
    s.quit()

class Notifier:
    def __init__(self, *args, timeout="0s", sender, saved={}, **kwargs):
        timeout_seconds = convert_timeout_to_second(timeout)
        now = datetime.datetime.now()
        self.deadline = now - datetime.timedelta(seconds=timeout_seconds)

        self.sender = sender
        self.default_receiver = kwargs.get("default_receiver", None)

        self.host = kwargs.get("host", "localhost")
        self.port = kwargs.get("port", 0)

        self.record = saved.copy()

    def send_raw_mail(self, receiver, subject, text):
        receiver = receiver or self.default_receiver

        send_mail(
            host=self.host,
            port=self.port,
            sender=self.sender,
            receiver=receiver,
            subject=subject,
            text=text)

        logger.info("Sent Email to %r", receiver)
        logger.debug("Subject: %r", subject)

    def send(self, pac, outtime):
        if outtime > self.deadline:
            return False

        objhash = pac.info
        if self.record.get(pac.name) == objhash:
            logger.info("Already sent mail to %r maintainer", pac.name)
            return False

        receiver = git.git_latest_committer(pac.path) or self.default_receiver
        if receiver:
            self.send_raw_mail(
                receiver=receiver,
                subject="Package %s is out-of-date" % pac.name,
                text="Local: %s\nRemote: %s" %
                     (pac.local_version, pac.remote_version))
        else:
            logger.warning("Don't know send email to whom (%s)", pac)
            return False

        self.record[pac.name] = objhash
        return True

    def finish(self):
        return self.record


text:
#pragma config(Sensor, S1,     Color1,         sensorEV3_Color)
//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

task main()
{
	while(true) {
		displayBigTextLine(0, "%d" , getColorAmbient(Color1));
	}

}