mirror of
https://github.com/aaPanel/aaPanel.git
synced 2026-08-17 21:25:47 +02:00
v6.8.4
1. After the update, the software and panel directory permissions will be set to strict mode (it will be restored automatically after modification) 2. Increase the panel comprehensive anti-riot mechanism 3. Enhance the security of the panel session<br> 4. Enhanced panel entry verification mechanism 5. Optimize the terminal 6. Optimize the panel memory release mechanism Note 1: Version 6.8.2/6.9.11 has security issues, please be sure to upgrade to the latest version Note 2: After this update is successful, it will automatically log out and you need to log in again
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from cachelib.base import BaseCache, NullCache
|
||||
from cachelib.simple import SimpleCache
|
||||
from cachelib.file import FileSystemCache
|
||||
from cachelib.memcached import MemcachedCache
|
||||
from cachelib.redis import RedisCache
|
||||
from cachelib.uwsgi import UWSGICache
|
||||
|
||||
__all__ = [
|
||||
'BaseCache',
|
||||
'NullCache',
|
||||
'SimpleCache',
|
||||
'FileSystemCache',
|
||||
'MemcachedCache',
|
||||
'RedisCache',
|
||||
'UWSGICache',
|
||||
]
|
||||
|
||||
__version__ = '0.1'
|
||||
__author__ = 'Pallets Team'
|
||||
@@ -0,0 +1,26 @@
|
||||
# flake8: noqa
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
|
||||
if PY2:
|
||||
text_type = unicode
|
||||
string_types = (str, unicode)
|
||||
integer_types = (int, long)
|
||||
iteritems = lambda d, *args, **kwargs: d.iteritems(*args, **kwargs)
|
||||
|
||||
def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
|
||||
if x is None or isinstance(x, str):
|
||||
return x
|
||||
return x.encode(charset, errors)
|
||||
|
||||
else:
|
||||
text_type = str
|
||||
string_types = (str, )
|
||||
integer_types = (int, )
|
||||
iteritems = lambda d, *args, **kwargs: iter(d.items(*args, **kwargs))
|
||||
|
||||
def to_native(x, charset=sys.getdefaultencoding(), errors='strict'):
|
||||
if x is None or isinstance(x, str):
|
||||
return x
|
||||
return x.decode(charset, errors)
|
||||
@@ -0,0 +1,198 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from cachelib._compat import iteritems
|
||||
|
||||
|
||||
def _items(mappingorseq):
|
||||
"""Wrapper for efficient iteration over mappings represented by dicts
|
||||
or sequences::
|
||||
|
||||
>>> for k, v in _items((i, i*i) for i in xrange(5)):
|
||||
... assert k*k == v
|
||||
|
||||
>>> for k, v in _items(dict((i, i*i) for i in xrange(5))):
|
||||
... assert k*k == v
|
||||
|
||||
"""
|
||||
if hasattr(mappingorseq, 'items'):
|
||||
return iteritems(mappingorseq)
|
||||
return mappingorseq
|
||||
|
||||
|
||||
class BaseCache(object):
|
||||
|
||||
"""Baseclass for the cache systems. All the cache systems implement this
|
||||
API or a superset of it.
|
||||
|
||||
:param default_timeout: the default timeout (in seconds) that is used if
|
||||
no timeout is specified on :meth:`set`. A timeout
|
||||
of 0 indicates that the cache never expires.
|
||||
"""
|
||||
|
||||
def __init__(self, default_timeout=300):
|
||||
self.default_timeout = default_timeout
|
||||
|
||||
def _normalize_timeout(self, timeout):
|
||||
if timeout is None:
|
||||
timeout = self.default_timeout
|
||||
return timeout
|
||||
|
||||
def get(self, key):
|
||||
"""Look up key in the cache and return the value for it.
|
||||
|
||||
:param key: the key to be looked up.
|
||||
:returns: The value if it exists and is readable, else ``None``.
|
||||
"""
|
||||
return None
|
||||
|
||||
def delete(self, key):
|
||||
"""Delete `key` from the cache.
|
||||
|
||||
:param key: the key to delete.
|
||||
:returns: Whether the key existed and has been deleted.
|
||||
:rtype: boolean
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_many(self, *keys):
|
||||
"""Returns a list of values for the given keys.
|
||||
For each key an item in the list is created::
|
||||
|
||||
foo, bar = cache.get_many("foo", "bar")
|
||||
|
||||
Has the same error handling as :meth:`get`.
|
||||
|
||||
:param keys: The function accepts multiple keys as positional
|
||||
arguments.
|
||||
"""
|
||||
return [self.get(k) for k in keys]
|
||||
|
||||
def get_dict(self, *keys):
|
||||
"""Like :meth:`get_many` but return a dict::
|
||||
|
||||
d = cache.get_dict("foo", "bar")
|
||||
foo = d["foo"]
|
||||
bar = d["bar"]
|
||||
|
||||
:param keys: The function accepts multiple keys as positional
|
||||
arguments.
|
||||
"""
|
||||
return dict(zip(keys, self.get_many(*keys)))
|
||||
|
||||
def set(self, key, value, timeout=None):
|
||||
"""Add a new key/value to the cache (overwrites value, if key already
|
||||
exists in the cache).
|
||||
|
||||
:param key: the key to set
|
||||
:param value: the value for the key
|
||||
:param timeout: the cache timeout for the key in seconds (if not
|
||||
specified, it uses the default timeout). A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:returns: ``True`` if key has been updated, ``False`` for backend
|
||||
errors. Pickling errors, however, will raise a subclass of
|
||||
``pickle.PickleError``.
|
||||
:rtype: boolean
|
||||
"""
|
||||
return True
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
"""Works like :meth:`set` but does not overwrite the values of already
|
||||
existing keys.
|
||||
|
||||
:param key: the key to set
|
||||
:param value: the value for the key
|
||||
:param timeout: the cache timeout for the key in seconds (if not
|
||||
specified, it uses the default timeout). A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:returns: Same as :meth:`set`, but also ``False`` for already
|
||||
existing keys.
|
||||
:rtype: boolean
|
||||
"""
|
||||
return True
|
||||
|
||||
def set_many(self, mapping, timeout=None):
|
||||
"""Sets multiple keys and values from a mapping.
|
||||
|
||||
:param mapping: a mapping with the keys/values to set.
|
||||
:param timeout: the cache timeout for the key in seconds (if not
|
||||
specified, it uses the default timeout). A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:returns: Whether all given keys have been set.
|
||||
:rtype: boolean
|
||||
"""
|
||||
rv = True
|
||||
for key, value in _items(mapping):
|
||||
if not self.set(key, value, timeout):
|
||||
rv = False
|
||||
return rv
|
||||
|
||||
def delete_many(self, *keys):
|
||||
"""Deletes multiple keys at once.
|
||||
|
||||
:param keys: The function accepts multiple keys as positional
|
||||
arguments.
|
||||
:returns: Whether all given keys have been deleted.
|
||||
:rtype: boolean
|
||||
"""
|
||||
return all(self.delete(key) for key in keys)
|
||||
|
||||
def has(self, key):
|
||||
"""Checks if a key exists in the cache without returning it. This is a
|
||||
cheap operation that bypasses loading the actual data on the backend.
|
||||
|
||||
This method is optional and may not be implemented on all caches.
|
||||
|
||||
:param key: the key to check
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
'%s doesn\'t have an efficient implementation of `has`. That '
|
||||
'means it is impossible to check whether a key exists without '
|
||||
'fully loading the key\'s data. Consider using `self.get` '
|
||||
'explicitly if you don\'t care about performance.'
|
||||
)
|
||||
|
||||
def clear(self):
|
||||
"""Clears the cache. Keep in mind that not all caches support
|
||||
completely clearing the cache.
|
||||
|
||||
:returns: Whether the cache has been cleared.
|
||||
:rtype: boolean
|
||||
"""
|
||||
return True
|
||||
|
||||
def inc(self, key, delta=1):
|
||||
"""Increments the value of a key by `delta`. If the key does
|
||||
not yet exist it is initialized with `delta`.
|
||||
|
||||
For supporting caches this is an atomic operation.
|
||||
|
||||
:param key: the key to increment.
|
||||
:param delta: the delta to add.
|
||||
:returns: The new value or ``None`` for backend errors.
|
||||
"""
|
||||
value = (self.get(key) or 0) + delta
|
||||
return value if self.set(key, value) else None
|
||||
|
||||
def dec(self, key, delta=1):
|
||||
"""Decrements the value of a key by `delta`. If the key does
|
||||
not yet exist it is initialized with `-delta`.
|
||||
|
||||
For supporting caches this is an atomic operation.
|
||||
|
||||
:param key: the key to increment.
|
||||
:param delta: the delta to subtract.
|
||||
:returns: The new value or `None` for backend errors.
|
||||
"""
|
||||
value = (self.get(key) or 0) - delta
|
||||
return value if self.set(key, value) else None
|
||||
|
||||
|
||||
class NullCache(BaseCache):
|
||||
|
||||
"""A cache that doesn't cache. This can be useful for unit testing.
|
||||
|
||||
:param default_timeout: a dummy parameter that is ignored but exists
|
||||
for API compatibility with other caches.
|
||||
"""
|
||||
|
||||
def has(self, key):
|
||||
return False
|
||||
@@ -0,0 +1,190 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import errno
|
||||
import tempfile
|
||||
from hashlib import md5
|
||||
from time import time
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError: # pragma: no cover
|
||||
import pickle
|
||||
|
||||
from cachelib.base import BaseCache
|
||||
from cachelib._compat import text_type
|
||||
|
||||
|
||||
class FileSystemCache(BaseCache):
|
||||
|
||||
"""A cache that stores the items on the file system. This cache depends
|
||||
on being the only user of the `cache_dir`. Make absolutely sure that
|
||||
nobody but this cache stores files there or otherwise the cache will
|
||||
randomly delete files therein.
|
||||
|
||||
:param cache_dir: the directory where cache files are stored.
|
||||
:param threshold: the maximum number of items the cache stores before
|
||||
it starts deleting some. A threshold value of 0
|
||||
indicates no threshold.
|
||||
:param default_timeout: the default timeout that is used if no timeout is
|
||||
specified on :meth:`~BaseCache.set`. A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:param mode: the file mode wanted for the cache files, default 0600
|
||||
"""
|
||||
|
||||
#: used for temporary files by the FileSystemCache
|
||||
_fs_transaction_suffix = '.__wz_cache'
|
||||
#: keep amount of files in a cache element
|
||||
_fs_count_file = '__wz_cache_count'
|
||||
|
||||
def __init__(self, cache_dir, threshold=500, default_timeout=300,
|
||||
mode=0o600):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
self._path = cache_dir
|
||||
self._threshold = threshold
|
||||
self._mode = mode
|
||||
|
||||
try:
|
||||
os.makedirs(self._path)
|
||||
except OSError as ex:
|
||||
if ex.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
# If there are many files and a zero threshold,
|
||||
# the list_dir can slow initialisation massively
|
||||
if self._threshold != 0:
|
||||
self._update_count(value=len(self._list_dir()))
|
||||
|
||||
@property
|
||||
def _file_count(self):
|
||||
return self.get(self._fs_count_file) or 0
|
||||
|
||||
def _update_count(self, delta=None, value=None):
|
||||
# If we have no threshold, don't count files
|
||||
if self._threshold == 0:
|
||||
return
|
||||
|
||||
if delta:
|
||||
new_count = self._file_count + delta
|
||||
else:
|
||||
new_count = value or 0
|
||||
self.set(self._fs_count_file, new_count, mgmt_element=True)
|
||||
|
||||
def _normalize_timeout(self, timeout):
|
||||
timeout = BaseCache._normalize_timeout(self, timeout)
|
||||
if timeout != 0:
|
||||
timeout = time() + timeout
|
||||
return int(timeout)
|
||||
|
||||
def _list_dir(self):
|
||||
"""return a list of (fully qualified) cache filenames
|
||||
"""
|
||||
mgmt_files = [self._get_filename(name).split('/')[-1]
|
||||
for name in (self._fs_count_file,)]
|
||||
return [os.path.join(self._path, fn) for fn in os.listdir(self._path)
|
||||
if not fn.endswith(self._fs_transaction_suffix)
|
||||
and fn not in mgmt_files]
|
||||
|
||||
def _prune(self):
|
||||
if self._threshold == 0 or not self._file_count > self._threshold:
|
||||
return
|
||||
|
||||
entries = self._list_dir()
|
||||
now = time()
|
||||
for idx, fname in enumerate(entries):
|
||||
try:
|
||||
remove = False
|
||||
with open(fname, 'rb') as f:
|
||||
expires = pickle.load(f)
|
||||
remove = (expires != 0 and expires <= now) or idx % 3 == 0
|
||||
|
||||
if remove:
|
||||
os.remove(fname)
|
||||
except (IOError, OSError):
|
||||
pass
|
||||
self._update_count(value=len(self._list_dir()))
|
||||
|
||||
def clear(self):
|
||||
for fname in self._list_dir():
|
||||
try:
|
||||
os.remove(fname)
|
||||
except (IOError, OSError):
|
||||
self._update_count(value=len(self._list_dir()))
|
||||
return False
|
||||
self._update_count(value=0)
|
||||
return True
|
||||
|
||||
def _get_filename(self, key):
|
||||
if isinstance(key, text_type):
|
||||
key = key.encode('utf-8') # XXX unicode review
|
||||
hash = md5(key).hexdigest()
|
||||
return os.path.join(self._path, hash)
|
||||
|
||||
def get(self, key):
|
||||
filename = self._get_filename(key)
|
||||
try:
|
||||
with open(filename, 'rb') as f:
|
||||
pickle_time = pickle.load(f)
|
||||
if pickle_time == 0 or pickle_time >= time():
|
||||
return pickle.load(f)
|
||||
else:
|
||||
os.remove(filename)
|
||||
return None
|
||||
except (IOError, OSError, pickle.PickleError):
|
||||
return None
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
filename = self._get_filename(key)
|
||||
if not os.path.exists(filename):
|
||||
return self.set(key, value, timeout)
|
||||
return False
|
||||
|
||||
def set(self, key, value, timeout=None, mgmt_element=False):
|
||||
# Management elements have no timeout
|
||||
if mgmt_element:
|
||||
timeout = 0
|
||||
|
||||
# Don't prune on management element update, to avoid loop
|
||||
else:
|
||||
self._prune()
|
||||
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
filename = self._get_filename(key)
|
||||
try:
|
||||
fd, tmp = tempfile.mkstemp(suffix=self._fs_transaction_suffix,
|
||||
dir=self._path)
|
||||
with os.fdopen(fd, 'wb') as f:
|
||||
pickle.dump(timeout, f, 1)
|
||||
pickle.dump(value, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
os.rename(tmp, filename)
|
||||
os.chmod(filename, self._mode)
|
||||
except (IOError, OSError):
|
||||
return False
|
||||
else:
|
||||
# Management elements should not count towards threshold
|
||||
if not mgmt_element:
|
||||
self._update_count(delta=1)
|
||||
return True
|
||||
|
||||
def delete(self, key, mgmt_element=False):
|
||||
try:
|
||||
os.remove(self._get_filename(key))
|
||||
except (IOError, OSError):
|
||||
return False
|
||||
else:
|
||||
# Management elements should not count towards threshold
|
||||
if not mgmt_element:
|
||||
self._update_count(delta=-1)
|
||||
return True
|
||||
|
||||
def has(self, key):
|
||||
filename = self._get_filename(key)
|
||||
try:
|
||||
with open(filename, 'rb') as f:
|
||||
pickle_time = pickle.load(f)
|
||||
if pickle_time == 0 or pickle_time >= time():
|
||||
return True
|
||||
else:
|
||||
os.remove(filename)
|
||||
return False
|
||||
except (IOError, OSError, pickle.PickleError):
|
||||
return False
|
||||
@@ -0,0 +1,186 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import re
|
||||
from time import time
|
||||
from cachelib._compat import iteritems, to_native
|
||||
from cachelib.base import BaseCache, _items
|
||||
|
||||
|
||||
_test_memcached_key = re.compile(r'[^\x00-\x21\xff]{1,250}$').match
|
||||
|
||||
|
||||
class MemcachedCache(BaseCache):
|
||||
|
||||
"""A cache that uses memcached as backend.
|
||||
|
||||
The first argument can either be an object that resembles the API of a
|
||||
:class:`memcache.Client` or a tuple/list of server addresses. In the
|
||||
event that a tuple/list is passed, Werkzeug tries to import the best
|
||||
available memcache library.
|
||||
|
||||
This cache looks into the following packages/modules to find bindings for
|
||||
memcached:
|
||||
|
||||
- ``pylibmc``
|
||||
- ``google.appengine.api.memcached``
|
||||
- ``memcached``
|
||||
- ``libmc``
|
||||
|
||||
Implementation notes: This cache backend works around some limitations in
|
||||
memcached to simplify the interface. For example unicode keys are encoded
|
||||
to utf-8 on the fly. Methods such as :meth:`~BaseCache.get_dict` return
|
||||
the keys in the same format as passed. Furthermore all get methods
|
||||
silently ignore key errors to not cause problems when untrusted user data
|
||||
is passed to the get methods which is often the case in web applications.
|
||||
|
||||
:param servers: a list or tuple of server addresses or alternatively
|
||||
a :class:`memcache.Client` or a compatible client.
|
||||
:param default_timeout: the default timeout that is used if no timeout is
|
||||
specified on :meth:`~BaseCache.set`. A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:param key_prefix: a prefix that is added before all keys. This makes it
|
||||
possible to use the same memcached server for different
|
||||
applications. Keep in mind that
|
||||
:meth:`~BaseCache.clear` will also clear keys with a
|
||||
different prefix.
|
||||
"""
|
||||
|
||||
def __init__(self, servers=None, default_timeout=300, key_prefix=None):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
if servers is None or isinstance(servers, (list, tuple)):
|
||||
if servers is None:
|
||||
servers = ['127.0.0.1:11211']
|
||||
self._client = self.import_preferred_memcache_lib(servers)
|
||||
if self._client is None:
|
||||
raise RuntimeError('no memcache module found')
|
||||
else:
|
||||
# NOTE: servers is actually an already initialized memcache
|
||||
# client.
|
||||
self._client = servers
|
||||
|
||||
self.key_prefix = to_native(key_prefix)
|
||||
|
||||
def _normalize_key(self, key):
|
||||
key = to_native(key, 'utf-8')
|
||||
if self.key_prefix:
|
||||
key = self.key_prefix + key
|
||||
return key
|
||||
|
||||
def _normalize_timeout(self, timeout):
|
||||
timeout = BaseCache._normalize_timeout(self, timeout)
|
||||
if timeout > 0:
|
||||
timeout = int(time()) + timeout
|
||||
return timeout
|
||||
|
||||
def get(self, key):
|
||||
key = self._normalize_key(key)
|
||||
# memcached doesn't support keys longer than that. Because often
|
||||
# checks for so long keys can occur because it's tested from user
|
||||
# submitted data etc we fail silently for getting.
|
||||
if _test_memcached_key(key):
|
||||
return self._client.get(key)
|
||||
|
||||
def get_dict(self, *keys):
|
||||
key_mapping = {}
|
||||
have_encoded_keys = False
|
||||
for key in keys:
|
||||
encoded_key = self._normalize_key(key)
|
||||
if not isinstance(key, str):
|
||||
have_encoded_keys = True
|
||||
if _test_memcached_key(key):
|
||||
key_mapping[encoded_key] = key
|
||||
_keys = list(key_mapping)
|
||||
d = rv = self._client.get_multi(_keys)
|
||||
if have_encoded_keys or self.key_prefix:
|
||||
rv = {}
|
||||
for key, value in iteritems(d):
|
||||
rv[key_mapping[key]] = value
|
||||
if len(rv) < len(keys):
|
||||
for key in keys:
|
||||
if key not in rv:
|
||||
rv[key] = None
|
||||
return rv
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
key = self._normalize_key(key)
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
return self._client.add(key, value, timeout)
|
||||
|
||||
def set(self, key, value, timeout=None):
|
||||
key = self._normalize_key(key)
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
return self._client.set(key, value, timeout)
|
||||
|
||||
def get_many(self, *keys):
|
||||
d = self.get_dict(*keys)
|
||||
return [d[key] for key in keys]
|
||||
|
||||
def set_many(self, mapping, timeout=None):
|
||||
new_mapping = {}
|
||||
for key, value in _items(mapping):
|
||||
key = self._normalize_key(key)
|
||||
new_mapping[key] = value
|
||||
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
failed_keys = self._client.set_multi(new_mapping, timeout)
|
||||
return not failed_keys
|
||||
|
||||
def delete(self, key):
|
||||
key = self._normalize_key(key)
|
||||
if _test_memcached_key(key):
|
||||
return self._client.delete(key)
|
||||
|
||||
def delete_many(self, *keys):
|
||||
new_keys = []
|
||||
for key in keys:
|
||||
key = self._normalize_key(key)
|
||||
if _test_memcached_key(key):
|
||||
new_keys.append(key)
|
||||
return self._client.delete_multi(new_keys)
|
||||
|
||||
def has(self, key):
|
||||
key = self._normalize_key(key)
|
||||
if _test_memcached_key(key):
|
||||
return self._client.append(key, '')
|
||||
return False
|
||||
|
||||
def clear(self):
|
||||
return self._client.flush_all()
|
||||
|
||||
def inc(self, key, delta=1):
|
||||
key = self._normalize_key(key)
|
||||
return self._client.incr(key, delta)
|
||||
|
||||
def dec(self, key, delta=1):
|
||||
key = self._normalize_key(key)
|
||||
return self._client.decr(key, delta)
|
||||
|
||||
def import_preferred_memcache_lib(self, servers):
|
||||
"""Returns an initialized memcache client. Used by the constructor."""
|
||||
try:
|
||||
import pylibmc
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
return pylibmc.Client(servers)
|
||||
|
||||
try:
|
||||
from google.appengine.api import memcache
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
return memcache.Client()
|
||||
|
||||
try:
|
||||
import memcache
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
return memcache.Client(servers)
|
||||
|
||||
try:
|
||||
import libmc
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
return libmc.Client(servers)
|
||||
@@ -0,0 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError: # pragma: no cover
|
||||
import pickle
|
||||
|
||||
from cachelib.base import BaseCache, _items
|
||||
from cachelib._compat import string_types, integer_types
|
||||
|
||||
|
||||
class RedisCache(BaseCache):
|
||||
"""Uses the Redis key-value store as a cache backend.
|
||||
|
||||
The first argument can be either a string denoting address of the Redis
|
||||
server or an object resembling an instance of a redis.Redis class.
|
||||
|
||||
Note: Python Redis API already takes care of encoding unicode strings on
|
||||
the fly.
|
||||
|
||||
:param host: address of the Redis server or an object which API is
|
||||
compatible with the official Python Redis client (redis-py).
|
||||
:param port: port number on which Redis server listens for connections.
|
||||
:param password: password authentication for the Redis server.
|
||||
:param db: db (zero-based numeric index) on Redis Server to connect.
|
||||
:param default_timeout: the default timeout that is used if no timeout is
|
||||
specified on :meth:`~BaseCache.set`. A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
:param key_prefix: A prefix that should be added to all keys.
|
||||
|
||||
Any additional keyword arguments will be passed to ``redis.Redis``.
|
||||
"""
|
||||
|
||||
def __init__(self, host='localhost', port=6379, password=None,
|
||||
db=0, default_timeout=300, key_prefix=None, **kwargs):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
if host is None:
|
||||
raise ValueError('RedisCache host parameter may not be None')
|
||||
if isinstance(host, string_types):
|
||||
try:
|
||||
import redis
|
||||
except ImportError:
|
||||
raise RuntimeError('no redis module found')
|
||||
if kwargs.get('decode_responses', None):
|
||||
raise ValueError('decode_responses is not supported by '
|
||||
'RedisCache.')
|
||||
self._client = redis.Redis(host=host, port=port, password=password,
|
||||
db=db, **kwargs)
|
||||
else:
|
||||
self._client = host
|
||||
self.key_prefix = key_prefix or ''
|
||||
|
||||
def _normalize_timeout(self, timeout):
|
||||
timeout = BaseCache._normalize_timeout(self, timeout)
|
||||
if timeout == 0:
|
||||
timeout = -1
|
||||
return timeout
|
||||
|
||||
def dump_object(self, value):
|
||||
"""Dumps an object into a string for redis. By default it serializes
|
||||
integers as regular string and pickle dumps everything else.
|
||||
"""
|
||||
t = type(value)
|
||||
if t in integer_types:
|
||||
return str(value).encode('ascii')
|
||||
return b'!' + pickle.dumps(value)
|
||||
|
||||
def load_object(self, value):
|
||||
"""The reversal of :meth:`dump_object`. This might be called with
|
||||
None.
|
||||
"""
|
||||
if value is None:
|
||||
return None
|
||||
if value.startswith(b'!'):
|
||||
try:
|
||||
return pickle.loads(value[1:])
|
||||
except pickle.PickleError:
|
||||
return None
|
||||
try:
|
||||
return int(value)
|
||||
except ValueError:
|
||||
# before 0.8 we did not have serialization. Still support that.
|
||||
return value
|
||||
|
||||
def get(self, key):
|
||||
return self.load_object(self._client.get(self.key_prefix + key))
|
||||
|
||||
def get_many(self, *keys):
|
||||
if self.key_prefix:
|
||||
keys = [self.key_prefix + key for key in keys]
|
||||
return [self.load_object(x) for x in self._client.mget(keys)]
|
||||
|
||||
def set(self, key, value, timeout=None):
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
dump = self.dump_object(value)
|
||||
if timeout == -1:
|
||||
result = self._client.set(name=self.key_prefix + key,
|
||||
value=dump)
|
||||
else:
|
||||
result = self._client.setex(name=self.key_prefix + key,
|
||||
value=dump, time=timeout)
|
||||
return result
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
dump = self.dump_object(value)
|
||||
return (
|
||||
self._client.setnx(name=self.key_prefix + key, value=dump) and
|
||||
self._client.expire(name=self.key_prefix + key, time=timeout)
|
||||
)
|
||||
|
||||
def set_many(self, mapping, timeout=None):
|
||||
timeout = self._normalize_timeout(timeout)
|
||||
# Use transaction=False to batch without calling redis MULTI
|
||||
# which is not supported by twemproxy
|
||||
pipe = self._client.pipeline(transaction=False)
|
||||
|
||||
for key, value in _items(mapping):
|
||||
dump = self.dump_object(value)
|
||||
if timeout == -1:
|
||||
pipe.set(name=self.key_prefix + key, value=dump)
|
||||
else:
|
||||
pipe.setex(name=self.key_prefix + key, value=dump,
|
||||
time=timeout)
|
||||
return pipe.execute()
|
||||
|
||||
def delete(self, key):
|
||||
return self._client.delete(self.key_prefix + key)
|
||||
|
||||
def delete_many(self, *keys):
|
||||
if not keys:
|
||||
return
|
||||
if self.key_prefix:
|
||||
keys = [self.key_prefix + key for key in keys]
|
||||
return self._client.delete(*keys)
|
||||
|
||||
def has(self, key):
|
||||
return self._client.exists(self.key_prefix + key)
|
||||
|
||||
def clear(self):
|
||||
status = False
|
||||
if self.key_prefix:
|
||||
keys = self._client.keys(self.key_prefix + '*')
|
||||
if keys:
|
||||
status = self._client.delete(*keys)
|
||||
else:
|
||||
status = self._client.flushdb()
|
||||
return status
|
||||
|
||||
def inc(self, key, delta=1):
|
||||
return self._client.incr(name=self.key_prefix + key, amount=delta)
|
||||
|
||||
def dec(self, key, delta=1):
|
||||
return self._client.decr(name=self.key_prefix + key, amount=delta)
|
||||
@@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from time import time
|
||||
import os,struct
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError: # pragma: no cover
|
||||
import pickle
|
||||
|
||||
from cachelib.base import BaseCache
|
||||
|
||||
|
||||
class SimpleCache(BaseCache):
|
||||
|
||||
"""Simple memory cache for single process environments. This class exists
|
||||
mainly for the development server and is not 100% thread safe. It tries
|
||||
to use as many atomic operations as possible and no locks for simplicity
|
||||
but it could happen under heavy load that keys are added multiple times.
|
||||
|
||||
:param threshold: the maximum number of items the cache stores before
|
||||
it starts deleting some.
|
||||
:param default_timeout: the default timeout that is used if no timeout is
|
||||
specified on :meth:`~BaseCache.set`. A timeout of
|
||||
0 indicates that the cache never expires.
|
||||
"""
|
||||
__session_key = 'BT_:'
|
||||
__session_basedir = '/www/server/panel/data/session'
|
||||
|
||||
def __init__(self, threshold=500, default_timeout=300):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
self._cache = {}
|
||||
self.clear = self._cache.clear
|
||||
self._threshold = threshold
|
||||
|
||||
def _prune(self):
|
||||
if len(self._cache) > self._threshold:
|
||||
now = time()
|
||||
toremove = []
|
||||
for idx, (key, (expires, _)) in enumerate(self._cache.items()):
|
||||
if (expires != 0 and expires <= now) or idx % 3 == 0:
|
||||
toremove.append(key)
|
||||
for key in toremove:
|
||||
self._cache.pop(key, None)
|
||||
|
||||
|
||||
def _normalize_timeout(self, timeout):
|
||||
timeout = BaseCache._normalize_timeout(self, timeout)
|
||||
if timeout > 0:
|
||||
timeout = time() + timeout
|
||||
return timeout
|
||||
|
||||
def get(self, key):
|
||||
try:
|
||||
|
||||
expires, value = self._cache[key]
|
||||
if expires == 0 or expires > time():
|
||||
return pickle.loads(value)
|
||||
|
||||
except (KeyError, pickle.PickleError):
|
||||
try:
|
||||
if key[:4] == self.__session_key:
|
||||
filename = '/'.join((self.__session_basedir,self.md5(key)))
|
||||
if not os.path.exists(filename): return None
|
||||
|
||||
with open(filename, 'rb') as fp:
|
||||
_val = fp.read()
|
||||
fp.close()
|
||||
|
||||
expires = struct.unpack('f',_val[:4])[0]
|
||||
if expires == 0 or expires > time():
|
||||
value = _val[4:]
|
||||
|
||||
self._cache[key] = (expires,value)
|
||||
return pickle.loads(value)
|
||||
except :pass
|
||||
return None
|
||||
|
||||
def set(self, key, value, timeout=None):
|
||||
|
||||
expires = self._normalize_timeout(timeout)
|
||||
self._prune()
|
||||
|
||||
_val = pickle.dumps(value, pickle.HIGHEST_PROTOCOL)
|
||||
self._cache[key] = (expires,_val)
|
||||
try:
|
||||
if key[:4] == self.__session_key:
|
||||
if len(_val) < 256: return True
|
||||
if not os.path.exists(self.__session_basedir): os.makedirs(self.__session_basedir,384)
|
||||
|
||||
expires = struct.pack('f',expires)
|
||||
filename = '/'.join((self.__session_basedir,self.md5(key)))
|
||||
fp = open(filename, 'wb+')
|
||||
fp.write(expires + _val)
|
||||
fp.close()
|
||||
os.chmod(filename,384)
|
||||
except :pass
|
||||
return True
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
expires = self._normalize_timeout(timeout)
|
||||
self._prune()
|
||||
item = (expires, pickle.dumps(value,
|
||||
pickle.HIGHEST_PROTOCOL))
|
||||
if key in self._cache:
|
||||
return False
|
||||
self._cache.setdefault(key, item)
|
||||
return True
|
||||
|
||||
def delete(self, key):
|
||||
result = self._cache.pop(key, None) is not None
|
||||
try:
|
||||
if key[:4] == self.__session_key:
|
||||
filename = '/'.join((self.__session_basedir,self.md5(key)))
|
||||
if os.path.exists(filename): os.remove(filename)
|
||||
except : pass
|
||||
return result
|
||||
|
||||
def has(self, key):
|
||||
try:
|
||||
expires, value = self._cache[key]
|
||||
return expires == 0 or expires > time()
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
def md5(self,strings):
|
||||
"""
|
||||
生成MD5
|
||||
@strings 要被处理的字符串
|
||||
return string(32)
|
||||
"""
|
||||
import hashlib
|
||||
m = hashlib.md5()
|
||||
|
||||
m.update(strings.encode('utf-8'))
|
||||
return m.hexdigest()
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError: # pragma: no cover
|
||||
import pickle
|
||||
|
||||
from cachelib.base import BaseCache
|
||||
|
||||
|
||||
class UWSGICache(BaseCache):
|
||||
""" Implements the cache using uWSGI's caching framework.
|
||||
|
||||
.. note::
|
||||
This class cannot be used when running under PyPy, because the uWSGI
|
||||
API implementation for PyPy is lacking the needed functionality.
|
||||
|
||||
:param default_timeout: The default timeout in seconds.
|
||||
:param cache: The name of the caching instance to connect to, for
|
||||
example: mycache@localhost:3031, defaults to an empty string, which
|
||||
means uWSGI will cache in the local instance. If the cache is in the
|
||||
same instance as the werkzeug app, you only have to provide the name of
|
||||
the cache.
|
||||
"""
|
||||
def __init__(self, default_timeout=300, cache=''):
|
||||
BaseCache.__init__(self, default_timeout)
|
||||
|
||||
if platform.python_implementation() == 'PyPy':
|
||||
raise RuntimeError("uWSGI caching does not work under PyPy, see "
|
||||
"the docs for more details.")
|
||||
|
||||
try:
|
||||
import uwsgi
|
||||
self._uwsgi = uwsgi
|
||||
except ImportError:
|
||||
raise RuntimeError("uWSGI could not be imported, are you "
|
||||
"running under uWSGI?")
|
||||
|
||||
self.cache = cache
|
||||
|
||||
def get(self, key):
|
||||
rv = self._uwsgi.cache_get(key, self.cache)
|
||||
if rv is None:
|
||||
return
|
||||
return pickle.loads(rv)
|
||||
|
||||
def delete(self, key):
|
||||
return self._uwsgi.cache_del(key, self.cache)
|
||||
|
||||
def set(self, key, value, timeout=None):
|
||||
return self._uwsgi.cache_update(key, pickle.dumps(value),
|
||||
self._normalize_timeout(timeout),
|
||||
self.cache)
|
||||
|
||||
def add(self, key, value, timeout=None):
|
||||
return self._uwsgi.cache_set(key, pickle.dumps(value),
|
||||
self._normalize_timeout(timeout),
|
||||
self.cache)
|
||||
|
||||
def clear(self):
|
||||
return self._uwsgi.cache_clear(self.cache)
|
||||
|
||||
def has(self, key):
|
||||
return self._uwsgi.cache_exists(key, self.cache) is not None
|
||||
+41
-15
@@ -6,8 +6,7 @@
|
||||
# +-------------------------------------------------------------------
|
||||
# | Author: hwliang <hwl@bt.cn>
|
||||
# +-------------------------------------------------------------------
|
||||
from flask import request, redirect, g
|
||||
from BTPanel import session, cache
|
||||
from BTPanel import session, cache , request, redirect, g
|
||||
from datetime import datetime
|
||||
import os
|
||||
import public
|
||||
@@ -34,10 +33,11 @@ class panelSetup:
|
||||
ua = ua.lower()
|
||||
if ua.find('spider') != -1 or ua.find('bot') != -1:
|
||||
return redirect('https://www.google.com')
|
||||
g.version = '6.8.2'
|
||||
g.version = '6.8.4'
|
||||
g.title = public.GetConfigValue('title')
|
||||
g.uri = request.path
|
||||
g.debug = os.path.exists('data/debug.pl')
|
||||
g.pyversion = sys.version_info[0]
|
||||
if not g.debug:
|
||||
g.cdn_url = public.get_cdn_url()
|
||||
if not g.cdn_url:
|
||||
@@ -50,6 +50,19 @@ class panelSetup:
|
||||
session['version'] = g.version
|
||||
session['title'] = g.title
|
||||
g.is_aes = False
|
||||
|
||||
dirPath = '/www/server/phpmyadmin/pma'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
dirPath = '/www/server/adminer'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
dirPath = '/www/server/panel/adminer'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
@@ -59,6 +72,9 @@ class panelAdmin(panelSetup):
|
||||
# 本地请求
|
||||
def local(self):
|
||||
result = panelSetup().init()
|
||||
if result:
|
||||
return result
|
||||
result = self.check_login()
|
||||
if result:
|
||||
return result
|
||||
result = self.setSession()
|
||||
@@ -68,9 +84,6 @@ class panelAdmin(panelSetup):
|
||||
if result:
|
||||
return result
|
||||
result = self.checkWebType()
|
||||
if result:
|
||||
return result
|
||||
result = self.check_login()
|
||||
if result:
|
||||
return result
|
||||
result = self.checkConfig()
|
||||
@@ -99,7 +112,7 @@ class panelAdmin(panelSetup):
|
||||
if not 'lan' in session:
|
||||
session['lan'] = public.GetLanguage()
|
||||
if not 'home' in session:
|
||||
session['home'] = 'http://www.aapanel.com'
|
||||
session['home'] = 'https://console.aapanel.com'
|
||||
return None
|
||||
|
||||
# 检查Web服务器类型
|
||||
@@ -185,26 +198,37 @@ class panelAdmin(panelSetup):
|
||||
return redirect('/login')
|
||||
from BTPanel import get_input
|
||||
get = get_input()
|
||||
|
||||
|
||||
client_ip = public.GetClientIp()
|
||||
if not 'client_bind_token' in get:
|
||||
if not 'request_token' in get or not 'request_time' in get:
|
||||
return redirect('/login')
|
||||
client_ip = public.GetClientIp()
|
||||
|
||||
num_key = client_ip + '_api'
|
||||
if not public.get_error_num(num_key,20):
|
||||
return public.returnMsg(False,'AUTH_FAILED1')
|
||||
|
||||
|
||||
if not client_ip in api_config['limit_addr']:
|
||||
return public.returnJson(False,'%s[' % public.GetMsg("CHECK_IP_FALSE")+client_ip+']')
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False,'%s[' % public.GetMsg("AUTH_FAILED1")+client_ip+']')
|
||||
else:
|
||||
num_key = client_ip + '_app'
|
||||
if not public.get_error_num(num_key,20):
|
||||
return public.returnMsg(False,'AUTH_FAILED1')
|
||||
a_file = '/dev/shm/' + get.client_bind_token
|
||||
if not os.path.exists(a_file):
|
||||
import panelApi
|
||||
if not panelApi.panelApi().get_app_find(get.client_bind_token):
|
||||
return public.returnMsg(False, 'Unbound device')
|
||||
public.writeFile(a_file, '')
|
||||
public.set_error_num(num_key)
|
||||
return public.returnMsg(False,'UNBOUND_DEVICE')
|
||||
public.writeFile(a_file,'')
|
||||
|
||||
if not 'key' in api_config:
|
||||
return public.returnJson(False, 'Key verification failed')
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False, 'KEY_ERR')
|
||||
if not 'form_data' in get:
|
||||
return public.returnJson(False, 'No form_data data found')
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False, 'FORM_DATA_ERR')
|
||||
|
||||
g.form_data = json.loads(public.aes_decrypt(get.form_data, api_config['key']))
|
||||
|
||||
@@ -215,7 +239,9 @@ class panelAdmin(panelSetup):
|
||||
g.aes_key = api_config['key']
|
||||
request_token = public.md5(get.request_time + api_config['token'])
|
||||
if get.request_token == request_token:
|
||||
public.set_error_num(num_key,True)
|
||||
return False
|
||||
public.set_error_num(num_key)
|
||||
return public.returnJson(False,'SECRET_KEY_CHECK_FALSE')
|
||||
|
||||
# 检查系统配置
|
||||
|
||||
+1
-2
@@ -12,8 +12,7 @@ try:
|
||||
except:
|
||||
public.ExecShell("pip install pyotp &")
|
||||
try:
|
||||
from BTPanel import session,admin_path_checks,g
|
||||
from flask import request
|
||||
from BTPanel import session,admin_path_checks,g,request
|
||||
import send_mail
|
||||
except:pass
|
||||
class config:
|
||||
|
||||
+11
-3
@@ -10,7 +10,8 @@
|
||||
import sqlite3
|
||||
import os,time,sys
|
||||
os.chdir('/www/server/panel')
|
||||
sys.path.insert(0,'class')
|
||||
if not 'class/' in sys.path:
|
||||
sys.path.insert(0,'class/')
|
||||
import public
|
||||
|
||||
class Sql():
|
||||
@@ -29,7 +30,13 @@ class Sql():
|
||||
|
||||
def __init__(self):
|
||||
self.__DB_FILE = 'data/default.db'
|
||||
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self,exc_type,exc_value,exc_trackback):
|
||||
self.close()
|
||||
|
||||
def __GetConn(self):
|
||||
#取数据库对象
|
||||
try:
|
||||
@@ -306,7 +313,8 @@ class Sql():
|
||||
#写锁
|
||||
def write_lock(self):
|
||||
self.is_lock()
|
||||
open(self.__LOCK,'wb+').close()
|
||||
with open(self.__LOCK,'wb+') as f:
|
||||
f.close()
|
||||
|
||||
#解锁
|
||||
def rm_lock(self):
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ session.save_handler = files'''.format(path, sess_path, sess_path)
|
||||
# 上传文件
|
||||
def UploadFile(self, get):
|
||||
from werkzeug.utils import secure_filename
|
||||
from flask import request
|
||||
from BTPanel import request
|
||||
if sys.version_info[0] == 2:
|
||||
get.path = get.path.encode('utf-8')
|
||||
if not os.path.exists(get.path):
|
||||
|
||||
+34
-4
@@ -10,7 +10,21 @@ import time,public,db,os,sys,json,re
|
||||
os.chdir('/www/server/panel')
|
||||
|
||||
def control_init():
|
||||
dirPath = '/www/server/phpmyadmin/pma'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
dirPath = '/www/server/adminer'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
dirPath = '/www/server/panel/adminer'
|
||||
if os.path.exists(dirPath):
|
||||
public.ExecShell("rm -rf {}".format(dirPath))
|
||||
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
sql = db.Sql().dbfile('system')
|
||||
if not sql.table('sqlite_master').where('type=? AND name=?', ('table', 'load_average')).count():
|
||||
csql = '''CREATE TABLE IF NOT EXISTS `load_average` (
|
||||
@@ -105,7 +119,7 @@ def control_init():
|
||||
public.ExecShell(c)
|
||||
p_file = 'class/plugin2.so'
|
||||
if os.path.exists(p_file): public.ExecShell("rm -f class/*.so")
|
||||
# public.ExecShell("chmod -R 600 /www/server/panel/data;chmod -R 600 /www/server/panel/config;chmod -R 700 /www/server/cron;chmod -R 600 /www/server/cron/*.log;chown -R root:root /www/server/panel/data;chown -R root:root /www/server/panel/config;chown -R www:www /www/server/phpmyadmin;chmod -R 700 /www/server/phpmyadmin")
|
||||
public.ExecShell("chmod -R 600 /www/server/panel/data;chmod -R 600 /www/server/panel/config;chmod -R 700 /www/server/cron;chmod -R 600 /www/server/cron/*.log;chown -R root:root /www/server/panel/data;chown -R root:root /www/server/panel/config;chown -R root:root /www/server/phpmyadmin;chmod -R 755 /www/server/phpmyadmin")
|
||||
if os.path.exists("/www/server/mysql"):
|
||||
public.ExecShell("chown mysql:mysql /etc/my.cnf;chmod 600 /etc/my.cnf")
|
||||
stop_path = '/www/server/stop'
|
||||
@@ -113,6 +127,14 @@ def control_init():
|
||||
os.makedirs(stop_path)
|
||||
public.ExecShell("chown -R root:root {path};chmod -R 755 {path}".format(path=stop_path))
|
||||
public.ExecShell('chmod 755 /www;chmod 755 /www/server')
|
||||
if os.path.exists('/www/server/phpmyadmin/pma'):
|
||||
public.ExecShell("rm -rf /www/server/phpmyadmin/pma")
|
||||
if os.path.exists("/www/server/adminer"):
|
||||
public.ExecShell("rm -rf /www/server/adminer")
|
||||
if os.path.exists("/www/server/panel/adminer"):
|
||||
public.ExecShell("rm -rf /www/server/panel/adminer")
|
||||
if os.path.exists('/dev/shm/session.db'):
|
||||
os.remove('/dev/shm/session.db')
|
||||
#disable_putenv('putenv')
|
||||
clean_session()
|
||||
#set_crond()
|
||||
@@ -141,7 +163,15 @@ def files_set_mode():
|
||||
["/www/server/speed","/*.lua","root",755,False],
|
||||
["/www/server/speed/total","","www",755,True],
|
||||
["/www/server/btwaf","/*.lua","root",755,False],
|
||||
|
||||
["/www/backup","","root",600,True],
|
||||
["/www/wwwlogs","","www",700,True],
|
||||
["/www/enterprise_backup","","root",600,True],
|
||||
["/www/server/cron","","root",700,True],
|
||||
["/www/server/cron","/*.log","root",600,True],
|
||||
["/www/server/stop","","root",755,True],
|
||||
["/www/server/redis","","redis",700,True],
|
||||
["/www/server/redis/redis.conf","","redis",600,False],
|
||||
["/www/Recycle_bin","","root",600,True],
|
||||
["/www/server/panel/class","","root",600,True],
|
||||
["/www/server/panel/data","","root",600,True],
|
||||
["/www/server/panel/plugin","","root",600,False],
|
||||
@@ -163,8 +193,8 @@ def files_set_mode():
|
||||
["/dev/shm/session.db","","root",600,False],
|
||||
["/dev/shm/session_py3","","root",600,True],
|
||||
["/dev/shm/session_py2","","root",600,True],
|
||||
|
||||
["/www/server/adminer","","www",700,True]
|
||||
["/www/server/phpmyadmin","","root",755,True],
|
||||
["/www/server/coll","","root",700,True]
|
||||
]
|
||||
|
||||
for m in m_paths:
|
||||
|
||||
+280
-270
@@ -12,8 +12,6 @@
|
||||
# +-------------------------------------------------------------------
|
||||
|
||||
import json,os,public,time,re,sys
|
||||
if __name__ != "__main__":
|
||||
from BTPanel import request,abort,send_file,Resp,cache
|
||||
import time
|
||||
import fastcgiClient as fcgi_client
|
||||
import struct
|
||||
@@ -57,11 +55,21 @@ class panelPHP:
|
||||
|
||||
#将参数写到文件
|
||||
def __write_args(self,args):
|
||||
from BTPanel import request
|
||||
if os.path.exists(self.__args_tmp): os.remove(self.__args_tmp)
|
||||
self.__clean_args_file()
|
||||
data = {}
|
||||
data['GET'] = request.args.to_dict()
|
||||
data['POST'] = request.form.to_dict()
|
||||
data['POST'] = {}
|
||||
x_token = request.headers.get('x-http-token')
|
||||
if x_token:
|
||||
aes_pwd = x_token[:8] + x_token[40:48]
|
||||
for key in request.form.keys():
|
||||
data['POST'][key] = str(request.form.get(key,''))
|
||||
if x_token:
|
||||
if len(data['POST'][key]) > 5:
|
||||
if data['POST'][key][:6] == 'BT-CRT':
|
||||
data['POST'][key] = public.aes_decrypt(data['POST'][key][6:],aes_pwd)
|
||||
data['POST']['client_ip'] = public.GetClientIp()
|
||||
data = json.dumps(data)
|
||||
public.writeFile(self.__args_tmp,data)
|
||||
@@ -127,273 +135,275 @@ class panelPHP:
|
||||
break
|
||||
return php_v
|
||||
|
||||
def get_phpmyadmin_phpversion(self):
|
||||
'''
|
||||
@name 获取当前phpmyadmin设置的PHP版本
|
||||
@author hwliang<2020-07-13>
|
||||
@return string
|
||||
'''
|
||||
ikey = 'pma_phpv'
|
||||
phpv = cache.get(ikey)
|
||||
if phpv: return phpv
|
||||
webserver = public.get_webserver()
|
||||
if webserver == 'nginx':
|
||||
filename = public.GetConfigValue('setup_path') + '/nginx/conf/enable-php.conf'
|
||||
conf = public.readFile(filename)
|
||||
if not conf: return None
|
||||
rep = r"php-cgi-(\d+)\.sock"
|
||||
phpv = re.findall(rep,conf)
|
||||
elif webserver == 'openlitespeed':
|
||||
filename = public.GetConfigValue('setup_path') + "/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
|
||||
conf = public.readFile(filename)
|
||||
if not conf: return None
|
||||
rep = r"/usr/local/lsws/lsphp(\d+)/bin/lsphp"
|
||||
phpv = re.findall(rep,conf)
|
||||
else:
|
||||
filename = public.GetConfigValue('setup_path') + '/apache/conf/extra/httpd-vhosts.conf'
|
||||
conf = public.readFile(filename)
|
||||
if not conf: return None
|
||||
rep = r"php-cgi-(\d+)\.sock"
|
||||
phpv = re.findall(rep,conf)
|
||||
# def get_phpmyadmin_phpversion(self):
|
||||
# '''
|
||||
# @name 获取当前phpmyadmin设置的PHP版本
|
||||
# @author hwliang<2020-07-13>
|
||||
# @return string
|
||||
# '''
|
||||
# from BTPanel import cache
|
||||
# ikey = 'pma_phpv'
|
||||
# phpv = cache.get(ikey)
|
||||
# if phpv: return phpv
|
||||
# webserver = public.get_webserver()
|
||||
# if webserver == 'nginx':
|
||||
# filename = public.GetConfigValue('setup_path') + '/nginx/conf/enable-php.conf'
|
||||
# conf = public.readFile(filename)
|
||||
# if not conf: return None
|
||||
# rep = r"php-cgi-(\d+)\.sock"
|
||||
# phpv = re.findall(rep,conf)
|
||||
# elif webserver == 'openlitespeed':
|
||||
# filename = public.GetConfigValue('setup_path') + "/panel/vhost/openlitespeed/detail/phpmyadmin.conf"
|
||||
# conf = public.readFile(filename)
|
||||
# if not conf: return None
|
||||
# rep = r"/usr/local/lsws/lsphp(\d+)/bin/lsphp"
|
||||
# phpv = re.findall(rep,conf)
|
||||
# else:
|
||||
# filename = public.GetConfigValue('setup_path') + '/apache/conf/extra/httpd-vhosts.conf'
|
||||
# conf = public.readFile(filename)
|
||||
# if not conf: return None
|
||||
# rep = r"php-cgi-(\d+)\.sock"
|
||||
# phpv = re.findall(rep,conf)
|
||||
|
||||
if not phpv: return None
|
||||
cache.set(ikey,phpv[0],3)
|
||||
return phpv[0]
|
||||
|
||||
def get_pma_root(self):
|
||||
'''
|
||||
@name 获取phpmyadmin根目录
|
||||
@author hwliang<2020-07-13>
|
||||
@return string
|
||||
'''
|
||||
pma_path = '/www/server/phpmyadmin/'
|
||||
if not os.path.exists(pma_path):
|
||||
os.makedirs(pma_path)
|
||||
for dname in os.listdir(pma_path):
|
||||
if dname.find('phpmyadmin_') != -1:
|
||||
return os.path.join(pma_path,dname)
|
||||
return None
|
||||
|
||||
def check_phpmyadmin_phpversion(self):
|
||||
'''
|
||||
@name 检查当前phpmyadmin版本可用的php版本列表
|
||||
@author hwliang<2020-07-13>
|
||||
@return list
|
||||
'''
|
||||
pma_path = '/www/server/phpmyadmin/'
|
||||
pma_version_f1 = os.path.join(pma_path,'version_check.pl')
|
||||
pma_root = os.path.join(pma_path,'pma')
|
||||
pma_version_f2 = os.path.join(pma_root,'version_check.pl')
|
||||
if not os.path.exists(pma_version_f1):
|
||||
src_vfile = os.path.join(pma_path,'version.pl')
|
||||
if os.path.exists(src_vfile):
|
||||
public.writeFile(pma_version_f1,public.readFile(src_vfile))
|
||||
v_sync = public.readFile(pma_version_f1) == public.readFile(pma_version_f2)
|
||||
|
||||
if not os.path.exists(pma_root + '/index.php') or not v_sync:
|
||||
o_pma_root = self.get_pma_root()
|
||||
|
||||
if o_pma_root:
|
||||
if not os.path.exists(pma_root):
|
||||
os.makedirs(pma_root)
|
||||
public.ExecShell("\cp -arf {}/* {}/".format(o_pma_root,pma_root))
|
||||
public.ExecShell("chown -R www:www {}".format(pma_root))
|
||||
public.ExecShell("chmod -R 700 {}".format(pma_root))
|
||||
public.ExecShell("\cp -arf {} {}".format(pma_version_f1,pma_version_f2))
|
||||
index = public.readFile(pma_root + '/index.php')
|
||||
if index:
|
||||
if index.find("use PhpMyAdmin\\Util") != -1:
|
||||
resp = "use PhpMyAdmin\\Util;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
index = index.replace("use PhpMyAdmin\\Util;",resp)
|
||||
elif index.find("use PMA\libraries\LanguageManager;") != -1:
|
||||
resp = "use PMA\libraries\LanguageManager;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
index = index.replace("use PMA\libraries\LanguageManager;",resp)
|
||||
elif index.find("require_once 'libraries/common.inc.php';") != -1:
|
||||
resp = "if(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');\nrequire_once 'libraries/common.inc.php';"
|
||||
index = index.replace("require_once 'libraries/common.inc.php';",resp)
|
||||
|
||||
|
||||
public.writeFile(pma_root + '/index.php',index)
|
||||
|
||||
if not os.path.exists(pma_version_f2):
|
||||
return False
|
||||
|
||||
pma_version = public.readFile(pma_version_f2)
|
||||
self.pma_version = pma_version
|
||||
if pma_version:
|
||||
pma_version = pma_version[:3]
|
||||
|
||||
if pma_version == '4.4':
|
||||
return ['53','54','55','56']
|
||||
elif pma_version == '4.0':
|
||||
return ['52','53']
|
||||
elif pma_version == '4.6':
|
||||
return None
|
||||
elif pma_version == '4.7':
|
||||
return ['55','56','70','71','72']
|
||||
elif pma_version in ['4.8','4.9','5.0']:
|
||||
return ['70','71','72','73','74']
|
||||
else:
|
||||
return ['55','56','70','71','72']
|
||||
|
||||
def get_mysql_port(self):
|
||||
'''
|
||||
@name 获取mysql当前端口号
|
||||
@author hwliang<2020-07-13>
|
||||
@return int
|
||||
'''
|
||||
try:
|
||||
myconf = public.readFile('/etc/my.cnf')
|
||||
rep = r"port\s*=\s*([0-9]+)"
|
||||
port = int(re.search(rep,myconf).groups()[0])
|
||||
if not port: port = 3306
|
||||
return port
|
||||
except:
|
||||
return 3306
|
||||
|
||||
def write_pma_passwd(self,username,password):
|
||||
'''
|
||||
@name 写入mysql帐号密码到配置文件
|
||||
@author hwliang<2020-07-13>
|
||||
@param username string(用户名)
|
||||
@param password string(密码)
|
||||
@return bool
|
||||
'''
|
||||
|
||||
self.check_phpmyadmin_phpversion()
|
||||
pconfig = 'cookie'
|
||||
if username:
|
||||
pconfig = 'config'
|
||||
pma_path = '/www/server/phpmyadmin/'
|
||||
pma_config_file = os.path.join(pma_path,'pma/config.inc.php')
|
||||
conf = public.readFile(pma_config_file)
|
||||
if not conf: return False
|
||||
rep = r"/\* Authentication type \*/(.|\n)+/\* Server parameters \*/"
|
||||
rstr = '''/* Authentication type */
|
||||
$cfg['Servers'][$i]['auth_type'] = '{}';
|
||||
$cfg['Servers'][$i]['host'] = 'localhost';
|
||||
$cfg['Servers'][$i]['port'] = '{}';
|
||||
$cfg['Servers'][$i]['user'] = '{}';
|
||||
$cfg['Servers'][$i]['password'] = '{}';
|
||||
/* Server parameters */'''.format(pconfig,self.get_mysql_port(),username,password)
|
||||
conf = re.sub(rep,rstr,conf)
|
||||
public.writeFile(pma_config_file,conf)
|
||||
return True
|
||||
|
||||
def request_php(self,uri):
|
||||
'''
|
||||
@name 发起fastcgi请求到PHP-FPM
|
||||
@author hwliang<2020-07-11>
|
||||
@param puri string(URI地址)
|
||||
@return socket
|
||||
'''
|
||||
php_unix_socket = '/tmp/php-cgi-{}.sock'.format(self.php_version)
|
||||
f = FPM(php_unix_socket,self.document_root,self.last_path)
|
||||
|
||||
if request.full_path.find('?') != -1:
|
||||
uri = request.full_path[request.full_path.find(uri):]
|
||||
if self.re_io:
|
||||
sock = f.load_url(uri,content=self.re_io)
|
||||
else:
|
||||
sock = f.load_url(uri,content=request.stream)
|
||||
return sock
|
||||
|
||||
def start(self,puri,document_root,last_path = ''):
|
||||
'''
|
||||
@name 开始处理PHP请求
|
||||
@author hwliang<2020-07-11>
|
||||
@param puri string(URI地址)
|
||||
@return socket or Response
|
||||
'''
|
||||
if puri in ['/','',None]: puri = 'index.php'
|
||||
if puri[0] == '/': puri = puri[1:]
|
||||
self.document_root = document_root
|
||||
self.last_path = last_path
|
||||
filename = document_root + puri
|
||||
|
||||
|
||||
#如果是PHP文件
|
||||
if puri[-4:] == '.php':
|
||||
if request.path.find('/phpmyadmin/') != -1:
|
||||
ikey = 'pma_php_version'
|
||||
self.php_version = cache.get(ikey)
|
||||
if not self.php_version:
|
||||
php_version = self.get_phpmyadmin_phpversion()
|
||||
php_versions = self.check_phpmyadmin_phpversion()
|
||||
if not php_versions:
|
||||
if php_versions == False:
|
||||
return Resp(
|
||||
'Phpmyadmin is not installed, or support for phpMyAdmin4.6 has been discontinued due to security issues, uninstall and install other secure versions in the software store!')
|
||||
else:
|
||||
return Resp('phpmyadmin is not installed')
|
||||
if not php_version or not php_version in php_versions:
|
||||
php_version = php_versions
|
||||
self.php_version = self.get_php_version(php_version)
|
||||
if not self.php_version:
|
||||
php_version = self.check_phpmyadmin_phpversion()
|
||||
self.php_version = self.get_php_version(php_version)
|
||||
if not php_version:
|
||||
return Resp('No supported PHP version found: {}'.format(php_versions))
|
||||
|
||||
if not self.php_version in php_versions:
|
||||
self.php_version = self.get_php_version(php_versions)
|
||||
|
||||
if not self.php_version:
|
||||
return Resp('No supported PHP version found: {}'.format(php_versions))
|
||||
cache.set(ikey,self.php_version,1)
|
||||
if request.method == 'POST':
|
||||
#登录phpmyadmin
|
||||
if puri in ['index.php','/index.php']:
|
||||
content = public.url_encode(request.form.to_dict())
|
||||
if not isinstance(content,bytes):
|
||||
content = content.encode()
|
||||
self.re_io = StringIO(content)
|
||||
username = request.form.get('pma_username')
|
||||
if username:
|
||||
password = request.form.get('pma_password')
|
||||
if not self.write_pma_passwd(username,password):
|
||||
return Resp('Phpmyadmin is not installed')
|
||||
|
||||
if puri in ['logout.php', '/logout.php']:
|
||||
self.write_pma_passwd(None, None)
|
||||
else:
|
||||
src_path = '/www/server/panel/adminer'
|
||||
dst_path = '/www/server/adminer'
|
||||
if os.path.exists(src_path):
|
||||
if not os.path.exists(dst_path): os.makedirs(dst_path)
|
||||
public.ExecShell("\cp -arf {}/* {}/".format(src_path, dst_path))
|
||||
public.ExecShell("chown -R www:www {}".format(dst_path))
|
||||
public.ExecShell("chmod -R 700 {}".format(dst_path))
|
||||
public.ExecShell("rm -rf {}".format(src_path))
|
||||
|
||||
if not os.path.exists(dst_path + '/index.php'):
|
||||
return Resp("The AdMiner file is missing. Please try again after the [Fix] panel on the first page!")
|
||||
|
||||
ikey = 'aer_php_version'
|
||||
self.php_version = cache.get(ikey)
|
||||
if not self.php_version:
|
||||
self.php_version = self.get_php_version(None)
|
||||
cache.set(ikey, self.php_version, 10)
|
||||
if not self.php_version:
|
||||
return Resp('没有找到可用的PHP版本')
|
||||
|
||||
#文件是否存在?
|
||||
if not os.path.exists(filename):
|
||||
return abort(404)
|
||||
|
||||
#发送到FPM
|
||||
try:
|
||||
return self.request_php(puri)
|
||||
except Exception as ex:
|
||||
if str(ex).find('No such file or directory') != -1:
|
||||
return Resp('Specify PHP version: {}, not started, or unable to connect!'.format(self.php_version))
|
||||
return Resp(str(ex))
|
||||
|
||||
if not os.path.exists(filename):
|
||||
return abort(404)
|
||||
|
||||
#如果是静态文件
|
||||
return send_file(filename)
|
||||
# if not phpv: return None
|
||||
# cache.set(ikey,phpv[0],3)
|
||||
# return phpv[0]
|
||||
#
|
||||
# def get_pma_root(self):
|
||||
# '''
|
||||
# @name 获取phpmyadmin根目录
|
||||
# @author hwliang<2020-07-13>
|
||||
# @return string
|
||||
# '''
|
||||
# pma_path = '/www/server/phpmyadmin/'
|
||||
# if not os.path.exists(pma_path):
|
||||
# os.makedirs(pma_path)
|
||||
# for dname in os.listdir(pma_path):
|
||||
# if dname.find('phpmyadmin_') != -1:
|
||||
# return os.path.join(pma_path,dname)
|
||||
# return None
|
||||
#
|
||||
# def check_phpmyadmin_phpversion(self):
|
||||
# '''
|
||||
# @name 检查当前phpmyadmin版本可用的php版本列表
|
||||
# @author hwliang<2020-07-13>
|
||||
# @return list
|
||||
# '''
|
||||
# return
|
||||
# pma_path = '/www/server/phpmyadmin/'
|
||||
# pma_version_f1 = os.path.join(pma_path,'version_check.pl')
|
||||
# pma_root = os.path.join(pma_path,'pma')
|
||||
# pma_version_f2 = os.path.join(pma_root,'version_check.pl')
|
||||
# if not os.path.exists(pma_version_f1):
|
||||
# src_vfile = os.path.join(pma_path,'version.pl')
|
||||
# if os.path.exists(src_vfile):
|
||||
# public.writeFile(pma_version_f1,public.readFile(src_vfile))
|
||||
# v_sync = public.readFile(pma_version_f1) == public.readFile(pma_version_f2)
|
||||
#
|
||||
# if not os.path.exists(pma_root + '/index.php') or not v_sync:
|
||||
# o_pma_root = self.get_pma_root()
|
||||
#
|
||||
# if o_pma_root:
|
||||
# if not os.path.exists(pma_root):
|
||||
# os.makedirs(pma_root)
|
||||
# public.ExecShell("\cp -arf {}/* {}/".format(o_pma_root,pma_root))
|
||||
# public.ExecShell("chown -R www:www {}".format(pma_root))
|
||||
# public.ExecShell("chmod -R 700 {}".format(pma_root))
|
||||
# public.ExecShell("\cp -arf {} {}".format(pma_version_f1,pma_version_f2))
|
||||
# index = public.readFile(pma_root + '/index.php')
|
||||
# if index:
|
||||
# if index.find("use PhpMyAdmin\\Util") != -1:
|
||||
# resp = "use PhpMyAdmin\\Util;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
# index = index.replace("use PhpMyAdmin\\Util;",resp)
|
||||
# elif index.find("use PMA\libraries\LanguageManager;") != -1:
|
||||
# resp = "use PMA\libraries\LanguageManager;\nif(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');"
|
||||
# index = index.replace("use PMA\libraries\LanguageManager;",resp)
|
||||
# elif index.find("require_once 'libraries/common.inc.php';") != -1:
|
||||
# resp = "if(function_exists('opcache_invalidate')) opcache_invalidate('/www/server/phpmyadmin/pma/config.inc.php');\nrequire_once 'libraries/common.inc.php';"
|
||||
# index = index.replace("require_once 'libraries/common.inc.php';",resp)
|
||||
#
|
||||
#
|
||||
# public.writeFile(pma_root + '/index.php',index)
|
||||
#
|
||||
# if not os.path.exists(pma_version_f2):
|
||||
# return False
|
||||
#
|
||||
# pma_version = public.readFile(pma_version_f2)
|
||||
# self.pma_version = pma_version
|
||||
# if pma_version:
|
||||
# pma_version = pma_version[:3]
|
||||
#
|
||||
# if pma_version == '4.4':
|
||||
# return ['53','54','55','56']
|
||||
# elif pma_version == '4.0':
|
||||
# return ['52','53']
|
||||
# elif pma_version == '4.6':
|
||||
# return None
|
||||
# elif pma_version == '4.7':
|
||||
# return ['55','56','70','71','72']
|
||||
# elif pma_version in ['4.8','4.9','5.0']:
|
||||
# return ['70','71','72','73','74']
|
||||
# else:
|
||||
# return ['55','56','70','71','72']
|
||||
#
|
||||
# def get_mysql_port(self):
|
||||
# '''
|
||||
# @name 获取mysql当前端口号
|
||||
# @author hwliang<2020-07-13>
|
||||
# @return int
|
||||
# '''
|
||||
# try:
|
||||
# myconf = public.readFile('/etc/my.cnf')
|
||||
# rep = r"port\s*=\s*([0-9]+)"
|
||||
# port = int(re.search(rep,myconf).groups()[0])
|
||||
# if not port: port = 3306
|
||||
# return port
|
||||
# except:
|
||||
# return 3306
|
||||
#
|
||||
# def write_pma_passwd(self,username,password):
|
||||
# '''
|
||||
# @name 写入mysql帐号密码到配置文件
|
||||
# @author hwliang<2020-07-13>
|
||||
# @param username string(用户名)
|
||||
# @param password string(密码)
|
||||
# @return bool
|
||||
# '''
|
||||
#
|
||||
# self.check_phpmyadmin_phpversion()
|
||||
# pconfig = 'cookie'
|
||||
# if username:
|
||||
# pconfig = 'config'
|
||||
# pma_path = '/www/server/phpmyadmin/'
|
||||
# pma_config_file = os.path.join(pma_path,'pma/config.inc.php')
|
||||
# conf = public.readFile(pma_config_file)
|
||||
# if not conf: return False
|
||||
# rep = r"/\* Authentication type \*/(.|\n)+/\* Server parameters \*/"
|
||||
# rstr = '''/* Authentication type */
|
||||
# $cfg['Servers'][$i]['auth_type'] = '{}';
|
||||
# $cfg['Servers'][$i]['host'] = 'localhost';
|
||||
# $cfg['Servers'][$i]['port'] = '{}';
|
||||
# $cfg['Servers'][$i]['user'] = '{}';
|
||||
# $cfg['Servers'][$i]['password'] = '{}';
|
||||
# /* Server parameters */'''.format(pconfig,self.get_mysql_port(),username,password)
|
||||
# conf = re.sub(rep,rstr,conf)
|
||||
# public.writeFile(pma_config_file,conf)
|
||||
# return True
|
||||
#
|
||||
# def request_php(self,uri):
|
||||
# '''
|
||||
# @name 发起fastcgi请求到PHP-FPM
|
||||
# @author hwliang<2020-07-11>
|
||||
# @param puri string(URI地址)
|
||||
# @return socket
|
||||
# '''
|
||||
# php_unix_socket = '/tmp/php-cgi-{}.sock'.format(self.php_version)
|
||||
# f = FPM(php_unix_socket,self.document_root,self.last_path)
|
||||
#
|
||||
# if request.full_path.find('?') != -1:
|
||||
# uri = request.full_path[request.full_path.find(uri):]
|
||||
# if self.re_io:
|
||||
# sock = f.load_url(uri,content=self.re_io)
|
||||
# else:
|
||||
# sock = f.load_url(uri,content=request.stream)
|
||||
# return sock
|
||||
#
|
||||
# def start(self,puri,document_root,last_path = ''):
|
||||
# '''
|
||||
# @name 开始处理PHP请求
|
||||
# @author hwliang<2020-07-11>
|
||||
# @param puri string(URI地址)
|
||||
# @return socket or Response
|
||||
# '''
|
||||
# if puri in ['/','',None]: puri = 'index.php'
|
||||
# if puri[0] == '/': puri = puri[1:]
|
||||
# self.document_root = document_root
|
||||
# self.last_path = last_path
|
||||
# filename = document_root + puri
|
||||
#
|
||||
#
|
||||
# #如果是PHP文件
|
||||
# if puri[-4:] == '.php':
|
||||
# if request.path.find('/phpmyadmin/') != -1:
|
||||
# ikey = 'pma_php_version'
|
||||
# self.php_version = cache.get(ikey)
|
||||
# if not self.php_version:
|
||||
# php_version = self.get_phpmyadmin_phpversion()
|
||||
# php_versions = self.check_phpmyadmin_phpversion()
|
||||
# if not php_versions:
|
||||
# if php_versions == False:
|
||||
# return Resp(
|
||||
# 'Phpmyadmin is not installed, or support for phpMyAdmin4.6 has been discontinued due to security issues, uninstall and install other secure versions in the software store!')
|
||||
# else:
|
||||
# return Resp('phpmyadmin is not installed')
|
||||
# if not php_version or not php_version in php_versions:
|
||||
# php_version = php_versions
|
||||
# self.php_version = self.get_php_version(php_version)
|
||||
# if not self.php_version:
|
||||
# php_version = self.check_phpmyadmin_phpversion()
|
||||
# self.php_version = self.get_php_version(php_version)
|
||||
# if not php_version:
|
||||
# return Resp('No supported PHP version found: {}'.format(php_versions))
|
||||
#
|
||||
# if not self.php_version in php_versions:
|
||||
# self.php_version = self.get_php_version(php_versions)
|
||||
#
|
||||
# if not self.php_version:
|
||||
# return Resp('No supported PHP version found: {}'.format(php_versions))
|
||||
# cache.set(ikey,self.php_version,1)
|
||||
# if request.method == 'POST':
|
||||
# #登录phpmyadmin
|
||||
# if puri in ['index.php','/index.php']:
|
||||
# content = public.url_encode(request.form.to_dict())
|
||||
# if not isinstance(content,bytes):
|
||||
# content = content.encode()
|
||||
# self.re_io = StringIO(content)
|
||||
# username = request.form.get('pma_username')
|
||||
# if username:
|
||||
# password = request.form.get('pma_password')
|
||||
# if not self.write_pma_passwd(username,password):
|
||||
# return Resp('Phpmyadmin is not installed')
|
||||
#
|
||||
# if puri in ['logout.php', '/logout.php']:
|
||||
# self.write_pma_passwd(None, None)
|
||||
# else:
|
||||
# src_path = '/www/server/panel/adminer'
|
||||
# dst_path = '/www/server/adminer'
|
||||
# if os.path.exists(src_path):
|
||||
# if not os.path.exists(dst_path): os.makedirs(dst_path)
|
||||
# public.ExecShell("\cp -arf {}/* {}/".format(src_path, dst_path))
|
||||
# public.ExecShell("chown -R www:www {}".format(dst_path))
|
||||
# public.ExecShell("chmod -R 700 {}".format(dst_path))
|
||||
# public.ExecShell("rm -rf {}".format(src_path))
|
||||
#
|
||||
# if not os.path.exists(dst_path + '/index.php'):
|
||||
# return Resp("The AdMiner file is missing. Please try again after the [Fix] panel on the first page!")
|
||||
#
|
||||
# ikey = 'aer_php_version'
|
||||
# self.php_version = cache.get(ikey)
|
||||
# if not self.php_version:
|
||||
# self.php_version = self.get_php_version(None)
|
||||
# cache.set(ikey, self.php_version, 10)
|
||||
# if not self.php_version:
|
||||
# return Resp('没有找到可用的PHP版本')
|
||||
#
|
||||
# #文件是否存在?
|
||||
# if not os.path.exists(filename):
|
||||
# return abort(404)
|
||||
#
|
||||
# #发送到FPM
|
||||
# try:
|
||||
# return self.request_php(puri)
|
||||
# except Exception as ex:
|
||||
# if str(ex).find('No such file or directory') != -1:
|
||||
# return Resp('Specify PHP version: {}, not started, or unable to connect!'.format(self.php_version))
|
||||
# return Resp(str(ex))
|
||||
#
|
||||
# if not os.path.exists(filename):
|
||||
# return abort(404)
|
||||
#
|
||||
# #如果是静态文件
|
||||
# return send_file(filename)
|
||||
|
||||
|
||||
|
||||
@@ -529,7 +539,7 @@ class FPM(object):
|
||||
except ValueError:
|
||||
script_name = url
|
||||
query_string = ''
|
||||
|
||||
from BTPanel import request
|
||||
env = {
|
||||
'SCRIPT_FILENAME': '%s%s' % (self.document_root, script_name),
|
||||
'QUERY_STRING': query_string,
|
||||
|
||||
@@ -171,6 +171,8 @@ class panelPlugin:
|
||||
if 'status' in result:
|
||||
if result['status']:
|
||||
public.httpPost(public.GetConfigValue('home') + '/api/panel/plugin_total',{"pid":pluginInfo['id'],'p_name':pluginInfo['name']},3)
|
||||
get.force = 1
|
||||
self.get_cloud_list(get)
|
||||
except:pass
|
||||
return result
|
||||
|
||||
@@ -1891,8 +1893,7 @@ class panelPlugin:
|
||||
return panelPHP.panelPHP(get.name).exec_php_script(get)
|
||||
return public.returnMsg(False,'PLUGIN_INPUT_B')
|
||||
if not self.check_accept(get):return public.returnMsg(False,public.to_string([24744, 26410, 36141, 20080, 91, 37, 115, 93, 25110, 25480, 26435, 24050, 21040, 26399, 33]) % (self.get_title_byname(get),))
|
||||
if not path in sys.path:
|
||||
sys.path.insert(0,path)
|
||||
public.package_path_append(path)
|
||||
plugin_main = __import__(get.name+'_main')
|
||||
try:
|
||||
reload(plugin_main)
|
||||
|
||||
+21
-13
@@ -11,7 +11,10 @@
|
||||
# 网站管理类
|
||||
#------------------------------
|
||||
import io,re,public,os,sys,shutil,json,hashlib,socket,time
|
||||
from BTPanel import session
|
||||
try:
|
||||
from BTPanel import session
|
||||
except:
|
||||
pass
|
||||
from panelRedirect import panelRedirect
|
||||
import site_dir_auth
|
||||
class panelSite(panelRedirect):
|
||||
@@ -93,10 +96,10 @@ class panelSite(panelRedirect):
|
||||
for key in tmp:
|
||||
if key == port: return False
|
||||
|
||||
listen = "\nListen "+tmp[0]
|
||||
listen = "\nListen "+ tmp[0] + "\n"
|
||||
listen_ipv6 = ''
|
||||
#if self.is_ipv6: listen_ipv6 = "\nListen [::]:" + port
|
||||
allConf = allConf.replace(listen,listen + "\nListen " + port + listen_ipv6)
|
||||
allConf = allConf.replace(listen,listen + "Listen " + port + listen_ipv6 + "\n")
|
||||
public.writeFile(filename, allConf)
|
||||
return True
|
||||
|
||||
@@ -633,7 +636,7 @@ include /www/server/panel/vhost/openlitespeed/proxy/BTSITENAME/*.conf
|
||||
public.ExecShell("rm -f " + public.GetConfigValue('logs_path') + '/' + siteName + "-*")
|
||||
|
||||
#删除备份
|
||||
public.ExecShell("rm -f "+session['config']['backup_path']+'/site/'+siteName+'_*')
|
||||
#public.ExecShell("rm -f "+session['config']['backup_path']+'/site/'+siteName+'_*')
|
||||
|
||||
#删除根目录
|
||||
if 'path' in get:
|
||||
@@ -1423,10 +1426,11 @@ listener SSL443 {
|
||||
ssl_certificate /www/server/panel/vhost/cert/%s/fullchain.pem;
|
||||
ssl_certificate_key /www/server/panel/vhost/cert/%s/privkey.pem;
|
||||
ssl_protocols TLSv1.1 TLSv1.2%s;
|
||||
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
|
||||
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_session_timeout 10m;
|
||||
add_header Strict-Transport-Security "max-age=31536000";
|
||||
error_page 497 https://$host$request_uri;
|
||||
""" % (get.first_domain, get.first_domain,self.get_tls13())
|
||||
if (conf.find('ssl_certificate') != -1):
|
||||
@@ -1500,7 +1504,7 @@ listener SSL443 {
|
||||
SSLEngine On
|
||||
SSLCertificateFile /www/server/panel/vhost/cert/%s/fullchain.pem
|
||||
SSLCertificateKeyFile /www/server/panel/vhost/cert/%s/privkey.pem
|
||||
SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
|
||||
SSLCipherSuite EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5
|
||||
SSLProtocol All -SSLv2 -SSLv3 -TLSv1
|
||||
SSLHonorCipherOrder On
|
||||
%s
|
||||
@@ -1701,7 +1705,6 @@ listener SSL443 {
|
||||
detail_file = self.setupPath + '/panel/vhost/openlitespeed/detail/' + siteName + '.conf'
|
||||
force_https = self.setupPath + '/panel/vhost/openlitespeed/redirect/' + siteName
|
||||
string = 'rm -f {}/force_https.conf*'.format(force_https)
|
||||
public.writeFile("/tmp/2",string)
|
||||
public.ExecShell(string)
|
||||
detail_conf = public.readFile(detail_file)
|
||||
if detail_conf:
|
||||
@@ -1739,6 +1742,7 @@ listener SSL443 {
|
||||
type = 0
|
||||
if os.path.exists(path + '/README'): type = 1
|
||||
if os.path.exists(path + '/partnerOrderId'): type = 2
|
||||
if os.path.exists(path + '/certOrderId'): type = 3
|
||||
csrpath = path + "/fullchain.pem" # 生成证书路径
|
||||
keypath = path + "/privkey.pem" # 密钥文件路径
|
||||
key = public.readFile(keypath)
|
||||
@@ -1792,8 +1796,11 @@ listener SSL443 {
|
||||
if 'dnsapi' in crontab_config[siteName]:
|
||||
auth_type = 'dns'
|
||||
|
||||
|
||||
return {'status': status, 'domain': domains, 'key': key, 'csr': csr, 'type': type, 'httpTohttps': toHttps,'cert_data':cert_data,'email':email,"index":index,'auth_type':auth_type}
|
||||
if os.path.exists(path + '/certOrderId'): type = 3
|
||||
oid = -1
|
||||
if type == 3:
|
||||
oid = int(public.readFile(path + '/certOrderId'))
|
||||
return {'status': status,'oid':oid, 'domain': domains, 'key': key, 'csr': csr, 'type': type, 'httpTohttps': toHttps,'cert_data':cert_data,'email':email,"index":index,'auth_type':auth_type}
|
||||
|
||||
|
||||
#启动站点
|
||||
@@ -2887,7 +2894,7 @@ server
|
||||
if get.todomain:
|
||||
if not re.search(tod,get.todomain):
|
||||
return public.returnMsg(False, 'SENT_DOMAIN_FORMAT', (get.todomain,))
|
||||
else:
|
||||
if public.get_webserver() != 'openlitespeed':
|
||||
get.todomain = "$host"
|
||||
|
||||
# 检测目标URL格式
|
||||
@@ -3085,9 +3092,10 @@ RewriteRule ^%s(.*)$ http://%s/$1 [P,E=Proxy-Host:%s]
|
||||
status = self.SetProxy(get)
|
||||
if not status["status"]:
|
||||
return status
|
||||
get.version = '00'
|
||||
get.siteName = get.sitename
|
||||
self.SetPHPVersion(get)
|
||||
if get.proxydir == '/':
|
||||
get.version = '00'
|
||||
get.siteName = get.sitename
|
||||
self.SetPHPVersion(get)
|
||||
public.serviceReload()
|
||||
return public.returnMsg(True, 'ADD_SUCCESS')
|
||||
|
||||
|
||||
+14
-12
@@ -17,15 +17,16 @@ import public
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
sys.path.insert(0, '/www/server/panel/class')
|
||||
os.chdir('/www/server/panel')
|
||||
|
||||
if not 'class/' in sys.path:
|
||||
sys.path.insert(0,'class/')
|
||||
|
||||
class bt_task:
|
||||
__table = 'task_list'
|
||||
__task_tips = '/dev/shm/bt_task_now.pl'
|
||||
__task_path = '/www/server/panel/tmp/'
|
||||
down_log_total_file = '/tmp/download_total.pl'
|
||||
not_web = False
|
||||
def __init__(self):
|
||||
|
||||
# 创建数据表
|
||||
@@ -66,7 +67,7 @@ class bt_task:
|
||||
data = sql.field('id,name,type,shell,other,status,exectime,endtime,addtime').order(
|
||||
'id asc').limit('10').select()
|
||||
if type(data) == str:
|
||||
public.WriteLog('Task queue',data)
|
||||
public.WriteLog('TASK_QUEUE',data)
|
||||
return []
|
||||
if not 'num' in get:
|
||||
get.num = 15
|
||||
@@ -139,7 +140,7 @@ class bt_task:
|
||||
"kill -9 $(ps aux|grep '"+task_info['shell']+"'|grep -v grep|awk '{print $2}')")
|
||||
|
||||
public.ExecShell("/etc/init.d/bt start")
|
||||
return public.returnMsg(True, '任务已取消!')
|
||||
return public.returnMsg(True, 'TASK_CANCEL')
|
||||
|
||||
# 取一条任务
|
||||
def get_task_find(self, id):
|
||||
@@ -219,7 +220,9 @@ class bt_task:
|
||||
log_file = self.__task_path + str(id) + '.log'
|
||||
if not os.path.exists(log_file):
|
||||
data = ''
|
||||
if(task_type == '1'): data = {'name':public.GetMsg("DOWNLOAD_FILE"),'total':0,'used':0,'pre':0,'speed':0}
|
||||
if(task_type == '1'):
|
||||
data = {'name': public.GetMsg("DOWNLOAD_FILE"), 'total': 0, 'used': 0,
|
||||
'pre': 0, 'speed': 0, 'time': 0}
|
||||
return data
|
||||
|
||||
if(task_type == '1'):
|
||||
@@ -245,7 +248,7 @@ class bt_task:
|
||||
speed_total = re.findall(
|
||||
r"([\d\.]+[BbKkMmGg]).+\s+(\d+)%\s+([\d\.]+[KMBGkmbg])\s+(\w+[sS])", speed_tmp)
|
||||
if not speed_total:
|
||||
data = {'name':'download file {}'.format(filename),'total':0,'used':0,'pre':0,'speed':0,'time':0}
|
||||
data = {'name':public.getMsg('DOWNLOAD_FILE1',(filename,)),'total':0,'used':0,'pre':0,'speed':0,'time':0}
|
||||
else:
|
||||
speed_total = speed_total[0]
|
||||
used = speed_total[0]
|
||||
@@ -312,7 +315,7 @@ class bt_task:
|
||||
return public.returnMsg(False,'NOT_SUP_COMP_FORMAT')
|
||||
|
||||
self.set_file_accept(dfile)
|
||||
public.WriteLog("TYPE_FILE", 'ZIP_SUCCESS', (sfiles, dfile))
|
||||
public.WriteLog("TYPE_FILE", 'ZIP_SUCCESS', (sfiles, dfile),not_web = self.not_web)
|
||||
return public.returnMsg(True, 'ZIP_SUCCESS')
|
||||
|
||||
# 文件解压
|
||||
@@ -356,7 +359,7 @@ class bt_task:
|
||||
user = pwd.getpwuid(os.stat(dfile).st_uid).pw_name
|
||||
public.ExecShell("chown %s:%s %s" % (user, user, dfile))
|
||||
|
||||
public.WriteLog("TYPE_FILE", 'UNZIP_SUCCESS', (sfile, dfile))
|
||||
public.WriteLog("TYPE_FILE", 'UNZIP_SUCCESS', (sfile, dfile),not_web = self.not_web)
|
||||
return public.returnMsg(True, 'UNZIP_SUCCESS')
|
||||
|
||||
# 备份网站
|
||||
@@ -378,7 +381,7 @@ class bt_task:
|
||||
|
||||
sql = public.M('backup').add('type,name,pid,filename,size,addtime',
|
||||
(0, fileName, find['id'], zipName, 0, public.getDate()))
|
||||
public.WriteLog('TYPE_SITE', 'SITE_BACKUP_SUCCESS', (find['name'],))
|
||||
public.WriteLog('TYPE_SITE', 'SITE_BACKUP_SUCCESS', (find['name'],),not_web = self.not_web)
|
||||
return public.returnMsg(True, 'BACKUP_SUCCESS')
|
||||
|
||||
# 备份数据库
|
||||
@@ -405,7 +408,7 @@ class bt_task:
|
||||
addTime = time.strftime('%Y-%m-%d %X', time.localtime())
|
||||
sql.add('type,name,pid,filename,size,addtime',
|
||||
(1, fileName, id, backupName, 0, addTime))
|
||||
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (name,))
|
||||
public.WriteLog("TYPE_DATABASE", "DATABASE_BACKUP_SUCCESS", (name,),not_web = self.not_web)
|
||||
return public.returnMsg(True, 'BACKUP_SUCCESS')
|
||||
|
||||
# 导入数据库
|
||||
@@ -454,7 +457,7 @@ class bt_task:
|
||||
'setup_path') + "/mysql/bin/mysql -uroot -p" + root + " --force \"" + name + "\" < " + file)
|
||||
self.mypass(False, root)
|
||||
|
||||
public.WriteLog("TYPE_DATABASE", 'DATABASE_INPUT_SUCCESS', (name,))
|
||||
public.WriteLog("TYPE_DATABASE", 'DATABASE_INPUT_SUCCESS', (name,),not_web = self.not_web)
|
||||
return public.returnMsg(True, 'DATABASE_INPUT_SUCCESS')
|
||||
|
||||
# 配置
|
||||
@@ -479,7 +482,6 @@ class bt_task:
|
||||
from collections import namedtuple
|
||||
get = namedtuple('get',['path'])
|
||||
get.path = filename
|
||||
public.writeFile('/tmp/2',str(get.path))
|
||||
files.files().fix_permissions(get)
|
||||
|
||||
# 检查敏感目录
|
||||
|
||||
@@ -164,7 +164,8 @@ class panel_restore:
|
||||
result = self._restore_backup(self._local_file, site_info, args)
|
||||
else:
|
||||
return public.ExecShell(False,'Currently only supports restoring local, Google storage and AWS S3 backups')
|
||||
os.remove(self._local_file)
|
||||
if os.path.exists(self._local_file):
|
||||
os.remove(self._local_file)
|
||||
if result:
|
||||
self._progress_rewrite('Recovery failed: {}'.format(str(site_info['site_path'])))
|
||||
return result
|
||||
|
||||
+101
-15
@@ -32,8 +32,9 @@ def M(table):
|
||||
ps: 默认访问data/default.db
|
||||
"""
|
||||
import db
|
||||
sql = db.Sql()
|
||||
return sql.table(table)
|
||||
with db.Sql() as sql:
|
||||
#sql = db.Sql()
|
||||
return sql.table(table)
|
||||
|
||||
def HttpGet(url,timeout = 6,headers = {}):
|
||||
"""
|
||||
@@ -317,7 +318,7 @@ def GetJson(data):
|
||||
try:
|
||||
return dumps(data,ensure_ascii=False)
|
||||
except:
|
||||
return dumps(returnMsg(False,"Wrong response: %s" % str(data)))
|
||||
return dumps(returnMsg(False,"WRONG_RESPONSE", (str(data))))
|
||||
|
||||
def getJson(data):
|
||||
return GetJson(data)
|
||||
@@ -341,10 +342,10 @@ def ReadFile(filename,mode = 'r'):
|
||||
f_body = fp.read()
|
||||
fp.close()
|
||||
except Exception as ex2:
|
||||
WriteLog('Open File',str(ex2))
|
||||
WriteLog('OPEN_FILE',str(ex2))
|
||||
return False
|
||||
else:
|
||||
WriteLog('Open File',str(ex))
|
||||
WriteLog('OPEN_FILE',str(ex))
|
||||
return False
|
||||
return f_body
|
||||
|
||||
@@ -375,19 +376,20 @@ def WriteFile(filename,s_body,mode='w+'):
|
||||
def writeFile(filename,s_body,mode='w+'):
|
||||
return WriteFile(filename,s_body,mode)
|
||||
|
||||
def WriteLog(type,logMsg,args=()):
|
||||
def WriteLog(type,logMsg,args=(),not_web = False):
|
||||
#写日志
|
||||
#try:
|
||||
import time,db,json
|
||||
username = 'system'
|
||||
uid = 1
|
||||
try:
|
||||
from BTPanel import session
|
||||
if 'username' in session:
|
||||
username = session['username']
|
||||
uid = session['uid']
|
||||
except:
|
||||
pass
|
||||
if not not_web:
|
||||
try:
|
||||
from BTPanel import session
|
||||
if 'username' in session:
|
||||
username = session['username']
|
||||
uid = session['uid']
|
||||
except:
|
||||
pass
|
||||
global _LAN_LOG
|
||||
if not _LAN_LOG:
|
||||
_LAN_LOG = json.loads(ReadFile('BTPanel/static/language/' + GetLanguage() + '/log.json'))
|
||||
@@ -624,8 +626,10 @@ def get_url(timeout = 0.5):
|
||||
mnode1 = []
|
||||
mnode2 = []
|
||||
mnode3 = []
|
||||
new_node_list = {}
|
||||
for node in node_list:
|
||||
node['net'],node['ping'] = get_timeout(node['protocol'] + node['address'] + ':' + node['port'] + '/net_test',1)
|
||||
new_node_list[node['address']] = node['ping']
|
||||
if not node['ping']: continue
|
||||
if node['ping'] < 100: #当响应时间<100ms且可用带宽大于1500KB时
|
||||
if node['net'] > 1500:
|
||||
@@ -645,6 +649,16 @@ def get_url(timeout = 0.5):
|
||||
mnode = sorted(mnode2,key= lambda x:x['ping'],reverse=False)
|
||||
|
||||
if not mnode: return 'http://download.bt.cn'
|
||||
|
||||
new_node_keys = new_node_list.keys()
|
||||
for i in range(len(node_list)):
|
||||
if node_list[i]['address'] in new_node_keys:
|
||||
node_list[i]['ping'] = new_node_list[node_list[i]['address']]
|
||||
else:
|
||||
node_list[i]['ping'] = 500
|
||||
|
||||
new_node_list = sorted(node_list,key=lambda x: x['ping'],reverse=False)
|
||||
writeFile(nodeFile,json.dumps(new_node_list))
|
||||
return mnode[0]['protocol'] + mnode[0]['address'] + ':' + mnode[0]['port']
|
||||
except:
|
||||
return 'http://download.bt.cn'
|
||||
@@ -1356,7 +1370,7 @@ def write_request_log(reques = None):
|
||||
log_file = getDate(format='%Y-%m-%d') + '.json'
|
||||
if not os.path.exists(log_path): os.makedirs(log_path)
|
||||
|
||||
from flask import request
|
||||
from BTPanel import request
|
||||
log_data = []
|
||||
log_data.append(getDate())
|
||||
log_data.append(GetClientIp() + ':' + str(request.environ.get('REMOTE_PORT')))
|
||||
@@ -1364,6 +1378,7 @@ def write_request_log(reques = None):
|
||||
log_data.append(request.full_path)
|
||||
log_data.append(request.headers.get('User-Agent'))
|
||||
WriteFile(log_path + '/' + log_file,json.dumps(log_data) + "\n",'a+')
|
||||
rep_sys_path()
|
||||
except: pass
|
||||
|
||||
# 重载模块
|
||||
@@ -1545,6 +1560,7 @@ def auto_backup_panel():
|
||||
shutil.copytree(panel_paeh + '/data',backup_path + '/data')
|
||||
shutil.copytree(panel_paeh + '/config',backup_path + '/config')
|
||||
shutil.copytree(panel_paeh + '/vhost',backup_path + '/vhost')
|
||||
ExecShell("chmod -R 600 {path};chown -R root.root {path}".format(paht=b_path))
|
||||
time_now = time.time() - (86400 * 15)
|
||||
for f in os.listdir(b_path):
|
||||
try:
|
||||
@@ -1723,7 +1739,7 @@ def import_cdn_plugin():
|
||||
try:
|
||||
import static_cdn_main
|
||||
except:
|
||||
sys.path.insert(0,plugin_path)
|
||||
package_path_append(plugin_path)
|
||||
import static_cdn_main
|
||||
|
||||
|
||||
@@ -1737,6 +1753,8 @@ def get_cdn_hosts():
|
||||
|
||||
def get_cdn_url():
|
||||
try:
|
||||
if os.path.exists('plugin/static_cdn/not_open.pl'):
|
||||
return False
|
||||
from BTPanel import cache
|
||||
cdn_url = cache.get('cdn_url')
|
||||
if cdn_url: return cdn_url
|
||||
@@ -1921,6 +1939,74 @@ def restore_file(file, act=None):
|
||||
file_type = "_def"
|
||||
ExecShell("/usr/bin/cp -p {1} {0}".format(file, file + file_type))
|
||||
|
||||
|
||||
def package_path_append(path):
|
||||
if not path in sys.path:
|
||||
sys.path.insert(0, path)
|
||||
|
||||
|
||||
def rep_sys_path():
|
||||
sys_path = []
|
||||
for p in sys.path:
|
||||
if p in sys_path: continue
|
||||
sys_path.append(p)
|
||||
sys.path = sys_path
|
||||
|
||||
|
||||
def get_ssh_port():
|
||||
'''
|
||||
@name 获取本机SSH端口
|
||||
@author hwliang<2020-08-07>
|
||||
@return int
|
||||
'''
|
||||
s_file = '/etc/ssh/sshd_config'
|
||||
conf = readFile(s_file)
|
||||
if not conf: conf = ''
|
||||
rep = r"#*Port\s+([0-9]+)\s*\n"
|
||||
tmp1 = re.search(rep, conf)
|
||||
ssh_port = 22
|
||||
if tmp1:
|
||||
ssh_port = int(tmp1.groups(0)[0])
|
||||
return ssh_port
|
||||
|
||||
def set_error_num(key,empty = False,expire=3600):
|
||||
'''
|
||||
@name 设置失败次数(每调用一次+1)
|
||||
@author hwliang<2020-08-21>
|
||||
@param key<string> 索引
|
||||
@param empty<bool> 是否清空计数
|
||||
@param expire<int> 计数器生命周期(秒)
|
||||
@return bool
|
||||
'''
|
||||
from BTPanel import cache
|
||||
num = cache.get(key)
|
||||
if not num:
|
||||
num = 0
|
||||
else:
|
||||
if empty:
|
||||
cache.delete(key)
|
||||
return True
|
||||
cache.set(key,num + 1,expire)
|
||||
return True
|
||||
|
||||
def get_error_num(key,limit=False):
|
||||
'''
|
||||
@name 获取失败次数
|
||||
@author hwliang<2020-08-21>
|
||||
@param key<string> 索引
|
||||
@param limit<False or int> 如果为False,则直接返回失败次数,否则与失败次数比较,若大于失败次数返回True,否则返回False
|
||||
@return int or bool
|
||||
'''
|
||||
from BTPanel import cache
|
||||
num = cache.get(key)
|
||||
if not num: num = 0
|
||||
if not limit:
|
||||
return num
|
||||
if limit > num:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
#取通用对象
|
||||
class dict_obj:
|
||||
def __contains__(self, key):
|
||||
|
||||
+861
-142
File diff suppressed because it is too large
Load Diff
+17
-11
@@ -12,19 +12,19 @@ try:
|
||||
except:
|
||||
pass
|
||||
class system:
|
||||
setupPath = None;
|
||||
setupPath = None
|
||||
ssh = None
|
||||
shell = None
|
||||
|
||||
def __init__(self):
|
||||
self.setupPath = public.GetConfigValue('setup_path');
|
||||
self.setupPath = public.GetConfigValue('setup_path')
|
||||
|
||||
def GetConcifInfo(self,get=None):
|
||||
#取环境配置信息
|
||||
if not 'config' in session:
|
||||
session['config'] = public.M('config').where("id=?",('1',)).field('webserver,sites_path,backup_path,status,mysql_root').find();
|
||||
session['config'] = public.M('config').where("id=?",('1',)).field('webserver,sites_path,backup_path,status,mysql_root').find()
|
||||
if not 'email' in session['config']:
|
||||
session['config']['email'] = public.M('users').where("id=?",('1',)).getField('email');
|
||||
session['config']['email'] = public.M('users').where("id=?",('1',)).getField('email')
|
||||
data = {}
|
||||
data = session['config']
|
||||
data['webserver'] = session['config']['webserver']
|
||||
@@ -66,8 +66,8 @@ class system:
|
||||
if rtmp:
|
||||
phpport = rtmp.groups()[0]
|
||||
|
||||
if conf.find('AUTH_START') != -1: pauth = True;
|
||||
if conf.find(self.setupPath + '/stop') == -1: pstatus = True;
|
||||
if conf.find('AUTH_START') != -1: pauth = True
|
||||
if conf.find(self.setupPath + '/stop') == -1: pstatus = True
|
||||
configFile = self.setupPath + '/nginx/conf/enable-php.conf'
|
||||
conf = public.readFile(configFile)
|
||||
rep = "php-cgi-([0-9]+)\.sock"
|
||||
@@ -75,7 +75,7 @@ class system:
|
||||
if rtmp:
|
||||
phpversion = rtmp.groups()[0]
|
||||
except:
|
||||
pass;
|
||||
pass
|
||||
|
||||
elif os.path.exists(self.setupPath+'/apache'):
|
||||
data['webserver'] = 'apache'
|
||||
@@ -93,8 +93,8 @@ class system:
|
||||
rtmp = re.search(rep,conf)
|
||||
if rtmp:
|
||||
phpport = rtmp.groups()[0]
|
||||
if conf.find('AUTH_START') != -1: pauth = True;
|
||||
if conf.find(self.setupPath + '/stop') == -1: pstatus = True;
|
||||
if conf.find('AUTH_START') != -1: pauth = True
|
||||
if conf.find(self.setupPath + '/stop') == -1: pstatus = True
|
||||
except:
|
||||
pass
|
||||
elif os.path.exists('/usr/local/lsws/bin/lswsctrl'):
|
||||
@@ -480,10 +480,16 @@ class system:
|
||||
|
||||
ntime = time.time()
|
||||
networkInfo = {}
|
||||
up = cache.get('up')
|
||||
down = cache.get('down')
|
||||
if not up:
|
||||
up = networkIo[0]
|
||||
if not down:
|
||||
down = networkIo[1]
|
||||
networkInfo['upTotal'] = networkIo[0]
|
||||
networkInfo['downTotal'] = networkIo[1]
|
||||
networkInfo['up'] = round(float(networkIo[0] - cache.get("up")) / 1024 / (ntime - otime),2)
|
||||
networkInfo['down'] = round(float(networkIo[1] - cache.get("down")) / 1024 / (ntime - otime),2)
|
||||
networkInfo['up'] = round(float(networkIo[0] - up) / 1024 / (ntime - otime),2)
|
||||
networkInfo['down'] = round(float(networkIo[1] - down) / 1024 / (ntime - otime),2)
|
||||
networkInfo['downPackets'] =networkIo[3]
|
||||
networkInfo['upPackets'] =networkIo[2]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user