NOEXPORT void tray_update(const int num) {
    NOTIFYICONDATA nid;
    static ICON_TYPE previous_icon=ICON_NONE;
    ICON_TYPE current_icon;
    LPTSTR tip;

    if(!global_options.option.taskbar) { /* currently disabled */
        tray_delete(); /* remove the taskbark icon if exists */
        return;
    }
    if(!tray_menu_handle) /* initialize taskbar */
        tray_menu_handle=LoadMenu(ghInst, MAKEINTRESOURCE(IDM_TRAYMENU));
    if(!tray_menu_handle) {
        ioerror("LoadMenu");
        return;
    }
    if(cmdline.service)
        EnableMenuItem(tray_menu_handle, IDM_EDIT_CONFIG, MF_GRAYED);

    ZeroMemory(&nid, sizeof nid);
    nid.cbSize=sizeof nid;
    nid.uID=1; /* application-defined icon ID */
    nid.uFlags=NIF_MESSAGE|NIF_TIP;
    nid.uCallbackMessage=WM_SYSTRAY; /* notification message */
    nid.hWnd=hwnd; /* window to receive notifications */
    if(num<0) {
        tip=str_tprintf(TEXT("Server is down"));
        current_icon=ICON_ERROR;
    } else if(num>0) {
        tip=str_tprintf(TEXT("%d active session(s)"), num);
        current_icon=ICON_ACTIVE;
    } else {
        tip=str_tprintf(TEXT("Server is idle"));
        current_icon=ICON_IDLE;
    }
    _tcsncpy(nid.szTip, tip, 63);
    nid.szTip[63]=TEXT('\0');
    str_free(tip);
    nid.hIcon=global_options.icon[current_icon];
    if(current_icon!=previous_icon) {
        nid.uFlags|=NIF_ICON;
        previous_icon=current_icon;
    }
    if(Shell_NotifyIcon(NIM_MODIFY, &nid)) /* modify tooltip */
        return; /* OK: taskbar icon exists */
    /* tooltip update failed - try to create the icon */
    nid.uFlags|=NIF_ICON;
    Shell_NotifyIcon(NIM_ADD, &nid);
}


jpeg_error_handler(j_common_ptr)
{
  return;
}


void fmtutil_macbitmap_read_pixmap_only_fields(deark *c, dbuf *f, struct fmtutil_macbitmap_info *bi,
	i64 pos)
{
	i64 pixmap_version;
	i64 pack_size;
	i64 plane_bytes;
	i64 n;

	de_dbg(c, "additional PixMap header fields, at %d", (int)pos);
	de_dbg_indent(c, 1);

	pixmap_version = dbuf_getu16be(f, pos+0);
	de_dbg(c, "pixmap version: %d", (int)pixmap_version);

	bi->packing_type = dbuf_getu16be(f, pos+2);
	de_dbg(c, "packing type: %d", (int)bi->packing_type);

	pack_size = dbuf_getu32be(f, pos+4);
	de_dbg(c, "pixel data length: %d", (int)pack_size);

	bi->hdpi = pict_read_fixed(f, pos+8);
	bi->vdpi = pict_read_fixed(f, pos+12);
	de_dbg(c, "dpi: %.2f"DE_CHAR_TIMES"%.2f", bi->hdpi, bi->vdpi);

	bi->pixeltype = dbuf_getu16be(f, pos+16);
	bi->pixelsize = dbuf_getu16be(f, pos+18);
	bi->cmpcount = dbuf_getu16be(f, pos+20);
	bi->cmpsize = dbuf_getu16be(f, pos+22);
	de_dbg(c, "pixel type=%d, bits/pixel=%d, components/pixel=%d, bits/comp=%d",
		(int)bi->pixeltype, (int)bi->pixelsize, (int)bi->cmpcount, (int)bi->cmpsize);

	bi->pdwidth = (bi->rowbytes*8)/bi->pixelsize;
	if(bi->pdwidth < bi->npwidth) {
		bi->pdwidth = bi->npwidth;
	}

	plane_bytes = dbuf_getu32be(f, pos+24);
	de_dbg(c, "plane bytes: %d", (int)plane_bytes);

	bi->pmTable = (u32)dbuf_getu32be(f, pos+28);
	de_dbg(c, "pmTable: 0x%08x", (unsigned int)bi->pmTable);

	n = dbuf_getu32be(f, pos+32);
	de_dbg(c, "pmReserved: 0x%08x", (unsigned int)n);

	de_dbg_indent(c, -1);
}


void trustedGetPublicSharesAES(int *errStatus, char *errString, uint8_t *encrypted_dkg_secret, uint32_t enc_len,
                               char *public_shares,
                               unsigned _t, unsigned _n) {
    LOG_INFO(__FUNCTION__);

    INIT_ERROR_STATE

    CHECK_STATE(encrypted_dkg_secret);
    CHECK_STATE(public_shares);
    CHECK_STATE(_t <= _n && _n > 0)

    SAFE_CHAR_BUF(decrypted_dkg_secret, DKG_MAX_SEALED_LEN);

    int status = AES_decrypt(encrypted_dkg_secret, enc_len, decrypted_dkg_secret,
                             DKG_MAX_SEALED_LEN);

    CHECK_STATUS2("aes decrypt data - encrypted_dkg_secret failed with status %d");

    status = calc_public_shares(decrypted_dkg_secret, public_shares, _t) != 0;
    CHECK_STATUS("t does not match polynomial in db");

    SET_SUCCESS

    clean:
    ;
    LOG_INFO("SGX call completed");
}


void mobi_buffer_move(MOBIBuffer *buf, const int offset, const size_t len) {
    size_t aoffset = (size_t) abs(offset);
    unsigned char *source = buf->data + buf->offset;
    if (offset >= 0) {
        if (buf->offset + aoffset + len > buf->maxlen) {
            debug_print("%s", "End of buffer\n");
            buf->error = MOBI_BUFFER_END;
            return;
        }
        source += aoffset;
    } else {
        if (buf->offset < aoffset) {
            debug_print("%s", "End of buffer\n");
            buf->error = MOBI_BUFFER_END;
            return;
        }
        source -= aoffset;
    }
    memmove(buf->data + buf->offset, source, len);
    buf->offset += len;
}


int audio_level_json(struct list *levell,
		     const char *userid_self, const char *clientid_self,
		     char **json_str, char **anon_str)
{
	struct json_object *jobj;
	struct json_object *jarr;
	char uid_anon[ANON_ID_LEN];
	char cid_anon[ANON_CLIENT_LEN];
	struct mbuf *pmb = NULL;
	int err = 0;
	struct le *le;

	if (!levell || !json_str)
		return EINVAL;

	jobj = jzon_alloc_object();
	if (!jobj)
		return ENOMEM;

	jarr = jzon_alloc_array();
	if (!jarr) {
		err = ENOMEM;
		goto out;
	}

	if (anon_str) {
		pmb = mbuf_alloc(512);
		mbuf_printf(pmb, "%zu levels: ", list_count(levell));
	}

	LIST_FOREACH(levell, le) {
		struct audio_level *a = le->data;
		struct json_object *ja;
		const char *userid = a->userid;
		const char *clientid = a->clientid;

		if (a->is_self) {
			if (userid_self)
				userid = userid_self;
			if (clientid_self)
				clientid = clientid_self;
		}

		ja = jzon_alloc_object();
		if (ja) {
			jzon_add_str(ja, "userid", userid);
			jzon_add_str(ja, "clientid", clientid);
			jzon_add_int(ja, "audio_level",
				     (int32_t)a->aulevel_smooth);
			jzon_add_int(ja, "audio_level_now",
				     (int32_t)a->aulevel);
		}
		json_object_array_add(jarr, ja);

		/* add to info string */
		if (pmb) {
			anon_id(uid_anon, userid);
			anon_client(cid_anon, clientid);
			mbuf_printf(pmb, "{[%s.%s] audio_level: %d/%d}",
				    uid_anon, cid_anon,
				    a->aulevel_smooth, a->aulevel);
			if (le != levell->tail)
				mbuf_printf(pmb, ",");
		}
	}
	json_object_object_add(jobj, "audio_levels", jarr);

	if (pmb) {
		pmb->pos = 0;
		mbuf_strdup(pmb, anon_str, pmb->end);
		mem_deref(pmb);
	}

	jzon_encode(json_str, jobj);
 out:
	mem_deref(jobj);

	return err;
}


def _inject_file_into_fs(fs, path, contents):
    absolute_path = os.path.join(fs, path.lstrip('/'))
    parent_dir = os.path.dirname(absolute_path)
    utils.execute('mkdir', '-p', parent_dir, run_as_root=True)
    utils.execute('tee', absolute_path, process_input=contents,
          run_as_root=True)


    def set(self, key, value, serialize=True, timeout=0):
        """
        Set a key/value pair in memcache

        :param key: key
        :param value: value
        :param serialize: if True, value is pickled before sending to memcache
        :param timeout: ttl in memcache
        """
        key = md5hash(key)
        if timeout > 0:
            timeout += time.time()
        flags = 0
        if serialize:
            value = pickle.dumps(value, PICKLE_PROTOCOL)
            flags |= PICKLE_FLAG
        for (server, fp, sock) in self._get_conns(key):
            try:
                sock.sendall('set %s %d %d %s noreply\r\n%s\r\n' % \
                              (key, flags, timeout, len(value), value))
                self._return_conn(server, fp, sock)
                return
            except Exception, e:
                self._exception_occurred(server, e)


    def get_multi(self, keys, server_key):
        """
        Gets multiple values from memcache for the given keys.

        :param keys: keys for values to be retrieved from memcache
        :param servery_key: key to use in determining which server in the ring
                            is used
        :returns: list of values
        """
        server_key = md5hash(server_key)
        keys = [md5hash(key) for key in keys]
        for (server, fp, sock) in self._get_conns(server_key):
            try:
                sock.sendall('get %s\r\n' % ' '.join(keys))
                line = fp.readline().strip().split()
                responses = {}
                while line[0].upper() != 'END':
                    if line[0].upper() == 'VALUE':
                        size = int(line[3])
                        value = fp.read(size)
                        if int(line[2]) & PICKLE_FLAG:
                            value = pickle.loads(value)
                        responses[line[1]] = value
                        fp.readline()
                    line = fp.readline().strip().split()
                values = []
                for key in keys:
                    if key in responses:
                        values.append(responses[key])
                    else:
                        values.append(None)
                self._return_conn(server, fp, sock)
                return values
            except Exception, e:
                self._exception_occurred(server, e)


    def get(self, key):
        """
        Gets the object specified by key.  It will also unpickle the object
        before returning if it is pickled in memcache.

        :param key: key
        :returns: value of the key in memcache
        """
        key = md5hash(key)
        value = None
        for (server, fp, sock) in self._get_conns(key):
            try:
                sock.sendall('get %s\r\n' % key)
                line = fp.readline().strip().split()
                while line[0].upper() != 'END':
                    if line[0].upper() == 'VALUE' and line[1] == key:
                        size = int(line[3])
                        value = fp.read(size)
                        if int(line[2]) & PICKLE_FLAG:
                            value = pickle.loads(value)
                        fp.readline()
                    line = fp.readline().strip().split()
                self._return_conn(server, fp, sock)
                return value
            except Exception, e:
                self._exception_occurred(server, e)


    def set_multi(self, mapping, server_key, serialize=True, timeout=0):
        """
        Sets multiple key/value pairs in memcache.

        :param mapping: dictonary of keys and values to be set in memcache
        :param servery_key: key to use in determining which server in the ring
                            is used
        :param serialize: if True, value is pickled before sending to memcache
        :param timeout: ttl for memcache
        """
        server_key = md5hash(server_key)
        if timeout > 0:
            timeout += time.time()
        msg = ''
        for key, value in mapping.iteritems():
            key = md5hash(key)
            flags = 0
            if serialize:
                value = pickle.dumps(value, PICKLE_PROTOCOL)
                flags |= PICKLE_FLAG
            msg += ('set %s %d %d %s noreply\r\n%s\r\n' %
                    (key, flags, timeout, len(value), value))
        for (server, fp, sock) in self._get_conns(server_key):
            try:
                sock.sendall(msg)
                self._return_conn(server, fp, sock)
                return
            except Exception, e:
                self._exception_occurred(server, e)


def is_safe_url(url, host=None):
    """
    Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
    a different host and uses a safe scheme).

    Always returns ``False`` on an empty url.
    """
    if url is not None:
        url = url.strip()
    if not url:
        return False
    # Chrome treats \ completely as /
    url = url.replace('\\', '/')
    # Chrome considers any URL with more than two slashes to be absolute, but
    # urlparse is not so flexible. Treat any url with three slashes as unsafe.
    if url.startswith('///'):
        return False
    url_info = urlparse(url)
    # Forbid URLs like http:///example.com - with a scheme, but without a hostname.
    # In that URL, example.com is not the hostname but, a path component. However,
    # Chrome will still consider example.com to be the hostname, so we must not
    # allow this syntax.
    if not url_info.netloc and url_info.scheme:
        return False
    # Forbid URLs that start with control characters. Some browsers (like
    # Chrome) ignore quite a few control characters at the start of a
    # URL and might consider the URL as scheme relative.
    if unicodedata.category(url[0])[0] == 'C':
        return False
    return ((not url_info.netloc or url_info.netloc == host) and
            (not url_info.scheme or url_info.scheme in ['http', 'https']))


    def load(self):

        if len(self.tile) != 1 or self.tile[0][0] != "iptc":
            return ImageFile.ImageFile.load(self)

        type, tile, box = self.tile[0]

        encoding, offset = tile

        self.fp.seek(offset)

        # Copy image data to temporary file
        outfile = tempfile.mktemp()
        o = open(outfile, "wb")
        if encoding == "raw":
            # To simplify access to the extracted file,
            # prepend a PPM header
            o.write("P5\n%d %d\n255\n" % self.size)
        while True:
            type, size = self.field()
            if type != (8, 10):
                break
            while size > 0:
                s = self.fp.read(min(size, 8192))
                if not s:
                    break
                o.write(s)
                size = size - len(s)
        o.close()

        try:
            try:
                # fast
                self.im = Image.core.open_ppm(outfile)
            except:
                # slightly slower
                im = Image.open(outfile)
                im.load()
                self.im = im.im
        finally:
            try: os.unlink(outfile)
            except: pass


def subscribe_for_tags(request):
    """process subscription of users by tags"""
    #todo - use special separator to split tags
    tag_names = request.REQUEST.get('tags','').strip().split()
    pure_tag_names, wildcards = forms.clean_marked_tagnames(tag_names)
    if request.user.is_authenticated():
        if request.method == 'POST':
            if 'ok' in request.POST:
                request.user.mark_tags(
                            pure_tag_names,
                            wildcards,
                            reason = 'good',
                            action = 'add'
                        )
                request.user.message_set.create(
                    message = _('Your tag subscription was saved, thanks!')
                )
            else:
                message = _(
                    'Tag subscription was canceled (undo).'
                ) % {'url': request.path + '?tags=' + request.REQUEST['tags']}
                request.user.message_set.create(message = message)
            return HttpResponseRedirect(reverse('index'))
        else:
            data = {'tags': tag_names}
            return render(request, 'subscribe_for_tags.html', data)
    else:
        all_tag_names = pure_tag_names + wildcards
        message = _('Please sign in to subscribe for: %(tags)s') \
                    % {'tags': ', '.join(all_tag_names)}
        request.user.message_set.create(message = message)
        request.session['subscribe_for_tags'] = (pure_tag_names, wildcards)
        return HttpResponseRedirect(url_utils.get_login_url())


    def fetch_file(self, in_path, out_path):
        ''' fetch a file from chroot to local '''

        in_path = self._normalize_path(in_path, self.get_jail_path())
        vvv("FETCH %s TO %s" % (in_path, out_path), host=self.jail)

        self._copy_file(in_path, out_path)


    def _normalize_path(self, path, prefix):
        if not path.startswith(os.path.sep):
            path = os.path.join(os.path.sep, path)
        normpath = os.path.normpath(path)
        return os.path.join(prefix, normpath[1:])


    def put_file(self, in_path, out_path):
        ''' transfer a file from local to zone '''

        out_path = self._normalize_path(out_path, self.get_zone_path())
        vvv("PUT %s TO %s" % (in_path, out_path), host=self.zone)

        self._copy_file(in_path, out_path)


    def fetch_file(self, in_path, out_path):
        ''' fetch a file from zone to local '''

        in_path = self._normalize_path(in_path, self.get_zone_path())
        vvv("FETCH %s TO %s" % (in_path, out_path), host=self.zone)

        self._copy_file(in_path, out_path)


def _websocket_mask_python(mask, data):
    """Websocket masking function.

    `mask` is a `bytes` object of length 4; `data` is a `bytes` object of any length.
    Returns a `bytes` object of the same length as `data` with the mask applied
    as specified in section 5.3 of RFC 6455.

    This pure-python implementation may be replaced by an optimized version when available.
    """
    mask = array.array("B", mask)
    unmasked = array.array("B", data)
    for i in xrange(len(data)):
        unmasked[i] = unmasked[i] ^ mask[i % 4]
    if hasattr(unmasked, 'tobytes'):
        # tostring was deprecated in py32.  It hasn't been removed,
        # but since we turn on deprecation warnings in our tests
        # we need to use the right one.
        return unmasked.tobytes()
    else:
        return unmasked.tostring()


    def GET(self, path, queries=()):
        return self._request('GET', path, queries)


def checkin(pickledata):
    config = pickle.loads(bz2.decompress(base64.urlsafe_b64decode(pickledata)))
    r, message = read_host_config(SESSION, config)
    if r is not None:
        return message + 'checked in successful'
    else:
        return message + 'error checking in'


def class_instances_from_soap_enveloped_saml_thingies(text, modules):
    """Parses a SOAP enveloped header and body SAML thing and returns the
    thing as a dictionary class instance.

    :param text: The SOAP object as XML
    :param modules: modules representing xsd schemas
    :return: The body and headers as class instances
    """
    try:
        envelope = ElementTree.fromstring(text)
    except Exception as exc:
        raise XmlParseError("%s" % exc)

    assert envelope.tag == '{%s}Envelope' % soapenv.NAMESPACE
    assert len(envelope) >= 1
    env = {"header": [], "body": None}

    for part in envelope:
        if part.tag == '{%s}Body' % soapenv.NAMESPACE:
            assert len(part) == 1
            env["body"] = instanciate_class(part[0], modules)
        elif part.tag == "{%s}Header" % soapenv.NAMESPACE:
            for item in part:
                env["header"].append(instanciate_class(item, modules))

    return env


    def prop_sentences_stats(self, type, vId = None):
        return {
            'get_data' : "SELECT victims.*, geo.*, victims.ip AS ip_local, COUNT(clicks.id) FROM victims INNER JOIN geo ON victims.id = geo.id LEFT JOIN clicks ON clicks.id = victims.id GROUP BY victims.id ORDER BY victims.time DESC",
            'all_networks' : "SELECT networks.* FROM networks ORDER BY id",
            'get_preview' : "SELECT victims.*, geo.*, victims.ip AS ip_local FROM victims INNER JOIN geo ON victims.id = geo.id WHERE victims.id = '%s'" % (vId),
            'id_networks' : "SELECT networks.* FROM networks WHERE id = '%s'" % (vId),
            'get_requests' : "SELECT requests.*, geo.ip FROM requests INNER JOIN geo on geo.id = requests.user_id ORDER BY requests.date DESC, requests.id ",
            'get_sessions' : "SELECT COUNT(*) AS Total FROM networks",
            'get_clicks' : "SELECT COUNT(*) AS Total FROM clicks",
            'get_online' : "SELECT COUNT(*) AS Total FROM victims WHERE status = '%s'" % ('online')
        }.get(type, False)


def home_get_preview():
    vId = request.form['vId']
    d = db.sentences_stats('get_preview', vId)
    n = db.sentences_stats('id_networks', vId)
    return json.dumps({'status' : 'OK', 'vId' : vId, 'd' : d, 'n' : n});


    def load(self, stream):
        '''read vault steam and return python object'''
        return yaml.load(self.vault.decrypt(stream))


    def make_homeserver(self, reactor, clock):
        hs = self.setup_test_homeserver(
            http_client=None, homeserver_to_use=GenericWorkerServer
        )
        return hs


    def make_homeserver(self, reactor, clock):
        # we mock out the keyring so as to skip the authentication check on the
        # federation API call.
        mock_keyring = Mock(spec=["verify_json_for_server"])
        mock_keyring.verify_json_for_server.return_value = defer.succeed(True)

        # we mock out the federation client too
        mock_federation_client = Mock(spec=["put_json"])
        mock_federation_client.put_json.return_value = defer.succeed((200, "OK"))

        # the tests assume that we are starting at unix time 1000
        reactor.pump((1000,))

        hs = self.setup_test_homeserver(
            notifier=Mock(),
            http_client=mock_federation_client,
            keyring=mock_keyring,
            replication_streams={},
        )

        return hs


    def prepare(self, reactor, clock, homeserver):
        # make a second homeserver, configured to use the first one as a key notary
        self.http_client2 = Mock()
        config = default_config(name="keyclient")
        config["trusted_key_servers"] = [
            {
                "server_name": self.hs.hostname,
                "verify_keys": {
                    "ed25519:%s"
                    % (
                        self.hs_signing_key.version,
                    ): signedjson.key.encode_verify_key_base64(
                        self.hs_signing_key.verify_key
                    )
                },
            }
        ]
        self.hs2 = self.setup_test_homeserver(
            http_client=self.http_client2, config=config
        )

        # wire up outbound POST /key/v2/query requests from hs2 so that they
        # will be forwarded to hs1
        async def post_json(destination, path, data):
            self.assertEqual(destination, self.hs.hostname)
            self.assertEqual(
                path, "/_matrix/key/v2/query",
            )

            channel = FakeChannel(self.site, self.reactor)
            req = SynapseRequest(channel)
            req.content = BytesIO(encode_canonical_json(data))

            req.requestReceived(
                b"POST", path.encode("utf-8"), b"1.1",
            )
            channel.await_result()
            self.assertEqual(channel.code, 200)
            resp = channel.json_body
            return resp

        self.http_client2.post_json.side_effect = post_json


  def testInputPreProcessFormats(self):
    input_str = 'input1=/path/file.txt[ab3];input2=file2'
    input_expr_str = 'input3=np.zeros([2,2]);input4=[4,5]'
    input_dict = saved_model_cli.preprocess_inputs_arg_string(input_str)
    input_expr_dict = saved_model_cli.preprocess_input_exprs_arg_string(
        input_expr_str)
    self.assertTrue(input_dict['input1'] == ('/path/file.txt', 'ab3'))
    self.assertTrue(input_dict['input2'] == ('file2', None))
    print(input_expr_dict['input3'])
    self.assertAllClose(input_expr_dict['input3'], np.zeros([2, 2]))
    self.assertAllClose(input_expr_dict['input4'], [4, 5])
    self.assertTrue(len(input_dict) == 2)
    self.assertTrue(len(input_expr_dict) == 2)


  def testRunCommandInvalidInputKeyError(self, use_tfrt):
    self.parser = saved_model_cli.create_parser()
    base_path = test.test_src_dir_path(SAVED_MODEL_PATH)
    args = self.parser.parse_args([
        'run', '--dir', base_path, '--tag_set', 'serve', '--signature_def',
        'regress_x2_to_y3', '--input_exprs', 'x2=np.ones((3,1))'
    ] + (['--use_tfrt'] if use_tfrt else []))
    with self.assertRaises(ValueError):
      saved_model_cli.run(args)


    def test_str(self):
        code = LoginCode(user=self.user, code='foo', timestamp=datetime(2018, 7, 1))
        self.assertEqual(str(code), 'test_user - 2018-07-01 00:00:00')


    def test_request_login_code(self):
        response = self.client.post('/accounts/login/', {
            'username': self.user.username,
            'next': '/private/',
        })

        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], '/accounts/login/code/')

        login_code = LoginCode.objects.filter(user=self.user).first()

        self.assertIsNotNone(login_code)
        self.assertEqual(login_code.next, '/private/')
        self.assertEqual(len(mail.outbox), 1)
        self.assertIn(
            'http://testserver/accounts/login/code/?code={}'.format(login_code.code),
            mail.outbox[0].body,
        )


    def test_received_preq_completed_connection_close(self):
        inst, sock, map = self._makeOneWithMap()
        inst.server = DummyServer()
        preq = DummyParser()
        inst.request = preq
        preq.completed = True
        preq.empty = True
        preq.connection_close = True
        inst.received(b"GET / HTTP/1.1\n\n" + b"a" * 50000)
        self.assertEqual(inst.request, None)
        self.assertEqual(inst.server.tasks, [])


    def test_bad_host_header(self):
        # https://corte.si/posts/code/pathod/pythonservers/index.html
        to_send = "GET / HTTP/1.0\n" " Host: 0\n\n"
        to_send = tobytes(to_send)
        self.connect()
        self.sock.send(to_send)
        fp = self.sock.makefile("rb", 0)
        line, headers, response_body = read_http(fp)
        self.assertline(line, "400", "Bad Request", "HTTP/1.0")
        self.assertEqual(headers.get("server"), "waitress")
        self.assertTrue(headers.get("date"))


    def test_before_start_response_http_11(self):
        to_send = "GET /before_start_response HTTP/1.1\n\n"
        to_send = tobytes(to_send)
        self.connect()
        self.sock.send(to_send)
        fp = self.sock.makefile("rb", 0)
        line, headers, response_body = read_http(fp)
        self.assertline(line, "500", "Internal Server Error", "HTTP/1.1")
        cl = int(headers["content-length"])
        self.assertEqual(cl, len(response_body))
        self.assertTrue(response_body.startswith(b"Internal Server Error"))
        self.assertEqual(
            sorted(headers.keys()), ["connection", "content-length", "content-type", "date", "server"]
        )
        # connection has been closed
        self.send_check_error(to_send)
        self.assertRaises(ConnectionClosed, read_http, fp)


    def test_filelike_shortcl_http11(self):
        to_send = "GET /filelike_shortcl HTTP/1.1\n\n"
        to_send = tobytes(to_send)

        self.connect()

        for t in range(0, 2):
            self.sock.send(to_send)
            fp = self.sock.makefile("rb", 0)
            line, headers, response_body = read_http(fp)
            self.assertline(line, "200", "OK", "HTTP/1.1")
            cl = int(headers["content-length"])
            self.assertEqual(cl, 1)
            self.assertEqual(cl, len(response_body))
            ct = headers["content-type"]
            self.assertEqual(ct, "image/jpeg")
            self.assertTrue(b"\377" in response_body)


    def test_request_body_too_large_with_no_cl_http11_connclose(self):
        body = "a" * self.toobig
        to_send = "GET / HTTP/1.1\nConnection: close\n\n"
        to_send += body
        to_send = tobytes(to_send)
        self.connect()
        self.sock.send(to_send)
        fp = self.sock.makefile("rb", 0)
        line, headers, response_body = read_http(fp)
        # server trusts the content-length header (assumed 0)
        self.assertline(line, "200", "OK", "HTTP/1.1")
        cl = int(headers["content-length"])
        self.assertEqual(cl, len(response_body))
        # connection has been closed
        self.send_check_error(to_send)
        self.assertRaises(ConnectionClosed, read_http, fp)


    def test_keepalive_http11_explicit(self):
        # Explicitly set keep-alive
        data = "Default: Keep me alive"
        s = tobytes(
            "GET / HTTP/1.1\n"
            "Connection: keep-alive\n"
            "Content-Length: %d\n"
            "\n"
            "%s" % (len(data), data)
        )
        self.connect()
        self.sock.send(s)
        response = httplib.HTTPResponse(self.sock)
        response.begin()
        self.assertEqual(int(response.status), 200)
        self.assertTrue(response.getheader("connection") != "close")


    def testSimpleGET(self):
        data = b"""\
GET /foobar HTTP/8.4
FirstName: mickey
lastname: Mouse
content-length: 7

Hello.
"""
        parser = self.parser
        self.feed(data)
        self.assertTrue(parser.completed)
        self.assertEqual(parser.version, "8.4")
        self.assertFalse(parser.empty)
        self.assertEqual(
            parser.headers,
            {"FIRSTNAME": "mickey", "LASTNAME": "Mouse", "CONTENT_LENGTH": "7",},
        )
        self.assertEqual(parser.path, "/foobar")
        self.assertEqual(parser.command, "GET")
        self.assertEqual(parser.query, "")
        self.assertEqual(parser.proxy_scheme, "")
        self.assertEqual(parser.proxy_netloc, "")
        self.assertEqual(parser.get_body_stream().getvalue(), b"Hello.\n")


    def test_parse_header_connection_close(self):
        data = b"GET /foobar HTTP/1.1\nConnection: close\n\n"
        self.parser.parse_header(data)
        self.assertEqual(self.parser.connection_close, True)


    def test_received_bad_host_header(self):
        from waitress.utilities import BadRequest

        data = b"""\
HTTP/1.0 GET /foobar
 Host: foo

"""
        result = self.parser.received(data)
        self.assertEqual(result, 33)
        self.assertTrue(self.parser.completed)
        self.assertEqual(self.parser.error.__class__, BadRequest)


    def test_received_no_doublecr(self):
        data = b"""\
GET /foobar HTTP/8.4
"""
        result = self.parser.received(data)
        self.assertEqual(result, 21)
        self.assertFalse(self.parser.completed)
        self.assertEqual(self.parser.headers, {})


    def testSpoofedHeadersDropped(self):
        data = b"""\
GET /foobar HTTP/8.4
x-auth_user: bob
content-length: 7

Hello.
"""
        self.feed(data)
        self.assertTrue(self.parser.completed)
        self.assertEqual(self.parser.headers, {"CONTENT_LENGTH": "7",})


    def test_parse_header_gardenpath(self):
        data = b"""\
GET /foobar HTTP/8.4
foo: bar"""
        self.parser.parse_header(data)
        self.assertEqual(self.parser.first_line, b"GET /foobar HTTP/8.4")
        self.assertEqual(self.parser.headers["FOO"], "bar")


    def test_received_control_line_finished_all_chunks_received(self):
        buf = DummyBuffer()
        inst = self._makeOne(buf)
        result = inst.received(b"0;discard\n")
        self.assertEqual(inst.control_line, b"")
        self.assertEqual(inst.all_chunks_received, True)
        self.assertEqual(result, 10)
        self.assertEqual(inst.completed, False)


    def rpn(self, irc, msg, args):
        """<rpn math expression>

        Returns the value of an RPN expression.
        """
        stack = []
        for arg in args:
            try:
                x = complex(arg)
                if x == abs(x):
                    x = abs(x)
                stack.append(x)
            except ValueError: # Not a float.
                if arg in self._mathSafeEnv:
                    f = self._mathSafeEnv[arg]
                    if callable(f):
                        called = False
                        arguments = []
                        while not called and stack:
                            arguments.append(stack.pop())
                            try:
                                stack.append(f(*arguments))
                                called = True
                            except TypeError:
                                pass
                        if not called:
                            irc.error(_('Not enough arguments for %s') % arg)
                            return
                    else:
                        stack.append(f)
                elif arg in self._rpnEnv:
                    self._rpnEnv[arg](stack)
                else:
                    arg2 = stack.pop()
                    arg1 = stack.pop()
                    s = '%s%s%s' % (arg1, arg, arg2)
                    try:
                        stack.append(eval(s, self._mathSafeEnv, self._mathSafeEnv))
                    except SyntaxError:
                        irc.error(format(_('%q is not a defined function.'),
                                         arg))
                        return
        if len(stack) == 1:
            irc.reply(str(self._complexToString(complex(stack[0]))))
        else:
            s = ', '.join(map(self._complexToString, list(map(complex, stack))))
            irc.reply(_('Stack: [%s]') % s)


    def _sqrt(x):
        if isinstance(x, complex) or x < 0:
            return cmath.sqrt(x)
        else:
            return math.sqrt(x)


    def icalc(self, irc, msg, args, text):
        """<math expression>

        This is the same as the calc command except that it allows integer
        math, and can thus cause the bot to suck up CPU.  Hence it requires
        the 'trusted' capability to use.
        """
        if self._calc_match_forbidden_chars.match(text):
            # Note: this is important to keep this to forbid usage of
            # __builtins__
            irc.error(_('There\'s really no reason why you should have '
                           'underscores or brackets in your mathematical '
                           'expression.  Please remove them.'))
            return
        # This removes spaces, too, but we'll leave the removal of _[] for
        # safety's sake.
        text = self._calc_remover(text)
        if 'lambda' in text:
            irc.error(_('You can\'t use lambda in this command.'))
            return
        text = text.replace('lambda', '')
        try:
            self.log.info('evaluating %q from %s', text, msg.prefix)
            irc.reply(str(eval(text, self._mathEnv, self._mathEnv)))
        except OverflowError:
            maxFloat = math.ldexp(0.9999999999999999, 1024)
            irc.error(_('The answer exceeded %s or so.') % maxFloat)
        except TypeError:
            irc.error(_('Something in there wasn\'t a valid number.'))
        except NameError as e:
            irc.error(_('%s is not a defined function.') % str(e).split()[1])
        except Exception as e:
            irc.error(utils.exnToString(e))


def insensitive_exact(field: Term, value: str) -> Criterion:
    return Upper(field).eq(Upper(f"{value}"))


def insensitive_ends_with(field: Term, value: str) -> Criterion:
    return Upper(field).like(Upper(f"%{value}"))


def google_remote_app():
    if "google" not in oauth.remote_apps:
        oauth.remote_app(
            "google",
            base_url="https://www.google.com/accounts/",
            authorize_url="https://accounts.google.com/o/oauth2/auth?prompt=select_account+consent",
            request_token_url=None,
            request_token_params={
                "scope": "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile"
            },
            access_token_url="https://accounts.google.com/o/oauth2/token",
            access_token_method="POST",
            consumer_key=settings.GOOGLE_CLIENT_ID,
            consumer_secret=settings.GOOGLE_CLIENT_SECRET,
        )

    return oauth.google


def login():
    callback = url_for(".callback", _external=True)
    next_path = request.args.get(
        "next", url_for("redash.index", org_slug=session.get("org_slug"))
    )
    logger.debug("Callback url: %s", callback)
    logger.debug("Next is: %s", next_path)
    return google_remote_app().authorize(callback=callback, state=next_path)


def is_private_address(url):
    hostname = urlparse(url).hostname
    ip_address = socket.gethostbyname(hostname)
    return ipaddress.ip_address(text_type(ip_address)).is_private


def env() -> Environment:
    from openapi_python_client import utils

    TEMPLATE_FILTERS = {"snakecase": utils.snake_case, "spinalcase": utils.spinal_case}
    env = Environment(loader=PackageLoader("openapi_python_client"), trim_blocks=True, lstrip_blocks=True)
    env.filters.update(TEMPLATE_FILTERS)
    return env


    def get_type_string(self) -> str:
        """ Get a string representation of type that should be used when declaring this property """
        if self.required:
            return self._type_string
        return f"Optional[{self._type_string}]"


def group_title(value: str) -> str:
    value = re.sub(r"([A-Z]{2,})([A-Z][a-z]|[ -_]|$)", lambda m: m.group(1).title() + m.group(2), value.strip())
    value = re.sub(r"(^|[ _-])([A-Z])", lambda m: m.group(1) + m.group(2).lower(), value)
    return value


def escape_text(text: EscapableEntity) -> str:
    """Escape HTML text

    We only strip some tags and allow some simple tags
    such as
,  or  to be part of the string.
    This is useful for messages where we want to keep formatting
    options. (Formerly known as 'permissive_attrencode')

    Args:
        text:

    Examples:

        >>> escape_text("Hello this is dog!")
        'Hello this is dog!'

        This is lame.

        >>> escape_text("Hello this is dog!")
        'Hello this <a href=>is dog!'

    Returns:

    """
    if isinstance(text, HTML):
        return text.__html__()

    text = escape_attribute(text)
    text = _UNESCAPER_TEXT.sub(r'<\1\2>', text)
    for a_href in _A_HREF.finditer(text):
        text = text.replace(a_href.group(0), u"" % _QUOTE.sub(u"\"", a_href.group(1)))
    return text.replace(u"&nbsp;", u" ")


def task_remove(request, task_id):
    """
    remove task by task_id
    :param request:
    :return:
    """
    if request.method == 'POST':
        try:
            # delete job from DjangoJob
            task = Task.objects.get(id=task_id)
            clients = clients_of_task(task)
            for client in clients:
                job_id = get_job_id(client, task)
                DjangoJob.objects.filter(name=job_id).delete()
            # delete task
            Task.objects.filter(id=task_id).delete()
            return JsonResponse({'result': '1'})
        except:
            return JsonResponse({'result': '0'})


def load_metadata_preview(request, c_type, c_id, conn=None, share_id=None, **kwargs):
    """
    This is the image 'Preview' tab for the right-hand panel.
    """
    context = {}

    # the index of a field within a well
    index = getIntOrDefault(request, "index", 0)

    manager = BaseContainer(conn, **{str(c_type): long(c_id)})
    if share_id:
        context["share"] = BaseShare(conn, share_id)
    if c_type == "well":
        manager.image = manager.well.getImage(index)

    allRdefs = manager.image.getAllRenderingDefs()
    rdefs = {}
    rdefId = manager.image.getRenderingDefId()
    # remove duplicates per user
    for r in allRdefs:
        ownerId = r["owner"]["id"]
        r["current"] = r["id"] == rdefId
        # if duplicate rdefs for user, pick one with highest ID
        if ownerId not in rdefs or rdefs[ownerId]["id"] < r["id"]:
            rdefs[ownerId] = r
    rdefs = rdefs.values()
    # format into rdef strings,
    # E.g. {c: '1|3118:35825$FF0000,2|2086:18975$FFFF00', m: 'c'}
    rdefQueries = []
    for r in rdefs:
        chs = []
        for i, c in enumerate(r["c"]):
            act = "-"
            if c["active"]:
                act = ""
            color = c["lut"] if "lut" in c else c["color"]
            reverse = "r" if c["inverted"] else "-r"
            chs.append(
                "%s%s|%s:%s%s$%s" % (act, i + 1, c["start"], c["end"], reverse, color)
            )
        rdefQueries.append(
            {
                "id": r["id"],
                "owner": r["owner"],
                "c": ",".join(chs),
                "m": r["model"] == "greyscale" and "g" or "c",
            }
        )
    max_w, max_h = conn.getMaxPlaneSize()
    size_x = manager.image.getSizeX()
    size_y = manager.image.getSizeY()

    context["tiledImage"] = (size_x * size_y) > (max_w * max_h)
    context["manager"] = manager
    context["rdefsJson"] = json.dumps(rdefQueries)
    context["rdefs"] = rdefs
    context["template"] = "webclient/annotations/metadata_preview.html"
    return context


	def decompile(self):
		self.writeln("** Decompiling APK...", clr.OKBLUE)
		with ZipFile(self.file) as zipped:
			try:
				dex = self.tempdir + "/" + self.apk.package + ".dex"
				with open(dex, "wb") as classes:
					classes.write(zipped.read("classes.dex"))
			except Exception as e:
				sys.exit(self.writeln(str(e), clr.WARNING))
		dec = "%s %s -d %s --deobf" % (self.jadx, dex, self.tempdir)
		os.system(dec)
		return self.tempdir


    def test_it_works_with_explicit_external_host(self, app, monkeypatch):
        with app.test_request_context():
            monkeypatch.setattr('flask.request.host_url', 'http://example.com')
            result = _validate_redirect_url('http://works.com',
                                            _external_host='works.com')
            assert result is True
            monkeypatch.undo()


    def __init__(self, sourceName: str):
        self.sourceName = sourceName
        self.type = "file"
        self.content = None


    def relative(self, relativePath) -> FileInputSource:
        return FileInputSource(os.path.join(self.directory(), relativePath))


def command_dispatch(request):
    """
    Xtheme command dispatch view.

    :param request: A request
    :type request: django.http.HttpRequest
    :return: A response
    :rtype: django.http.HttpResponse
    """
    command = request.POST.get("command")
    if command:
        response = handle_command(request, command)
        if response:
            return response
    raise Problem("Error! Unknown command: `%r`" % command)


def view_configuration():
    read_column = calibre_db.session.query(db.Custom_Columns)\
        .filter(and_(db.Custom_Columns.datatype == 'bool', db.Custom_Columns.mark_for_delete == 0)).all()
    restrict_columns = calibre_db.session.query(db.Custom_Columns)\
        .filter(and_(db.Custom_Columns.datatype == 'text', db.Custom_Columns.mark_for_delete == 0)).all()
    languages = calibre_db.speaking_language()
    translations = [LC('en')] + babel.list_translations()
    return render_title_template("config_view_edit.html", conf=config, readColumns=read_column,
                                 restrictColumns=restrict_columns,
                                 languages=languages,
                                 translations=translations,
                                 title=_(u"UI Configuration"), page="uiconfig")


def edit_user(user_id):
    content = ub.session.query(ub.User).filter(ub.User.id == int(user_id)).first()  # type: ub.User
    if not content or (not config.config_anonbrowse and content.name == "Guest"):
        flash(_(u"User not found"), category="error")
        return redirect(url_for('admin.admin'))
    languages = calibre_db.speaking_language(return_all_languages=True)
    translations = babel.list_translations() + [LC('en')]
    kobo_support = feature_support['kobo'] and config.config_kobo_sync
    if request.method == "POST":
        to_save = request.form.to_dict()
        resp = _handle_edit_user(to_save, content, languages, translations, kobo_support)
        if resp:
            return resp
    return render_title_template("user_edit.html",
                                 translations=translations,
                                 languages=languages,
                                 new_user=0,
                                 content=content,
                                 config=config,
                                 registered_oauth=oauth_check,
                                 mail_configured=config.get_mail_server_configured(),
                                 kobo_support=kobo_support,
                                 title=_(u"Edit User %(nick)s", nick=content.name),
                                 page="edituser")


    def get_search_results(self, term, offset=None, order=None, limit=None, allow_show_archived=False,
                           config_read_column=False, *join):


    def setup_db(cls, config_calibre_dir, app_db_path):
        cls.dispose()

        if not config_calibre_dir:
            cls.config.invalidate()
            return False

        dbpath = os.path.join(config_calibre_dir, "metadata.db")
        if not os.path.exists(dbpath):
            cls.config.invalidate()
            return False

        try:
            cls.engine = create_engine('sqlite://',
                                       echo=False,
                                       isolation_level="SERIALIZABLE",
                                       connect_args={'check_same_thread': False},
                                       poolclass=StaticPool)
            with cls.engine.begin() as connection:
                connection.execute(text("attach database '{}' as calibre;".format(dbpath)))
                connection.execute(text("attach database '{}' as app_settings;".format(app_db_path)))

            conn = cls.engine.connect()
            # conn.text_factory = lambda b: b.decode(errors = 'ignore') possible fix for #1302
        except Exception as ex:
            cls.config.invalidate(ex)
            return False

        cls.config.db_configured = True

        if not cc_classes:
            try:
                cc = conn.execute(text("SELECT id, datatype FROM custom_columns"))
                cls.setup_db_cc_classes(cc)
            except OperationalError as e:
                log.error_or_exception(e)

        cls.session_factory = scoped_session(sessionmaker(autocommit=False,
                                                          autoflush=True,
                                                          bind=cls.engine))
        for inst in cls.instances:
            inst.initSession()

        cls._init = True
        return True


def edit_book_series_index(series_index, book):
    # Add default series_index to book
    modif_date = False
    series_index = series_index or '1'
    if not series_index.replace('.', '', 1).isdigit():
        flash(_("%(seriesindex)s is not a valid number, skipping", seriesindex=series_index), category="warning")
        return False
    if str(book.series_index) != series_index:
        book.series_index = series_index
        modif_date = True
    return modif_date


def table_xchange_author_title():
    vals = request.get_json().get('xchange')
    if vals:
        for val in vals:
            modif_date = False
            book = calibre_db.get_book(val)
            authors = book.title
            book.authors = calibre_db.order_authors([book])
            author_names = []
            for authr in book.authors:
                author_names.append(authr.name.replace('|', ','))

            title_change = handle_title_on_edit(book, " ".join(author_names))
            input_authors, authorchange, renamed = handle_author_on_edit(book, authors)
            if authorchange or title_change:
                edited_books_id = book.id
                modif_date = True

            if config.config_use_google_drive:
                gdriveutils.updateGdriveCalibreFromLocal()

            if edited_books_id:
                helper.update_dir_structure(edited_books_id, config.config_calibre_dir, input_authors[0],
                                           renamed_author=renamed)
            if modif_date:
                book.last_modified = datetime.utcnow()
            try:
                calibre_db.session.commit()
            except (OperationalError, IntegrityError) as e:
                calibre_db.session.rollback()
                log.error_or_exception("Database error: %s", e)
                return json.dumps({'success': False})

            if config.config_use_google_drive:
                gdriveutils.updateGdriveCalibreFromLocal()
        return json.dumps({'success': True})
    return ""


def merge_list_book():
    vals = request.get_json().get('Merge_books')
    to_file = list()
    if vals:
        # load all formats from target book
        to_book = calibre_db.get_book(vals[0])
        vals.pop(0)
        if to_book:
            for file in to_book.data:
                to_file.append(file.format)
            to_name = helper.get_valid_filename(to_book.title, chars=96) + ' - ' + \
                      helper.get_valid_filename(to_book.authors[0].name, chars=96)
            for book_id in vals:
                from_book = calibre_db.get_book(book_id)
                if from_book:
                    for element in from_book.data:
                        if element.format not in to_file:
                            # create new data entry with: book_id, book_format, uncompressed_size, name
                            filepath_new = os.path.normpath(os.path.join(config.config_calibre_dir,
                                                                         to_book.path,
                                                                         to_name + "." + element.format.lower()))
                            filepath_old = os.path.normpath(os.path.join(config.config_calibre_dir,
                                                                         from_book.path,
                                                                         element.name + "." + element.format.lower()))
                            copyfile(filepath_old, filepath_new)
                            to_book.data.append(db.Data(to_book.id,
                                                        element.format,
                                                        element.uncompressed_size,
                                                        to_name))
                    delete_book_from_table(from_book.id,"", True)
                    return json.dumps({'success': True})
    return ""


def table_get_custom_enum(c_id):
    ret = list()
    cc = (calibre_db.session.query(db.Custom_Columns)
              .filter(db.Custom_Columns.id == c_id)
              .filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).one_or_none())
    ret.append({'value': "", 'text': ""})
    for idx, en in enumerate(cc.get_display_dict()['enum_values']):
        ret.append({'value': en, 'text': en})
    return json.dumps(ret)


def render_edit_book(book_id):
    cc = calibre_db.session.query(db.Custom_Columns).filter(db.Custom_Columns.datatype.notin_(db.cc_exceptions)).all()
    book = calibre_db.get_filtered_book(book_id, allow_show_archived=True)
    if not book:
        flash(_(u"Oops! Selected book title is unavailable. File does not exist or is not accessible"), category="error")
        return redirect(url_for("web.index"))

    for lang in book.languages:
        lang.language_name = isoLanguages.get_language_name(get_locale(), lang.lang_code)

    book.authors = calibre_db.order_authors([book])

    author_names = []
    for authr in book.authors:
        author_names.append(authr.name.replace('|', ','))

    # Option for showing convertbook button
    valid_source_formats=list()
    allowed_conversion_formats = list()
    kepub_possible=None
    if config.config_converterpath:
        for file in book.data:
            if file.format.lower() in constants.EXTENSIONS_CONVERT_FROM:
                valid_source_formats.append(file.format.lower())
    if config.config_kepubifypath and 'epub' in [file.format.lower() for file in book.data]:
        kepub_possible = True
        if not config.config_converterpath:
            valid_source_formats.append('epub')

    # Determine what formats don't already exist
    if config.config_converterpath:
        allowed_conversion_formats = constants.EXTENSIONS_CONVERT_TO[:]
        for file in book.data:
            if file.format.lower() in allowed_conversion_formats:
                allowed_conversion_formats.remove(file.format.lower())
    if kepub_possible:
        allowed_conversion_formats.append('kepub')
    return render_title_template('book_edit.html', book=book, authors=author_names, cc=cc,
                                 title=_(u"edit metadata"), page="editbook",
                                 conversion_formats=allowed_conversion_formats,
                                 config=config,
                                 source_formats=valid_source_formats)


def update_dir_structure_gdrive(book_id, first_author, renamed_author):
    book = calibre_db.get_book(book_id)

    authordir = book.path.split('/')[0]
    titledir = book.path.split('/')[1]
    new_authordir = rename_all_authors(first_author, renamed_author, gdrive=True)
    new_titledir = get_valid_filename(book.title, chars=96) + u" (" + str(book_id) + u")"

    if titledir != new_titledir:
        gFile = gd.getFileFromEbooksFolder(os.path.dirname(book.path), titledir)
        if gFile:
            gd.moveGdriveFileRemote(gFile, new_titledir)
            book.path = book.path.split('/')[0] + u'/' + new_titledir
            gd.updateDatabaseOnEdit(gFile['id'], book.path)     # only child folder affected
        else:
            return _(u'File %(file)s not found on Google Drive', file=book.path)  # file not found

    if authordir != new_authordir and authordir not in renamed_author:
        gFile = gd.getFileFromEbooksFolder(os.path.dirname(book.path), new_titledir)
        if gFile:
            gd.moveGdriveFolderRemote(gFile, new_authordir)
            book.path = new_authordir + u'/' + book.path.split('/')[1]
            gd.updateDatabaseOnEdit(gFile['id'], book.path)
        else:
            return _(u'File %(file)s not found on Google Drive', file=authordir)  # file not found

    # change location in database to new author/title path
    book.path = os.path.join(new_authordir, new_titledir).replace('\\', '/')
    return rename_files_on_change(first_author, renamed_author, book, gdrive=True)


def uniq(inpt):
    output = []
    inpt = [ " ".join(inp.split()) for inp in inpt]
    for x in inpt:
        if x not in output:
            output.append(x)
    return output


def check_unrar(unrarLocation):
    if not unrarLocation:
        return

    if not os.path.exists(unrarLocation):
        return _('Unrar binary file not found')

    try:
        unrarLocation = [unrarLocation]
        value = process_wait(unrarLocation, pattern='UNRAR (.*) freeware')
        if value:
            version = value.group(1)
            log.debug("unrar version %s", version)

    except (OSError, UnicodeDecodeError) as err:
        log.error_or_exception(err)
        return _('Error excecuting UnRar')


def rename_all_authors(first_author, renamed_author, calibre_path="", localbook=None, gdrive=False):
    # Create new_author_dir from parameter or from database
    # Create new title_dir from database and add id
    if first_author:
        new_authordir = get_valid_filename(first_author, chars=96)
        for r in renamed_author:
            new_author = calibre_db.session.query(db.Authors).filter(db.Authors.name == r).first()
            old_author_dir = get_valid_filename(r, chars=96)
            new_author_rename_dir = get_valid_filename(new_author.name, chars=96)
            if gdrive:
                gFile = gd.getFileFromEbooksFolder(None, old_author_dir)
                if gFile:
                    gd.moveGdriveFolderRemote(gFile, new_author_rename_dir)
            else:
                if os.path.isdir(os.path.join(calibre_path, old_author_dir)):
                    try:
                        old_author_path = os.path.join(calibre_path, old_author_dir)
                        new_author_path = os.path.join(calibre_path, new_author_rename_dir)
                        shutil.move(os.path.normcase(old_author_path), os.path.normcase(new_author_path))
                    except (OSError) as ex:
                        log.error("Rename author from: %s to %s: %s", old_author_path, new_author_path, ex)
                        log.debug(ex, exc_info=True)
                        return _("Rename author from: '%(src)s' to '%(dest)s' failed with error: %(error)s",
                                 src=old_author_path, dest=new_author_path, error=str(ex))
    else:
        new_authordir = get_valid_filename(localbook.authors[0].name, chars=96)
    return new_authordir


def feed_category(book_id):
    off = request.args.get("offset") or 0
    entries, __, pagination = calibre_db.fill_indexpage((int(off) / (int(config.config_books_per_page)) + 1), 0,
                                                        db.Books,
                                                        db.Books.tags.any(db.Tags.id == book_id),
                                                        [db.Books.timestamp.desc()])
    return render_xml_template('feed.xml', entries=entries, pagination=pagination)


def feed_unread_books():
    off = request.args.get("offset") or 0
    result, pagination = render_read_books(int(off) / (int(config.config_books_per_page)) + 1, False, True)
    return render_xml_template('feed.xml', entries=result, pagination=pagination)


def render_hot_books(page, order):
    if current_user.check_visibility(constants.SIDEBAR_HOT):
        if order[1] not in ['hotasc', 'hotdesc']:
        # Unary expression comparsion only working (for this expression) in sqlalchemy 1.4+
        #if not (order[0][0].compare(func.count(ub.Downloads.book_id).desc()) or
        #        order[0][0].compare(func.count(ub.Downloads.book_id).asc())):
            order = [func.count(ub.Downloads.book_id).desc()], 'hotdesc'
        if current_user.show_detail_random():
            random = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()) \
                .order_by(func.random()).limit(config.config_random_books)
        else:
            random = false()
        off = int(int(config.config_books_per_page) * (page - 1))
        all_books = ub.session.query(ub.Downloads, func.count(ub.Downloads.book_id))\
            .order_by(*order[0]).group_by(ub.Downloads.book_id)
        hot_books = all_books.offset(off).limit(config.config_books_per_page)
        entries = list()
        for book in hot_books:
            downloadBook = calibre_db.session.query(db.Books).filter(calibre_db.common_filters()).filter(
                db.Books.id == book.Downloads.book_id).first()
            if downloadBook:
                entries.append(downloadBook)
            else:
                ub.delete_download(book.Downloads.book_id)
        numBooks = entries.__len__()
        pagination = Pagination(page, config.config_books_per_page, numBooks)
        return render_title_template('index.html', random=random, entries=entries, pagination=pagination,
                                     title=_(u"Hot Books (Most Downloaded)"), page="hot", order=order[1])
    else:
        abort(404)


def adv_search_extension(q, include_extension_inputs, exclude_extension_inputs):
    for extension in include_extension_inputs:
        q = q.filter(db.Books.data.any(db.Data.format == extension))
    for extension in exclude_extension_inputs:
        q = q.filter(not_(db.Books.data.any(db.Data.format == extension)))
    return q


def logout():
    if current_user is not None and current_user.is_authenticated:
        ub.delete_user_session(current_user.id, flask_session.get('_id',""))
        logout_user()
        if feature_support['oauth'] and (config.config_login_type == 2 or config.config_login_type == 3):
            logout_oauth_user()
    log.debug(u"User logged out")
    return redirect(url_for('web.login'))


def profile():
    languages = calibre_db.speaking_language()
    translations = babel.list_translations() + [LC('en')]
    kobo_support = feature_support['kobo'] and config.config_kobo_sync
    if feature_support['oauth'] and config.config_login_type == 2:
        oauth_status = get_oauth_status()
        local_oauth_check = oauth_check
    else:
        oauth_status = None
        local_oauth_check = {}

    if request.method == "POST":
        change_profile(kobo_support, local_oauth_check, oauth_status, translations, languages)
    return render_title_template("user_edit.html",
                                 translations=translations,
                                 profile=1,
                                 languages=languages,
                                 content=current_user,
                                 kobo_support=kobo_support,
                                 title=_(u"%(name)s's profile", name=current_user.name),
                                 page="me",
                                 registered_oauth=local_oauth_check,
                                 oauth_status=oauth_status)


def set_bookmark(book_id, book_format):
    bookmark_key = request.form["bookmark"]
    ub.session.query(ub.Bookmark).filter(and_(ub.Bookmark.user_id == int(current_user.id),
                                              ub.Bookmark.book_id == book_id,
                                              ub.Bookmark.format == book_format)).delete()
    if not bookmark_key:
        ub.session_commit()
        return "", 204

    lbookmark = ub.Bookmark(user_id=current_user.id,
                            book_id=book_id,
                            format=book_format,
                            bookmark_key=bookmark_key)
    ub.session.merge(lbookmark)
    ub.session_commit("Bookmark for user {} in book {} created".format(current_user.id, book_id))
    return "", 201


    def test_more_custom_templates(self):
        """
        Test custom templates and metadata
        Template is relative to collection-specific dir
        Add custom metadata and test its presence in custom search page
        """
        custom_search = os.path.join(self.root_dir, COLLECTIONS, 'test',
                                      'templates', 'search.html')

        # add metadata
        main(['metadata', 'test', '--set', 'some=value'])

        with open(custom_search, 'w+b') as fh:
            fh.write(b'overriden search page: ')
            fh.write(b'{{ metadata | tojson }}\n')

        # force clear of jinja env cache to reload
        self.app.rewriterapp.jinja_env.jinja_env.cache = {}

        resp = self.testapp.get('/test/')
        resp.charset = 'utf-8'
        assert resp.status_int == 200
        assert resp.content_type == 'text/html'
        assert 'overriden search page: ' in resp.text
        print(resp.text)
        assert '"some":"value"' in resp.text, resp.text


def test_unicorn_render_kwarg():
    token = Token(
        TokenType.TEXT,
        "unicorn 'tests.templatetags.test_unicorn_render.FakeComponentKwargs' test_kwarg='tested!'",
    )
    unicorn_node = unicorn(None, token)
    context = {}
    actual = unicorn_node.render(context)

    assert "->tested!<-" in actual


def create(request, topic_id):
    topic = get_object_or_404(
        Topic.objects.for_access(request.user),
        pk=topic_id)
    form = NotificationCreationForm(
        user=request.user,
        topic=topic,
        data=request.POST)

    if form.is_valid():
        form.save()
    else:
        messages.error(request, utils.render_form_errors(form))

    return redirect(request.POST.get('next', topic.get_absolute_url()))


def custom_logout(request, **kwargs):
    if not request.user.is_authenticated:
        return redirect(request.GET.get('next', reverse(settings.LOGIN_URL)))

    if request.method == 'POST':
        return _logout_view(request, **kwargs)

    return render(request, 'spirit/user/auth/logout.html')


def test_remote_static(app):
    """Test endpoint that serves files as a logged user"""
    # GIVEN a file on disk
    file = "../demo/ACC5963A1_lanes_1234_star_sorted_sj_filtered_sorted.bed.gz"

    # GIVEN a running demo app
    with app.test_client() as client:
        # GIVEN that user is logged in
        client.get(url_for("auto_login"))
        with client.session_transaction() as session:
            # GIVEN that resource file exists in user session
            session["igv_tracks"] = [file]

        # THEN the resource should be available to the user
        resp = client.get(
            url_for(
                "alignviewers.remote_static",
                file=file,
            )
        )
        assert resp.status_code == 200


def validate_and_sanitize_search_inputs(fn, instance, args, kwargs):
	kwargs.update(dict(zip(fn.__code__.co_varnames, args)))
	sanitize_searchfield(kwargs['searchfield'])
	kwargs['start'] = cint(kwargs['start'])
	kwargs['page_len'] = cint(kwargs['page_len'])

	if kwargs['doctype'] and not frappe.db.exists('DocType', kwargs['doctype']):
		return []

	return fn(**kwargs)


def new_type_to_old_type(typ: new.BasePrimitive) -> old.NodeType:
    if isinstance(typ, new.BoolDefinition):
        return old.BaseType("bool")
    if isinstance(typ, new.AddressDefinition):
        return old.BaseType("address")
    if isinstance(typ, new.InterfaceDefinition):
        return old.InterfaceType(typ._id)
    if isinstance(typ, new.BytesMDefinition):
        m = typ._length  # type: ignore
        return old.BaseType(f"bytes{m}")
    if isinstance(typ, new.BytesArrayDefinition):
        return old.ByteArrayType(typ.length)
    if isinstance(typ, new.StringDefinition):
        return old.StringType(typ.length)
    if isinstance(typ, new.DecimalDefinition):
        return old.BaseType("decimal")
    if isinstance(typ, new.SignedIntegerAbstractType):
        bits = typ._bits  # type: ignore
        return old.BaseType("int" + str(bits))
    if isinstance(typ, new.UnsignedIntegerAbstractType):
        bits = typ._bits  # type: ignore
        return old.BaseType("uint" + str(bits))
    if isinstance(typ, new.ArrayDefinition):
        return old.SArrayType(new_type_to_old_type(typ.value_type), typ.length)
    if isinstance(typ, new.DynamicArrayDefinition):
        return old.DArrayType(new_type_to_old_type(typ.value_type), typ.length)
    if isinstance(typ, new.TupleDefinition):
        return old.TupleType(typ.value_type)
    if isinstance(typ, new.StructDefinition):
        return old.StructType(
            {n: new_type_to_old_type(t) for (n, t) in typ.members.items()}, typ._id
        )
    raise InvalidType(f"unknown type {typ}")


    def __call__(self, request):
        file_fields = request.POST.getlist("s3file")
        for field_name in file_fields:
            paths = request.POST.getlist(field_name)
            request.FILES.setlist(field_name, list(self.get_files_from_storage(paths)))

        if local_dev and request.path == "/__s3_mock__/":
            return views.S3MockView.as_view()(request)

        return self.get_response(request)


    def test_process_request(self, rf):
        uploaded_file = SimpleUploadedFile("uploaded_file.txt", b"uploaded")
        request = rf.post("/", data={"file": uploaded_file})
        S3FileMiddleware(lambda x: None)(request)
        assert request.FILES.getlist("file")
        assert request.FILES.get("file").read() == b"uploaded"

        storage.save("tmp/s3file/s3_file.txt", ContentFile(b"s3file"))
        request = rf.post(
            "/",
            data={
                "file": "custom/location/tmp/s3file/s3_file.txt",
                "s3file": "file",
            },
        )
        S3FileMiddleware(lambda x: None)(request)
        assert request.FILES.getlist("file")
        assert request.FILES.get("file").read() == b"s3file"


    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {

        Integer sc = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        String msg = (String) request.getAttribute(RequestDispatcher.ERROR_MESSAGE);
        Throwable err = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);

        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        if (err != null) {
            err.printStackTrace(pw);
        } else {
            pw.println("(none)");
        }
        pw.flush();

        // If we are here there was no error servlet, so show the default error page
        String output = Launcher.RESOURCES.getString("WinstoneResponse.ErrorPage",
                new String[] { sc + "", (msg == null ? "" : msg), sw.toString(),
                Launcher.RESOURCES.getString("ServerVersion"),
                        "" + new Date() });
        response.setContentLength(output.getBytes(response.getCharacterEncoding()).length);
        Writer out = response.getWriter();
        out.write(output);
        out.flush();
    }


    private boolean exractAndLoad(ArrayList<String> errors, String version, String customPath, String resourcePath) {
        URL resource = classLoader.getResource(resourcePath);
        if( resource !=null ) {

            String libName = name + "-" + getBitModel();
            if( version !=null) {
                libName += "-" + version;
            }

            if( customPath!=null ) {
                // Try to extract it to the custom path...
                File target = file(customPath, map(libName));
                if( extract(errors, resource, target) ) {
                    if( load(errors, target) ) {
                        return true;
                    }
                }
            }

            // Fall back to extracting to the tmp dir
            customPath = System.getProperty("java.io.tmpdir");
            File target = file(customPath, map(libName));
            if( extract(errors, resource, target) ) {
                if( load(errors, target) ) {
                    return true;
                }
            }
        }
        return false;
    }


    private String getMimeType(ParsedUri pParsedUri) {
        if (pParsedUri.getParameter(ConfigKey.CALLBACK.getKeyValue()) != null) {
            return "text/javascript";
        } else {
            String mimeType = pParsedUri.getParameter(ConfigKey.MIME_TYPE.getKeyValue());
            if (mimeType != null) {
                return mimeType;
            }
            mimeType = configuration.get(ConfigKey.MIME_TYPE);
            return mimeType != null ? mimeType : ConfigKey.MIME_TYPE.getDefaultValue();
        }
    }


    public void testCallbackPost() throws URISyntaxException, IOException, java.text.ParseException {
        HttpExchange exchange = prepareExchange("http://localhost:8080/jolokia?callback=data",
                                                "Content-Type","text/plain; charset=UTF-8",
                                                "Origin",null
                                               );

        // Simple GET method
        prepareMemoryPostReadRequest(exchange);
        Headers header = new Headers();
        ByteArrayOutputStream out = prepareResponse(handler, exchange, header);

        handler.doHandle(exchange);

        assertEquals(header.getFirst("content-type"),"text/javascript; charset=utf-8");
        String result = out.toString("utf-8");
        assertTrue(result.endsWith("});"));
        assertTrue(result.startsWith("data({"));
        assertTrue(result.contains("\"used\""));

        assertEquals(header.getFirst("Cache-Control"),"no-cache");
        assertEquals(header.getFirst("Pragma"),"no-cache");
        SimpleDateFormat rfc1123Format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
        rfc1123Format.setTimeZone(TimeZone.getTimeZone("GMT"));

        String expires = header.getFirst("Expires");
        String date = header.getFirst("Date");

        Date parsedExpires = rfc1123Format.parse(expires);
        Date parsedDate = rfc1123Format.parse(date);
        assertTrue(parsedExpires.before(parsedDate) || parsedExpires.equals(parsedDate));
        Date now = new Date();
        assertTrue(parsedExpires.before(now) || parsedExpires.equals(now));
    }


    private File tempFile() throws IOException {
        String newpostfix;
        String diskFilename = getDiskFilename();
        if (diskFilename != null) {
            newpostfix = '_' + diskFilename;
        } else {
            newpostfix = getPostfix();
        }
        File tmpFile;
        if (getBaseDirectory() == null) {
            // create a temporary file
            tmpFile = File.createTempFile(getPrefix(), newpostfix);
        } else {
            tmpFile = File.createTempFile(getPrefix(), newpostfix, new File(
                    getBaseDirectory()));
        }
        if (deleteOnExit()) {
            // See https://github.com/netty/netty/issues/10351
            DeleteFileOnExitHook.add(tmpFile.getPath());
        }
        return tmpFile;
    }


    public void testRenameTo() throws Exception {
        TestHttpData test = new TestHttpData("test", UTF_8, 0);
        try {
            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
            tmpFile.deleteOnExit();
            final int totalByteCount = 4096;
            byte[] bytes = new byte[totalByteCount];
            PlatformDependent.threadLocalRandom().nextBytes(bytes);
            ByteBuf content = Unpooled.wrappedBuffer(bytes);
            test.setContent(content);
            boolean succ = test.renameTo(tmpFile);
            assertTrue(succ);
            FileInputStream fis = new FileInputStream(tmpFile);
            try {
                byte[] buf = new byte[totalByteCount];
                int count = 0;
                int offset = 0;
                int size = totalByteCount;
                while ((count = fis.read(buf, offset, size)) > 0) {
                    offset += count;
                    size -= count;
                    if (offset >= totalByteCount || size <= 0) {
                        break;
                    }
                }
                assertArrayEquals(bytes, buf);
                assertEquals(0, fis.available());
            } finally {
                fis.close();
            }
        } finally {
            //release the ByteBuf in AbstractMemoryHttpData
            test.delete();
        }
    }


    public static void beforeClass() throws IOException {
        final Random r = new Random();
        for (int i = 0; i < BYTES.length; i++) {
            BYTES[i] = (byte) r.nextInt(255);
        }

        tmp = File.createTempFile("netty-traffic", ".tmp");
        tmp.deleteOnExit();
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(tmp);
            out.write(BYTES);
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }


    public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
        if (javaVersion() >= 7) {
            if (directory == null) {
                return Files.createTempFile(prefix, suffix).toFile();
            }
            return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
        }
        if (directory == null) {
            return File.createTempFile(prefix, suffix);
        }
        File file = File.createTempFile(prefix, suffix, directory);
        // Try to adjust the perms, if this fails there is not much else we can do...
        file.setReadable(false, false);
        file.setReadable(true, true);
        return file;
    }


   protected boolean evaluate(InputSource inputSource)
   {
      try
      {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setNamespaceAware(true);
         DocumentBuilder dbuilder = factory.newDocumentBuilder();
         Document doc = dbuilder.parse(inputSource);

         //An XPath expression could return a true or false value instead of a node.
         //eval() is a better way to determine the boolean value of the exp.
         //For compliance with legacy behavior where selecting an empty node returns true,
         //selectNodeIterator is attempted in case of a failure.

         CachedXPathAPI cachedXPathAPI = new CachedXPathAPI();
         XObject result = cachedXPathAPI.eval(doc, xpath);
         if (result.bool())
            return true;
         else
         {
            NodeIterator iterator = cachedXPathAPI.selectNodeIterator(doc, xpath);
            return (iterator.nextNode() != null);
         }

      }
      catch (Throwable e)
      {
         return false;
      }
   }


    public byte[] toByteArray()
    {
		/* index || secretKeySeed || secretKeyPRF || publicSeed || root */
        int n = params.getDigestSize();
        int indexSize = (params.getHeight() + 7) / 8;
        int secretKeySize = n;
        int secretKeyPRFSize = n;
        int publicSeedSize = n;
        int rootSize = n;
        int totalSize = indexSize + secretKeySize + secretKeyPRFSize + publicSeedSize + rootSize;
        byte[] out = new byte[totalSize];
        int position = 0;
		/* copy index */
        byte[] indexBytes = XMSSUtil.toBytesBigEndian(index, indexSize);
        XMSSUtil.copyBytesAtOffset(out, indexBytes, position);
        position += indexSize;
		/* copy secretKeySeed */
        XMSSUtil.copyBytesAtOffset(out, secretKeySeed, position);
        position += secretKeySize;
		/* copy secretKeyPRF */
        XMSSUtil.copyBytesAtOffset(out, secretKeyPRF, position);
        position += secretKeyPRFSize;
		/* copy publicSeed */
        XMSSUtil.copyBytesAtOffset(out, publicSeed, position);
        position += publicSeedSize;
		/* copy root */
        XMSSUtil.copyBytesAtOffset(out, root, position);
		/* concatenate bdsState */
        byte[] bdsStateOut = null;
        try
        {
            bdsStateOut = XMSSUtil.serialize(bdsState);
        }
        catch (IOException e)
        {
            e.printStackTrace();
            throw new RuntimeException("error serializing bds state");
        }
        return Arrays.concatenate(out, bdsStateOut);
    }


    public BCXMSSPrivateKey(PrivateKeyInfo keyInfo)
        throws IOException
    {
        XMSSKeyParams keyParams = XMSSKeyParams.getInstance(keyInfo.getPrivateKeyAlgorithm().getParameters());
        this.treeDigest = keyParams.getTreeDigest().getAlgorithm();

        XMSSPrivateKey xmssPrivateKey = XMSSPrivateKey.getInstance(keyInfo.parsePrivateKey());

        try
        {
            XMSSPrivateKeyParameters.Builder keyBuilder = new XMSSPrivateKeyParameters
                .Builder(new XMSSParameters(keyParams.getHeight(), DigestUtil.getDigest(treeDigest)))
                .withIndex(xmssPrivateKey.getIndex())
                .withSecretKeySeed(xmssPrivateKey.getSecretKeySeed())
                .withSecretKeyPRF(xmssPrivateKey.getSecretKeyPRF())
                .withPublicSeed(xmssPrivateKey.getPublicSeed())
                .withRoot(xmssPrivateKey.getRoot());

            if (xmssPrivateKey.getBdsState() != null)
            {
                keyBuilder.withBDSState((BDS)XMSSUtil.deserialize(xmssPrivateKey.getBdsState()));
            }

            this.keyParams = keyBuilder.build();
        }
        catch (ClassNotFoundException e)
        {
            throw new IOException("ClassNotFoundException processing BDS state: " + e.getMessage());
        }
    }


    protected BigInteger[] derDecode(
        byte[]  encoding)
        throws IOException
    {
        ByteArrayInputStream    bIn = new ByteArrayInputStream(encoding);
        ASN1InputStream         aIn = new ASN1InputStream(bIn);
        ASN1Sequence            s = (ASN1Sequence)aIn.readObject();

        BigInteger[]            sig = new BigInteger[2];

        sig[0] = ((ASN1Integer)s.getObjectAt(0)).getValue();
        sig[1] = ((ASN1Integer)s.getObjectAt(1)).getValue();

        return sig;
    }


    protected String getExecutionPreamble()
    {
        if ( getWorkingDirectoryAsString() == null )
        {
            return null;
        }

        String dir = getWorkingDirectoryAsString();
        StringBuilder sb = new StringBuilder();
        sb.append( "cd " );

        sb.append( unifyQuotes( dir ) );
        sb.append( " && " );

        return sb.toString();
    }


    public void testPreserveSingleQuotesOnArgument()
    {
        Shell sh = newShell();

        sh.setWorkingDirectory( "/usr/bin" );
        sh.setExecutable( "chmod" );

        String[] args = { "\'some arg with spaces\'" };

        List shellCommandLine = sh.getShellCommandLine( args );

        String cli = StringUtils.join( shellCommandLine.iterator(), " " );
        System.out.println( cli );
        assertTrue( cli.endsWith( args[0] ) );
    }


	public byte[] decrypt(final JWEHeader header,
			      final Base64URL encryptedKey,
			      final Base64URL iv,
			      final Base64URL cipherText,
			      final Base64URL authTag)
		throws JOSEException {

		final JWEAlgorithm alg = header.getAlgorithm();
		final ECDH.AlgorithmMode algMode = ECDH.resolveAlgorithmMode(alg);

		critPolicy.ensureHeaderPasses(header);

		// Get ephemeral EC key
		ECKey ephemeralKey = header.getEphemeralPublicKey();

		if (ephemeralKey == null) {
			throw new JOSEException("Missing ephemeral public EC key \"epk\" JWE header parameter");
		}

		ECPublicKey ephemeralPublicKey = ephemeralKey.toECPublicKey();

		// Curve check
		ECDH.ensurePointOnCurve(ephemeralPublicKey, getPrivateKey());

		// Derive 'Z'
		SecretKey Z = ECDH.deriveSharedSecret(
			ephemeralPublicKey,
			privateKey,
			getJCAContext().getKeyEncryptionProvider());

		// Derive shared key via concat KDF
		getConcatKDF().getJCAContext().setProvider(getJCAContext().getMACProvider()); // update before concat
		SecretKey sharedKey = ECDH.deriveSharedKey(header, Z, getConcatKDF());

		final SecretKey cek;

		if (algMode.equals(ECDH.AlgorithmMode.DIRECT)) {
			cek = sharedKey;
		} else if (algMode.equals(ECDH.AlgorithmMode.KW)) {
			if (encryptedKey == null) {
				throw new JOSEException("Missing JWE encrypted key");
			}
			cek = AESKW.unwrapCEK(sharedKey, encryptedKey.decode(), getJCAContext().getKeyEncryptionProvider());
		} else {
			throw new JOSEException("Unexpected JWE ECDH algorithm mode: " + algMode);
		}

		return ContentCryptoProvider.decrypt(header, encryptedKey, iv, cipherText, authTag, cek, getJCAContext());
	}


	public static byte[] decryptWithConcatKDF(final JWEHeader header,
						  final SecretKey secretKey,
						  final Base64URL encryptedKey,
						  final Base64URL iv,
						  final Base64URL cipherText,
						  final Base64URL authTag,
						  final Provider ceProvider,
						  final Provider macProvider)
		throws JOSEException {

		byte[] epu = null;

		if (header.getCustomParam("epu") instanceof String) {

			epu = new Base64URL((String)header.getCustomParam("epu")).decode();
		}

		byte[] epv = null;

		if (header.getCustomParam("epv") instanceof String) {

			epv = new Base64URL((String)header.getCustomParam("epv")).decode();
		}

		SecretKey cekAlt = LegacyConcatKDF.generateCEK(secretKey, header.getEncryptionMethod(), epu, epv);

		final byte[] plainText = AESCBC.decrypt(cekAlt, iv.decode(), cipherText.decode(), ceProvider);

		SecretKey cik = LegacyConcatKDF.generateCIK(secretKey, header.getEncryptionMethod(), epu, epv);

		String macInput = header.toBase64URL().toString() + "." +
			encryptedKey.toString() + "." +
			iv.toString() + "." +
			cipherText.toString();

		byte[] mac = HMAC.compute(cik, macInput.getBytes(), macProvider);

		if (! ConstantTimeUtils.areEqual(authTag.decode(), mac)) {

			throw new JOSEException("HMAC integrity check failed");
		}

		return plainText;
	}


    protected DispatchHandler getDispatchHandler() {
        if (dispatchHandler == null) {
            dispatchHandler = new DispatchHandler();
        }

        return dispatchHandler;
    }


    public void setFeature(String name, boolean value) throws SAXException {
        getXMLReader().setFeature(name, value);
    }


    public void removeHandler(String path) {
        getDispatchHandler().removeHandler(path);
    }


    public Document read(InputStream in, String systemId)
            throws DocumentException {
        InputSource source = new InputSource(in);
        source.setSystemId(systemId);
        if (this.encoding != null) {
            source.setEncoding(this.encoding);
        }

        return read(source);
    }


    public void setIncludeExternalDTDDeclarations(boolean include) {
        this.includeExternalDTDDeclarations = include;
    }


    public EntityResolver getEntityResolver() {
        return entityResolver;
    }


    public SAXReader(boolean validating) {
        this.validating = validating;
    }


    public void setXMLReaderClassName(String xmlReaderClassName)
            throws SAXException {
        setXMLReader(XMLReaderFactory.createXMLReader(xmlReaderClassName));
    }


    private String getLocalePrefix(FacesContext context) {

        String localePrefix = null;

        localePrefix = context.getExternalContext().getRequestParameterMap().get("loc");

        if(localePrefix != null){
            return localePrefix;
        }

        String appBundleName = context.getApplication().getMessageBundle();
        if (null != appBundleName) {

            Locale locale = null;
            if (context.getViewRoot() != null) {
                locale = context.getViewRoot().getLocale();
            } else {
                locale = context.getApplication().getViewHandler().calculateLocale(context);
            }

                try {
                    ResourceBundle appBundle =
                          ResourceBundle.getBundle(appBundleName,
                                                   locale,
                                                   Util.getCurrentLoader(ResourceManager.class));
                    localePrefix =
                          appBundle
                                .getString(ResourceHandler.LOCALE_PREFIX);
                } catch (MissingResourceException mre) {
                    if (LOGGER.isLoggable(Level.FINEST)) {
                        LOGGER.log(Level.FINEST, "Ignoring missing resource", mre);
                    }
                }
        }
        return localePrefix;

    }


    public static void main(String[] args) {

        // Will serve all static file are under "/public" in classpath if the route isn't consumed by others routes.
        staticFileLocation("/public");

        get("/hello", (request, response) -> {
            return "Hello World!";
        });
    }


    void rawUnicode() {
        // 2- and 3-byte UTF-8
        final PathAndQuery res1 = PathAndQuery.parse("/\u00A2?\u20AC"); // ¢ and €
        assertThat(res1).isNotNull();
        assertThat(res1.path()).isEqualTo("/%C2%A2");
        assertThat(res1.query()).isEqualTo("%E2%82%AC");

        // 4-byte UTF-8
        final PathAndQuery res2 = PathAndQuery.parse("/\uD800\uDF48"); // 𐍈
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/%F0%90%8D%88");
        assertThat(res2.query()).isNull();

        // 5- and 6-byte forms are only theoretically possible, so we won't test them here.
    }


    void doubleDots() {
        assertThat(PathAndQuery.parse("/..")).isNull();
        assertThat(PathAndQuery.parse("/../")).isNull();
        assertThat(PathAndQuery.parse("/../foo")).isNull();
        assertThat(PathAndQuery.parse("/foo/..")).isNull();
        assertThat(PathAndQuery.parse("/foo/../")).isNull();
        assertThat(PathAndQuery.parse("/foo/../bar")).isNull();

        // Escaped
        assertThat(PathAndQuery.parse("/.%2e")).isNull();
        assertThat(PathAndQuery.parse("/%2E./")).isNull();
        assertThat(PathAndQuery.parse("/foo/.%2e")).isNull();
        assertThat(PathAndQuery.parse("/foo/%2E./")).isNull();

        // Not the double dots we are looking for.
        final PathAndQuery res = PathAndQuery.parse("/..a");
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/..a");
        final PathAndQuery res2 = PathAndQuery.parse("/a..");
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/a..");
    }


    void controlChars() {
        assertThat(PathAndQuery.parse("/\0")).isNull();
        assertThat(PathAndQuery.parse("/a\nb")).isNull();
        assertThat(PathAndQuery.parse("/a\u007fb")).isNull();

        // Escaped
        assertThat(PathAndQuery.parse("/%00")).isNull();
        assertThat(PathAndQuery.parse("/a%09b")).isNull();
        assertThat(PathAndQuery.parse("/a%0ab")).isNull();
        assertThat(PathAndQuery.parse("/a%0db")).isNull();
        assertThat(PathAndQuery.parse("/a%7fb")).isNull();

        // With query string
        assertThat(PathAndQuery.parse("/\0?c")).isNull();
        assertThat(PathAndQuery.parse("/a\tb?c")).isNull();
        assertThat(PathAndQuery.parse("/a\nb?c")).isNull();
        assertThat(PathAndQuery.parse("/a\rb?c")).isNull();
        assertThat(PathAndQuery.parse("/a\u007fb?c")).isNull();

        // With query string with control chars
        assertThat(PathAndQuery.parse("/?\0")).isNull();
        assertThat(PathAndQuery.parse("/?%00")).isNull();
        assertThat(PathAndQuery.parse("/?a\u007fb")).isNull();
        assertThat(PathAndQuery.parse("/?a%7Fb")).isNull();
        // However, 0x0A, 0x0D, 0x09 should be accepted in a query string.
        assertThat(PathAndQuery.parse("/?a\tb").query()).isEqualTo("a%09b");
        assertThat(PathAndQuery.parse("/?a\nb").query()).isEqualTo("a%0Ab");
        assertThat(PathAndQuery.parse("/?a\rb").query()).isEqualTo("a%0Db");
        assertThat(PathAndQuery.parse("/?a%09b").query()).isEqualTo("a%09b");
        assertThat(PathAndQuery.parse("/?a%0Ab").query()).isEqualTo("a%0Ab");
        assertThat(PathAndQuery.parse("/?a%0Db").query()).isEqualTo("a%0Db");
    }


    void space() {
        final PathAndQuery res = PathAndQuery.parse("/ ? ");
        assertThat(res).isNotNull();
        assertThat(res.path()).isEqualTo("/%20");
        assertThat(res.query()).isEqualTo("+");

        final PathAndQuery res2 = PathAndQuery.parse("/%20?%20");
        assertThat(res2).isNotNull();
        assertThat(res2.path()).isEqualTo("/%20");
        assertThat(res2.query()).isEqualTo("+");
    }


	    public String getHeader(String name) {
	        //logger.info("Ineader .. parameter .......");
	        String value = super.getHeader(name);
	        if (value == null)
	            return null;
	        //logger.info("Ineader RequestWrapper ........... value ....");
	        return cleanXSS(value);
	    }


	public String displayCategoryWithReference(@PathVariable final String friendlyUrl, @PathVariable final String ref, Model model, HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {

		return this.displayCategory(friendlyUrl,ref,model,request,response,locale);
	}


	public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset,
			byte[] ciphertext, int ciphertextOffset, int length)
			throws ShortBufferException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (!haskey) {
			// The key is not set yet - return the plaintext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
			return length;
		}
		if (space < 16 || length > (space - 16))
			throw new ShortBufferException();
		setup(ad);
		encryptCTR(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
		ghash.update(ciphertext, ciphertextOffset, length);
		ghash.pad(ad != null ? ad.length : 0, length);
		ghash.finish(ciphertext, ciphertextOffset + length, 16);
		for (int index = 0; index < 16; ++index)
			ciphertext[ciphertextOffset + length + index] ^= hashKey[index];
		return length + 16;
	}


	public int encryptWithAd(byte[] ad, byte[] plaintext, int plaintextOffset,
			byte[] ciphertext, int ciphertextOffset, int length)
			throws ShortBufferException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the plaintext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(plaintext, plaintextOffset, ciphertext, ciphertextOffset, length);
			return length;
		}
		if (space < 16 || length > (space - 16))
			throw new ShortBufferException();
		try {
			setup(ad);
			int result = cipher.update(plaintext, plaintextOffset, length, ciphertext, ciphertextOffset);
			cipher.doFinal(ciphertext, ciphertextOffset + result);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, length);
		ghash.pad(ad != null ? ad.length : 0, length);
		ghash.finish(ciphertext, ciphertextOffset + length, 16);
		for (int index = 0; index < 16; ++index)
			ciphertext[ciphertextOffset + length + index] ^= hashKey[index];
		return length + 16;
	}


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (keySpec == null) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		try {
			setup(ad);
		} catch (InvalidKeyException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (InvalidAlgorithmParameterException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		ghash.update(ciphertext, ciphertextOffset, dataLen);
		ghash.pad(ad != null ? ad.length : 0, dataLen);
		ghash.finish(iv, 0, 16);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (hashKey[index] ^ iv[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		try {
			int result = cipher.update(ciphertext, ciphertextOffset, dataLen, plaintext, plaintextOffset);
			cipher.doFinal(plaintext, plaintextOffset + result);
		} catch (IllegalBlockSizeException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		} catch (BadPaddingException e) {
			// Shouldn't happen.
			throw new IllegalStateException(e);
		}
		return dataLen;
	}


	public int decryptWithAd(byte[] ad, byte[] ciphertext,
			int ciphertextOffset, byte[] plaintext, int plaintextOffset,
			int length) throws ShortBufferException, BadPaddingException {
		int space;
		if (ciphertextOffset > ciphertext.length)
			space = 0;
		else
			space = ciphertext.length - ciphertextOffset;
		if (length > space)
			throw new ShortBufferException();
		if (plaintextOffset > plaintext.length)
			space = 0;
		else
			space = plaintext.length - plaintextOffset;
		if (!haskey) {
			// The key is not set yet - return the ciphertext as-is.
			if (length > space)
				throw new ShortBufferException();
			if (plaintext != ciphertext || plaintextOffset != ciphertextOffset)
				System.arraycopy(ciphertext, ciphertextOffset, plaintext, plaintextOffset, length);
			return length;
		}
		if (length < 16)
			Noise.throwBadTagException();
		int dataLen = length - 16;
		if (dataLen > space)
			throw new ShortBufferException();
		setup(ad);
		poly.update(ciphertext, ciphertextOffset, dataLen);
		finish(ad, dataLen);
		int temp = 0;
		for (int index = 0; index < 16; ++index)
			temp |= (polyKey[index] ^ ciphertext[ciphertextOffset + dataLen + index]);
		if ((temp & 0xFF) != 0)
			Noise.throwBadTagException();
		encrypt(ciphertext, ciphertextOffset, plaintext, plaintextOffset, dataLen);
		return dataLen;
	}


    static XmlSchema createSchemaInstance(ThreadContext context, RubyClass klazz, Source source) {
        Ruby runtime = context.getRuntime();
        XmlSchema xmlSchema = (XmlSchema) NokogiriService.XML_SCHEMA_ALLOCATOR.allocate(runtime, klazz);
        xmlSchema.setInstanceVariable("@errors", runtime.newEmptyArray());

        try {
            SchemaErrorHandler error_handler = new SchemaErrorHandler(context.getRuntime(), (RubyArray)xmlSchema.getInstanceVariable("@errors"));
            Schema schema = xmlSchema.getSchema(source, context.getRuntime().getCurrentDirectory(), context.getRuntime().getInstanceConfig().getScriptFileName(), error_handler);
            xmlSchema.setValidator(schema.newValidator());
            return xmlSchema;
        } catch (SAXException ex) {
            throw context.getRuntime().newRuntimeError("Could not parse document: " + ex.getMessage());
        }
    }


    public DefaultFileSystemResourceLoader() {
        this.baseDirPath = Optional.empty();
    }